stats.c 8.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268
  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 = clamp(-value, 0, 33) * 3;
  41. if (ret_val == 99)
  42. ret_val = 100;
  43. return ret_val;
  44. }
  45. EXPORT_SYMBOL(rtl_evm_db_to_percentage);
  46. static long rtl_translate_todbm(struct ieee80211_hw *hw,
  47. u8 signal_strength_index)
  48. {
  49. long signal_power;
  50. signal_power = (long)((signal_strength_index + 1) >> 1);
  51. signal_power -= 95;
  52. return signal_power;
  53. }
  54. long rtl_signal_scale_mapping(struct ieee80211_hw *hw, long currsig)
  55. {
  56. long retsig;
  57. if (currsig >= 61 && currsig <= 100)
  58. retsig = 90 + ((currsig - 60) / 4);
  59. else if (currsig >= 41 && currsig <= 60)
  60. retsig = 78 + ((currsig - 40) / 2);
  61. else if (currsig >= 31 && currsig <= 40)
  62. retsig = 66 + (currsig - 30);
  63. else if (currsig >= 21 && currsig <= 30)
  64. retsig = 54 + (currsig - 20);
  65. else if (currsig >= 5 && currsig <= 20)
  66. retsig = 42 + (((currsig - 5) * 2) / 3);
  67. else if (currsig == 4)
  68. retsig = 36;
  69. else if (currsig == 3)
  70. retsig = 27;
  71. else if (currsig == 2)
  72. retsig = 18;
  73. else if (currsig == 1)
  74. retsig = 9;
  75. else
  76. retsig = currsig;
  77. return retsig;
  78. }
  79. EXPORT_SYMBOL(rtl_signal_scale_mapping);
  80. static void rtl_process_ui_rssi(struct ieee80211_hw *hw,
  81. struct rtl_stats *pstatus)
  82. {
  83. struct rtl_priv *rtlpriv = rtl_priv(hw);
  84. struct rtl_phy *rtlphy = &(rtlpriv->phy);
  85. u8 rfpath;
  86. u32 last_rssi, tmpval;
  87. if (!pstatus->packet_toself && !pstatus->packet_beacon)
  88. return;
  89. rtlpriv->stats.pwdb_all_cnt += pstatus->rx_pwdb_all;
  90. rtlpriv->stats.rssi_calculate_cnt++;
  91. if (rtlpriv->stats.ui_rssi.total_num++ >= PHY_RSSI_SLID_WIN_MAX) {
  92. rtlpriv->stats.ui_rssi.total_num = PHY_RSSI_SLID_WIN_MAX;
  93. last_rssi = rtlpriv->stats.ui_rssi.elements[
  94. rtlpriv->stats.ui_rssi.index];
  95. rtlpriv->stats.ui_rssi.total_val -= last_rssi;
  96. }
  97. rtlpriv->stats.ui_rssi.total_val += pstatus->signalstrength;
  98. rtlpriv->stats.ui_rssi.elements[rtlpriv->stats.ui_rssi.index++] =
  99. pstatus->signalstrength;
  100. if (rtlpriv->stats.ui_rssi.index >= PHY_RSSI_SLID_WIN_MAX)
  101. rtlpriv->stats.ui_rssi.index = 0;
  102. tmpval = rtlpriv->stats.ui_rssi.total_val /
  103. rtlpriv->stats.ui_rssi.total_num;
  104. rtlpriv->stats.signal_strength = rtl_translate_todbm(hw,
  105. (u8) tmpval);
  106. pstatus->rssi = rtlpriv->stats.signal_strength;
  107. if (pstatus->is_cck)
  108. return;
  109. for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath;
  110. rfpath++) {
  111. if (rtlpriv->stats.rx_rssi_percentage[rfpath] == 0) {
  112. rtlpriv->stats.rx_rssi_percentage[rfpath] =
  113. pstatus->rx_mimo_signalstrength[rfpath];
  114. }
  115. if (pstatus->rx_mimo_signalstrength[rfpath] >
  116. rtlpriv->stats.rx_rssi_percentage[rfpath]) {
  117. rtlpriv->stats.rx_rssi_percentage[rfpath] =
  118. ((rtlpriv->stats.rx_rssi_percentage[rfpath] *
  119. (RX_SMOOTH_FACTOR - 1)) +
  120. (pstatus->rx_mimo_signalstrength[rfpath])) /
  121. (RX_SMOOTH_FACTOR);
  122. rtlpriv->stats.rx_rssi_percentage[rfpath] =
  123. rtlpriv->stats.rx_rssi_percentage[rfpath] + 1;
  124. } else {
  125. rtlpriv->stats.rx_rssi_percentage[rfpath] =
  126. ((rtlpriv->stats.rx_rssi_percentage[rfpath] *
  127. (RX_SMOOTH_FACTOR - 1)) +
  128. (pstatus->rx_mimo_signalstrength[rfpath])) /
  129. (RX_SMOOTH_FACTOR);
  130. }
  131. rtlpriv->stats.rx_snr_db[rfpath] = pstatus->rx_snr[rfpath];
  132. rtlpriv->stats.rx_evm_dbm[rfpath] =
  133. pstatus->rx_mimo_evm_dbm[rfpath];
  134. rtlpriv->stats.rx_cfo_short[rfpath] =
  135. pstatus->cfo_short[rfpath];
  136. rtlpriv->stats.rx_cfo_tail[rfpath] = pstatus->cfo_tail[rfpath];
  137. }
  138. }
  139. static void rtl_update_rxsignalstatistics(struct ieee80211_hw *hw,
  140. struct rtl_stats *pstatus)
  141. {
  142. struct rtl_priv *rtlpriv = rtl_priv(hw);
  143. int weighting = 0;
  144. if (rtlpriv->stats.recv_signal_power == 0)
  145. rtlpriv->stats.recv_signal_power = pstatus->recvsignalpower;
  146. if (pstatus->recvsignalpower > rtlpriv->stats.recv_signal_power)
  147. weighting = 5;
  148. else if (pstatus->recvsignalpower < rtlpriv->stats.recv_signal_power)
  149. weighting = (-5);
  150. rtlpriv->stats.recv_signal_power = (rtlpriv->stats.recv_signal_power *
  151. 5 + pstatus->recvsignalpower + weighting) / 6;
  152. }
  153. static void rtl_process_pwdb(struct ieee80211_hw *hw, struct rtl_stats *pstatus)
  154. {
  155. struct rtl_priv *rtlpriv = rtl_priv(hw);
  156. struct rtl_sta_info *drv_priv = NULL;
  157. struct ieee80211_sta *sta = NULL;
  158. long undec_sm_pwdb;
  159. rcu_read_lock();
  160. if (rtlpriv->mac80211.opmode != NL80211_IFTYPE_STATION)
  161. sta = rtl_find_sta(hw, pstatus->psaddr);
  162. /* adhoc or ap mode */
  163. if (sta) {
  164. drv_priv = (struct rtl_sta_info *) sta->drv_priv;
  165. undec_sm_pwdb = drv_priv->rssi_stat.undec_sm_pwdb;
  166. } else {
  167. undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb;
  168. }
  169. if (undec_sm_pwdb < 0)
  170. undec_sm_pwdb = pstatus->rx_pwdb_all;
  171. if (pstatus->rx_pwdb_all > (u32) undec_sm_pwdb) {
  172. undec_sm_pwdb = (((undec_sm_pwdb) *
  173. (RX_SMOOTH_FACTOR - 1)) +
  174. (pstatus->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
  175. undec_sm_pwdb = undec_sm_pwdb + 1;
  176. } else {
  177. undec_sm_pwdb = (((undec_sm_pwdb) *
  178. (RX_SMOOTH_FACTOR - 1)) +
  179. (pstatus->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
  180. }
  181. if (sta) {
  182. drv_priv->rssi_stat.undec_sm_pwdb = undec_sm_pwdb;
  183. } else {
  184. rtlpriv->dm.undec_sm_pwdb = undec_sm_pwdb;
  185. }
  186. rcu_read_unlock();
  187. rtl_update_rxsignalstatistics(hw, pstatus);
  188. }
  189. static void rtl_process_ui_link_quality(struct ieee80211_hw *hw,
  190. struct rtl_stats *pstatus)
  191. {
  192. struct rtl_priv *rtlpriv = rtl_priv(hw);
  193. u32 last_evm, n_stream, tmpval;
  194. if (pstatus->signalquality == 0)
  195. return;
  196. if (rtlpriv->stats.ui_link_quality.total_num++ >=
  197. PHY_LINKQUALITY_SLID_WIN_MAX) {
  198. rtlpriv->stats.ui_link_quality.total_num =
  199. PHY_LINKQUALITY_SLID_WIN_MAX;
  200. last_evm = rtlpriv->stats.ui_link_quality.elements[
  201. rtlpriv->stats.ui_link_quality.index];
  202. rtlpriv->stats.ui_link_quality.total_val -= last_evm;
  203. }
  204. rtlpriv->stats.ui_link_quality.total_val += pstatus->signalquality;
  205. rtlpriv->stats.ui_link_quality.elements[
  206. rtlpriv->stats.ui_link_quality.index++] =
  207. pstatus->signalquality;
  208. if (rtlpriv->stats.ui_link_quality.index >=
  209. PHY_LINKQUALITY_SLID_WIN_MAX)
  210. rtlpriv->stats.ui_link_quality.index = 0;
  211. tmpval = rtlpriv->stats.ui_link_quality.total_val /
  212. rtlpriv->stats.ui_link_quality.total_num;
  213. rtlpriv->stats.signal_quality = tmpval;
  214. rtlpriv->stats.last_sigstrength_inpercent = tmpval;
  215. for (n_stream = 0; n_stream < 2; n_stream++) {
  216. if (pstatus->rx_mimo_sig_qual[n_stream] != -1) {
  217. if (rtlpriv->stats.rx_evm_percentage[n_stream] == 0) {
  218. rtlpriv->stats.rx_evm_percentage[n_stream] =
  219. pstatus->rx_mimo_sig_qual[n_stream];
  220. }
  221. rtlpriv->stats.rx_evm_percentage[n_stream] =
  222. ((rtlpriv->stats.rx_evm_percentage[n_stream]
  223. * (RX_SMOOTH_FACTOR - 1)) +
  224. (pstatus->rx_mimo_sig_qual[n_stream] * 1)) /
  225. (RX_SMOOTH_FACTOR);
  226. }
  227. }
  228. }
  229. void rtl_process_phyinfo(struct ieee80211_hw *hw, u8 *buffer,
  230. struct rtl_stats *pstatus)
  231. {
  232. if (!pstatus->packet_matchbssid)
  233. return;
  234. rtl_process_ui_rssi(hw, pstatus);
  235. rtl_process_pwdb(hw, pstatus);
  236. rtl_process_ui_link_quality(hw, pstatus);
  237. }
  238. EXPORT_SYMBOL(rtl_process_phyinfo);