phydm_dynamic_rx_path.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357
  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. #if (CONFIG_DYNAMIC_RX_PATH == 1)
  26. void
  27. phydm_process_phy_status_for_dynamic_rx_path(
  28. void *p_dm_void,
  29. void *p_phy_info_void,
  30. void *p_pkt_info_void
  31. )
  32. {
  33. struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
  34. struct _odm_phy_status_info_ *p_phy_info = (struct _odm_phy_status_info_ *)p_phy_info_void;
  35. struct _odm_per_pkt_info_ *p_pktinfo = (struct _odm_per_pkt_info_ *)p_pkt_info_void;
  36. struct _DYNAMIC_RX_PATH_ *p_dm_drp_table = &(p_dm_odm->dm_drp_table);
  37. /*u8 is_cck_rate=0;*/
  38. }
  39. void
  40. phydm_drp_get_statistic(
  41. void *p_dm_void
  42. )
  43. {
  44. struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
  45. struct _DYNAMIC_RX_PATH_ *p_dm_drp_table = &(p_dm_odm->dm_drp_table);
  46. struct _FALSE_ALARM_STATISTICS *false_alm_cnt = (struct _FALSE_ALARM_STATISTICS *)phydm_get_structure(p_dm_odm, PHYDM_FALSEALMCNT);
  47. odm_false_alarm_counter_statistics(p_dm_odm);
  48. ODM_RT_TRACE(p_dm_odm, ODM_COMP_DYNAMIC_RX_PATH, ODM_DBG_LOUD, ("[CCA Cnt] {CCK, OFDM, Total} = {%d, %d, %d}\n",
  49. false_alm_cnt->cnt_cck_cca, false_alm_cnt->cnt_ofdm_cca, false_alm_cnt->cnt_cca_all));
  50. ODM_RT_TRACE(p_dm_odm, ODM_COMP_DYNAMIC_RX_PATH, ODM_DBG_LOUD, ("[FA Cnt] {CCK, OFDM, Total} = {%d, %d, %d}\n",
  51. false_alm_cnt->cnt_cck_fail, false_alm_cnt->cnt_ofdm_fail, false_alm_cnt->cnt_all));
  52. }
  53. void
  54. phydm_dynamic_rx_path(
  55. void *p_dm_void
  56. )
  57. {
  58. struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
  59. struct _DYNAMIC_RX_PATH_ *p_dm_drp_table = &(p_dm_odm->dm_drp_table);
  60. u8 training_set_timmer_en;
  61. u8 curr_drp_state;
  62. u32 rx_ok_cal;
  63. u32 RSSI = 0;
  64. struct _FALSE_ALARM_STATISTICS *false_alm_cnt = (struct _FALSE_ALARM_STATISTICS *)phydm_get_structure(p_dm_odm, PHYDM_FALSEALMCNT);
  65. if (!(p_dm_odm->support_ability & ODM_BB_DYNAMIC_RX_PATH)) {
  66. ODM_RT_TRACE(p_dm_odm, ODM_COMP_DYNAMIC_RX_PATH, ODM_DBG_LOUD, ("[Return Init] Not Support Dynamic RX PAth\n"));
  67. return;
  68. }
  69. ODM_RT_TRACE(p_dm_odm, ODM_COMP_DYNAMIC_RX_PATH, ODM_DBG_LOUD, ("Current drp_state = ((%d))\n", p_dm_drp_table->drp_state));
  70. curr_drp_state = p_dm_drp_table->drp_state;
  71. if (p_dm_drp_table->drp_state == DRP_INIT_STATE) {
  72. phydm_drp_get_statistic(p_dm_odm);
  73. if (false_alm_cnt->cnt_crc32_ok_all > 20) {
  74. ODM_RT_TRACE(p_dm_odm, ODM_COMP_DYNAMIC_RX_PATH, ODM_DBG_LOUD, ("[Stop DRP Training] cnt_crc32_ok_all = ((%d))\n", false_alm_cnt->cnt_crc32_ok_all));
  75. p_dm_drp_table->drp_state = DRP_INIT_STATE;
  76. training_set_timmer_en = false;
  77. } else {
  78. ODM_RT_TRACE(p_dm_odm, ODM_COMP_DYNAMIC_RX_PATH, ODM_DBG_LOUD, ("[Start DRP Training] cnt_crc32_ok_all = ((%d))\n", false_alm_cnt->cnt_crc32_ok_all));
  79. p_dm_drp_table->drp_state = DRP_TRAINING_STATE_0;
  80. p_dm_drp_table->curr_rx_path = PHYDM_AB;
  81. training_set_timmer_en = true;
  82. }
  83. } else if (p_dm_drp_table->drp_state == DRP_TRAINING_STATE_0) {
  84. phydm_drp_get_statistic(p_dm_odm);
  85. p_dm_drp_table->curr_cca_all_cnt_0 = false_alm_cnt->cnt_cca_all;
  86. p_dm_drp_table->curr_fa_all_cnt_0 = false_alm_cnt->cnt_all;
  87. p_dm_drp_table->drp_state = DRP_TRAINING_STATE_1;
  88. p_dm_drp_table->curr_rx_path = PHYDM_B;
  89. training_set_timmer_en = true;
  90. } else if (p_dm_drp_table->drp_state == DRP_TRAINING_STATE_1) {
  91. phydm_drp_get_statistic(p_dm_odm);
  92. p_dm_drp_table->curr_cca_all_cnt_1 = false_alm_cnt->cnt_cca_all;
  93. p_dm_drp_table->curr_fa_all_cnt_1 = false_alm_cnt->cnt_all;
  94. #if 1
  95. p_dm_drp_table->drp_state = DRP_DECISION_STATE;
  96. #else
  97. if (p_dm_odm->mp_mode) {
  98. rx_ok_cal = p_dm_odm->phy_dbg_info.num_qry_phy_status_cck + p_dm_odm->phy_dbg_info.num_qry_phy_status_ofdm;
  99. RSSI = (rx_ok_cal != 0) ? p_dm_odm->rx_pwdb_ave / rx_ok_cal : 0;
  100. ODM_RT_TRACE(p_dm_odm, ODM_COMP_DYNAMIC_RX_PATH, ODM_DBG_LOUD, ("MP RSSI = ((%d))\n", RSSI));
  101. }
  102. if (RSSI > p_dm_drp_table->rssi_threshold)
  103. p_dm_drp_table->drp_state = DRP_DECISION_STATE;
  104. else {
  105. p_dm_drp_table->drp_state = DRP_TRAINING_STATE_2;
  106. p_dm_drp_table->curr_rx_path = PHYDM_A;
  107. training_set_timmer_en = true;
  108. }
  109. #endif
  110. } else if (p_dm_drp_table->drp_state == DRP_TRAINING_STATE_2) {
  111. phydm_drp_get_statistic(p_dm_odm);
  112. p_dm_drp_table->curr_cca_all_cnt_2 = false_alm_cnt->cnt_cca_all;
  113. p_dm_drp_table->curr_fa_all_cnt_2 = false_alm_cnt->cnt_all;
  114. p_dm_drp_table->drp_state = DRP_DECISION_STATE;
  115. }
  116. if (p_dm_drp_table->drp_state == DRP_DECISION_STATE) {
  117. ODM_RT_TRACE(p_dm_odm, ODM_COMP_DYNAMIC_RX_PATH, ODM_DBG_LOUD, ("Current drp_state = ((%d))\n", p_dm_drp_table->drp_state));
  118. ODM_RT_TRACE(p_dm_odm, ODM_COMP_DYNAMIC_RX_PATH, ODM_DBG_LOUD, ("[0] {CCA, FA} = {%d, %d}\n", p_dm_drp_table->curr_cca_all_cnt_0, p_dm_drp_table->curr_fa_all_cnt_0));
  119. ODM_RT_TRACE(p_dm_odm, ODM_COMP_DYNAMIC_RX_PATH, ODM_DBG_LOUD, ("[1] {CCA, FA} = {%d, %d}\n", p_dm_drp_table->curr_cca_all_cnt_1, p_dm_drp_table->curr_fa_all_cnt_1));
  120. ODM_RT_TRACE(p_dm_odm, ODM_COMP_DYNAMIC_RX_PATH, ODM_DBG_LOUD, ("[2] {CCA, FA} = {%d, %d}\n", p_dm_drp_table->curr_cca_all_cnt_2, p_dm_drp_table->curr_fa_all_cnt_2));
  121. if (p_dm_drp_table->curr_fa_all_cnt_1 < p_dm_drp_table->curr_fa_all_cnt_0) {
  122. if ((p_dm_drp_table->curr_fa_all_cnt_0 - p_dm_drp_table->curr_fa_all_cnt_1) > p_dm_drp_table->fa_diff_threshold)
  123. p_dm_drp_table->curr_rx_path = PHYDM_B;
  124. else
  125. p_dm_drp_table->curr_rx_path = PHYDM_AB;
  126. } else
  127. p_dm_drp_table->curr_rx_path = PHYDM_AB;
  128. phydm_config_ofdm_rx_path(p_dm_odm, p_dm_drp_table->curr_rx_path);
  129. ODM_RT_TRACE(p_dm_odm, ODM_COMP_DYNAMIC_RX_PATH, ODM_DBG_LOUD, ("[Training Result] curr_rx_path = ((%s%s)),\n",
  130. ((p_dm_drp_table->curr_rx_path & PHYDM_A) ? "A" : " "), ((p_dm_drp_table->curr_rx_path & PHYDM_B) ? "B" : " ")));
  131. p_dm_drp_table->drp_state = DRP_INIT_STATE;
  132. training_set_timmer_en = false;
  133. }
  134. ODM_RT_TRACE(p_dm_odm, ODM_COMP_DYNAMIC_RX_PATH, ODM_DBG_LOUD, ("DRP_state: ((%d)) -> ((%d))\n", curr_drp_state, p_dm_drp_table->drp_state));
  135. if (training_set_timmer_en) {
  136. ODM_RT_TRACE(p_dm_odm, ODM_COMP_DYNAMIC_RX_PATH, ODM_DBG_LOUD, ("[Training en] curr_rx_path = ((%s%s)), training_time = ((%d ms))\n",
  137. ((p_dm_drp_table->curr_rx_path & PHYDM_A) ? "A" : " "), ((p_dm_drp_table->curr_rx_path & PHYDM_B) ? "B" : " "), p_dm_drp_table->training_time));
  138. phydm_config_ofdm_rx_path(p_dm_odm, p_dm_drp_table->curr_rx_path);
  139. odm_set_timer(p_dm_odm, &(p_dm_drp_table->phydm_dynamic_rx_path_timer), p_dm_drp_table->training_time); /*ms*/
  140. } else
  141. ODM_RT_TRACE(p_dm_odm, ODM_COMP_DYNAMIC_RX_PATH, ODM_DBG_LOUD, ("DRP period end\n\n", curr_drp_state, p_dm_drp_table->drp_state));
  142. }
  143. #if (DM_ODM_SUPPORT_TYPE == ODM_WIN)
  144. void
  145. phydm_dynamic_rx_path_callback(
  146. struct timer_list *p_timer
  147. )
  148. {
  149. struct _ADAPTER *adapter = (struct _ADAPTER *)p_timer->adapter;
  150. HAL_DATA_TYPE *p_hal_data = GET_HAL_DATA(adapter);
  151. struct PHY_DM_STRUCT *p_dm_odm = &(p_hal_data->DM_OutSrc);
  152. struct _DYNAMIC_RX_PATH_ *p_dm_drp_table = &(p_dm_odm->dm_drp_table);
  153. #if DEV_BUS_TYPE == RT_PCI_INTERFACE
  154. #if USE_WORKITEM
  155. odm_schedule_work_item(&(p_dm_drp_table->phydm_dynamic_rx_path_workitem));
  156. #else
  157. {
  158. /* dbg_print("phydm_dynamic_rx_path\n"); */
  159. phydm_dynamic_rx_path(p_dm_odm);
  160. }
  161. #endif
  162. #else
  163. odm_schedule_work_item(&(p_dm_drp_table->phydm_dynamic_rx_path_workitem));
  164. #endif
  165. }
  166. void
  167. phydm_dynamic_rx_path_workitem_callback(
  168. void *p_context
  169. )
  170. {
  171. struct _ADAPTER *p_adapter = (struct _ADAPTER *)p_context;
  172. HAL_DATA_TYPE *p_hal_data = GET_HAL_DATA(p_adapter);
  173. struct PHY_DM_STRUCT *p_dm_odm = &(p_hal_data->DM_OutSrc);
  174. /* dbg_print("phydm_dynamic_rx_path\n"); */
  175. phydm_dynamic_rx_path(p_dm_odm);
  176. }
  177. #else if (DM_ODM_SUPPORT_TYPE == ODM_CE)
  178. void
  179. phydm_dynamic_rx_path_callback(
  180. void *function_context
  181. )
  182. {
  183. struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)function_context;
  184. struct _ADAPTER *padapter = p_dm_odm->adapter;
  185. if (padapter->net_closed == _TRUE)
  186. return;
  187. #if 0 /* Can't do I/O in timer callback*/
  188. odm_s0s1_sw_ant_div(p_dm_odm, SWAW_STEP_DETERMINE);
  189. #else
  190. /*rtw_run_in_thread_cmd(padapter, odm_sw_antdiv_workitem_callback, padapter);*/
  191. #endif
  192. }
  193. #endif
  194. void
  195. phydm_dynamic_rx_path_timers(
  196. void *p_dm_void,
  197. u8 state
  198. )
  199. {
  200. struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
  201. struct _DYNAMIC_RX_PATH_ *p_dm_drp_table = &(p_dm_odm->dm_drp_table);
  202. if (state == INIT_DRP_TIMMER) {
  203. odm_initialize_timer(p_dm_odm, &(p_dm_drp_table->phydm_dynamic_rx_path_timer),
  204. (void *)phydm_dynamic_rx_path_callback, NULL, "phydm_sw_antenna_switch_timer");
  205. } else if (state == CANCEL_DRP_TIMMER)
  206. odm_cancel_timer(p_dm_odm, &(p_dm_drp_table->phydm_dynamic_rx_path_timer));
  207. else if (state == RELEASE_DRP_TIMMER)
  208. odm_release_timer(p_dm_odm, &(p_dm_drp_table->phydm_dynamic_rx_path_timer));
  209. }
  210. void
  211. phydm_dynamic_rx_path_init(
  212. void *p_dm_void
  213. )
  214. {
  215. struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
  216. struct _DYNAMIC_RX_PATH_ *p_dm_drp_table = &(p_dm_odm->dm_drp_table);
  217. boolean ret_value;
  218. if (!(p_dm_odm->support_ability & ODM_BB_DYNAMIC_RX_PATH)) {
  219. ODM_RT_TRACE(p_dm_odm, ODM_COMP_DYNAMIC_RX_PATH, ODM_DBG_LOUD, ("[Return] Not Support Dynamic RX PAth\n"));
  220. return;
  221. }
  222. ODM_RT_TRACE(p_dm_odm, ODM_COMP_DYNAMIC_RX_PATH, ODM_DBG_LOUD, ("phydm_dynamic_rx_path_init\n"));
  223. p_dm_drp_table->drp_state = DRP_INIT_STATE;
  224. p_dm_drp_table->rssi_threshold = DRP_RSSI_TH;
  225. p_dm_drp_table->fa_count_thresold = 50;
  226. p_dm_drp_table->fa_diff_threshold = 50;
  227. p_dm_drp_table->training_time = 100; /*ms*/
  228. p_dm_drp_table->drp_skip_counter = 0;
  229. p_dm_drp_table->drp_period = 0;
  230. p_dm_drp_table->drp_init_finished = true;
  231. ret_value = phydm_api_trx_mode(p_dm_odm, (enum odm_rf_path_e)(ODM_RF_A | ODM_RF_B), (enum odm_rf_path_e)(ODM_RF_A | ODM_RF_B), true);
  232. }
  233. void
  234. phydm_drp_debug(
  235. void *p_dm_void,
  236. u32 *const dm_value,
  237. u32 *_used,
  238. char *output,
  239. u32 *_out_len
  240. )
  241. {
  242. struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
  243. u32 used = *_used;
  244. u32 out_len = *_out_len;
  245. struct _DYNAMIC_RX_PATH_ *p_dm_drp_table = &(p_dm_odm->dm_drp_table);
  246. switch (dm_value[0]) {
  247. case DRP_TRAINING_TIME:
  248. p_dm_drp_table->training_time = (u16)dm_value[1];
  249. break;
  250. case DRP_TRAINING_PERIOD:
  251. p_dm_drp_table->drp_period = (u8)dm_value[1];
  252. break;
  253. case DRP_RSSI_THRESHOLD:
  254. p_dm_drp_table->rssi_threshold = (u8)dm_value[1];
  255. break;
  256. case DRP_FA_THRESHOLD:
  257. p_dm_drp_table->fa_count_thresold = dm_value[1];
  258. break;
  259. case DRP_FA_DIFF_THRESHOLD:
  260. p_dm_drp_table->fa_diff_threshold = dm_value[1];
  261. break;
  262. default:
  263. PHYDM_SNPRINTF((output + used, out_len - used, "[DRP] unknown command\n"));
  264. break;
  265. }
  266. }
  267. void
  268. phydm_dynamic_rx_path_caller(
  269. void *p_dm_void
  270. )
  271. {
  272. struct PHY_DM_STRUCT *p_dm_odm = (struct PHY_DM_STRUCT *)p_dm_void;
  273. struct _DYNAMIC_RX_PATH_ *p_dm_drp_table = &(p_dm_odm->dm_drp_table);
  274. if (p_dm_drp_table->drp_skip_counter < p_dm_drp_table->drp_period)
  275. p_dm_drp_table->drp_skip_counter++;
  276. else
  277. p_dm_drp_table->drp_skip_counter = 0;
  278. if (p_dm_drp_table->drp_skip_counter != 0)
  279. return;
  280. if (p_dm_drp_table->drp_init_finished != true)
  281. return;
  282. phydm_dynamic_rx_path(p_dm_odm);
  283. }
  284. #endif