stats.c 8.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290
  1. /******************************************************************************
  2. *
  3. * Copyright(c) 2009-2012 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. * The full GNU General Public License is included in this distribution in the
  15. * file called LICENSE.
  16. *
  17. * Contact Information:
  18. * wlanfae <wlanfae@realtek.com>
  19. * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
  20. * Hsinchu 300, Taiwan.
  21. *
  22. * Larry Finger <Larry.Finger@lwfinger.net>
  23. *
  24. *****************************************************************************/
  25. #include "wifi.h"
  26. #include "stats.h"
  27. #include <linux/export.h>
  28. u8 rtl_query_rxpwrpercentage(char antpower)
  29. {
  30. if ((antpower <= -100) || (antpower >= 20))
  31. return 0;
  32. else if (antpower >= 0)
  33. return 100;
  34. else
  35. return 100 + antpower;
  36. }
  37. EXPORT_SYMBOL(rtl_query_rxpwrpercentage);
  38. u8 rtl_evm_db_to_percentage(char value)
  39. {
  40. char ret_val;
  41. ret_val = value;
  42. if (ret_val >= 0)
  43. ret_val = 0;
  44. if (ret_val <= -33)
  45. ret_val = -33;
  46. ret_val = 0 - ret_val;
  47. ret_val *= 3;
  48. if (ret_val == 99)
  49. ret_val = 100;
  50. return ret_val;
  51. }
  52. EXPORT_SYMBOL(rtl_evm_db_to_percentage);
  53. u8 rtl_evm_dbm_jaguar(char value)
  54. {
  55. char ret_val = value;
  56. /* -33dB~0dB to 33dB ~ 0dB*/
  57. if (ret_val == -128)
  58. ret_val = 127;
  59. else if (ret_val < 0)
  60. ret_val = 0 - ret_val;
  61. ret_val = ret_val >> 1;
  62. return ret_val;
  63. }
  64. EXPORT_SYMBOL(rtl_evm_dbm_jaguar);
  65. static long rtl_translate_todbm(struct ieee80211_hw *hw,
  66. u8 signal_strength_index)
  67. {
  68. long signal_power;
  69. signal_power = (long)((signal_strength_index + 1) >> 1);
  70. signal_power -= 95;
  71. return signal_power;
  72. }
  73. long rtl_signal_scale_mapping(struct ieee80211_hw *hw, long currsig)
  74. {
  75. long retsig;
  76. if (currsig >= 61 && currsig <= 100)
  77. retsig = 90 + ((currsig - 60) / 4);
  78. else if (currsig >= 41 && currsig <= 60)
  79. retsig = 78 + ((currsig - 40) / 2);
  80. else if (currsig >= 31 && currsig <= 40)
  81. retsig = 66 + (currsig - 30);
  82. else if (currsig >= 21 && currsig <= 30)
  83. retsig = 54 + (currsig - 20);
  84. else if (currsig >= 5 && currsig <= 20)
  85. retsig = 42 + (((currsig - 5) * 2) / 3);
  86. else if (currsig == 4)
  87. retsig = 36;
  88. else if (currsig == 3)
  89. retsig = 27;
  90. else if (currsig == 2)
  91. retsig = 18;
  92. else if (currsig == 1)
  93. retsig = 9;
  94. else
  95. retsig = currsig;
  96. return retsig;
  97. }
  98. EXPORT_SYMBOL(rtl_signal_scale_mapping);
  99. static void rtl_process_ui_rssi(struct ieee80211_hw *hw,
  100. struct rtl_stats *pstatus)
  101. {
  102. struct rtl_priv *rtlpriv = rtl_priv(hw);
  103. struct rtl_phy *rtlphy = &(rtlpriv->phy);
  104. u8 rfpath;
  105. u32 last_rssi, tmpval;
  106. if (!pstatus->packet_toself && !pstatus->packet_beacon)
  107. return;
  108. rtlpriv->stats.pwdb_all_cnt += pstatus->rx_pwdb_all;
  109. rtlpriv->stats.rssi_calculate_cnt++;
  110. if (rtlpriv->stats.ui_rssi.total_num++ >= PHY_RSSI_SLID_WIN_MAX) {
  111. rtlpriv->stats.ui_rssi.total_num = PHY_RSSI_SLID_WIN_MAX;
  112. last_rssi = rtlpriv->stats.ui_rssi.elements[
  113. rtlpriv->stats.ui_rssi.index];
  114. rtlpriv->stats.ui_rssi.total_val -= last_rssi;
  115. }
  116. rtlpriv->stats.ui_rssi.total_val += pstatus->signalstrength;
  117. rtlpriv->stats.ui_rssi.elements[rtlpriv->stats.ui_rssi.index++] =
  118. pstatus->signalstrength;
  119. if (rtlpriv->stats.ui_rssi.index >= PHY_RSSI_SLID_WIN_MAX)
  120. rtlpriv->stats.ui_rssi.index = 0;
  121. tmpval = rtlpriv->stats.ui_rssi.total_val /
  122. rtlpriv->stats.ui_rssi.total_num;
  123. rtlpriv->stats.signal_strength = rtl_translate_todbm(hw,
  124. (u8) tmpval);
  125. pstatus->rssi = rtlpriv->stats.signal_strength;
  126. if (pstatus->is_cck)
  127. return;
  128. for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath;
  129. rfpath++) {
  130. if (rtlpriv->stats.rx_rssi_percentage[rfpath] == 0) {
  131. rtlpriv->stats.rx_rssi_percentage[rfpath] =
  132. pstatus->rx_mimo_signalstrength[rfpath];
  133. }
  134. if (pstatus->rx_mimo_signalstrength[rfpath] >
  135. rtlpriv->stats.rx_rssi_percentage[rfpath]) {
  136. rtlpriv->stats.rx_rssi_percentage[rfpath] =
  137. ((rtlpriv->stats.rx_rssi_percentage[rfpath] *
  138. (RX_SMOOTH_FACTOR - 1)) +
  139. (pstatus->rx_mimo_signalstrength[rfpath])) /
  140. (RX_SMOOTH_FACTOR);
  141. rtlpriv->stats.rx_rssi_percentage[rfpath] =
  142. rtlpriv->stats.rx_rssi_percentage[rfpath] + 1;
  143. } else {
  144. rtlpriv->stats.rx_rssi_percentage[rfpath] =
  145. ((rtlpriv->stats.rx_rssi_percentage[rfpath] *
  146. (RX_SMOOTH_FACTOR - 1)) +
  147. (pstatus->rx_mimo_signalstrength[rfpath])) /
  148. (RX_SMOOTH_FACTOR);
  149. }
  150. rtlpriv->stats.rx_snr_db[rfpath] = pstatus->rx_snr[rfpath];
  151. rtlpriv->stats.rx_evm_dbm[rfpath] =
  152. pstatus->rx_mimo_evm_dbm[rfpath];
  153. rtlpriv->stats.rx_cfo_short[rfpath] =
  154. pstatus->cfo_short[rfpath];
  155. rtlpriv->stats.rx_cfo_tail[rfpath] = pstatus->cfo_tail[rfpath];
  156. }
  157. }
  158. static void rtl_update_rxsignalstatistics(struct ieee80211_hw *hw,
  159. struct rtl_stats *pstatus)
  160. {
  161. struct rtl_priv *rtlpriv = rtl_priv(hw);
  162. int weighting = 0;
  163. if (rtlpriv->stats.recv_signal_power == 0)
  164. rtlpriv->stats.recv_signal_power = pstatus->recvsignalpower;
  165. if (pstatus->recvsignalpower > rtlpriv->stats.recv_signal_power)
  166. weighting = 5;
  167. else if (pstatus->recvsignalpower < rtlpriv->stats.recv_signal_power)
  168. weighting = (-5);
  169. rtlpriv->stats.recv_signal_power = (rtlpriv->stats.recv_signal_power *
  170. 5 + pstatus->recvsignalpower + weighting) / 6;
  171. }
  172. static void rtl_process_pwdb(struct ieee80211_hw *hw, struct rtl_stats *pstatus)
  173. {
  174. struct rtl_priv *rtlpriv = rtl_priv(hw);
  175. struct rtl_sta_info *drv_priv = NULL;
  176. struct ieee80211_sta *sta = NULL;
  177. long undec_sm_pwdb;
  178. rcu_read_lock();
  179. if (rtlpriv->mac80211.opmode != NL80211_IFTYPE_STATION)
  180. sta = rtl_find_sta(hw, pstatus->psaddr);
  181. /* adhoc or ap mode */
  182. if (sta) {
  183. drv_priv = (struct rtl_sta_info *) sta->drv_priv;
  184. undec_sm_pwdb = drv_priv->rssi_stat.undec_sm_pwdb;
  185. } else {
  186. undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb;
  187. }
  188. if (undec_sm_pwdb < 0)
  189. undec_sm_pwdb = pstatus->rx_pwdb_all;
  190. if (pstatus->rx_pwdb_all > (u32) undec_sm_pwdb) {
  191. undec_sm_pwdb = (((undec_sm_pwdb) *
  192. (RX_SMOOTH_FACTOR - 1)) +
  193. (pstatus->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
  194. undec_sm_pwdb = undec_sm_pwdb + 1;
  195. } else {
  196. undec_sm_pwdb = (((undec_sm_pwdb) *
  197. (RX_SMOOTH_FACTOR - 1)) +
  198. (pstatus->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
  199. }
  200. if (sta) {
  201. drv_priv->rssi_stat.undec_sm_pwdb = undec_sm_pwdb;
  202. } else {
  203. rtlpriv->dm.undec_sm_pwdb = undec_sm_pwdb;
  204. }
  205. rcu_read_unlock();
  206. rtl_update_rxsignalstatistics(hw, pstatus);
  207. }
  208. static void rtl_process_ui_link_quality(struct ieee80211_hw *hw,
  209. struct rtl_stats *pstatus)
  210. {
  211. struct rtl_priv *rtlpriv = rtl_priv(hw);
  212. u32 last_evm, n_stream, tmpval;
  213. if (pstatus->signalquality == 0)
  214. return;
  215. if (rtlpriv->stats.ui_link_quality.total_num++ >=
  216. PHY_LINKQUALITY_SLID_WIN_MAX) {
  217. rtlpriv->stats.ui_link_quality.total_num =
  218. PHY_LINKQUALITY_SLID_WIN_MAX;
  219. last_evm = rtlpriv->stats.ui_link_quality.elements[
  220. rtlpriv->stats.ui_link_quality.index];
  221. rtlpriv->stats.ui_link_quality.total_val -= last_evm;
  222. }
  223. rtlpriv->stats.ui_link_quality.total_val += pstatus->signalquality;
  224. rtlpriv->stats.ui_link_quality.elements[
  225. rtlpriv->stats.ui_link_quality.index++] =
  226. pstatus->signalquality;
  227. if (rtlpriv->stats.ui_link_quality.index >=
  228. PHY_LINKQUALITY_SLID_WIN_MAX)
  229. rtlpriv->stats.ui_link_quality.index = 0;
  230. tmpval = rtlpriv->stats.ui_link_quality.total_val /
  231. rtlpriv->stats.ui_link_quality.total_num;
  232. rtlpriv->stats.signal_quality = tmpval;
  233. rtlpriv->stats.last_sigstrength_inpercent = tmpval;
  234. for (n_stream = 0; n_stream < 2; n_stream++) {
  235. if (pstatus->rx_mimo_sig_qual[n_stream] != -1) {
  236. if (rtlpriv->stats.rx_evm_percentage[n_stream] == 0) {
  237. rtlpriv->stats.rx_evm_percentage[n_stream] =
  238. pstatus->rx_mimo_sig_qual[n_stream];
  239. }
  240. rtlpriv->stats.rx_evm_percentage[n_stream] =
  241. ((rtlpriv->stats.rx_evm_percentage[n_stream]
  242. * (RX_SMOOTH_FACTOR - 1)) +
  243. (pstatus->rx_mimo_sig_qual[n_stream] * 1)) /
  244. (RX_SMOOTH_FACTOR);
  245. }
  246. }
  247. }
  248. void rtl_process_phyinfo(struct ieee80211_hw *hw, u8 *buffer,
  249. struct rtl_stats *pstatus)
  250. {
  251. if (!pstatus->packet_matchbssid)
  252. return;
  253. rtl_process_ui_rssi(hw, pstatus);
  254. rtl_process_pwdb(hw, pstatus);
  255. rtl_process_ui_link_quality(hw, pstatus);
  256. }
  257. EXPORT_SYMBOL(rtl_process_phyinfo);