0001
0002
0003
0004 #include "wifi.h"
0005 #include "stats.h"
0006 #include <linux/export.h>
0007
0008 u8 rtl_query_rxpwrpercentage(s8 antpower)
0009 {
0010 if ((antpower <= -100) || (antpower >= 20))
0011 return 0;
0012 else if (antpower >= 0)
0013 return 100;
0014 else
0015 return 100 + antpower;
0016 }
0017 EXPORT_SYMBOL(rtl_query_rxpwrpercentage);
0018
0019 u8 rtl_evm_db_to_percentage(s8 value)
0020 {
0021 s8 ret_val = clamp(-value, 0, 33) * 3;
0022
0023 if (ret_val == 99)
0024 ret_val = 100;
0025
0026 return ret_val;
0027 }
0028 EXPORT_SYMBOL(rtl_evm_db_to_percentage);
0029
0030 static long rtl_translate_todbm(struct ieee80211_hw *hw,
0031 u8 signal_strength_index)
0032 {
0033 long signal_power;
0034
0035 signal_power = (long)((signal_strength_index + 1) >> 1);
0036 signal_power -= 95;
0037 return signal_power;
0038 }
0039
0040 long rtl_signal_scale_mapping(struct ieee80211_hw *hw, long currsig)
0041 {
0042 long retsig;
0043
0044 if (currsig >= 61 && currsig <= 100)
0045 retsig = 90 + ((currsig - 60) / 4);
0046 else if (currsig >= 41 && currsig <= 60)
0047 retsig = 78 + ((currsig - 40) / 2);
0048 else if (currsig >= 31 && currsig <= 40)
0049 retsig = 66 + (currsig - 30);
0050 else if (currsig >= 21 && currsig <= 30)
0051 retsig = 54 + (currsig - 20);
0052 else if (currsig >= 5 && currsig <= 20)
0053 retsig = 42 + (((currsig - 5) * 2) / 3);
0054 else if (currsig == 4)
0055 retsig = 36;
0056 else if (currsig == 3)
0057 retsig = 27;
0058 else if (currsig == 2)
0059 retsig = 18;
0060 else if (currsig == 1)
0061 retsig = 9;
0062 else
0063 retsig = currsig;
0064
0065 return retsig;
0066 }
0067 EXPORT_SYMBOL(rtl_signal_scale_mapping);
0068
0069 static void rtl_process_ui_rssi(struct ieee80211_hw *hw,
0070 struct rtl_stats *pstatus)
0071 {
0072 struct rtl_priv *rtlpriv = rtl_priv(hw);
0073 struct rtl_phy *rtlphy = &(rtlpriv->phy);
0074 u8 rfpath;
0075 u32 last_rssi, tmpval;
0076
0077 if (!pstatus->packet_toself && !pstatus->packet_beacon)
0078 return;
0079
0080 rtlpriv->stats.pwdb_all_cnt += pstatus->rx_pwdb_all;
0081 rtlpriv->stats.rssi_calculate_cnt++;
0082
0083 if (rtlpriv->stats.ui_rssi.total_num++ >= PHY_RSSI_SLID_WIN_MAX) {
0084 rtlpriv->stats.ui_rssi.total_num = PHY_RSSI_SLID_WIN_MAX;
0085 last_rssi = rtlpriv->stats.ui_rssi.elements[
0086 rtlpriv->stats.ui_rssi.index];
0087 rtlpriv->stats.ui_rssi.total_val -= last_rssi;
0088 }
0089 rtlpriv->stats.ui_rssi.total_val += pstatus->signalstrength;
0090 rtlpriv->stats.ui_rssi.elements[rtlpriv->stats.ui_rssi.index++] =
0091 pstatus->signalstrength;
0092 if (rtlpriv->stats.ui_rssi.index >= PHY_RSSI_SLID_WIN_MAX)
0093 rtlpriv->stats.ui_rssi.index = 0;
0094 tmpval = rtlpriv->stats.ui_rssi.total_val /
0095 rtlpriv->stats.ui_rssi.total_num;
0096 rtlpriv->stats.signal_strength = rtl_translate_todbm(hw,
0097 (u8) tmpval);
0098 pstatus->rssi = rtlpriv->stats.signal_strength;
0099
0100 if (pstatus->is_cck)
0101 return;
0102
0103 for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath;
0104 rfpath++) {
0105 if (rtlpriv->stats.rx_rssi_percentage[rfpath] == 0) {
0106 rtlpriv->stats.rx_rssi_percentage[rfpath] =
0107 pstatus->rx_mimo_signalstrength[rfpath];
0108
0109 }
0110 if (pstatus->rx_mimo_signalstrength[rfpath] >
0111 rtlpriv->stats.rx_rssi_percentage[rfpath]) {
0112 rtlpriv->stats.rx_rssi_percentage[rfpath] =
0113 ((rtlpriv->stats.rx_rssi_percentage[rfpath] *
0114 (RX_SMOOTH_FACTOR - 1)) +
0115 (pstatus->rx_mimo_signalstrength[rfpath])) /
0116 (RX_SMOOTH_FACTOR);
0117 rtlpriv->stats.rx_rssi_percentage[rfpath] =
0118 rtlpriv->stats.rx_rssi_percentage[rfpath] + 1;
0119 } else {
0120 rtlpriv->stats.rx_rssi_percentage[rfpath] =
0121 ((rtlpriv->stats.rx_rssi_percentage[rfpath] *
0122 (RX_SMOOTH_FACTOR - 1)) +
0123 (pstatus->rx_mimo_signalstrength[rfpath])) /
0124 (RX_SMOOTH_FACTOR);
0125 }
0126 rtlpriv->stats.rx_snr_db[rfpath] = pstatus->rx_snr[rfpath];
0127 rtlpriv->stats.rx_evm_dbm[rfpath] =
0128 pstatus->rx_mimo_evm_dbm[rfpath];
0129 rtlpriv->stats.rx_cfo_short[rfpath] =
0130 pstatus->cfo_short[rfpath];
0131 rtlpriv->stats.rx_cfo_tail[rfpath] = pstatus->cfo_tail[rfpath];
0132 }
0133 }
0134
0135 static void rtl_update_rxsignalstatistics(struct ieee80211_hw *hw,
0136 struct rtl_stats *pstatus)
0137 {
0138 struct rtl_priv *rtlpriv = rtl_priv(hw);
0139 int weighting = 0;
0140
0141 if (rtlpriv->stats.recv_signal_power == 0)
0142 rtlpriv->stats.recv_signal_power = pstatus->recvsignalpower;
0143 if (pstatus->recvsignalpower > rtlpriv->stats.recv_signal_power)
0144 weighting = 5;
0145 else if (pstatus->recvsignalpower < rtlpriv->stats.recv_signal_power)
0146 weighting = (-5);
0147 rtlpriv->stats.recv_signal_power = (rtlpriv->stats.recv_signal_power *
0148 5 + pstatus->recvsignalpower + weighting) / 6;
0149 }
0150
0151 static void rtl_process_pwdb(struct ieee80211_hw *hw, struct rtl_stats *pstatus)
0152 {
0153 struct rtl_priv *rtlpriv = rtl_priv(hw);
0154 struct rtl_sta_info *drv_priv = NULL;
0155 struct ieee80211_sta *sta = NULL;
0156 long undec_sm_pwdb;
0157
0158 rcu_read_lock();
0159 if (rtlpriv->mac80211.opmode != NL80211_IFTYPE_STATION)
0160 sta = rtl_find_sta(hw, pstatus->psaddr);
0161
0162
0163 if (sta) {
0164 drv_priv = (struct rtl_sta_info *) sta->drv_priv;
0165 undec_sm_pwdb = drv_priv->rssi_stat.undec_sm_pwdb;
0166 } else {
0167 undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb;
0168 }
0169
0170 if (undec_sm_pwdb < 0)
0171 undec_sm_pwdb = pstatus->rx_pwdb_all;
0172 if (pstatus->rx_pwdb_all > (u32) undec_sm_pwdb) {
0173 undec_sm_pwdb = (((undec_sm_pwdb) *
0174 (RX_SMOOTH_FACTOR - 1)) +
0175 (pstatus->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
0176 undec_sm_pwdb = undec_sm_pwdb + 1;
0177 } else {
0178 undec_sm_pwdb = (((undec_sm_pwdb) *
0179 (RX_SMOOTH_FACTOR - 1)) +
0180 (pstatus->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
0181 }
0182
0183 if (sta) {
0184 drv_priv->rssi_stat.undec_sm_pwdb = undec_sm_pwdb;
0185 } else {
0186 rtlpriv->dm.undec_sm_pwdb = undec_sm_pwdb;
0187 }
0188 rcu_read_unlock();
0189
0190 rtl_update_rxsignalstatistics(hw, pstatus);
0191 }
0192
0193 static void rtl_process_ui_link_quality(struct ieee80211_hw *hw,
0194 struct rtl_stats *pstatus)
0195 {
0196 struct rtl_priv *rtlpriv = rtl_priv(hw);
0197 u32 last_evm, n_stream, tmpval;
0198
0199 if (pstatus->signalquality == 0)
0200 return;
0201
0202 if (rtlpriv->stats.ui_link_quality.total_num++ >=
0203 PHY_LINKQUALITY_SLID_WIN_MAX) {
0204 rtlpriv->stats.ui_link_quality.total_num =
0205 PHY_LINKQUALITY_SLID_WIN_MAX;
0206 last_evm = rtlpriv->stats.ui_link_quality.elements[
0207 rtlpriv->stats.ui_link_quality.index];
0208 rtlpriv->stats.ui_link_quality.total_val -= last_evm;
0209 }
0210 rtlpriv->stats.ui_link_quality.total_val += pstatus->signalquality;
0211 rtlpriv->stats.ui_link_quality.elements[
0212 rtlpriv->stats.ui_link_quality.index++] =
0213 pstatus->signalquality;
0214 if (rtlpriv->stats.ui_link_quality.index >=
0215 PHY_LINKQUALITY_SLID_WIN_MAX)
0216 rtlpriv->stats.ui_link_quality.index = 0;
0217 tmpval = rtlpriv->stats.ui_link_quality.total_val /
0218 rtlpriv->stats.ui_link_quality.total_num;
0219 rtlpriv->stats.signal_quality = tmpval;
0220 rtlpriv->stats.last_sigstrength_inpercent = tmpval;
0221 for (n_stream = 0; n_stream < 2; n_stream++) {
0222 if (pstatus->rx_mimo_sig_qual[n_stream] != -1) {
0223 if (rtlpriv->stats.rx_evm_percentage[n_stream] == 0) {
0224 rtlpriv->stats.rx_evm_percentage[n_stream] =
0225 pstatus->rx_mimo_sig_qual[n_stream];
0226 }
0227 rtlpriv->stats.rx_evm_percentage[n_stream] =
0228 ((rtlpriv->stats.rx_evm_percentage[n_stream]
0229 * (RX_SMOOTH_FACTOR - 1)) +
0230 (pstatus->rx_mimo_sig_qual[n_stream] * 1)) /
0231 (RX_SMOOTH_FACTOR);
0232 }
0233 }
0234 }
0235
0236 void rtl_process_phyinfo(struct ieee80211_hw *hw, u8 *buffer,
0237 struct rtl_stats *pstatus)
0238 {
0239
0240 if (!pstatus->packet_matchbssid)
0241 return;
0242
0243 rtl_process_ui_rssi(hw, pstatus);
0244 rtl_process_pwdb(hw, pstatus);
0245 rtl_process_ui_link_quality(hw, pstatus);
0246 }
0247 EXPORT_SYMBOL(rtl_process_phyinfo);