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