1 /******************************************************************************
2 *
3 * Copyright(c) 2007 - 2017 Realtek Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 *****************************************************************************/
15
16 /* ************************************************************
17 * include files
18 * ************************************************************ */
19 #include "mp_precomp.h"
20 #include "phydm_precomp.h"
21
22
23 u8
odm_get_auto_channel_select_result(void * p_dm_void,u8 band)24 odm_get_auto_channel_select_result(
25 void *p_dm_void,
26 u8 band
27 )
28 {
29 struct PHY_DM_STRUCT *p_dm = (struct PHY_DM_STRUCT *)p_dm_void;
30 struct _ACS_ *p_acs = &p_dm->dm_acs;
31
32 PHYDM_DBG(p_dm, ODM_COMP_API, ("%s ======>\n", __func__));
33
34 #if (DM_ODM_SUPPORT_TYPE & (ODM_WIN | ODM_CE))
35 if (band == ODM_BAND_2_4G) {
36 PHYDM_DBG(p_dm, ODM_COMP_API, ("clean_CH_2g=%d\n", p_acs->clean_channel_2g));
37 return (u8)p_acs->clean_channel_2g;
38 } else {
39 PHYDM_DBG(p_dm, ODM_COMP_API, ("clean_CH_5g=%d\n", p_acs->clean_channel_5g));
40 return (u8)p_acs->clean_channel_5g;
41 }
42 #else
43 return (u8)p_acs->clean_channel_2g;
44 #endif
45
46 }
47
48 void
odm_auto_channel_select_init(void * p_dm_void)49 odm_auto_channel_select_init(
50 void *p_dm_void
51 )
52 {
53 #if (DM_ODM_SUPPORT_TYPE & (ODM_WIN | ODM_CE))
54 struct PHY_DM_STRUCT *p_dm = (struct PHY_DM_STRUCT *)p_dm_void;
55 struct _ACS_ *p_acs = &p_dm->dm_acs;
56 u8 i;
57
58 if (!(p_dm->support_ability & ODM_BB_ENV_MONITOR))
59 return;
60
61 if (p_acs->is_force_acs_result)
62 return;
63
64 PHYDM_DBG(p_dm, ODM_COMP_API, ("%s ======>\n", __func__));
65
66 p_acs->clean_channel_2g = 1;
67 p_acs->clean_channel_5g = 36;
68
69 for (i = 0; i < ODM_MAX_CHANNEL_2G; ++i) {
70 p_acs->channel_info_2g[0][i] = 0;
71 p_acs->channel_info_2g[1][i] = 0;
72 }
73
74 if (p_dm->support_ic_type & ODM_IC_11AC_SERIES) {
75 for (i = 0; i < ODM_MAX_CHANNEL_5G; ++i) {
76 p_acs->channel_info_5g[0][i] = 0;
77 p_acs->channel_info_5g[1][i] = 0;
78 }
79 }
80 #endif
81 }
82
83 void
odm_auto_channel_select_reset(void * p_dm_void)84 odm_auto_channel_select_reset(
85 void *p_dm_void
86 )
87 {
88 #if (DM_ODM_SUPPORT_TYPE & (ODM_WIN | ODM_CE))
89 struct PHY_DM_STRUCT *p_dm = (struct PHY_DM_STRUCT *)p_dm_void;
90 struct _ACS_ *p_acs = &p_dm->dm_acs;
91 struct _CCX_INFO *ccx_info = &p_dm->dm_ccx_info;
92
93 if (!(p_dm->support_ability & ODM_BB_ENV_MONITOR))
94 return;
95
96 if (p_acs->is_force_acs_result)
97 return;
98
99 PHYDM_DBG(p_dm, ODM_COMP_API, ("%s ======>\n", __func__));
100
101 ccx_info->nhm_period = 0x1388; /*20ms*/
102 phydm_nhm_setting(p_dm, SET_NHM_SETTING);
103 phydm_nhm_trigger(p_dm);
104 #endif
105 }
106
107 void
odm_auto_channel_select(void * p_dm_void,u8 channel)108 odm_auto_channel_select(
109 void *p_dm_void,
110 u8 channel
111 )
112 {
113 #if (DM_ODM_SUPPORT_TYPE & (ODM_WIN | ODM_CE))
114 struct PHY_DM_STRUCT *p_dm = (struct PHY_DM_STRUCT *)p_dm_void;
115 struct _ACS_ *p_acs = &p_dm->dm_acs;
116 struct _CCX_INFO *ccx_info = &p_dm->dm_ccx_info;
117 u8 channel_idx = 0, search_idx = 0;
118 u8 noisy_nhm_th = 0x52;
119 u8 i, noisy_nhm_th_index, low_pwr_cnt = 0;
120 u16 max_score = 0;
121
122 PHYDM_DBG(p_dm, ODM_COMP_API, ("%s ======>\n", __func__));
123
124 if (!(p_dm->support_ability & ODM_BB_ENV_MONITOR)) {
125 PHYDM_DBG(p_dm, DBG_DIG, ("Return: Not support\n"));
126 return;
127 }
128
129 if (p_acs->is_force_acs_result) {
130 PHYDM_DBG(p_dm, DBG_DIG, ("Force clean CH{2G,5G}={%d,%d}\n",
131 p_acs->clean_channel_2g, p_acs->clean_channel_5g));
132 return;
133 }
134
135 PHYDM_DBG(p_dm, ODM_COMP_API, ("CH=%d\n", channel));
136
137 phydm_get_nhm_result(p_dm);
138 noisy_nhm_th_index = (noisy_nhm_th - ccx_info->nhm_th[0]) << 2;
139
140 for (i = 0; i <= 11; i++) {
141 if (i <= noisy_nhm_th_index)
142 low_pwr_cnt += ccx_info->nhm_result[i];
143 }
144
145 ccx_info->nhm_period = 0x2710;
146 phydm_nhm_setting(p_dm, SET_NHM_SETTING);
147
148 if (channel >= 1 && channel <= 14) {
149 channel_idx = channel - 1;
150 p_acs->channel_info_2g[1][channel_idx]++;
151
152 if (p_acs->channel_info_2g[1][channel_idx] >= 2)
153 p_acs->channel_info_2g[0][channel_idx] = (p_acs->channel_info_2g[0][channel_idx] >> 1) +
154 (p_acs->channel_info_2g[0][channel_idx] >> 2) + (low_pwr_cnt >> 2);
155 else
156 p_acs->channel_info_2g[0][channel_idx] = low_pwr_cnt;
157
158 PHYDM_DBG(p_dm, ODM_COMP_API, ("low_pwr_cnt = %d\n", low_pwr_cnt));
159 PHYDM_DBG(p_dm, ODM_COMP_API, ("CH_Info[0][%d]=%d, CH_Info[1][%d]=%d\n", channel_idx, p_acs->channel_info_2g[0][channel_idx], channel_idx, p_acs->channel_info_2g[1][channel_idx]));
160
161 for (search_idx = 0; search_idx < ODM_MAX_CHANNEL_2G; search_idx++) {
162 if (p_acs->channel_info_2g[1][search_idx] != 0 && p_acs->channel_info_2g[0][search_idx] >= max_score) {
163 max_score = p_acs->channel_info_2g[0][search_idx];
164 p_acs->clean_channel_2g = search_idx + 1;
165 }
166 }
167 PHYDM_DBG(p_dm, ODM_COMP_API, ("clean_CH_2g=%d, max_score=%d\n",
168 p_acs->clean_channel_2g, max_score));
169
170 } else if (channel >= 36) {
171 /* Need to do */
172 p_acs->clean_channel_5g = channel;
173 }
174 #endif
175 }
176
177 boolean
phydm_acs_check(void * p_dm_void)178 phydm_acs_check(
179 void *p_dm_void
180 )
181 {
182 #if (DM_ODM_SUPPORT_TYPE == ODM_AP)
183 struct PHY_DM_STRUCT *p_dm = (struct PHY_DM_STRUCT *)p_dm_void;
184 struct rtl8192cd_priv *priv = p_dm->priv;
185
186 if ((priv->auto_channel != 0) && (priv->auto_channel != 2)) /* if struct _ACS_ running, do not do FA/CCA counter read */
187 return true;
188 else
189 return false;
190 #else
191 return false;
192 #endif
193 }
194
195 #if (DM_ODM_SUPPORT_TYPE & ODM_AP)
196
197 void
phydm_auto_channel_select_setting_ap(void * p_dm_void,u32 setting,u32 acs_step)198 phydm_auto_channel_select_setting_ap(
199 void *p_dm_void,
200 u32 setting, /* 0: STORE_DEFAULT_NHM_SETTING; 1: RESTORE_DEFAULT_NHM_SETTING, 2: ACS_NHM_SETTING */
201 u32 acs_step
202 )
203 {
204 struct PHY_DM_STRUCT *p_dm = (struct PHY_DM_STRUCT *)p_dm_void;
205 struct rtl8192cd_priv *priv = p_dm->priv;
206 struct _ACS_ *p_acs = &p_dm->dm_acs;
207
208 PHYDM_DBG(p_dm, ODM_COMP_API, ("%s ======>\n", __func__));
209
210 /* 3 Store Default setting */
211 if (setting == STORE_DEFAULT_NHM_SETTING) {
212 PHYDM_DBG(p_dm, ODM_COMP_API, ("STORE_DEFAULT_NHM_SETTING\n"));
213
214 if (p_dm->support_ic_type & ODM_IC_11AC_SERIES) { /* store reg0x990, reg0x994, reg0x998, reg0x99c, Reg0x9a0 */
215 p_acs->reg0x990 = odm_read_4byte(p_dm, ODM_REG_CCX_PERIOD_11AC); /* reg0x990 */
216 p_acs->reg0x994 = odm_read_4byte(p_dm, ODM_REG_NHM_TH9_TH10_11AC); /* reg0x994 */
217 p_acs->reg0x998 = odm_read_4byte(p_dm, ODM_REG_NHM_TH3_TO_TH0_11AC); /* reg0x998 */
218 p_acs->reg0x99c = odm_read_4byte(p_dm, ODM_REG_NHM_TH7_TO_TH4_11AC); /* Reg0x99c */
219 p_acs->reg0x9a0 = odm_read_1byte(p_dm, ODM_REG_NHM_TH8_11AC); /* Reg0x9a0, u8 */
220 } else if (p_dm->support_ic_type & ODM_IC_11N_SERIES) {
221 p_acs->reg0x890 = odm_read_4byte(p_dm, ODM_REG_NHM_TH9_TH10_11N); /* reg0x890 */
222 p_acs->reg0x894 = odm_read_4byte(p_dm, ODM_REG_CCX_PERIOD_11N); /* reg0x894 */
223 p_acs->reg0x898 = odm_read_4byte(p_dm, ODM_REG_NHM_TH3_TO_TH0_11N); /* reg0x898 */
224 p_acs->reg0x89c = odm_read_4byte(p_dm, ODM_REG_NHM_TH7_TO_TH4_11N); /* Reg0x89c */
225 p_acs->reg0xe28 = odm_read_1byte(p_dm, ODM_REG_NHM_TH8_11N); /* Reg0xe28, u8 */
226 }
227 }
228
229 /* 3 Restore Default setting */
230 else if (setting == RESTORE_DEFAULT_NHM_SETTING) {
231 PHYDM_DBG(p_dm, ODM_COMP_API, ("RESTORE_DEFAULT_NHM_SETTING\n"));
232
233 if (p_dm->support_ic_type & ODM_IC_11AC_SERIES) { /* store reg0x990, reg0x994, reg0x998, reg0x99c, Reg0x9a0 */
234 odm_write_4byte(p_dm, ODM_REG_CCX_PERIOD_11AC, p_acs->reg0x990);
235 odm_write_4byte(p_dm, ODM_REG_NHM_TH9_TH10_11AC, p_acs->reg0x994);
236 odm_write_4byte(p_dm, ODM_REG_NHM_TH3_TO_TH0_11AC, p_acs->reg0x998);
237 odm_write_4byte(p_dm, ODM_REG_NHM_TH7_TO_TH4_11AC, p_acs->reg0x99c);
238 odm_write_1byte(p_dm, ODM_REG_NHM_TH8_11AC, p_acs->reg0x9a0);
239 } else if (p_dm->support_ic_type & ODM_IC_11N_SERIES) {
240 odm_write_4byte(p_dm, ODM_REG_NHM_TH9_TH10_11N, p_acs->reg0x890);
241 odm_write_4byte(p_dm, ODM_REG_CCX_PERIOD_11AC, p_acs->reg0x894);
242 odm_write_4byte(p_dm, ODM_REG_NHM_TH3_TO_TH0_11N, p_acs->reg0x898);
243 odm_write_4byte(p_dm, ODM_REG_NHM_TH7_TO_TH4_11N, p_acs->reg0x89c);
244 odm_write_1byte(p_dm, ODM_REG_NHM_TH8_11N, p_acs->reg0xe28);
245 }
246 }
247
248 /* 3 struct _ACS_ setting */
249 else if (setting == ACS_NHM_SETTING) {
250 PHYDM_DBG(p_dm, ODM_COMP_API, ("ACS_NHM_SETTING\n"));
251 u16 period;
252 period = 0x61a8;
253 p_acs->acs_step = acs_step;
254
255 if (p_dm->support_ic_type & ODM_IC_11AC_SERIES) {
256 /* 4 Set NHM period, 0x990[31:16]=0x61a8, Time duration for NHM unit: 4us, 0x61a8=100ms */
257 odm_write_2byte(p_dm, ODM_REG_CCX_PERIOD_11AC + 2, period);
258 /* 4 Set NHM ignore_cca=1, ignore_txon=1, ccx_en=0 */
259 odm_set_bb_reg(p_dm, ODM_REG_NHM_TH9_TH10_11AC, BIT(8) | BIT(9) | BIT(10), 3);
260
261 if (p_acs->acs_step == 0) {
262 /* 4 Set IGI */
263 odm_set_bb_reg(p_dm, 0xc50, BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | BIT(6), 0x3E);
264 if (get_rf_mimo_mode(priv) != RF_1T1R)
265 odm_set_bb_reg(p_dm, 0xe50, BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | BIT(6), 0x3E);
266
267 /* 4 Set struct _ACS_ NHM threshold */
268 odm_write_4byte(p_dm, ODM_REG_NHM_TH3_TO_TH0_11AC, 0x82786e64);
269 odm_write_4byte(p_dm, ODM_REG_NHM_TH7_TO_TH4_11AC, 0xffffff8c);
270 odm_write_1byte(p_dm, ODM_REG_NHM_TH8_11AC, 0xff);
271 odm_write_2byte(p_dm, ODM_REG_NHM_TH9_TH10_11AC + 2, 0xffff);
272
273 } else if (p_acs->acs_step == 1) {
274 /* 4 Set IGI */
275 odm_set_bb_reg(p_dm, 0xc50, BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | BIT(6), 0x2A);
276 if (get_rf_mimo_mode(priv) != RF_1T1R)
277 odm_set_bb_reg(p_dm, 0xe50, BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | BIT(6), 0x2A);
278
279 /* 4 Set struct _ACS_ NHM threshold */
280 odm_write_4byte(p_dm, ODM_REG_NHM_TH3_TO_TH0_11AC, 0x5a50463c);
281 odm_write_4byte(p_dm, ODM_REG_NHM_TH7_TO_TH4_11AC, 0xffffff64);
282
283 }
284
285 } else if (p_dm->support_ic_type & ODM_IC_11N_SERIES) {
286 /* 4 Set NHM period, 0x894[31:16]=0x61a8, Time duration for NHM unit: 4us, 0x61a8=100ms */
287 odm_write_2byte(p_dm, ODM_REG_CCX_PERIOD_11AC + 2, period);
288 /* 4 Set NHM ignore_cca=1, ignore_txon=1, ccx_en=0 */
289 odm_set_bb_reg(p_dm, ODM_REG_NHM_TH9_TH10_11N, BIT(8) | BIT(9) | BIT(10), 3);
290
291 if (p_acs->acs_step == 0) {
292 /* 4 Set IGI */
293 odm_set_bb_reg(p_dm, 0xc50, BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | BIT(6), 0x3E);
294 if (get_rf_mimo_mode(priv) != RF_1T1R)
295 odm_set_bb_reg(p_dm, 0xc58, BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | BIT(6), 0x3E);
296
297 /* 4 Set struct _ACS_ NHM threshold */
298 odm_write_4byte(p_dm, ODM_REG_NHM_TH3_TO_TH0_11N, 0x82786e64);
299 odm_write_4byte(p_dm, ODM_REG_NHM_TH7_TO_TH4_11N, 0xffffff8c);
300 odm_write_1byte(p_dm, ODM_REG_NHM_TH8_11N, 0xff);
301 odm_write_2byte(p_dm, ODM_REG_NHM_TH9_TH10_11N + 2, 0xffff);
302
303 } else if (p_acs->acs_step == 1) {
304 /* 4 Set IGI */
305 odm_set_bb_reg(p_dm, 0xc50, BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | BIT(6), 0x2A);
306 if (get_rf_mimo_mode(priv) != RF_1T1R)
307 odm_set_bb_reg(p_dm, 0xc58, BIT(0) | BIT(1) | BIT(2) | BIT(3) | BIT(4) | BIT(5) | BIT(6), 0x2A);
308
309 /* 4 Set struct _ACS_ NHM threshold */
310 odm_write_4byte(p_dm, ODM_REG_NHM_TH3_TO_TH0_11N, 0x5a50463c);
311 odm_write_4byte(p_dm, ODM_REG_NHM_TH7_TO_TH4_11N, 0xffffff64);
312
313 }
314 }
315 }
316
317 }
318
319 void
phydm_get_nhm_statistics_ap(void * p_dm_void,u32 idx,u32 acs_step)320 phydm_get_nhm_statistics_ap(
321 void *p_dm_void,
322 u32 idx, /* @ 2G, Real channel number = idx+1 */
323 u32 acs_step
324 )
325 {
326 struct PHY_DM_STRUCT *p_dm = (struct PHY_DM_STRUCT *)p_dm_void;
327 struct rtl8192cd_priv *priv = p_dm->priv;
328 struct _ACS_ *p_acs = &p_dm->dm_acs;
329 u32 value32 = 0;
330 u8 i;
331
332 p_acs->acs_step = acs_step;
333
334 if (p_dm->support_ic_type & ODM_IC_11N_SERIES) {
335 /* 4 Check if NHM result is ready */
336 for (i = 0; i < 20; i++) {
337
338 ODM_delay_ms(1);
339 if (odm_get_bb_reg(p_dm, REG_FPGA0_PSD_REPORT, BIT(17)))
340 break;
341 }
342
343 /* 4 Get NHM Statistics */
344 if (p_acs->acs_step == 1) {
345
346 value32 = odm_read_4byte(p_dm, ODM_REG_NHM_CNT7_TO_CNT4_11N);
347
348 p_acs->nhm_cnt[idx][9] = (value32 & MASKBYTE1) >> 8;
349 p_acs->nhm_cnt[idx][8] = (value32 & MASKBYTE0);
350
351 value32 = odm_read_4byte(p_dm, ODM_REG_NHM_CNT_11N); /* ODM_REG_NHM_CNT3_TO_CNT0_11N */
352
353 p_acs->nhm_cnt[idx][7] = (value32 & MASKBYTE3) >> 24;
354 p_acs->nhm_cnt[idx][6] = (value32 & MASKBYTE2) >> 16;
355 p_acs->nhm_cnt[idx][5] = (value32 & MASKBYTE1) >> 8;
356
357 } else if (p_acs->acs_step == 2) {
358
359 value32 = odm_read_4byte(p_dm, ODM_REG_NHM_CNT_11N); /* ODM_REG_NHM_CNT3_TO_CNT0_11N */
360
361 p_acs->nhm_cnt[idx][4] = odm_read_1byte(p_dm, ODM_REG_NHM_CNT7_TO_CNT4_11N);
362 p_acs->nhm_cnt[idx][3] = (value32 & MASKBYTE3) >> 24;
363 p_acs->nhm_cnt[idx][2] = (value32 & MASKBYTE2) >> 16;
364 p_acs->nhm_cnt[idx][1] = (value32 & MASKBYTE1) >> 8;
365 p_acs->nhm_cnt[idx][0] = (value32 & MASKBYTE0);
366 }
367 } else if (p_dm->support_ic_type & ODM_IC_11AC_SERIES) {
368 /* 4 Check if NHM result is ready */
369 for (i = 0; i < 20; i++) {
370
371 ODM_delay_ms(1);
372 if (odm_get_bb_reg(p_dm, ODM_REG_NHM_DUR_READY_11AC, BIT(16)))
373 break;
374 }
375
376 if (p_acs->acs_step == 1) {
377
378 value32 = odm_read_4byte(p_dm, ODM_REG_NHM_CNT7_TO_CNT4_11AC);
379
380 p_acs->nhm_cnt[idx][9] = (value32 & MASKBYTE1) >> 8;
381 p_acs->nhm_cnt[idx][8] = (value32 & MASKBYTE0);
382
383 value32 = odm_read_4byte(p_dm, ODM_REG_NHM_CNT_11AC); /* ODM_REG_NHM_CNT3_TO_CNT0_11AC */
384
385 p_acs->nhm_cnt[idx][7] = (value32 & MASKBYTE3) >> 24;
386 p_acs->nhm_cnt[idx][6] = (value32 & MASKBYTE2) >> 16;
387 p_acs->nhm_cnt[idx][5] = (value32 & MASKBYTE1) >> 8;
388
389 } else if (p_acs->acs_step == 2) {
390
391 value32 = odm_read_4byte(p_dm, ODM_REG_NHM_CNT_11AC); /* ODM_REG_NHM_CNT3_TO_CNT0_11AC */
392
393 p_acs->nhm_cnt[idx][4] = odm_read_1byte(p_dm, ODM_REG_NHM_CNT7_TO_CNT4_11AC);
394 p_acs->nhm_cnt[idx][3] = (value32 & MASKBYTE3) >> 24;
395 p_acs->nhm_cnt[idx][2] = (value32 & MASKBYTE2) >> 16;
396 p_acs->nhm_cnt[idx][1] = (value32 & MASKBYTE1) >> 8;
397 p_acs->nhm_cnt[idx][0] = (value32 & MASKBYTE0);
398 }
399 }
400
401 }
402
403
404 /* #define ACS_DEBUG_INFO */ /* acs debug default off */
405 #if 0
406 int phydm_AutoChannelSelectAP(
407 void *p_dm_void,
408 u32 ACS_Type, /* 0: RXCount_Type, 1:NHM_Type */
409 u32 available_chnl_num /* amount of all channels */
410 )
411 {
412 struct PHY_DM_STRUCT *p_dm = (struct PHY_DM_STRUCT *)p_dm_void;
413 struct _ACS_ *p_acs = &p_dm->dm_acs;
414 struct rtl8192cd_priv *priv = p_dm->priv;
415
416 static u32 score2G[MAX_2G_CHANNEL_NUM], score5G[MAX_5G_CHANNEL_NUM];
417 u32 score[MAX_BSS_NUM], use_nhm = 0;
418 u32 minScore = 0xffffffff;
419 u32 tmpScore, tmpIdx = 0;
420 u32 traffic_check = 0;
421 u32 fa_count_weighting = 1;
422 int i, j, idx = 0, idx_2G_end = -1, idx_5G_begin = -1, minChan = 0;
423 struct bss_desc *pBss = NULL;
424
425 #ifdef _DEBUG_RTL8192CD_
426 char tmpbuf[400];
427 int len = 0;
428 #endif
429
430 memset(score2G, '\0', sizeof(score2G));
431 memset(score5G, '\0', sizeof(score5G));
432
433 for (i = 0; i < priv->available_chnl_num; i++) {
434 if (priv->available_chnl[i] <= 14)
435 idx_2G_end = i;
436 else
437 break;
438 }
439
440 for (i = 0; i < priv->available_chnl_num; i++) {
441 if (priv->available_chnl[i] > 14) {
442 idx_5G_begin = i;
443 break;
444 }
445 }
446
447 /* DELETE */
448 #ifndef CONFIG_RTL_NEW_AUTOCH
449 for (i = 0; i < priv->site_survey->count; i++) {
450 pBss = &priv->site_survey->bss[i];
451 for (idx = 0; idx < priv->available_chnl_num; idx++) {
452 if (pBss->channel == priv->available_chnl[idx]) {
453 if (pBss->channel <= 14)
454 setChannelScore(idx, score2G, 0, MAX_2G_CHANNEL_NUM - 1);
455 else
456 score5G[idx - idx_5G_begin] += 5;
457 break;
458 }
459 }
460 }
461 #endif
462
463 if (idx_2G_end >= 0)
464 for (i = 0; i <= idx_2G_end; i++)
465 score[i] = score2G[i];
466 if (idx_5G_begin >= 0)
467 for (i = idx_5G_begin; i < priv->available_chnl_num; i++)
468 score[i] = score5G[i - idx_5G_begin];
469
470 #ifdef CONFIG_RTL_NEW_AUTOCH
471 {
472 u32 y, ch_begin = 0, ch_end = priv->available_chnl_num;
473
474 u32 do_ap_check = 1, ap_ratio = 0;
475
476 if (idx_2G_end >= 0)
477 ch_end = idx_2G_end + 1;
478 if (idx_5G_begin >= 0)
479 ch_begin = idx_5G_begin;
480
481 #ifdef ACS_DEBUG_INFO/* for debug */
482 printk("\n");
483 for (y = ch_begin; y < ch_end; y++)
484 printk("1. init: chnl[%d] 20M_rx[%d] 40M_rx[%d] fa_cnt[%d] score[%d]\n",
485 priv->available_chnl[y],
486 priv->chnl_ss_mac_rx_count[y],
487 priv->chnl_ss_mac_rx_count_40M[y],
488 priv->chnl_ss_fa_count[y],
489 score[y]);
490 printk("\n");
491 #endif
492
493 #if defined(CONFIG_RTL_88E_SUPPORT) || defined(CONFIG_WLAN_HAL_8192EE)
494 if (p_dm->support_ic_type & (ODM_RTL8188E | ODM_RTL8192E) && priv->pmib->dot11RFEntry.acs_type) {
495 u32 tmp_score[MAX_BSS_NUM];
496 memcpy(tmp_score, score, sizeof(score));
497 if (find_clean_channel(priv, ch_begin, ch_end, tmp_score)) {
498 /* memcpy(score, tmp_score, sizeof(score)); */
499 #ifdef _DEBUG_RTL8192CD_
500 printk("!! Found clean channel, select minimum FA channel\n");
501 #endif
502 goto USE_CLN_CH;
503 }
504 #ifdef _DEBUG_RTL8192CD_
505 printk("!! Not found clean channel, use NHM algorithm\n");
506 #endif
507 use_nhm = 1;
508 USE_CLN_CH:
509 for (y = ch_begin; y < ch_end; y++) {
510 for (i = 0; i <= 9; i++) {
511 u32 val32 = priv->nhm_cnt[y][i];
512 for (j = 0; j < i; j++)
513 val32 *= 3;
514 score[y] += val32;
515 }
516
517 #ifdef _DEBUG_RTL8192CD_
518 printk("nhm_cnt_%d: H<-[ %3d %3d %3d %3d %3d %3d %3d %3d %3d %3d]->L, score: %d\n",
519 y + 1, priv->nhm_cnt[y][9], priv->nhm_cnt[y][8], priv->nhm_cnt[y][7],
520 priv->nhm_cnt[y][6], priv->nhm_cnt[y][5], priv->nhm_cnt[y][4],
521 priv->nhm_cnt[y][3], priv->nhm_cnt[y][2], priv->nhm_cnt[y][1],
522 priv->nhm_cnt[y][0], score[y]);
523 #endif
524 }
525
526 if (!use_nhm)
527 memcpy(score, tmp_score, sizeof(score));
528
529 goto choose_ch;
530 }
531 #endif
532
533 /* For each channel, weighting behind channels with MAC RX counter */
534 /* For each channel, weighting the channel with FA counter */
535
536 for (y = ch_begin; y < ch_end; y++) {
537 score[y] += 8 * priv->chnl_ss_mac_rx_count[y];
538 if (priv->chnl_ss_mac_rx_count[y] > 30)
539 do_ap_check = 0;
540 if (priv->chnl_ss_mac_rx_count[y] > MAC_RX_COUNT_THRESHOLD)
541 traffic_check = 1;
542
543 #ifdef RTK_5G_SUPPORT
544 if (*p_dm->p_band_type == ODM_BAND_2_4G)
545 #endif
546 {
547 if ((int)(y - 4) >= (int)ch_begin)
548 score[y - 4] += 2 * priv->chnl_ss_mac_rx_count[y];
549 if ((int)(y - 3) >= (int)ch_begin)
550 score[y - 3] += 8 * priv->chnl_ss_mac_rx_count[y];
551 if ((int)(y - 2) >= (int)ch_begin)
552 score[y - 2] += 8 * priv->chnl_ss_mac_rx_count[y];
553 if ((int)(y - 1) >= (int)ch_begin)
554 score[y - 1] += 10 * priv->chnl_ss_mac_rx_count[y];
555 if ((int)(y + 1) < (int)ch_end)
556 score[y + 1] += 10 * priv->chnl_ss_mac_rx_count[y];
557 if ((int)(y + 2) < (int)ch_end)
558 score[y + 2] += 8 * priv->chnl_ss_mac_rx_count[y];
559 if ((int)(y + 3) < (int)ch_end)
560 score[y + 3] += 8 * priv->chnl_ss_mac_rx_count[y];
561 if ((int)(y + 4) < (int)ch_end)
562 score[y + 4] += 2 * priv->chnl_ss_mac_rx_count[y];
563 }
564
565 /* this is for CH_LOAD caculation */
566 if (priv->chnl_ss_cca_count[y] > priv->chnl_ss_fa_count[y])
567 priv->chnl_ss_cca_count[y] -= priv->chnl_ss_fa_count[y];
568 else
569 priv->chnl_ss_cca_count[y] = 0;
570 }
571
572 #ifdef ACS_DEBUG_INFO/* for debug */
573 printk("\n");
574 for (y = ch_begin; y < ch_end; y++)
575 printk("2. after 20M check: chnl[%d] score[%d]\n", priv->available_chnl[y], score[y]);
576 printk("\n");
577 #endif
578
579 for (y = ch_begin; y < ch_end; y++) {
580 if (priv->chnl_ss_mac_rx_count_40M[y]) {
581 score[y] += 5 * priv->chnl_ss_mac_rx_count_40M[y];
582 if (priv->chnl_ss_mac_rx_count_40M[y] > 30)
583 do_ap_check = 0;
584 if (priv->chnl_ss_mac_rx_count_40M[y] > MAC_RX_COUNT_THRESHOLD)
585 traffic_check = 1;
586
587 #ifdef RTK_5G_SUPPORT
588 if (*p_dm->p_band_type == ODM_BAND_2_4G)
589 #endif
590 {
591 if ((int)(y - 6) >= (int)ch_begin)
592 score[y - 6] += 1 * priv->chnl_ss_mac_rx_count_40M[y];
593 if ((int)(y - 5) >= (int)ch_begin)
594 score[y - 5] += 4 * priv->chnl_ss_mac_rx_count_40M[y];
595 if ((int)(y - 4) >= (int)ch_begin)
596 score[y - 4] += 4 * priv->chnl_ss_mac_rx_count_40M[y];
597 if ((int)(y - 3) >= (int)ch_begin)
598 score[y - 3] += 5 * priv->chnl_ss_mac_rx_count_40M[y];
599 if ((int)(y - 2) >= (int)ch_begin)
600 score[y - 2] += (5 * priv->chnl_ss_mac_rx_count_40M[y]) / 2;
601 if ((int)(y - 1) >= (int)ch_begin)
602 score[y - 1] += 5 * priv->chnl_ss_mac_rx_count_40M[y];
603 if ((int)(y + 1) < (int)ch_end)
604 score[y + 1] += 5 * priv->chnl_ss_mac_rx_count_40M[y];
605 if ((int)(y + 2) < (int)ch_end)
606 score[y + 2] += (5 * priv->chnl_ss_mac_rx_count_40M[y]) / 2;
607 if ((int)(y + 3) < (int)ch_end)
608 score[y + 3] += 5 * priv->chnl_ss_mac_rx_count_40M[y];
609 if ((int)(y + 4) < (int)ch_end)
610 score[y + 4] += 4 * priv->chnl_ss_mac_rx_count_40M[y];
611 if ((int)(y + 5) < (int)ch_end)
612 score[y + 5] += 4 * priv->chnl_ss_mac_rx_count_40M[y];
613 if ((int)(y + 6) < (int)ch_end)
614 score[y + 6] += 1 * priv->chnl_ss_mac_rx_count_40M[y];
615 }
616 }
617 }
618
619 #ifdef ACS_DEBUG_INFO/* for debug */
620 printk("\n");
621 for (y = ch_begin; y < ch_end; y++)
622 printk("3. after 40M check: chnl[%d] score[%d]\n", priv->available_chnl[y], score[y]);
623 printk("\n");
624 printk("4. do_ap_check=%d traffic_check=%d\n", do_ap_check, traffic_check);
625 printk("\n");
626 #endif
627
628 if (traffic_check == 0)
629 fa_count_weighting = 5;
630 else
631 fa_count_weighting = 1;
632
633 for (y = ch_begin; y < ch_end; y++)
634 score[y] += fa_count_weighting * priv->chnl_ss_fa_count[y];
635
636 #ifdef ACS_DEBUG_INFO/* for debug */
637 printk("\n");
638 for (y = ch_begin; y < ch_end; y++)
639 printk("5. after fa check: chnl[%d] score[%d]\n", priv->available_chnl[y], score[y]);
640 printk("\n");
641 #endif
642
643 if (do_ap_check) {
644 for (i = 0; i < priv->site_survey->count; i++) {
645 pBss = &priv->site_survey->bss[i];
646 for (y = ch_begin; y < ch_end; y++) {
647 if (pBss->channel == priv->available_chnl[y]) {
648 if (pBss->channel <= 14) {
649 #ifdef ACS_DEBUG_INFO/* for debug */
650 printk("\n");
651 printk("chnl[%d] has ap rssi=%d bw[0x%02x]\n",
652 pBss->channel, pBss->rssi, pBss->t_stamp[1]);
653 printk("\n");
654 #endif
655 if (pBss->rssi > 60)
656 ap_ratio = 4;
657 else if (pBss->rssi > 35)
658 ap_ratio = 2;
659 else
660 ap_ratio = 1;
661
662 if ((pBss->t_stamp[1] & 0x6) == 0) {
663 score[y] += 50 * ap_ratio;
664 if ((int)(y - 4) >= (int)ch_begin)
665 score[y - 4] += 10 * ap_ratio;
666 if ((int)(y - 3) >= (int)ch_begin)
667 score[y - 3] += 20 * ap_ratio;
668 if ((int)(y - 2) >= (int)ch_begin)
669 score[y - 2] += 30 * ap_ratio;
670 if ((int)(y - 1) >= (int)ch_begin)
671 score[y - 1] += 40 * ap_ratio;
672 if ((int)(y + 1) < (int)ch_end)
673 score[y + 1] += 40 * ap_ratio;
674 if ((int)(y + 2) < (int)ch_end)
675 score[y + 2] += 30 * ap_ratio;
676 if ((int)(y + 3) < (int)ch_end)
677 score[y + 3] += 20 * ap_ratio;
678 if ((int)(y + 4) < (int)ch_end)
679 score[y + 4] += 10 * ap_ratio;
680 } else if ((pBss->t_stamp[1] & 0x4) == 0) {
681 score[y] += 50 * ap_ratio;
682 if ((int)(y - 3) >= (int)ch_begin)
683 score[y - 3] += 20 * ap_ratio;
684 if ((int)(y - 2) >= (int)ch_begin)
685 score[y - 2] += 30 * ap_ratio;
686 if ((int)(y - 1) >= (int)ch_begin)
687 score[y - 1] += 40 * ap_ratio;
688 if ((int)(y + 1) < (int)ch_end)
689 score[y + 1] += 50 * ap_ratio;
690 if ((int)(y + 2) < (int)ch_end)
691 score[y + 2] += 50 * ap_ratio;
692 if ((int)(y + 3) < (int)ch_end)
693 score[y + 3] += 50 * ap_ratio;
694 if ((int)(y + 4) < (int)ch_end)
695 score[y + 4] += 50 * ap_ratio;
696 if ((int)(y + 5) < (int)ch_end)
697 score[y + 5] += 40 * ap_ratio;
698 if ((int)(y + 6) < (int)ch_end)
699 score[y + 6] += 30 * ap_ratio;
700 if ((int)(y + 7) < (int)ch_end)
701 score[y + 7] += 20 * ap_ratio;
702 } else {
703 score[y] += 50 * ap_ratio;
704 if ((int)(y - 7) >= (int)ch_begin)
705 score[y - 7] += 20 * ap_ratio;
706 if ((int)(y - 6) >= (int)ch_begin)
707 score[y - 6] += 30 * ap_ratio;
708 if ((int)(y - 5) >= (int)ch_begin)
709 score[y - 5] += 40 * ap_ratio;
710 if ((int)(y - 4) >= (int)ch_begin)
711 score[y - 4] += 50 * ap_ratio;
712 if ((int)(y - 3) >= (int)ch_begin)
713 score[y - 3] += 50 * ap_ratio;
714 if ((int)(y - 2) >= (int)ch_begin)
715 score[y - 2] += 50 * ap_ratio;
716 if ((int)(y - 1) >= (int)ch_begin)
717 score[y - 1] += 50 * ap_ratio;
718 if ((int)(y + 1) < (int)ch_end)
719 score[y + 1] += 40 * ap_ratio;
720 if ((int)(y + 2) < (int)ch_end)
721 score[y + 2] += 30 * ap_ratio;
722 if ((int)(y + 3) < (int)ch_end)
723 score[y + 3] += 20 * ap_ratio;
724 }
725 } else {
726 if ((pBss->t_stamp[1] & 0x6) == 0)
727 score[y] += 500;
728 else if ((pBss->t_stamp[1] & 0x4) == 0) {
729 score[y] += 500;
730 if ((int)(y + 1) < (int)ch_end)
731 score[y + 1] += 500;
732 } else {
733 score[y] += 500;
734 if ((int)(y - 1) >= (int)ch_begin)
735 score[y - 1] += 500;
736 }
737 }
738 break;
739 }
740 }
741 }
742 }
743
744 #ifdef ACS_DEBUG_INFO/* for debug */
745 printk("\n");
746 for (y = ch_begin; y < ch_end; y++)
747 printk("6. after ap check: chnl[%d]:%d\n", priv->available_chnl[y], score[y]);
748 printk("\n");
749 #endif
750
751 #ifdef SS_CH_LOAD_PROC
752
753 /* caculate noise level -- suggested by wilson */
754 for (y = ch_begin; y < ch_end; y++) {
755 int fa_lv = 0, cca_lv = 0;
756 if (priv->chnl_ss_fa_count[y] > 1000)
757 fa_lv = 100;
758 else if (priv->chnl_ss_fa_count[y] > 500)
759 fa_lv = 34 * (priv->chnl_ss_fa_count[y] - 500) / 500 + 66;
760 else if (priv->chnl_ss_fa_count[y] > 200)
761 fa_lv = 33 * (priv->chnl_ss_fa_count[y] - 200) / 300 + 33;
762 else if (priv->chnl_ss_fa_count[y] > 100)
763 fa_lv = 18 * (priv->chnl_ss_fa_count[y] - 100) / 100 + 15;
764 else
765 fa_lv = 15 * priv->chnl_ss_fa_count[y] / 100;
766 if (priv->chnl_ss_cca_count[y] > 400)
767 cca_lv = 100;
768 else if (priv->chnl_ss_cca_count[y] > 200)
769 cca_lv = 34 * (priv->chnl_ss_cca_count[y] - 200) / 200 + 66;
770 else if (priv->chnl_ss_cca_count[y] > 80)
771 cca_lv = 33 * (priv->chnl_ss_cca_count[y] - 80) / 120 + 33;
772 else if (priv->chnl_ss_cca_count[y] > 40)
773 cca_lv = 18 * (priv->chnl_ss_cca_count[y] - 40) / 40 + 15;
774 else
775 cca_lv = 15 * priv->chnl_ss_cca_count[y] / 40;
776
777 priv->chnl_ss_load[y] = (((fa_lv > cca_lv) ? fa_lv : cca_lv) * 75 + ((score[y] > 100) ? 100 : score[y]) * 25) / 100;
778
779 DEBUG_INFO("ch:%d f=%d (%d), c=%d (%d), fl=%d, cl=%d, sc=%d, cu=%d\n",
780 priv->available_chnl[y],
781 priv->chnl_ss_fa_count[y], fa_thd,
782 priv->chnl_ss_cca_count[y], cca_thd,
783 fa_lv,
784 cca_lv,
785 score[y],
786 priv->chnl_ss_load[y]);
787
788 }
789 #endif
790 }
791 #endif
792
793 choose_ch:
794
795 #ifdef DFS
796 /* heavy weighted DFS channel */
797 if (idx_5G_begin >= 0) {
798 for (i = idx_5G_begin; i < priv->available_chnl_num; i++) {
799 if (!priv->pmib->dot11DFSEntry.disable_DFS && is_DFS_channel(priv->available_chnl[i])
800 && (score[i] != 0xffffffff))
801 score[i] += 1600;
802 }
803 }
804 #endif
805
806
807 /* prevent Auto channel selecting wrong channel in 40M mode----------------- */
808 if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N)
809 && priv->pshare->is_40m_bw) {
810 #if 0
811 if (GET_MIB(priv)->dot11nConfigEntry.dot11n2ndChOffset == 1) {
812 /* Upper Primary channel, cannot select the two lowest channels */
813 if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11G) {
814 score[0] = 0xffffffff;
815 score[1] = 0xffffffff;
816 score[2] = 0xffffffff;
817 score[3] = 0xffffffff;
818 score[4] = 0xffffffff;
819
820 score[13] = 0xffffffff;
821 score[12] = 0xffffffff;
822 score[11] = 0xffffffff;
823 }
824
825 /* if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) { */
826 /* score[idx_5G_begin] = 0xffffffff; */
827 /* score[idx_5G_begin + 1] = 0xffffffff; */
828 /* } */
829 } else if (GET_MIB(priv)->dot11nConfigEntry.dot11n2ndChOffset == 2) {
830 /* Lower Primary channel, cannot select the two highest channels */
831 if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11G) {
832 score[0] = 0xffffffff;
833 score[1] = 0xffffffff;
834 score[2] = 0xffffffff;
835
836 score[13] = 0xffffffff;
837 score[12] = 0xffffffff;
838 score[11] = 0xffffffff;
839 score[10] = 0xffffffff;
840 score[9] = 0xffffffff;
841 }
842
843 /* if (priv->pmib->dot11BssType.net_work_type & WIRELESS_11A) { */
844 /* score[priv->available_chnl_num - 2] = 0xffffffff; */
845 /* score[priv->available_chnl_num - 1] = 0xffffffff; */
846 /* } */
847 }
848 #endif
849 for (i = 0; i <= idx_2G_end; ++i)
850 if (priv->available_chnl[i] == 14)
851 score[i] = 0xffffffff; /* mask chan14 */
852
853 #ifdef RTK_5G_SUPPORT
854 if (idx_5G_begin >= 0) {
855 for (i = idx_5G_begin; i < priv->available_chnl_num; i++) {
856 int ch = priv->available_chnl[i];
857 if (priv->available_chnl[i] > 144)
858 --ch;
859 if ((ch % 4) || ch == 140 || ch == 164) /* mask ch 140, ch 165, ch 184... */
860 score[i] = 0xffffffff;
861 }
862 }
863 #endif
864
865
866 }
867
868 if (priv->pmib->dot11RFEntry.disable_ch1213) {
869 for (i = 0; i <= idx_2G_end; ++i) {
870 int ch = priv->available_chnl[i];
871 if ((ch == 12) || (ch == 13))
872 score[i] = 0xffffffff;
873 }
874 }
875
876 if (((priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_GLOBAL) ||
877 (priv->pmib->dot11StationConfigEntry.dot11RegDomain == DOMAIN_WORLD_WIDE)) &&
878 (idx_2G_end >= 11) && (idx_2G_end < 14)) {
879 score[13] = 0xffffffff; /* mask chan14 */
880 score[12] = 0xffffffff; /* mask chan13 */
881 score[11] = 0xffffffff; /* mask chan12 */
882 }
883
884 /* ------------------------------------------------------------------ */
885
886 #ifdef _DEBUG_RTL8192CD_
887 for (i = 0; i < priv->available_chnl_num; i++)
888 len += sprintf(tmpbuf + len, "ch%d:%u ", priv->available_chnl[i], score[i]);
889 strcat(tmpbuf, "\n");
890 panic_printk("%s", tmpbuf);
891
892 #endif
893
894 if ((*p_dm->p_band_type == ODM_BAND_5G)
895 && (priv->pmib->dot11nConfigEntry.dot11nUse40M == CHANNEL_WIDTH_80)) {
896 for (i = 0; i < priv->available_chnl_num; i++) {
897 if (is80MChannel(priv->available_chnl, priv->available_chnl_num, priv->available_chnl[i])) {
898 tmpScore = 0;
899 for (j = 0; j < 4; j++) {
900 if ((tmpScore != 0xffffffff) && (score[i + j] != 0xffffffff))
901 tmpScore += score[i + j];
902 else
903 tmpScore = 0xffffffff;
904 }
905 tmpScore = tmpScore / 4;
906 if (minScore > tmpScore) {
907 minScore = tmpScore;
908
909 tmpScore = 0xffffffff;
910 for (j = 0; j < 4; j++) {
911 if (score[i + j] < tmpScore) {
912 tmpScore = score[i + j];
913 tmpIdx = i + j;
914 }
915 }
916
917 idx = tmpIdx;
918 }
919 i += 3;
920 }
921 }
922 if (minScore == 0xffffffff) {
923 /* there is no 80M channels */
924 priv->pshare->is_40m_bw = CHANNEL_WIDTH_20;
925 for (i = 0; i < priv->available_chnl_num; i++) {
926 if (score[i] < minScore) {
927 minScore = score[i];
928 idx = i;
929 }
930 }
931 }
932 } else if ((*p_dm->p_band_type == ODM_BAND_5G)
933 && (priv->pmib->dot11nConfigEntry.dot11nUse40M == CHANNEL_WIDTH_40)) {
934 for (i = 0; i < priv->available_chnl_num; i++) {
935 if (is40MChannel(priv->available_chnl, priv->available_chnl_num, priv->available_chnl[i])) {
936 tmpScore = 0;
937 for (j = 0; j < 2; j++) {
938 if ((tmpScore != 0xffffffff) && (score[i + j] != 0xffffffff))
939 tmpScore += score[i + j];
940 else
941 tmpScore = 0xffffffff;
942 }
943 tmpScore = tmpScore / 2;
944 if (minScore > tmpScore) {
945 minScore = tmpScore;
946
947 tmpScore = 0xffffffff;
948 for (j = 0; j < 2; j++) {
949 if (score[i + j] < tmpScore) {
950 tmpScore = score[i + j];
951 tmpIdx = i + j;
952 }
953 }
954
955 idx = tmpIdx;
956 }
957 i += 1;
958 }
959 }
960 if (minScore == 0xffffffff) {
961 /* there is no 40M channels */
962 priv->pshare->is_40m_bw = CHANNEL_WIDTH_20;
963 for (i = 0; i < priv->available_chnl_num; i++) {
964 if (score[i] < minScore) {
965 minScore = score[i];
966 idx = i;
967 }
968 }
969 }
970 } else if ((*p_dm->p_band_type == ODM_BAND_2_4G)
971 && (priv->pmib->dot11nConfigEntry.dot11nUse40M == CHANNEL_WIDTH_40)
972 && (priv->available_chnl_num >= 8)) {
973 u32 groupScore[14];
974
975 memset(groupScore, 0xff, sizeof(groupScore));
976 for (i = 0; i < priv->available_chnl_num - 4; i++) {
977 if (score[i] != 0xffffffff && score[i + 4] != 0xffffffff) {
978 groupScore[i] = score[i] + score[i + 4];
979 DEBUG_INFO("groupScore, ch %d,%d: %d\n", i + 1, i + 5, groupScore[i]);
980 if (groupScore[i] < minScore) {
981 #ifdef AUTOCH_SS_SPEEDUP
982 if (priv->pmib->miscEntry.autoch_1611_enable) {
983 if (priv->available_chnl[i] == 1 || priv->available_chnl[i] == 6 || priv->available_chnl[i] == 11) {
984 minScore = groupScore[i];
985 idx = i;
986 }
987 } else
988 #endif
989 {
990 minScore = groupScore[i];
991 idx = i;
992 }
993 }
994 }
995 }
996
997 if (score[idx] < score[idx + 4]) {
998 GET_MIB(priv)->dot11nConfigEntry.dot11n2ndChOffset = HT_2NDCH_OFFSET_ABOVE;
999 priv->pshare->offset_2nd_chan = HT_2NDCH_OFFSET_ABOVE;
1000 } else {
1001 idx = idx + 4;
1002 GET_MIB(priv)->dot11nConfigEntry.dot11n2ndChOffset = HT_2NDCH_OFFSET_BELOW;
1003 priv->pshare->offset_2nd_chan = HT_2NDCH_OFFSET_BELOW;
1004 }
1005 } else {
1006 for (i = 0; i < priv->available_chnl_num; i++) {
1007 if (score[i] < minScore) {
1008 #ifdef AUTOCH_SS_SPEEDUP
1009 if (priv->pmib->miscEntry.autoch_1611_enable) {
1010 if (priv->available_chnl[i] == 1 || priv->available_chnl[i] == 6 || priv->available_chnl[i] == 11) {
1011 minScore = score[i];
1012 idx = i;
1013 }
1014 } else
1015 #endif
1016 {
1017 minScore = score[i];
1018 idx = i;
1019 }
1020 }
1021 }
1022 }
1023
1024 if (IS_A_CUT_8881A(priv) &&
1025 (priv->pmib->dot11nConfigEntry.dot11nUse40M == CHANNEL_WIDTH_80)) {
1026 if ((priv->available_chnl[idx] == 36) ||
1027 (priv->available_chnl[idx] == 52) ||
1028 (priv->available_chnl[idx] == 100) ||
1029 (priv->available_chnl[idx] == 116) ||
1030 (priv->available_chnl[idx] == 132) ||
1031 (priv->available_chnl[idx] == 149) ||
1032 (priv->available_chnl[idx] == 165))
1033 idx++;
1034 else if ((priv->available_chnl[idx] == 48) ||
1035 (priv->available_chnl[idx] == 64) ||
1036 (priv->available_chnl[idx] == 112) ||
1037 (priv->available_chnl[idx] == 128) ||
1038 (priv->available_chnl[idx] == 144) ||
1039 (priv->available_chnl[idx] == 161) ||
1040 (priv->available_chnl[idx] == 177))
1041 idx--;
1042 }
1043
1044 minChan = priv->available_chnl[idx];
1045
1046 /* skip channel 14 if don't support ofdm */
1047 if ((priv->pmib->dot11RFEntry.disable_ch14_ofdm) &&
1048 (minChan == 14)) {
1049 score[idx] = 0xffffffff;
1050
1051 minScore = 0xffffffff;
1052 for (i = 0; i < priv->available_chnl_num; i++) {
1053 if (score[i] < minScore) {
1054 minScore = score[i];
1055 idx = i;
1056 }
1057 }
1058 minChan = priv->available_chnl[idx];
1059 }
1060
1061 #if 0
1062 /* Check if selected channel available for 80M/40M BW or NOT ? */
1063 if (*p_dm->p_band_type == ODM_BAND_5G) {
1064 if (priv->pmib->dot11nConfigEntry.dot11nUse40M == CHANNEL_WIDTH_80) {
1065 if (!is80MChannel(priv->available_chnl, priv->available_chnl_num, minChan)) {
1066
1067 /* priv->pmib->dot11n_config_entry.dot11nUse40M = CHANNEL_WIDTH_40; */
1068 priv->pshare->is_40m_bw = CHANNEL_WIDTH_40;
1069 }
1070 }
1071
1072 if (priv->pmib->dot11nConfigEntry.dot11nUse40M == CHANNEL_WIDTH_40) {
1073 if (!is40MChannel(priv->available_chnl, priv->available_chnl_num, minChan)) {
1074
1075 /* priv->pmib->dot11n_config_entry.dot11nUse40M = CHANNEL_WIDTH_20; */
1076 priv->pshare->is_40m_bw = CHANNEL_WIDTH_20;
1077 }
1078 }
1079 }
1080 #endif
1081
1082 #ifdef CONFIG_RTL_NEW_AUTOCH
1083 RTL_W32(RXERR_RPT, RXERR_RPT_RST);
1084 #endif
1085
1086 /* auto adjust contro-sideband */
1087 if ((priv->pmib->dot11BssType.net_work_type & WIRELESS_11N)
1088 && (priv->pshare->is_40m_bw == 1 || priv->pshare->is_40m_bw == 2)) {
1089
1090 #ifdef RTK_5G_SUPPORT
1091 if (*p_dm->p_band_type == ODM_BAND_5G) {
1092 if ((minChan > 144) ? ((minChan - 1) % 8) : (minChan % 8)) {
1093 GET_MIB(priv)->dot11nConfigEntry.dot11n2ndChOffset = HT_2NDCH_OFFSET_ABOVE;
1094 priv->pshare->offset_2nd_chan = HT_2NDCH_OFFSET_ABOVE;
1095 } else {
1096 GET_MIB(priv)->dot11nConfigEntry.dot11n2ndChOffset = HT_2NDCH_OFFSET_BELOW;
1097 priv->pshare->offset_2nd_chan = HT_2NDCH_OFFSET_BELOW;
1098 }
1099
1100 } else
1101 #endif
1102 {
1103 #if 0
1104 #ifdef CONFIG_RTL_NEW_AUTOCH
1105 unsigned int ch_max;
1106
1107 if (priv->available_chnl[idx_2G_end] >= 13)
1108 ch_max = 13;
1109 else
1110 ch_max = priv->available_chnl[idx_2G_end];
1111
1112 if ((minChan >= 5) && (minChan <= (ch_max - 5))) {
1113 if (score[minChan + 4] > score[minChan - 4]) { /* what if some channels were cancelled? */
1114 GET_MIB(priv)->dot11nConfigEntry.dot11n2ndChOffset = HT_2NDCH_OFFSET_BELOW;
1115 priv->pshare->offset_2nd_chan = HT_2NDCH_OFFSET_BELOW;
1116 } else {
1117 GET_MIB(priv)->dot11nConfigEntry.dot11n2ndChOffset = HT_2NDCH_OFFSET_ABOVE;
1118 priv->pshare->offset_2nd_chan = HT_2NDCH_OFFSET_ABOVE;
1119 }
1120 } else
1121 #endif
1122 {
1123 if (minChan < 5) {
1124 GET_MIB(priv)->dot11nConfigEntry.dot11n2ndChOffset = HT_2NDCH_OFFSET_ABOVE;
1125 priv->pshare->offset_2nd_chan = HT_2NDCH_OFFSET_ABOVE;
1126 } else if (minChan > 7) {
1127 GET_MIB(priv)->dot11nConfigEntry.dot11n2ndChOffset = HT_2NDCH_OFFSET_BELOW;
1128 priv->pshare->offset_2nd_chan = HT_2NDCH_OFFSET_BELOW;
1129 }
1130 }
1131 #endif
1132 }
1133 }
1134 /* ----------------------- */
1135
1136 #if defined(__ECOS) && defined(CONFIG_SDIO_HCI)
1137 panic_printk("Auto channel choose ch:%d\n", minChan);
1138 #else
1139 #ifdef _DEBUG_RTL8192CD_
1140 panic_printk("Auto channel choose ch:%d\n", minChan);
1141 #endif
1142 #endif
1143 #ifdef ACS_DEBUG_INFO/* for debug */
1144 printk("7. minChan:%d 2nd_offset:%d\n", minChan, priv->pshare->offset_2nd_chan);
1145 #endif
1146
1147 return minChan;
1148 }
1149 #endif
1150
1151 #endif
1152