1 /******************************************************************************
3 * Copyright(c) 2009-2012 Realtek Corporation.
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.
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
14 * The full GNU General Public License is included in this distribution in the
15 * file called LICENSE.
17 * Contact Information:
18 * wlanfae <wlanfae@realtek.com>
19 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
20 * Hsinchu 300, Taiwan.
22 * Larry Finger <Larry.Finger@lwfinger.net>
24 *****************************************************************************/
27 #include <linux/export.h>
29 u8
rtl_query_rxpwrpercentage(char antpower
)
31 if ((antpower
<= -100) || (antpower
>= 20))
33 else if (antpower
>= 0)
36 return 100 + antpower
;
38 EXPORT_SYMBOL(rtl_query_rxpwrpercentage
);
40 u8
rtl_evm_db_to_percentage(char value
)
49 ret_val
= 0 - ret_val
;
56 EXPORT_SYMBOL(rtl_evm_db_to_percentage
);
58 u8
rtl_evm_dbm_jaguar(char value
)
62 /* -33dB~0dB to 33dB ~ 0dB*/
66 ret_val
= 0 - ret_val
;
68 ret_val
= ret_val
>> 1;
71 EXPORT_SYMBOL(rtl_evm_dbm_jaguar
);
73 static long rtl_translate_todbm(struct ieee80211_hw
*hw
,
74 u8 signal_strength_index
)
78 signal_power
= (long)((signal_strength_index
+ 1) >> 1);
83 long rtl_signal_scale_mapping(struct ieee80211_hw
*hw
, long currsig
)
87 if (currsig
>= 61 && currsig
<= 100)
88 retsig
= 90 + ((currsig
- 60) / 4);
89 else if (currsig
>= 41 && currsig
<= 60)
90 retsig
= 78 + ((currsig
- 40) / 2);
91 else if (currsig
>= 31 && currsig
<= 40)
92 retsig
= 66 + (currsig
- 30);
93 else if (currsig
>= 21 && currsig
<= 30)
94 retsig
= 54 + (currsig
- 20);
95 else if (currsig
>= 5 && currsig
<= 20)
96 retsig
= 42 + (((currsig
- 5) * 2) / 3);
97 else if (currsig
== 4)
99 else if (currsig
== 3)
101 else if (currsig
== 2)
103 else if (currsig
== 1)
110 EXPORT_SYMBOL(rtl_signal_scale_mapping
);
112 static void rtl_process_ui_rssi(struct ieee80211_hw
*hw
,
113 struct rtl_stats
*pstatus
)
115 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
116 struct rtl_phy
*rtlphy
= &(rtlpriv
->phy
);
118 u32 last_rssi
, tmpval
;
120 if (!pstatus
->packet_toself
&& !pstatus
->packet_beacon
)
123 rtlpriv
->stats
.pwdb_all_cnt
+= pstatus
->rx_pwdb_all
;
124 rtlpriv
->stats
.rssi_calculate_cnt
++;
126 if (rtlpriv
->stats
.ui_rssi
.total_num
++ >= PHY_RSSI_SLID_WIN_MAX
) {
127 rtlpriv
->stats
.ui_rssi
.total_num
= PHY_RSSI_SLID_WIN_MAX
;
128 last_rssi
= rtlpriv
->stats
.ui_rssi
.elements
[
129 rtlpriv
->stats
.ui_rssi
.index
];
130 rtlpriv
->stats
.ui_rssi
.total_val
-= last_rssi
;
132 rtlpriv
->stats
.ui_rssi
.total_val
+= pstatus
->signalstrength
;
133 rtlpriv
->stats
.ui_rssi
.elements
[rtlpriv
->stats
.ui_rssi
.index
++] =
134 pstatus
->signalstrength
;
135 if (rtlpriv
->stats
.ui_rssi
.index
>= PHY_RSSI_SLID_WIN_MAX
)
136 rtlpriv
->stats
.ui_rssi
.index
= 0;
137 tmpval
= rtlpriv
->stats
.ui_rssi
.total_val
/
138 rtlpriv
->stats
.ui_rssi
.total_num
;
139 rtlpriv
->stats
.signal_strength
= rtl_translate_todbm(hw
,
141 pstatus
->rssi
= rtlpriv
->stats
.signal_strength
;
146 for (rfpath
= RF90_PATH_A
; rfpath
< rtlphy
->num_total_rfpath
;
148 if (rtlpriv
->stats
.rx_rssi_percentage
[rfpath
] == 0) {
149 rtlpriv
->stats
.rx_rssi_percentage
[rfpath
] =
150 pstatus
->rx_mimo_signalstrength
[rfpath
];
153 if (pstatus
->rx_mimo_signalstrength
[rfpath
] >
154 rtlpriv
->stats
.rx_rssi_percentage
[rfpath
]) {
155 rtlpriv
->stats
.rx_rssi_percentage
[rfpath
] =
156 ((rtlpriv
->stats
.rx_rssi_percentage
[rfpath
] *
157 (RX_SMOOTH_FACTOR
- 1)) +
158 (pstatus
->rx_mimo_signalstrength
[rfpath
])) /
160 rtlpriv
->stats
.rx_rssi_percentage
[rfpath
] =
161 rtlpriv
->stats
.rx_rssi_percentage
[rfpath
] + 1;
163 rtlpriv
->stats
.rx_rssi_percentage
[rfpath
] =
164 ((rtlpriv
->stats
.rx_rssi_percentage
[rfpath
] *
165 (RX_SMOOTH_FACTOR
- 1)) +
166 (pstatus
->rx_mimo_signalstrength
[rfpath
])) /
169 rtlpriv
->stats
.rx_snr_db
[rfpath
] = pstatus
->rx_snr
[rfpath
];
170 rtlpriv
->stats
.rx_evm_dbm
[rfpath
] =
171 pstatus
->rx_mimo_evm_dbm
[rfpath
];
172 rtlpriv
->stats
.rx_cfo_short
[rfpath
] =
173 pstatus
->cfo_short
[rfpath
];
174 rtlpriv
->stats
.rx_cfo_tail
[rfpath
] = pstatus
->cfo_tail
[rfpath
];
178 static void rtl_update_rxsignalstatistics(struct ieee80211_hw
*hw
,
179 struct rtl_stats
*pstatus
)
181 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
184 if (rtlpriv
->stats
.recv_signal_power
== 0)
185 rtlpriv
->stats
.recv_signal_power
= pstatus
->recvsignalpower
;
186 if (pstatus
->recvsignalpower
> rtlpriv
->stats
.recv_signal_power
)
188 else if (pstatus
->recvsignalpower
< rtlpriv
->stats
.recv_signal_power
)
190 rtlpriv
->stats
.recv_signal_power
= (rtlpriv
->stats
.recv_signal_power
*
191 5 + pstatus
->recvsignalpower
+ weighting
) / 6;
194 static void rtl_process_pwdb(struct ieee80211_hw
*hw
, struct rtl_stats
*pstatus
)
196 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
197 struct rtl_sta_info
*drv_priv
= NULL
;
198 struct ieee80211_sta
*sta
= NULL
;
202 if (rtlpriv
->mac80211
.opmode
!= NL80211_IFTYPE_STATION
)
203 sta
= rtl_find_sta(hw
, pstatus
->psaddr
);
205 /* adhoc or ap mode */
207 drv_priv
= (struct rtl_sta_info
*) sta
->drv_priv
;
208 undec_sm_pwdb
= drv_priv
->rssi_stat
.undec_sm_pwdb
;
210 undec_sm_pwdb
= rtlpriv
->dm
.undec_sm_pwdb
;
213 if (undec_sm_pwdb
< 0)
214 undec_sm_pwdb
= pstatus
->rx_pwdb_all
;
215 if (pstatus
->rx_pwdb_all
> (u32
) undec_sm_pwdb
) {
216 undec_sm_pwdb
= (((undec_sm_pwdb
) *
217 (RX_SMOOTH_FACTOR
- 1)) +
218 (pstatus
->rx_pwdb_all
)) / (RX_SMOOTH_FACTOR
);
219 undec_sm_pwdb
= undec_sm_pwdb
+ 1;
221 undec_sm_pwdb
= (((undec_sm_pwdb
) *
222 (RX_SMOOTH_FACTOR
- 1)) +
223 (pstatus
->rx_pwdb_all
)) / (RX_SMOOTH_FACTOR
);
227 drv_priv
->rssi_stat
.undec_sm_pwdb
= undec_sm_pwdb
;
229 rtlpriv
->dm
.undec_sm_pwdb
= undec_sm_pwdb
;
233 rtl_update_rxsignalstatistics(hw
, pstatus
);
236 static void rtl_process_ui_link_quality(struct ieee80211_hw
*hw
,
237 struct rtl_stats
*pstatus
)
239 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
240 u32 last_evm
, n_stream
, tmpval
;
242 if (pstatus
->signalquality
== 0)
245 if (rtlpriv
->stats
.ui_link_quality
.total_num
++ >=
246 PHY_LINKQUALITY_SLID_WIN_MAX
) {
247 rtlpriv
->stats
.ui_link_quality
.total_num
=
248 PHY_LINKQUALITY_SLID_WIN_MAX
;
249 last_evm
= rtlpriv
->stats
.ui_link_quality
.elements
[
250 rtlpriv
->stats
.ui_link_quality
.index
];
251 rtlpriv
->stats
.ui_link_quality
.total_val
-= last_evm
;
253 rtlpriv
->stats
.ui_link_quality
.total_val
+= pstatus
->signalquality
;
254 rtlpriv
->stats
.ui_link_quality
.elements
[
255 rtlpriv
->stats
.ui_link_quality
.index
++] =
256 pstatus
->signalquality
;
257 if (rtlpriv
->stats
.ui_link_quality
.index
>=
258 PHY_LINKQUALITY_SLID_WIN_MAX
)
259 rtlpriv
->stats
.ui_link_quality
.index
= 0;
260 tmpval
= rtlpriv
->stats
.ui_link_quality
.total_val
/
261 rtlpriv
->stats
.ui_link_quality
.total_num
;
262 rtlpriv
->stats
.signal_quality
= tmpval
;
263 rtlpriv
->stats
.last_sigstrength_inpercent
= tmpval
;
264 for (n_stream
= 0; n_stream
< 2; n_stream
++) {
265 if (pstatus
->rx_mimo_sig_qual
[n_stream
] != -1) {
266 if (rtlpriv
->stats
.rx_evm_percentage
[n_stream
] == 0) {
267 rtlpriv
->stats
.rx_evm_percentage
[n_stream
] =
268 pstatus
->rx_mimo_sig_qual
[n_stream
];
270 rtlpriv
->stats
.rx_evm_percentage
[n_stream
] =
271 ((rtlpriv
->stats
.rx_evm_percentage
[n_stream
]
272 * (RX_SMOOTH_FACTOR
- 1)) +
273 (pstatus
->rx_mimo_sig_qual
[n_stream
] * 1)) /
279 void rtl_process_phyinfo(struct ieee80211_hw
*hw
, u8
*buffer
,
280 struct rtl_stats
*pstatus
)
283 if (!pstatus
->packet_matchbssid
)
286 rtl_process_ui_rssi(hw
, pstatus
);
287 rtl_process_pwdb(hw
, pstatus
);
288 rtl_process_ui_link_quality(hw
, pstatus
);
290 EXPORT_SYMBOL(rtl_process_phyinfo
);