Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /* Copyright(c) 2009-2012  Realtek Corporation.*/
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     /* adhoc or ap mode */
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);