phydm_acs.c 38 KB

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