xref: /linux/drivers/net/wireless/realtek/rtlwifi/rtl8192d/trx_common.c (revision a1ff5a7d78a036d6c2178ee5acd6ba4946243800)
1db5ae2e1SBitterblue Smith // SPDX-License-Identifier: GPL-2.0
2db5ae2e1SBitterblue Smith /* Copyright(c) 2009-2012  Realtek Corporation.*/
3db5ae2e1SBitterblue Smith 
4db5ae2e1SBitterblue Smith #include "../wifi.h"
5db5ae2e1SBitterblue Smith #include "../base.h"
6db5ae2e1SBitterblue Smith #include "../stats.h"
7db5ae2e1SBitterblue Smith #include "def.h"
8db5ae2e1SBitterblue Smith #include "trx_common.h"
9db5ae2e1SBitterblue Smith 
_rtl92d_translate_todbm(struct ieee80211_hw * hw,u8 signal_strength_index)10*b21faf0eSBitterblue Smith static long _rtl92d_translate_todbm(struct ieee80211_hw *hw,
11db5ae2e1SBitterblue Smith 				    u8 signal_strength_index)
12db5ae2e1SBitterblue Smith {
13db5ae2e1SBitterblue Smith 	long signal_power;
14db5ae2e1SBitterblue Smith 
15db5ae2e1SBitterblue Smith 	signal_power = (long)((signal_strength_index + 1) >> 1);
16db5ae2e1SBitterblue Smith 	signal_power -= 95;
17db5ae2e1SBitterblue Smith 	return signal_power;
18db5ae2e1SBitterblue Smith }
19db5ae2e1SBitterblue Smith 
_rtl92d_query_rxphystatus(struct ieee80211_hw * hw,struct rtl_stats * pstats,__le32 * pdesc,struct rx_fwinfo_92d * p_drvinfo,bool packet_match_bssid,bool packet_toself,bool packet_beacon)20*b21faf0eSBitterblue Smith static void _rtl92d_query_rxphystatus(struct ieee80211_hw *hw,
21db5ae2e1SBitterblue Smith 				      struct rtl_stats *pstats,
22db5ae2e1SBitterblue Smith 				      __le32 *pdesc,
23db5ae2e1SBitterblue Smith 				      struct rx_fwinfo_92d *p_drvinfo,
24db5ae2e1SBitterblue Smith 				      bool packet_match_bssid,
25db5ae2e1SBitterblue Smith 				      bool packet_toself,
26db5ae2e1SBitterblue Smith 				      bool packet_beacon)
27db5ae2e1SBitterblue Smith {
28db5ae2e1SBitterblue Smith 	struct rtl_priv *rtlpriv = rtl_priv(hw);
29db5ae2e1SBitterblue Smith 	struct rtl_phy *rtlphy = &rtlpriv->phy;
30db5ae2e1SBitterblue Smith 	struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv);
31db5ae2e1SBitterblue Smith 	struct phy_sts_cck_8192d *cck_buf;
32db5ae2e1SBitterblue Smith 	s8 rx_pwr_all, rx_pwr[4];
33db5ae2e1SBitterblue Smith 	u8 rf_rx_num = 0, evm, pwdb_all;
34db5ae2e1SBitterblue Smith 	u8 i, max_spatial_stream;
35db5ae2e1SBitterblue Smith 	u32 rssi, total_rssi = 0;
36db5ae2e1SBitterblue Smith 	bool is_cck_rate;
37db5ae2e1SBitterblue Smith 	u8 rxmcs;
38db5ae2e1SBitterblue Smith 
39db5ae2e1SBitterblue Smith 	rxmcs = get_rx_desc_rxmcs(pdesc);
40db5ae2e1SBitterblue Smith 	is_cck_rate = rxmcs <= DESC_RATE11M;
41db5ae2e1SBitterblue Smith 	pstats->packet_matchbssid = packet_match_bssid;
42db5ae2e1SBitterblue Smith 	pstats->packet_toself = packet_toself;
43db5ae2e1SBitterblue Smith 	pstats->packet_beacon = packet_beacon;
44db5ae2e1SBitterblue Smith 	pstats->is_cck = is_cck_rate;
45db5ae2e1SBitterblue Smith 	pstats->rx_mimo_sig_qual[0] = -1;
46db5ae2e1SBitterblue Smith 	pstats->rx_mimo_sig_qual[1] = -1;
47db5ae2e1SBitterblue Smith 
48db5ae2e1SBitterblue Smith 	if (is_cck_rate) {
49db5ae2e1SBitterblue Smith 		u8 report, cck_highpwr;
50db5ae2e1SBitterblue Smith 
51db5ae2e1SBitterblue Smith 		cck_buf = (struct phy_sts_cck_8192d *)p_drvinfo;
52db5ae2e1SBitterblue Smith 		if (ppsc->rfpwr_state == ERFON)
53db5ae2e1SBitterblue Smith 			cck_highpwr = rtlphy->cck_high_power;
54db5ae2e1SBitterblue Smith 		else
55db5ae2e1SBitterblue Smith 			cck_highpwr = false;
56db5ae2e1SBitterblue Smith 		if (!cck_highpwr) {
57db5ae2e1SBitterblue Smith 			u8 cck_agc_rpt = cck_buf->cck_agc_rpt;
58db5ae2e1SBitterblue Smith 
59db5ae2e1SBitterblue Smith 			report = cck_buf->cck_agc_rpt & 0xc0;
60db5ae2e1SBitterblue Smith 			report = report >> 6;
61db5ae2e1SBitterblue Smith 			switch (report) {
62db5ae2e1SBitterblue Smith 			case 0x3:
63db5ae2e1SBitterblue Smith 				rx_pwr_all = -46 - (cck_agc_rpt & 0x3e);
64db5ae2e1SBitterblue Smith 				break;
65db5ae2e1SBitterblue Smith 			case 0x2:
66db5ae2e1SBitterblue Smith 				rx_pwr_all = -26 - (cck_agc_rpt & 0x3e);
67db5ae2e1SBitterblue Smith 				break;
68db5ae2e1SBitterblue Smith 			case 0x1:
69db5ae2e1SBitterblue Smith 				rx_pwr_all = -12 - (cck_agc_rpt & 0x3e);
70db5ae2e1SBitterblue Smith 				break;
71db5ae2e1SBitterblue Smith 			case 0x0:
72db5ae2e1SBitterblue Smith 				rx_pwr_all = 16 - (cck_agc_rpt & 0x3e);
73db5ae2e1SBitterblue Smith 				break;
74db5ae2e1SBitterblue Smith 			}
75db5ae2e1SBitterblue Smith 		} else {
76db5ae2e1SBitterblue Smith 			u8 cck_agc_rpt = cck_buf->cck_agc_rpt;
77db5ae2e1SBitterblue Smith 
78db5ae2e1SBitterblue Smith 			report = p_drvinfo->cfosho[0] & 0x60;
79db5ae2e1SBitterblue Smith 			report = report >> 5;
80db5ae2e1SBitterblue Smith 			switch (report) {
81db5ae2e1SBitterblue Smith 			case 0x3:
82db5ae2e1SBitterblue Smith 				rx_pwr_all = -46 - ((cck_agc_rpt & 0x1f) << 1);
83db5ae2e1SBitterblue Smith 				break;
84db5ae2e1SBitterblue Smith 			case 0x2:
85db5ae2e1SBitterblue Smith 				rx_pwr_all = -26 - ((cck_agc_rpt & 0x1f) << 1);
86db5ae2e1SBitterblue Smith 				break;
87db5ae2e1SBitterblue Smith 			case 0x1:
88db5ae2e1SBitterblue Smith 				rx_pwr_all = -12 - ((cck_agc_rpt & 0x1f) << 1);
89db5ae2e1SBitterblue Smith 				break;
90db5ae2e1SBitterblue Smith 			case 0x0:
91db5ae2e1SBitterblue Smith 				rx_pwr_all = 16 - ((cck_agc_rpt & 0x1f) << 1);
92db5ae2e1SBitterblue Smith 				break;
93db5ae2e1SBitterblue Smith 			}
94db5ae2e1SBitterblue Smith 		}
95db5ae2e1SBitterblue Smith 		pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all);
96db5ae2e1SBitterblue Smith 		/* CCK gain is smaller than OFDM/MCS gain,  */
97db5ae2e1SBitterblue Smith 		/* so we add gain diff by experiences, the val is 6 */
98db5ae2e1SBitterblue Smith 		pwdb_all += 6;
99db5ae2e1SBitterblue Smith 		if (pwdb_all > 100)
100db5ae2e1SBitterblue Smith 			pwdb_all = 100;
101db5ae2e1SBitterblue Smith 		/* modify the offset to make the same gain index with OFDM. */
102db5ae2e1SBitterblue Smith 		if (pwdb_all > 34 && pwdb_all <= 42)
103db5ae2e1SBitterblue Smith 			pwdb_all -= 2;
104db5ae2e1SBitterblue Smith 		else if (pwdb_all > 26 && pwdb_all <= 34)
105db5ae2e1SBitterblue Smith 			pwdb_all -= 6;
106db5ae2e1SBitterblue Smith 		else if (pwdb_all > 14 && pwdb_all <= 26)
107db5ae2e1SBitterblue Smith 			pwdb_all -= 8;
108db5ae2e1SBitterblue Smith 		else if (pwdb_all > 4 && pwdb_all <= 14)
109db5ae2e1SBitterblue Smith 			pwdb_all -= 4;
110db5ae2e1SBitterblue Smith 		pstats->rx_pwdb_all = pwdb_all;
111db5ae2e1SBitterblue Smith 		pstats->recvsignalpower = rx_pwr_all;
112db5ae2e1SBitterblue Smith 		if (packet_match_bssid) {
113db5ae2e1SBitterblue Smith 			u8 sq;
114db5ae2e1SBitterblue Smith 
115db5ae2e1SBitterblue Smith 			if (pstats->rx_pwdb_all > 40) {
116db5ae2e1SBitterblue Smith 				sq = 100;
117db5ae2e1SBitterblue Smith 			} else {
118db5ae2e1SBitterblue Smith 				sq = cck_buf->sq_rpt;
119db5ae2e1SBitterblue Smith 				if (sq > 64)
120db5ae2e1SBitterblue Smith 					sq = 0;
121db5ae2e1SBitterblue Smith 				else if (sq < 20)
122db5ae2e1SBitterblue Smith 					sq = 100;
123db5ae2e1SBitterblue Smith 				else
124db5ae2e1SBitterblue Smith 					sq = ((64 - sq) * 100) / 44;
125db5ae2e1SBitterblue Smith 			}
126db5ae2e1SBitterblue Smith 			pstats->signalquality = sq;
127db5ae2e1SBitterblue Smith 			pstats->rx_mimo_sig_qual[0] = sq;
128db5ae2e1SBitterblue Smith 			pstats->rx_mimo_sig_qual[1] = -1;
129db5ae2e1SBitterblue Smith 		}
130db5ae2e1SBitterblue Smith 	} else {
131db5ae2e1SBitterblue Smith 		rtlpriv->dm.rfpath_rxenable[0] = true;
132db5ae2e1SBitterblue Smith 		rtlpriv->dm.rfpath_rxenable[1] = true;
133db5ae2e1SBitterblue Smith 		for (i = RF90_PATH_A; i < RF6052_MAX_PATH; i++) {
134db5ae2e1SBitterblue Smith 			if (rtlpriv->dm.rfpath_rxenable[i])
135db5ae2e1SBitterblue Smith 				rf_rx_num++;
136db5ae2e1SBitterblue Smith 			rx_pwr[i] = ((p_drvinfo->gain_trsw[i] & 0x3f) * 2)
137db5ae2e1SBitterblue Smith 				    - 110;
138db5ae2e1SBitterblue Smith 			rssi = rtl_query_rxpwrpercentage(rx_pwr[i]);
139db5ae2e1SBitterblue Smith 			total_rssi += rssi;
140db5ae2e1SBitterblue Smith 			rtlpriv->stats.rx_snr_db[i] =
141db5ae2e1SBitterblue Smith 					 (long)(p_drvinfo->rxsnr[i] / 2);
142db5ae2e1SBitterblue Smith 			if (packet_match_bssid)
143db5ae2e1SBitterblue Smith 				pstats->rx_mimo_signalstrength[i] = (u8)rssi;
144db5ae2e1SBitterblue Smith 		}
145db5ae2e1SBitterblue Smith 		rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 106;
146db5ae2e1SBitterblue Smith 		pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all);
147db5ae2e1SBitterblue Smith 		pstats->rx_pwdb_all = pwdb_all;
148db5ae2e1SBitterblue Smith 		pstats->rxpower = rx_pwr_all;
149db5ae2e1SBitterblue Smith 		pstats->recvsignalpower = rx_pwr_all;
150db5ae2e1SBitterblue Smith 		if (get_rx_desc_rxht(pdesc) && rxmcs >= DESC_RATEMCS8 &&
151db5ae2e1SBitterblue Smith 		    rxmcs <= DESC_RATEMCS15)
152db5ae2e1SBitterblue Smith 			max_spatial_stream = 2;
153db5ae2e1SBitterblue Smith 		else
154db5ae2e1SBitterblue Smith 			max_spatial_stream = 1;
155db5ae2e1SBitterblue Smith 		for (i = 0; i < max_spatial_stream; i++) {
156db5ae2e1SBitterblue Smith 			evm = rtl_evm_db_to_percentage(p_drvinfo->rxevm[i]);
157db5ae2e1SBitterblue Smith 			if (packet_match_bssid) {
158db5ae2e1SBitterblue Smith 				if (i == 0)
159db5ae2e1SBitterblue Smith 					pstats->signalquality =
160db5ae2e1SBitterblue Smith 						 (u8)(evm & 0xff);
161db5ae2e1SBitterblue Smith 				pstats->rx_mimo_sig_qual[i] =
162db5ae2e1SBitterblue Smith 						 (u8)(evm & 0xff);
163db5ae2e1SBitterblue Smith 			}
164db5ae2e1SBitterblue Smith 		}
165db5ae2e1SBitterblue Smith 	}
166db5ae2e1SBitterblue Smith 	if (is_cck_rate)
167db5ae2e1SBitterblue Smith 		pstats->signalstrength = (u8)(rtl_signal_scale_mapping(hw,
168db5ae2e1SBitterblue Smith 				pwdb_all));
169db5ae2e1SBitterblue Smith 	else if (rf_rx_num != 0)
170db5ae2e1SBitterblue Smith 		pstats->signalstrength = (u8)(rtl_signal_scale_mapping(hw,
171db5ae2e1SBitterblue Smith 				total_rssi /= rf_rx_num));
172db5ae2e1SBitterblue Smith }
173db5ae2e1SBitterblue Smith 
rtl92d_loop_over_paths(struct ieee80211_hw * hw,struct rtl_stats * pstats)174db5ae2e1SBitterblue Smith static void rtl92d_loop_over_paths(struct ieee80211_hw *hw,
175db5ae2e1SBitterblue Smith 				   struct rtl_stats *pstats)
176db5ae2e1SBitterblue Smith {
177db5ae2e1SBitterblue Smith 	struct rtl_priv *rtlpriv = rtl_priv(hw);
178db5ae2e1SBitterblue Smith 	struct rtl_phy *rtlphy = &rtlpriv->phy;
179db5ae2e1SBitterblue Smith 	u8 rfpath;
180db5ae2e1SBitterblue Smith 
181db5ae2e1SBitterblue Smith 	for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath;
182db5ae2e1SBitterblue Smith 	     rfpath++) {
183db5ae2e1SBitterblue Smith 		if (rtlpriv->stats.rx_rssi_percentage[rfpath] == 0) {
184db5ae2e1SBitterblue Smith 			rtlpriv->stats.rx_rssi_percentage[rfpath] =
185db5ae2e1SBitterblue Smith 			    pstats->rx_mimo_signalstrength[rfpath];
186db5ae2e1SBitterblue Smith 		}
187db5ae2e1SBitterblue Smith 		if (pstats->rx_mimo_signalstrength[rfpath] >
188db5ae2e1SBitterblue Smith 		    rtlpriv->stats.rx_rssi_percentage[rfpath]) {
189db5ae2e1SBitterblue Smith 			rtlpriv->stats.rx_rssi_percentage[rfpath] =
190db5ae2e1SBitterblue Smith 			    ((rtlpriv->stats.rx_rssi_percentage[rfpath] *
191db5ae2e1SBitterblue Smith 			      (RX_SMOOTH_FACTOR - 1)) +
192db5ae2e1SBitterblue Smith 			     (pstats->rx_mimo_signalstrength[rfpath])) /
193db5ae2e1SBitterblue Smith 			    (RX_SMOOTH_FACTOR);
194db5ae2e1SBitterblue Smith 			rtlpriv->stats.rx_rssi_percentage[rfpath] =
195db5ae2e1SBitterblue Smith 			    rtlpriv->stats.rx_rssi_percentage[rfpath] + 1;
196db5ae2e1SBitterblue Smith 		} else {
197db5ae2e1SBitterblue Smith 			rtlpriv->stats.rx_rssi_percentage[rfpath] =
198db5ae2e1SBitterblue Smith 			    ((rtlpriv->stats.rx_rssi_percentage[rfpath] *
199db5ae2e1SBitterblue Smith 			      (RX_SMOOTH_FACTOR - 1)) +
200db5ae2e1SBitterblue Smith 			     (pstats->rx_mimo_signalstrength[rfpath])) /
201db5ae2e1SBitterblue Smith 			    (RX_SMOOTH_FACTOR);
202db5ae2e1SBitterblue Smith 		}
203db5ae2e1SBitterblue Smith 	}
204db5ae2e1SBitterblue Smith }
205db5ae2e1SBitterblue Smith 
_rtl92d_process_ui_rssi(struct ieee80211_hw * hw,struct rtl_stats * pstats)206*b21faf0eSBitterblue Smith static void _rtl92d_process_ui_rssi(struct ieee80211_hw *hw,
207db5ae2e1SBitterblue Smith 				    struct rtl_stats *pstats)
208db5ae2e1SBitterblue Smith {
209db5ae2e1SBitterblue Smith 	struct rtl_priv *rtlpriv = rtl_priv(hw);
210db5ae2e1SBitterblue Smith 	struct rt_smooth_data *ui_rssi;
211db5ae2e1SBitterblue Smith 	u32 last_rssi, tmpval;
212db5ae2e1SBitterblue Smith 
213db5ae2e1SBitterblue Smith 	if (!pstats->packet_toself && !pstats->packet_beacon)
214db5ae2e1SBitterblue Smith 		return;
215db5ae2e1SBitterblue Smith 
216db5ae2e1SBitterblue Smith 	ui_rssi = &rtlpriv->stats.ui_rssi;
217db5ae2e1SBitterblue Smith 
218db5ae2e1SBitterblue Smith 	rtlpriv->stats.rssi_calculate_cnt++;
219db5ae2e1SBitterblue Smith 	if (ui_rssi->total_num++ >= PHY_RSSI_SLID_WIN_MAX) {
220db5ae2e1SBitterblue Smith 		ui_rssi->total_num = PHY_RSSI_SLID_WIN_MAX;
221db5ae2e1SBitterblue Smith 		last_rssi = ui_rssi->elements[ui_rssi->index];
222db5ae2e1SBitterblue Smith 		ui_rssi->total_val -= last_rssi;
223db5ae2e1SBitterblue Smith 	}
224db5ae2e1SBitterblue Smith 	ui_rssi->total_val += pstats->signalstrength;
225db5ae2e1SBitterblue Smith 	ui_rssi->elements[ui_rssi->index++] = pstats->signalstrength;
226db5ae2e1SBitterblue Smith 	if (ui_rssi->index >= PHY_RSSI_SLID_WIN_MAX)
227db5ae2e1SBitterblue Smith 		ui_rssi->index = 0;
228db5ae2e1SBitterblue Smith 	tmpval = ui_rssi->total_val / ui_rssi->total_num;
229*b21faf0eSBitterblue Smith 	rtlpriv->stats.signal_strength = _rtl92d_translate_todbm(hw, (u8)tmpval);
230db5ae2e1SBitterblue Smith 	pstats->rssi = rtlpriv->stats.signal_strength;
231db5ae2e1SBitterblue Smith 
232db5ae2e1SBitterblue Smith 	if (!pstats->is_cck && pstats->packet_toself)
233db5ae2e1SBitterblue Smith 		rtl92d_loop_over_paths(hw, pstats);
234db5ae2e1SBitterblue Smith }
235db5ae2e1SBitterblue Smith 
_rtl92d_update_rxsignalstatistics(struct ieee80211_hw * hw,struct rtl_stats * pstats)236*b21faf0eSBitterblue Smith static void _rtl92d_update_rxsignalstatistics(struct ieee80211_hw *hw,
237db5ae2e1SBitterblue Smith 					      struct rtl_stats *pstats)
238db5ae2e1SBitterblue Smith {
239db5ae2e1SBitterblue Smith 	struct rtl_priv *rtlpriv = rtl_priv(hw);
240db5ae2e1SBitterblue Smith 	int weighting = 0;
241db5ae2e1SBitterblue Smith 
242db5ae2e1SBitterblue Smith 	if (rtlpriv->stats.recv_signal_power == 0)
243db5ae2e1SBitterblue Smith 		rtlpriv->stats.recv_signal_power = pstats->recvsignalpower;
244db5ae2e1SBitterblue Smith 	if (pstats->recvsignalpower > rtlpriv->stats.recv_signal_power)
245db5ae2e1SBitterblue Smith 		weighting = 5;
246db5ae2e1SBitterblue Smith 	else if (pstats->recvsignalpower < rtlpriv->stats.recv_signal_power)
247db5ae2e1SBitterblue Smith 		weighting = (-5);
248db5ae2e1SBitterblue Smith 	rtlpriv->stats.recv_signal_power = (rtlpriv->stats.recv_signal_power *
249db5ae2e1SBitterblue Smith 		5 + pstats->recvsignalpower + weighting) / 6;
250db5ae2e1SBitterblue Smith }
251db5ae2e1SBitterblue Smith 
_rtl92d_process_pwdb(struct ieee80211_hw * hw,struct rtl_stats * pstats)252*b21faf0eSBitterblue Smith static void _rtl92d_process_pwdb(struct ieee80211_hw *hw,
253db5ae2e1SBitterblue Smith 				 struct rtl_stats *pstats)
254db5ae2e1SBitterblue Smith {
255db5ae2e1SBitterblue Smith 	struct rtl_priv *rtlpriv = rtl_priv(hw);
256db5ae2e1SBitterblue Smith 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
257db5ae2e1SBitterblue Smith 	long undec_sm_pwdb;
258db5ae2e1SBitterblue Smith 
259db5ae2e1SBitterblue Smith 	if (mac->opmode == NL80211_IFTYPE_ADHOC	||
260db5ae2e1SBitterblue Smith 	    mac->opmode == NL80211_IFTYPE_AP)
261db5ae2e1SBitterblue Smith 		return;
262db5ae2e1SBitterblue Smith 
263db5ae2e1SBitterblue Smith 	undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb;
264db5ae2e1SBitterblue Smith 
265db5ae2e1SBitterblue Smith 	if (pstats->packet_toself || pstats->packet_beacon) {
266db5ae2e1SBitterblue Smith 		if (undec_sm_pwdb < 0)
267db5ae2e1SBitterblue Smith 			undec_sm_pwdb = pstats->rx_pwdb_all;
268db5ae2e1SBitterblue Smith 		if (pstats->rx_pwdb_all > (u32)undec_sm_pwdb) {
269db5ae2e1SBitterblue Smith 			undec_sm_pwdb = (((undec_sm_pwdb) *
270db5ae2e1SBitterblue Smith 			      (RX_SMOOTH_FACTOR - 1)) +
271db5ae2e1SBitterblue Smith 			      (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
272db5ae2e1SBitterblue Smith 			undec_sm_pwdb = undec_sm_pwdb + 1;
273db5ae2e1SBitterblue Smith 		} else {
274db5ae2e1SBitterblue Smith 			undec_sm_pwdb = (((undec_sm_pwdb) *
275db5ae2e1SBitterblue Smith 			      (RX_SMOOTH_FACTOR - 1)) +
276db5ae2e1SBitterblue Smith 			      (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
277db5ae2e1SBitterblue Smith 		}
278db5ae2e1SBitterblue Smith 		rtlpriv->dm.undec_sm_pwdb = undec_sm_pwdb;
279*b21faf0eSBitterblue Smith 		_rtl92d_update_rxsignalstatistics(hw, pstats);
280db5ae2e1SBitterblue Smith 	}
281db5ae2e1SBitterblue Smith }
282db5ae2e1SBitterblue Smith 
rtl92d_loop_over_streams(struct ieee80211_hw * hw,struct rtl_stats * pstats)283db5ae2e1SBitterblue Smith static void rtl92d_loop_over_streams(struct ieee80211_hw *hw,
284db5ae2e1SBitterblue Smith 				     struct rtl_stats *pstats)
285db5ae2e1SBitterblue Smith {
286db5ae2e1SBitterblue Smith 	struct rtl_priv *rtlpriv = rtl_priv(hw);
287db5ae2e1SBitterblue Smith 	int stream;
288db5ae2e1SBitterblue Smith 
289db5ae2e1SBitterblue Smith 	for (stream = 0; stream < 2; stream++) {
290db5ae2e1SBitterblue Smith 		if (pstats->rx_mimo_sig_qual[stream] != -1) {
291db5ae2e1SBitterblue Smith 			if (rtlpriv->stats.rx_evm_percentage[stream] == 0) {
292db5ae2e1SBitterblue Smith 				rtlpriv->stats.rx_evm_percentage[stream] =
293db5ae2e1SBitterblue Smith 				    pstats->rx_mimo_sig_qual[stream];
294db5ae2e1SBitterblue Smith 			}
295db5ae2e1SBitterblue Smith 			rtlpriv->stats.rx_evm_percentage[stream] =
296db5ae2e1SBitterblue Smith 			    ((rtlpriv->stats.rx_evm_percentage[stream]
297db5ae2e1SBitterblue Smith 			      * (RX_SMOOTH_FACTOR - 1)) +
298db5ae2e1SBitterblue Smith 			     (pstats->rx_mimo_sig_qual[stream] * 1)) /
299db5ae2e1SBitterblue Smith 			    (RX_SMOOTH_FACTOR);
300db5ae2e1SBitterblue Smith 		}
301db5ae2e1SBitterblue Smith 	}
302db5ae2e1SBitterblue Smith }
303db5ae2e1SBitterblue Smith 
_rtl92d_process_ui_link_quality(struct ieee80211_hw * hw,struct rtl_stats * pstats)304*b21faf0eSBitterblue Smith static void _rtl92d_process_ui_link_quality(struct ieee80211_hw *hw,
305db5ae2e1SBitterblue Smith 					    struct rtl_stats *pstats)
306db5ae2e1SBitterblue Smith {
307db5ae2e1SBitterblue Smith 	struct rtl_priv *rtlpriv = rtl_priv(hw);
308db5ae2e1SBitterblue Smith 	struct rt_smooth_data *ui_link_quality;
309db5ae2e1SBitterblue Smith 	u32 last_evm, tmpval;
310db5ae2e1SBitterblue Smith 
311db5ae2e1SBitterblue Smith 	if (pstats->signalquality == 0)
312db5ae2e1SBitterblue Smith 		return;
313db5ae2e1SBitterblue Smith 	if (!pstats->packet_toself && !pstats->packet_beacon)
314db5ae2e1SBitterblue Smith 		return;
315db5ae2e1SBitterblue Smith 
316db5ae2e1SBitterblue Smith 	ui_link_quality = &rtlpriv->stats.ui_link_quality;
317db5ae2e1SBitterblue Smith 
318db5ae2e1SBitterblue Smith 	if (ui_link_quality->total_num++ >= PHY_LINKQUALITY_SLID_WIN_MAX) {
319db5ae2e1SBitterblue Smith 		ui_link_quality->total_num = PHY_LINKQUALITY_SLID_WIN_MAX;
320db5ae2e1SBitterblue Smith 		last_evm = ui_link_quality->elements[ui_link_quality->index];
321db5ae2e1SBitterblue Smith 		ui_link_quality->total_val -= last_evm;
322db5ae2e1SBitterblue Smith 	}
323db5ae2e1SBitterblue Smith 	ui_link_quality->total_val += pstats->signalquality;
324db5ae2e1SBitterblue Smith 	ui_link_quality->elements[ui_link_quality->index++] = pstats->signalquality;
325db5ae2e1SBitterblue Smith 	if (ui_link_quality->index >= PHY_LINKQUALITY_SLID_WIN_MAX)
326db5ae2e1SBitterblue Smith 		ui_link_quality->index = 0;
327db5ae2e1SBitterblue Smith 	tmpval = ui_link_quality->total_val / ui_link_quality->total_num;
328db5ae2e1SBitterblue Smith 	rtlpriv->stats.signal_quality = tmpval;
329db5ae2e1SBitterblue Smith 	rtlpriv->stats.last_sigstrength_inpercent = tmpval;
330db5ae2e1SBitterblue Smith 	rtl92d_loop_over_streams(hw, pstats);
331db5ae2e1SBitterblue Smith }
332db5ae2e1SBitterblue Smith 
_rtl92d_process_phyinfo(struct ieee80211_hw * hw,u8 * buffer,struct rtl_stats * pcurrent_stats)333*b21faf0eSBitterblue Smith static void _rtl92d_process_phyinfo(struct ieee80211_hw *hw,
334db5ae2e1SBitterblue Smith 				    u8 *buffer,
335db5ae2e1SBitterblue Smith 				    struct rtl_stats *pcurrent_stats)
336db5ae2e1SBitterblue Smith {
337db5ae2e1SBitterblue Smith 	if (!pcurrent_stats->packet_matchbssid &&
338db5ae2e1SBitterblue Smith 	    !pcurrent_stats->packet_beacon)
339db5ae2e1SBitterblue Smith 		return;
340db5ae2e1SBitterblue Smith 
341*b21faf0eSBitterblue Smith 	_rtl92d_process_ui_rssi(hw, pcurrent_stats);
342*b21faf0eSBitterblue Smith 	_rtl92d_process_pwdb(hw, pcurrent_stats);
343*b21faf0eSBitterblue Smith 	_rtl92d_process_ui_link_quality(hw, pcurrent_stats);
344db5ae2e1SBitterblue Smith }
345db5ae2e1SBitterblue Smith 
_rtl92d_translate_rx_signal_stuff(struct ieee80211_hw * hw,struct sk_buff * skb,struct rtl_stats * pstats,__le32 * pdesc,struct rx_fwinfo_92d * p_drvinfo)346*b21faf0eSBitterblue Smith static void _rtl92d_translate_rx_signal_stuff(struct ieee80211_hw *hw,
347db5ae2e1SBitterblue Smith 					      struct sk_buff *skb,
348db5ae2e1SBitterblue Smith 					      struct rtl_stats *pstats,
349db5ae2e1SBitterblue Smith 					      __le32 *pdesc,
350db5ae2e1SBitterblue Smith 					      struct rx_fwinfo_92d *p_drvinfo)
351db5ae2e1SBitterblue Smith {
352db5ae2e1SBitterblue Smith 	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
353d75589a0SBitterblue Smith 	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
354db5ae2e1SBitterblue Smith 	struct ieee80211_hdr *hdr;
355d75589a0SBitterblue Smith 	bool packet_matchbssid;
356d75589a0SBitterblue Smith 	bool packet_beacon;
357d75589a0SBitterblue Smith 	bool packet_toself;
358d75589a0SBitterblue Smith 	u16 type, cfc;
359db5ae2e1SBitterblue Smith 	u8 *tmp_buf;
360db5ae2e1SBitterblue Smith 	u8 *praddr;
361db5ae2e1SBitterblue Smith 	__le16 fc;
362db5ae2e1SBitterblue Smith 
363db5ae2e1SBitterblue Smith 	tmp_buf = skb->data + pstats->rx_drvinfo_size + pstats->rx_bufshift;
364db5ae2e1SBitterblue Smith 	hdr = (struct ieee80211_hdr *)tmp_buf;
365db5ae2e1SBitterblue Smith 	fc = hdr->frame_control;
366db5ae2e1SBitterblue Smith 	cfc = le16_to_cpu(fc);
367db5ae2e1SBitterblue Smith 	type = WLAN_FC_GET_TYPE(fc);
368db5ae2e1SBitterblue Smith 	praddr = hdr->addr1;
369db5ae2e1SBitterblue Smith 	packet_matchbssid = ((type != IEEE80211_FTYPE_CTL) &&
370db5ae2e1SBitterblue Smith 	     ether_addr_equal(mac->bssid,
371db5ae2e1SBitterblue Smith 			      (cfc & IEEE80211_FCTL_TODS) ? hdr->addr1 :
372db5ae2e1SBitterblue Smith 			      (cfc & IEEE80211_FCTL_FROMDS) ? hdr->addr2 :
373db5ae2e1SBitterblue Smith 			      hdr->addr3) &&
374db5ae2e1SBitterblue Smith 	     (!pstats->hwerror) && (!pstats->crc) && (!pstats->icv));
375db5ae2e1SBitterblue Smith 	packet_toself = packet_matchbssid &&
376db5ae2e1SBitterblue Smith 			ether_addr_equal(praddr, rtlefuse->dev_addr);
377d75589a0SBitterblue Smith 	packet_beacon = ieee80211_is_beacon(fc);
378*b21faf0eSBitterblue Smith 	_rtl92d_query_rxphystatus(hw, pstats, pdesc, p_drvinfo,
379db5ae2e1SBitterblue Smith 				  packet_matchbssid, packet_toself,
380db5ae2e1SBitterblue Smith 				  packet_beacon);
381*b21faf0eSBitterblue Smith 	_rtl92d_process_phyinfo(hw, tmp_buf, pstats);
382db5ae2e1SBitterblue Smith }
383db5ae2e1SBitterblue Smith 
rtl92d_rx_query_desc(struct ieee80211_hw * hw,struct rtl_stats * stats,struct ieee80211_rx_status * rx_status,u8 * pdesc8,struct sk_buff * skb)384*b21faf0eSBitterblue Smith bool rtl92d_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats,
385db5ae2e1SBitterblue Smith 			  struct ieee80211_rx_status *rx_status,
386db5ae2e1SBitterblue Smith 			  u8 *pdesc8, struct sk_buff *skb)
387db5ae2e1SBitterblue Smith {
388db5ae2e1SBitterblue Smith 	__le32 *pdesc = (__le32 *)pdesc8;
389db5ae2e1SBitterblue Smith 	struct rx_fwinfo_92d *p_drvinfo;
390db5ae2e1SBitterblue Smith 	u32 phystatus = get_rx_desc_physt(pdesc);
391db5ae2e1SBitterblue Smith 
392db5ae2e1SBitterblue Smith 	stats->length = (u16)get_rx_desc_pkt_len(pdesc);
393db5ae2e1SBitterblue Smith 	stats->rx_drvinfo_size = (u8)get_rx_desc_drv_info_size(pdesc) *
394db5ae2e1SBitterblue Smith 				 RX_DRV_INFO_SIZE_UNIT;
395db5ae2e1SBitterblue Smith 	stats->rx_bufshift = (u8)(get_rx_desc_shift(pdesc) & 0x03);
396db5ae2e1SBitterblue Smith 	stats->icv = (u16)get_rx_desc_icv(pdesc);
397db5ae2e1SBitterblue Smith 	stats->crc = (u16)get_rx_desc_crc32(pdesc);
398db5ae2e1SBitterblue Smith 	stats->hwerror = (stats->crc | stats->icv);
399db5ae2e1SBitterblue Smith 	stats->decrypted = !get_rx_desc_swdec(pdesc) &&
400db5ae2e1SBitterblue Smith 			   get_rx_desc_enc_type(pdesc) != RX_DESC_ENC_NONE;
401db5ae2e1SBitterblue Smith 	stats->rate = (u8)get_rx_desc_rxmcs(pdesc);
402db5ae2e1SBitterblue Smith 	stats->shortpreamble = (u16)get_rx_desc_splcp(pdesc);
403db5ae2e1SBitterblue Smith 	stats->isampdu = (bool)(get_rx_desc_paggr(pdesc) == 1);
404db5ae2e1SBitterblue Smith 	stats->isfirst_ampdu = (bool)((get_rx_desc_paggr(pdesc) == 1) &&
405db5ae2e1SBitterblue Smith 				      (get_rx_desc_faggr(pdesc) == 1));
406db5ae2e1SBitterblue Smith 	stats->timestamp_low = get_rx_desc_tsfl(pdesc);
407db5ae2e1SBitterblue Smith 	stats->rx_is40mhzpacket = (bool)get_rx_desc_bw(pdesc);
408db5ae2e1SBitterblue Smith 	stats->is_ht = (bool)get_rx_desc_rxht(pdesc);
409db5ae2e1SBitterblue Smith 	rx_status->freq = hw->conf.chandef.chan->center_freq;
410db5ae2e1SBitterblue Smith 	rx_status->band = hw->conf.chandef.chan->band;
411db5ae2e1SBitterblue Smith 	if (get_rx_desc_crc32(pdesc))
412db5ae2e1SBitterblue Smith 		rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
413db5ae2e1SBitterblue Smith 	if (get_rx_desc_bw(pdesc))
414db5ae2e1SBitterblue Smith 		rx_status->bw = RATE_INFO_BW_40;
415db5ae2e1SBitterblue Smith 	if (get_rx_desc_rxht(pdesc))
416db5ae2e1SBitterblue Smith 		rx_status->encoding = RX_ENC_HT;
417db5ae2e1SBitterblue Smith 	rx_status->flag |= RX_FLAG_MACTIME_START;
418db5ae2e1SBitterblue Smith 	if (stats->decrypted)
419db5ae2e1SBitterblue Smith 		rx_status->flag |= RX_FLAG_DECRYPTED;
420db5ae2e1SBitterblue Smith 	rx_status->rate_idx = rtlwifi_rate_mapping(hw, stats->is_ht,
421db5ae2e1SBitterblue Smith 						   false, stats->rate);
422db5ae2e1SBitterblue Smith 	rx_status->mactime = get_rx_desc_tsfl(pdesc);
423db5ae2e1SBitterblue Smith 	if (phystatus) {
424db5ae2e1SBitterblue Smith 		p_drvinfo = (struct rx_fwinfo_92d *)(skb->data +
425db5ae2e1SBitterblue Smith 						     stats->rx_bufshift);
426*b21faf0eSBitterblue Smith 		_rtl92d_translate_rx_signal_stuff(hw, skb, stats, pdesc,
427db5ae2e1SBitterblue Smith 						  p_drvinfo);
428db5ae2e1SBitterblue Smith 	}
429db5ae2e1SBitterblue Smith 	/*rx_status->qual = stats->signal; */
430db5ae2e1SBitterblue Smith 	rx_status->signal = stats->recvsignalpower + 10;
431db5ae2e1SBitterblue Smith 	return true;
432db5ae2e1SBitterblue Smith }
433*b21faf0eSBitterblue Smith EXPORT_SYMBOL_GPL(rtl92d_rx_query_desc);
434db5ae2e1SBitterblue Smith 
rtl92d_set_desc(struct ieee80211_hw * hw,u8 * pdesc8,bool istx,u8 desc_name,u8 * val)435*b21faf0eSBitterblue Smith void rtl92d_set_desc(struct ieee80211_hw *hw, u8 *pdesc8, bool istx,
436db5ae2e1SBitterblue Smith 		     u8 desc_name, u8 *val)
437db5ae2e1SBitterblue Smith {
438db5ae2e1SBitterblue Smith 	__le32 *pdesc = (__le32 *)pdesc8;
439db5ae2e1SBitterblue Smith 
440db5ae2e1SBitterblue Smith 	if (istx) {
441db5ae2e1SBitterblue Smith 		switch (desc_name) {
442db5ae2e1SBitterblue Smith 		case HW_DESC_OWN:
443db5ae2e1SBitterblue Smith 			wmb();
444db5ae2e1SBitterblue Smith 			set_tx_desc_own(pdesc, 1);
445db5ae2e1SBitterblue Smith 			break;
446db5ae2e1SBitterblue Smith 		case HW_DESC_TX_NEXTDESC_ADDR:
447db5ae2e1SBitterblue Smith 			set_tx_desc_next_desc_address(pdesc, *(u32 *)val);
448db5ae2e1SBitterblue Smith 			break;
449db5ae2e1SBitterblue Smith 		default:
450db5ae2e1SBitterblue Smith 			WARN_ONCE(true, "rtl8192de: ERR txdesc :%d not processed\n",
451db5ae2e1SBitterblue Smith 				  desc_name);
452db5ae2e1SBitterblue Smith 			break;
453db5ae2e1SBitterblue Smith 		}
454db5ae2e1SBitterblue Smith 	} else {
455db5ae2e1SBitterblue Smith 		switch (desc_name) {
456db5ae2e1SBitterblue Smith 		case HW_DESC_RXOWN:
457db5ae2e1SBitterblue Smith 			wmb();
458db5ae2e1SBitterblue Smith 			set_rx_desc_own(pdesc, 1);
459db5ae2e1SBitterblue Smith 			break;
460db5ae2e1SBitterblue Smith 		case HW_DESC_RXBUFF_ADDR:
461db5ae2e1SBitterblue Smith 			set_rx_desc_buff_addr(pdesc, *(u32 *)val);
462db5ae2e1SBitterblue Smith 			break;
463db5ae2e1SBitterblue Smith 		case HW_DESC_RXPKT_LEN:
464db5ae2e1SBitterblue Smith 			set_rx_desc_pkt_len(pdesc, *(u32 *)val);
465db5ae2e1SBitterblue Smith 			break;
466db5ae2e1SBitterblue Smith 		case HW_DESC_RXERO:
467db5ae2e1SBitterblue Smith 			set_rx_desc_eor(pdesc, 1);
468db5ae2e1SBitterblue Smith 			break;
469db5ae2e1SBitterblue Smith 		default:
470db5ae2e1SBitterblue Smith 			WARN_ONCE(true, "rtl8192de: ERR rxdesc :%d not processed\n",
471db5ae2e1SBitterblue Smith 				  desc_name);
472db5ae2e1SBitterblue Smith 			break;
473db5ae2e1SBitterblue Smith 		}
474db5ae2e1SBitterblue Smith 	}
475db5ae2e1SBitterblue Smith }
476*b21faf0eSBitterblue Smith EXPORT_SYMBOL_GPL(rtl92d_set_desc);
477db5ae2e1SBitterblue Smith 
rtl92d_get_desc(struct ieee80211_hw * hw,u8 * p_desc8,bool istx,u8 desc_name)478*b21faf0eSBitterblue Smith u64 rtl92d_get_desc(struct ieee80211_hw *hw,
479db5ae2e1SBitterblue Smith 		    u8 *p_desc8, bool istx, u8 desc_name)
480db5ae2e1SBitterblue Smith {
481db5ae2e1SBitterblue Smith 	__le32 *p_desc = (__le32 *)p_desc8;
482db5ae2e1SBitterblue Smith 	u32 ret = 0;
483db5ae2e1SBitterblue Smith 
484db5ae2e1SBitterblue Smith 	if (istx) {
485db5ae2e1SBitterblue Smith 		switch (desc_name) {
486db5ae2e1SBitterblue Smith 		case HW_DESC_OWN:
487db5ae2e1SBitterblue Smith 			ret = get_tx_desc_own(p_desc);
488db5ae2e1SBitterblue Smith 			break;
489db5ae2e1SBitterblue Smith 		case HW_DESC_TXBUFF_ADDR:
490db5ae2e1SBitterblue Smith 			ret = get_tx_desc_tx_buffer_address(p_desc);
491db5ae2e1SBitterblue Smith 			break;
492db5ae2e1SBitterblue Smith 		default:
493db5ae2e1SBitterblue Smith 			WARN_ONCE(true, "rtl8192de: ERR txdesc :%d not processed\n",
494db5ae2e1SBitterblue Smith 				  desc_name);
495db5ae2e1SBitterblue Smith 			break;
496db5ae2e1SBitterblue Smith 		}
497db5ae2e1SBitterblue Smith 	} else {
498db5ae2e1SBitterblue Smith 		switch (desc_name) {
499db5ae2e1SBitterblue Smith 		case HW_DESC_OWN:
500db5ae2e1SBitterblue Smith 			ret = get_rx_desc_own(p_desc);
501db5ae2e1SBitterblue Smith 			break;
502db5ae2e1SBitterblue Smith 		case HW_DESC_RXPKT_LEN:
503db5ae2e1SBitterblue Smith 			ret = get_rx_desc_pkt_len(p_desc);
504db5ae2e1SBitterblue Smith 		break;
505db5ae2e1SBitterblue Smith 		case HW_DESC_RXBUFF_ADDR:
506db5ae2e1SBitterblue Smith 			ret = get_rx_desc_buff_addr(p_desc);
507db5ae2e1SBitterblue Smith 			break;
508db5ae2e1SBitterblue Smith 		default:
509db5ae2e1SBitterblue Smith 			WARN_ONCE(true, "rtl8192de: ERR rxdesc :%d not processed\n",
510db5ae2e1SBitterblue Smith 				  desc_name);
511db5ae2e1SBitterblue Smith 			break;
512db5ae2e1SBitterblue Smith 		}
513db5ae2e1SBitterblue Smith 	}
514db5ae2e1SBitterblue Smith 	return ret;
515db5ae2e1SBitterblue Smith }
516*b21faf0eSBitterblue Smith EXPORT_SYMBOL_GPL(rtl92d_get_desc);
517