Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.6.
  1/******************************************************************************
  2 *
  3 * Copyright(c) 2009-2010  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
 30#include "../wifi.h"
 31#include "../pci.h"
 32#include "../base.h"
 33#include "reg.h"
 34#include "def.h"
 35#include "phy.h"
 36#include "trx.h"
 37#include "led.h"
 38
 39static u8 _rtl92de_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 hw_queue)
 40{
 41	__le16 fc = rtl_get_fc(skb);
 42
 43	if (unlikely(ieee80211_is_beacon(fc)))
 44		return QSLT_BEACON;
 45	if (ieee80211_is_mgmt(fc))
 46		return QSLT_MGNT;
 47
 48	return skb->priority;
 49}
 50
 51static int _rtl92de_rate_mapping(bool isht, u8 desc_rate)
 52{
 53	int rate_idx;
 54
 55	if (false == isht) {
 56		switch (desc_rate) {
 57		case DESC92D_RATE1M:
 58			rate_idx = 0;
 59			break;
 60		case DESC92D_RATE2M:
 61			rate_idx = 1;
 62			break;
 63		case DESC92D_RATE5_5M:
 64			rate_idx = 2;
 65			break;
 66		case DESC92D_RATE11M:
 67			rate_idx = 3;
 68			break;
 69		case DESC92D_RATE6M:
 70			rate_idx = 4;
 71			break;
 72		case DESC92D_RATE9M:
 73			rate_idx = 5;
 74			break;
 75		case DESC92D_RATE12M:
 76			rate_idx = 6;
 77			break;
 78		case DESC92D_RATE18M:
 79			rate_idx = 7;
 80			break;
 81		case DESC92D_RATE24M:
 82			rate_idx = 8;
 83			break;
 84		case DESC92D_RATE36M:
 85			rate_idx = 9;
 86			break;
 87		case DESC92D_RATE48M:
 88			rate_idx = 10;
 89			break;
 90		case DESC92D_RATE54M:
 91			rate_idx = 11;
 92			break;
 93		default:
 94			rate_idx = 0;
 95			break;
 96		}
 97		return rate_idx;
 98	} else {
 99		switch (desc_rate) {
100		case DESC92D_RATE1M:
101			rate_idx = 0;
102			break;
103		case DESC92D_RATE2M:
104			rate_idx = 1;
105			break;
106		case DESC92D_RATE5_5M:
107			rate_idx = 2;
108			break;
109		case DESC92D_RATE11M:
110			rate_idx = 3;
111			break;
112		case DESC92D_RATE6M:
113			rate_idx = 4;
114			break;
115		case DESC92D_RATE9M:
116			rate_idx = 5;
117			break;
118		case DESC92D_RATE12M:
119			rate_idx = 6;
120			break;
121		case DESC92D_RATE18M:
122			rate_idx = 7;
123			break;
124		case DESC92D_RATE24M:
125			rate_idx = 8;
126			break;
127		case DESC92D_RATE36M:
128			rate_idx = 9;
129			break;
130		case DESC92D_RATE48M:
131			rate_idx = 10;
132			break;
133		case DESC92D_RATE54M:
134			rate_idx = 11;
135			break;
136		default:
137			rate_idx = 11;
138			break;
139		}
140		return rate_idx;
141	}
142}
143
144static u8 _rtl92d_query_rxpwrpercentage(char antpower)
145{
146	if ((antpower <= -100) || (antpower >= 20))
147		return 0;
148	else if (antpower >= 0)
149		return 100;
150	else
151		return 100 + antpower;
152}
153
154static u8 _rtl92d_evm_db_to_percentage(char value)
155{
156	char ret_val = value;
157
158	if (ret_val >= 0)
159		ret_val = 0;
160	if (ret_val <= -33)
161		ret_val = -33;
162	ret_val = 0 - ret_val;
163	ret_val *= 3;
164	if (ret_val == 99)
165		ret_val = 100;
166	return ret_val;
167}
168
169static long _rtl92de_translate_todbm(struct ieee80211_hw *hw,
170				     u8 signal_strength_index)
171{
172	long signal_power;
173
174	signal_power = (long)((signal_strength_index + 1) >> 1);
175	signal_power -= 95;
176	return signal_power;
177}
178
179static long _rtl92de_signal_scale_mapping(struct ieee80211_hw *hw, long currsig)
180{
181	long retsig;
182
183	if (currsig >= 61 && currsig <= 100)
184		retsig = 90 + ((currsig - 60) / 4);
185	else if (currsig >= 41 && currsig <= 60)
186		retsig = 78 + ((currsig - 40) / 2);
187	else if (currsig >= 31 && currsig <= 40)
188		retsig = 66 + (currsig - 30);
189	else if (currsig >= 21 && currsig <= 30)
190		retsig = 54 + (currsig - 20);
191	else if (currsig >= 5 && currsig <= 20)
192		retsig = 42 + (((currsig - 5) * 2) / 3);
193	else if (currsig == 4)
194		retsig = 36;
195	else if (currsig == 3)
196		retsig = 27;
197	else if (currsig == 2)
198		retsig = 18;
199	else if (currsig == 1)
200		retsig = 9;
201	else
202		retsig = currsig;
203	return retsig;
204}
205
206static void _rtl92de_query_rxphystatus(struct ieee80211_hw *hw,
207				       struct rtl_stats *pstats,
208				       struct rx_desc_92d *pdesc,
209				       struct rx_fwinfo_92d *p_drvinfo,
210				       bool packet_match_bssid,
211				       bool packet_toself,
212				       bool packet_beacon)
213{
214	struct rtl_priv *rtlpriv = rtl_priv(hw);
215	struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv);
216	struct phy_sts_cck_8192d *cck_buf;
217	s8 rx_pwr_all, rx_pwr[4];
218	u8 rf_rx_num = 0, evm, pwdb_all;
219	u8 i, max_spatial_stream;
220	u32 rssi, total_rssi = 0;
221	bool is_cck_rate;
222
223	is_cck_rate = RX_HAL_IS_CCK_RATE(pdesc);
224	pstats->packet_matchbssid = packet_match_bssid;
225	pstats->packet_toself = packet_toself;
226	pstats->packet_beacon = packet_beacon;
227	pstats->is_cck = is_cck_rate;
228	pstats->rx_mimo_signalquality[0] = -1;
229	pstats->rx_mimo_signalquality[1] = -1;
230
231	if (is_cck_rate) {
232		u8 report, cck_highpwr;
233		cck_buf = (struct phy_sts_cck_8192d *)p_drvinfo;
234		if (ppsc->rfpwr_state == ERFON)
235			cck_highpwr = (u8) rtl_get_bbreg(hw,
236						 RFPGA0_XA_HSSIPARAMETER2,
237						 BIT(9));
238		else
239			cck_highpwr = false;
240		if (!cck_highpwr) {
241			u8 cck_agc_rpt = cck_buf->cck_agc_rpt;
242			report = cck_buf->cck_agc_rpt & 0xc0;
243			report = report >> 6;
244			switch (report) {
245			case 0x3:
246				rx_pwr_all = -46 - (cck_agc_rpt & 0x3e);
247				break;
248			case 0x2:
249				rx_pwr_all = -26 - (cck_agc_rpt & 0x3e);
250				break;
251			case 0x1:
252				rx_pwr_all = -12 - (cck_agc_rpt & 0x3e);
253				break;
254			case 0x0:
255				rx_pwr_all = 16 - (cck_agc_rpt & 0x3e);
256				break;
257			}
258		} else {
259			u8 cck_agc_rpt = cck_buf->cck_agc_rpt;
260			report = p_drvinfo->cfosho[0] & 0x60;
261			report = report >> 5;
262			switch (report) {
263			case 0x3:
264				rx_pwr_all = -46 - ((cck_agc_rpt & 0x1f) << 1);
265				break;
266			case 0x2:
267				rx_pwr_all = -26 - ((cck_agc_rpt & 0x1f) << 1);
268				break;
269			case 0x1:
270				rx_pwr_all = -12 - ((cck_agc_rpt & 0x1f) << 1);
271				break;
272			case 0x0:
273				rx_pwr_all = 16 - ((cck_agc_rpt & 0x1f) << 1);
274				break;
275			}
276		}
277		pwdb_all = _rtl92d_query_rxpwrpercentage(rx_pwr_all);
278		/* CCK gain is smaller than OFDM/MCS gain,  */
279		/* so we add gain diff by experiences, the val is 6 */
280		pwdb_all += 6;
281		if (pwdb_all > 100)
282			pwdb_all = 100;
283		/* modify the offset to make the same gain index with OFDM. */
284		if (pwdb_all > 34 && pwdb_all <= 42)
285			pwdb_all -= 2;
286		else if (pwdb_all > 26 && pwdb_all <= 34)
287			pwdb_all -= 6;
288		else if (pwdb_all > 14 && pwdb_all <= 26)
289			pwdb_all -= 8;
290		else if (pwdb_all > 4 && pwdb_all <= 14)
291			pwdb_all -= 4;
292		pstats->rx_pwdb_all = pwdb_all;
293		pstats->recvsignalpower = rx_pwr_all;
294		if (packet_match_bssid) {
295			u8 sq;
296			if (pstats->rx_pwdb_all > 40) {
297				sq = 100;
298			} else {
299				sq = cck_buf->sq_rpt;
300				if (sq > 64)
301					sq = 0;
302				else if (sq < 20)
303					sq = 100;
304				else
305					sq = ((64 - sq) * 100) / 44;
306			}
307			pstats->signalquality = sq;
308			pstats->rx_mimo_signalquality[0] = sq;
309			pstats->rx_mimo_signalquality[1] = -1;
310		}
311	} else {
312		rtlpriv->dm.rfpath_rxenable[0] = true;
313		rtlpriv->dm.rfpath_rxenable[1] = true;
314		for (i = RF90_PATH_A; i < RF6052_MAX_PATH; i++) {
315			if (rtlpriv->dm.rfpath_rxenable[i])
316				rf_rx_num++;
317			rx_pwr[i] = ((p_drvinfo->gain_trsw[i] & 0x3f) * 2)
318				    - 110;
319			rssi = _rtl92d_query_rxpwrpercentage(rx_pwr[i]);
320			total_rssi += rssi;
321			rtlpriv->stats.rx_snr_db[i] =
322					 (long)(p_drvinfo->rxsnr[i] / 2);
323			if (packet_match_bssid)
324				pstats->rx_mimo_signalstrength[i] = (u8) rssi;
325		}
326		rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 106;
327		pwdb_all = _rtl92d_query_rxpwrpercentage(rx_pwr_all);
328		pstats->rx_pwdb_all = pwdb_all;
329		pstats->rxpower = rx_pwr_all;
330		pstats->recvsignalpower = rx_pwr_all;
331		if (pdesc->rxht && pdesc->rxmcs >= DESC92D_RATEMCS8 &&
332		    pdesc->rxmcs <= DESC92D_RATEMCS15)
333			max_spatial_stream = 2;
334		else
335			max_spatial_stream = 1;
336		for (i = 0; i < max_spatial_stream; i++) {
337			evm = _rtl92d_evm_db_to_percentage(p_drvinfo->rxevm[i]);
338			if (packet_match_bssid) {
339				if (i == 0)
340					pstats->signalquality =
341						 (u8)(evm & 0xff);
342				pstats->rx_mimo_signalquality[i] =
343						 (u8)(evm & 0xff);
344			}
345		}
346	}
347	if (is_cck_rate)
348		pstats->signalstrength = (u8)(_rtl92de_signal_scale_mapping(hw,
349				pwdb_all));
350	else if (rf_rx_num != 0)
351		pstats->signalstrength = (u8)(_rtl92de_signal_scale_mapping(hw,
352				total_rssi /= rf_rx_num));
353}
354
355static void rtl92d_loop_over_paths(struct ieee80211_hw *hw,
356				   struct rtl_stats *pstats)
357{
358	struct rtl_priv *rtlpriv = rtl_priv(hw);
359	struct rtl_phy *rtlphy = &(rtlpriv->phy);
360	u8 rfpath;
361
362	for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath;
363	     rfpath++) {
364		if (rtlpriv->stats.rx_rssi_percentage[rfpath] == 0) {
365			rtlpriv->stats.rx_rssi_percentage[rfpath] =
366			    pstats->rx_mimo_signalstrength[rfpath];
367
368		}
369		if (pstats->rx_mimo_signalstrength[rfpath] >
370		    rtlpriv->stats.rx_rssi_percentage[rfpath]) {
371			rtlpriv->stats.rx_rssi_percentage[rfpath] =
372			    ((rtlpriv->stats.rx_rssi_percentage[rfpath] *
373			      (RX_SMOOTH_FACTOR - 1)) +
374			     (pstats->rx_mimo_signalstrength[rfpath])) /
375			    (RX_SMOOTH_FACTOR);
376			rtlpriv->stats.rx_rssi_percentage[rfpath] =
377			    rtlpriv->stats.rx_rssi_percentage[rfpath] + 1;
378		} else {
379			rtlpriv->stats.rx_rssi_percentage[rfpath] =
380			    ((rtlpriv->stats.rx_rssi_percentage[rfpath] *
381			      (RX_SMOOTH_FACTOR - 1)) +
382			     (pstats->rx_mimo_signalstrength[rfpath])) /
383			    (RX_SMOOTH_FACTOR);
384		}
385	}
386}
387
388static void _rtl92de_process_ui_rssi(struct ieee80211_hw *hw,
389				     struct rtl_stats *pstats)
390{
391	struct rtl_priv *rtlpriv = rtl_priv(hw);
392	u32 last_rssi, tmpval;
393
394	if (pstats->packet_toself || pstats->packet_beacon) {
395		rtlpriv->stats.rssi_calculate_cnt++;
396		if (rtlpriv->stats.ui_rssi.total_num++ >=
397		    PHY_RSSI_SLID_WIN_MAX) {
398			rtlpriv->stats.ui_rssi.total_num =
399						 PHY_RSSI_SLID_WIN_MAX;
400			last_rssi = rtlpriv->stats.ui_rssi.elements[
401				rtlpriv->stats.ui_rssi.index];
402			rtlpriv->stats.ui_rssi.total_val -= last_rssi;
403		}
404		rtlpriv->stats.ui_rssi.total_val += pstats->signalstrength;
405		rtlpriv->stats.ui_rssi.elements
406			[rtlpriv->stats.ui_rssi.index++] =
407			pstats->signalstrength;
408		if (rtlpriv->stats.ui_rssi.index >= PHY_RSSI_SLID_WIN_MAX)
409			rtlpriv->stats.ui_rssi.index = 0;
410		tmpval = rtlpriv->stats.ui_rssi.total_val /
411			rtlpriv->stats.ui_rssi.total_num;
412		rtlpriv->stats.signal_strength = _rtl92de_translate_todbm(hw,
413			(u8) tmpval);
414		pstats->rssi = rtlpriv->stats.signal_strength;
415	}
416	if (!pstats->is_cck && pstats->packet_toself)
417		rtl92d_loop_over_paths(hw, pstats);
418}
419
420static void _rtl92de_update_rxsignalstatistics(struct ieee80211_hw *hw,
421					       struct rtl_stats *pstats)
422{
423	struct rtl_priv *rtlpriv = rtl_priv(hw);
424	int weighting = 0;
425
426	if (rtlpriv->stats.recv_signal_power == 0)
427		rtlpriv->stats.recv_signal_power = pstats->recvsignalpower;
428	if (pstats->recvsignalpower > rtlpriv->stats.recv_signal_power)
429		weighting = 5;
430	else if (pstats->recvsignalpower < rtlpriv->stats.recv_signal_power)
431		weighting = (-5);
432	rtlpriv->stats.recv_signal_power = (rtlpriv->stats.recv_signal_power *
433		5 + pstats->recvsignalpower + weighting) / 6;
434}
435
436static void _rtl92de_process_pwdb(struct ieee80211_hw *hw,
437				  struct rtl_stats *pstats)
438{
439	struct rtl_priv *rtlpriv = rtl_priv(hw);
440	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
441	long undecorated_smoothed_pwdb;
442
443	if (mac->opmode == NL80211_IFTYPE_ADHOC	||
444		mac->opmode == NL80211_IFTYPE_AP)
445		return;
446	else
447		undecorated_smoothed_pwdb =
448		    rtlpriv->dm.undecorated_smoothed_pwdb;
449
450	if (pstats->packet_toself || pstats->packet_beacon) {
451		if (undecorated_smoothed_pwdb < 0)
452			undecorated_smoothed_pwdb = pstats->rx_pwdb_all;
453		if (pstats->rx_pwdb_all > (u32) undecorated_smoothed_pwdb) {
454			undecorated_smoothed_pwdb =
455			      (((undecorated_smoothed_pwdb) *
456			      (RX_SMOOTH_FACTOR - 1)) +
457			      (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
458			undecorated_smoothed_pwdb =
459			      undecorated_smoothed_pwdb + 1;
460		} else {
461			undecorated_smoothed_pwdb =
462			      (((undecorated_smoothed_pwdb) *
463			      (RX_SMOOTH_FACTOR - 1)) +
464			      (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
465		}
466		rtlpriv->dm.undecorated_smoothed_pwdb =
467				 undecorated_smoothed_pwdb;
468		_rtl92de_update_rxsignalstatistics(hw, pstats);
469	}
470}
471
472static void rtl92d_loop_over_streams(struct ieee80211_hw *hw,
473				     struct rtl_stats *pstats)
474{
475	struct rtl_priv *rtlpriv = rtl_priv(hw);
476	int stream;
477
478	for (stream = 0; stream < 2; stream++) {
479		if (pstats->rx_mimo_signalquality[stream] != -1) {
480			if (rtlpriv->stats.rx_evm_percentage[stream] == 0) {
481				rtlpriv->stats.rx_evm_percentage[stream] =
482				    pstats->rx_mimo_signalquality[stream];
483			}
484			rtlpriv->stats.rx_evm_percentage[stream] =
485			    ((rtlpriv->stats.rx_evm_percentage[stream]
486			      * (RX_SMOOTH_FACTOR - 1)) +
487			     (pstats->rx_mimo_signalquality[stream] * 1)) /
488			    (RX_SMOOTH_FACTOR);
489		}
490	}
491}
492
493static void _rtl92de_process_ui_link_quality(struct ieee80211_hw *hw,
494					     struct rtl_stats *pstats)
495{
496	struct rtl_priv *rtlpriv = rtl_priv(hw);
497	u32 last_evm, tmpval;
498
499	if (pstats->signalquality == 0)
500		return;
501	if (pstats->packet_toself || pstats->packet_beacon) {
502		if (rtlpriv->stats.ui_link_quality.total_num++ >=
503		    PHY_LINKQUALITY_SLID_WIN_MAX) {
504			rtlpriv->stats.ui_link_quality.total_num =
505			    PHY_LINKQUALITY_SLID_WIN_MAX;
506			last_evm = rtlpriv->stats.ui_link_quality.elements[
507				rtlpriv->stats.ui_link_quality.index];
508			rtlpriv->stats.ui_link_quality.total_val -= last_evm;
509		}
510		rtlpriv->stats.ui_link_quality.total_val +=
511						 pstats->signalquality;
512		rtlpriv->stats.ui_link_quality.elements[
513			rtlpriv->stats.ui_link_quality.index++] =
514						 pstats->signalquality;
515		if (rtlpriv->stats.ui_link_quality.index >=
516		    PHY_LINKQUALITY_SLID_WIN_MAX)
517			rtlpriv->stats.ui_link_quality.index = 0;
518		tmpval = rtlpriv->stats.ui_link_quality.total_val /
519		    rtlpriv->stats.ui_link_quality.total_num;
520		rtlpriv->stats.signal_quality = tmpval;
521		rtlpriv->stats.last_sigstrength_inpercent = tmpval;
522		rtl92d_loop_over_streams(hw, pstats);
523	}
524}
525
526static void _rtl92de_process_phyinfo(struct ieee80211_hw *hw,
527				     u8 *buffer,
528				     struct rtl_stats *pcurrent_stats)
529{
530
531	if (!pcurrent_stats->packet_matchbssid &&
532	    !pcurrent_stats->packet_beacon)
533		return;
534
535	_rtl92de_process_ui_rssi(hw, pcurrent_stats);
536	_rtl92de_process_pwdb(hw, pcurrent_stats);
537	_rtl92de_process_ui_link_quality(hw, pcurrent_stats);
538}
539
540static void _rtl92de_translate_rx_signal_stuff(struct ieee80211_hw *hw,
541					       struct sk_buff *skb,
542					       struct rtl_stats *pstats,
543					       struct rx_desc_92d *pdesc,
544					       struct rx_fwinfo_92d *p_drvinfo)
545{
546	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
547	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
548	struct ieee80211_hdr *hdr;
549	u8 *tmp_buf;
550	u8 *praddr;
551	u16 type, cfc;
552	__le16 fc;
553	bool packet_matchbssid, packet_toself, packet_beacon;
554
555	tmp_buf = skb->data + pstats->rx_drvinfo_size + pstats->rx_bufshift;
556	hdr = (struct ieee80211_hdr *)tmp_buf;
557	fc = hdr->frame_control;
558	cfc = le16_to_cpu(fc);
559	type = WLAN_FC_GET_TYPE(fc);
560	praddr = hdr->addr1;
561	packet_matchbssid = ((IEEE80211_FTYPE_CTL != type) &&
562	     (!compare_ether_addr(mac->bssid, (cfc & IEEE80211_FCTL_TODS) ?
563		  hdr->addr1 : (cfc & IEEE80211_FCTL_FROMDS) ?
564		  hdr->addr2 : hdr->addr3)) && (!pstats->hwerror) &&
565		  (!pstats->crc) && (!pstats->icv));
566	packet_toself = packet_matchbssid &&
567			(!compare_ether_addr(praddr, rtlefuse->dev_addr));
568	if (ieee80211_is_beacon(fc))
569		packet_beacon = true;
570	_rtl92de_query_rxphystatus(hw, pstats, pdesc, p_drvinfo,
571				   packet_matchbssid, packet_toself,
572				   packet_beacon);
573	_rtl92de_process_phyinfo(hw, tmp_buf, pstats);
574}
575
576bool rtl92de_rx_query_desc(struct ieee80211_hw *hw,	struct rtl_stats *stats,
577		struct ieee80211_rx_status *rx_status,
578		u8 *p_desc, struct sk_buff *skb)
579{
580	struct rx_fwinfo_92d *p_drvinfo;
581	struct rx_desc_92d *pdesc = (struct rx_desc_92d *)p_desc;
582	u32 phystatus = GET_RX_DESC_PHYST(pdesc);
583
584	stats->length = (u16) GET_RX_DESC_PKT_LEN(pdesc);
585	stats->rx_drvinfo_size = (u8) GET_RX_DESC_DRV_INFO_SIZE(pdesc) *
586				 RX_DRV_INFO_SIZE_UNIT;
587	stats->rx_bufshift = (u8) (GET_RX_DESC_SHIFT(pdesc) & 0x03);
588	stats->icv = (u16) GET_RX_DESC_ICV(pdesc);
589	stats->crc = (u16) GET_RX_DESC_CRC32(pdesc);
590	stats->hwerror = (stats->crc | stats->icv);
591	stats->decrypted = !GET_RX_DESC_SWDEC(pdesc);
592	stats->rate = (u8) GET_RX_DESC_RXMCS(pdesc);
593	stats->shortpreamble = (u16) GET_RX_DESC_SPLCP(pdesc);
594	stats->isampdu = (bool) (GET_RX_DESC_PAGGR(pdesc) == 1);
595	stats->isfirst_ampdu = (bool) ((GET_RX_DESC_PAGGR(pdesc) == 1)
596					 && (GET_RX_DESC_FAGGR(pdesc) == 1));
597	stats->timestamp_low = GET_RX_DESC_TSFL(pdesc);
598	stats->rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(pdesc);
599	rx_status->freq = hw->conf.channel->center_freq;
600	rx_status->band = hw->conf.channel->band;
601	if (GET_RX_DESC_CRC32(pdesc))
602		rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
603	if (!GET_RX_DESC_SWDEC(pdesc))
604		rx_status->flag |= RX_FLAG_DECRYPTED;
605	if (GET_RX_DESC_BW(pdesc))
606		rx_status->flag |= RX_FLAG_40MHZ;
607	if (GET_RX_DESC_RXHT(pdesc))
608		rx_status->flag |= RX_FLAG_HT;
609	rx_status->flag |= RX_FLAG_MACTIME_MPDU;
610	if (stats->decrypted)
611		rx_status->flag |= RX_FLAG_DECRYPTED;
612	rx_status->rate_idx = _rtl92de_rate_mapping((bool)
613						    GET_RX_DESC_RXHT(pdesc),
614						    (u8)
615						    GET_RX_DESC_RXMCS(pdesc));
616	rx_status->mactime = GET_RX_DESC_TSFL(pdesc);
617	if (phystatus) {
618		p_drvinfo = (struct rx_fwinfo_92d *)(skb->data +
619						     stats->rx_bufshift);
620		_rtl92de_translate_rx_signal_stuff(hw,
621						   skb, stats, pdesc,
622						   p_drvinfo);
623	}
624	/*rx_status->qual = stats->signal; */
625	rx_status->signal = stats->rssi + 10;
626	/*rx_status->noise = -stats->noise; */
627	return true;
628}
629
630static void _rtl92de_insert_emcontent(struct rtl_tcb_desc *ptcb_desc,
631				      u8 *virtualaddress)
632{
633	memset(virtualaddress, 0, 8);
634
635	SET_EARLYMODE_PKTNUM(virtualaddress, ptcb_desc->empkt_num);
636	SET_EARLYMODE_LEN0(virtualaddress, ptcb_desc->empkt_len[0]);
637	SET_EARLYMODE_LEN1(virtualaddress, ptcb_desc->empkt_len[1]);
638	SET_EARLYMODE_LEN2_1(virtualaddress, ptcb_desc->empkt_len[2] & 0xF);
639	SET_EARLYMODE_LEN2_2(virtualaddress, ptcb_desc->empkt_len[2] >> 4);
640	SET_EARLYMODE_LEN3(virtualaddress, ptcb_desc->empkt_len[3]);
641	SET_EARLYMODE_LEN4(virtualaddress, ptcb_desc->empkt_len[4]);
642}
643
644void rtl92de_tx_fill_desc(struct ieee80211_hw *hw,
645			  struct ieee80211_hdr *hdr, u8 *pdesc_tx,
646			  struct ieee80211_tx_info *info, struct sk_buff *skb,
647			  u8 hw_queue, struct rtl_tcb_desc *ptcb_desc)
648{
649	struct rtl_priv *rtlpriv = rtl_priv(hw);
650	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
651	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
652	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
653	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
654	struct ieee80211_sta *sta = info->control.sta;
655	u8 *pdesc = (u8 *) pdesc_tx;
656	u16 seq_number;
657	__le16 fc = hdr->frame_control;
658	unsigned int buf_len = 0;
659	unsigned int skb_len = skb->len;
660	u8 fw_qsel = _rtl92de_map_hwqueue_to_fwqueue(skb, hw_queue);
661	bool firstseg = ((hdr->seq_ctrl &
662			cpu_to_le16(IEEE80211_SCTL_FRAG)) == 0);
663	bool lastseg = ((hdr->frame_control &
664			cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)) == 0);
665	dma_addr_t mapping;
666	u8 bw_40 = 0;
667
668	if (mac->opmode == NL80211_IFTYPE_STATION) {
669		bw_40 = mac->bw_40;
670	} else if (mac->opmode == NL80211_IFTYPE_AP ||
671		mac->opmode == NL80211_IFTYPE_ADHOC) {
672		if (sta)
673			bw_40 = sta->ht_cap.cap &
674				IEEE80211_HT_CAP_SUP_WIDTH_20_40;
675	}
676	seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4;
677	rtl_get_tcb_desc(hw, info, sta, skb, ptcb_desc);
678	/* reserve 8 byte for AMPDU early mode */
679	if (rtlhal->earlymode_enable) {
680		skb_push(skb, EM_HDR_LEN);
681		memset(skb->data, 0, EM_HDR_LEN);
682	}
683	buf_len = skb->len;
684	mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len,
685				 PCI_DMA_TODEVICE);
686	CLEAR_PCI_TX_DESC_CONTENT(pdesc, sizeof(struct tx_desc_92d));
687	if (ieee80211_is_nullfunc(fc) || ieee80211_is_ctl(fc)) {
688		firstseg = true;
689		lastseg = true;
690	}
691	if (firstseg) {
692		if (rtlhal->earlymode_enable) {
693			SET_TX_DESC_PKT_OFFSET(pdesc, 1);
694			SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN +
695					   EM_HDR_LEN);
696			if (ptcb_desc->empkt_num) {
697				RT_TRACE(rtlpriv, COMP_SEND, DBG_LOUD,
698					 ("Insert 8 byte.pTcb->EMPktNum:%d\n",
699					  ptcb_desc->empkt_num));
700				_rtl92de_insert_emcontent(ptcb_desc,
701							  (u8 *)(skb->data));
702			}
703		} else {
704			SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN);
705		}
706		/* 5G have no CCK rate */
707		if (rtlhal->current_bandtype == BAND_ON_5G)
708			if (ptcb_desc->hw_rate < DESC92D_RATE6M)
709				ptcb_desc->hw_rate = DESC92D_RATE6M;
710		SET_TX_DESC_TX_RATE(pdesc, ptcb_desc->hw_rate);
711		if (ptcb_desc->use_shortgi || ptcb_desc->use_shortpreamble)
712			SET_TX_DESC_DATA_SHORTGI(pdesc, 1);
713
714		if (rtlhal->macphymode == DUALMAC_DUALPHY &&
715			ptcb_desc->hw_rate == DESC92D_RATEMCS7)
716			SET_TX_DESC_DATA_SHORTGI(pdesc, 1);
717
718		if (info->flags & IEEE80211_TX_CTL_AMPDU) {
719			SET_TX_DESC_AGG_ENABLE(pdesc, 1);
720			SET_TX_DESC_MAX_AGG_NUM(pdesc, 0x14);
721		}
722		SET_TX_DESC_SEQ(pdesc, seq_number);
723		SET_TX_DESC_RTS_ENABLE(pdesc, ((ptcb_desc->rts_enable &&
724				       !ptcb_desc->cts_enable) ? 1 : 0));
725		SET_TX_DESC_HW_RTS_ENABLE(pdesc, ((ptcb_desc->rts_enable
726					  || ptcb_desc->cts_enable) ? 1 : 0));
727		SET_TX_DESC_CTS2SELF(pdesc, ((ptcb_desc->cts_enable) ? 1 : 0));
728		SET_TX_DESC_RTS_STBC(pdesc, ((ptcb_desc->rts_stbc) ? 1 : 0));
729		/* 5G have no CCK rate */
730		if (rtlhal->current_bandtype == BAND_ON_5G)
731			if (ptcb_desc->rts_rate < DESC92D_RATE6M)
732				ptcb_desc->rts_rate = DESC92D_RATE6M;
733		SET_TX_DESC_RTS_RATE(pdesc, ptcb_desc->rts_rate);
734		SET_TX_DESC_RTS_BW(pdesc, 0);
735		SET_TX_DESC_RTS_SC(pdesc, ptcb_desc->rts_sc);
736		SET_TX_DESC_RTS_SHORT(pdesc, ((ptcb_desc->rts_rate <=
737			DESC92D_RATE54M) ?
738			(ptcb_desc->rts_use_shortpreamble ? 1 : 0) :
739			(ptcb_desc->rts_use_shortgi ? 1 : 0)));
740		if (bw_40) {
741			if (ptcb_desc->packet_bw) {
742				SET_TX_DESC_DATA_BW(pdesc, 1);
743				SET_TX_DESC_TX_SUB_CARRIER(pdesc, 3);
744			} else {
745				SET_TX_DESC_DATA_BW(pdesc, 0);
746				SET_TX_DESC_TX_SUB_CARRIER(pdesc,
747							mac->cur_40_prime_sc);
748			}
749		} else {
750			SET_TX_DESC_DATA_BW(pdesc, 0);
751			SET_TX_DESC_TX_SUB_CARRIER(pdesc, 0);
752		}
753		SET_TX_DESC_LINIP(pdesc, 0);
754		SET_TX_DESC_PKT_SIZE(pdesc, (u16) skb_len);
755		if (sta) {
756			u8 ampdu_density = sta->ht_cap.ampdu_density;
757			SET_TX_DESC_AMPDU_DENSITY(pdesc, ampdu_density);
758		}
759		if (info->control.hw_key) {
760			struct ieee80211_key_conf *keyconf;
761
762			keyconf = info->control.hw_key;
763			switch (keyconf->cipher) {
764			case WLAN_CIPHER_SUITE_WEP40:
765			case WLAN_CIPHER_SUITE_WEP104:
766			case WLAN_CIPHER_SUITE_TKIP:
767				SET_TX_DESC_SEC_TYPE(pdesc, 0x1);
768				break;
769			case WLAN_CIPHER_SUITE_CCMP:
770				SET_TX_DESC_SEC_TYPE(pdesc, 0x3);
771				break;
772			default:
773				SET_TX_DESC_SEC_TYPE(pdesc, 0x0);
774				break;
775
776			}
777		}
778		SET_TX_DESC_PKT_ID(pdesc, 0);
779		SET_TX_DESC_QUEUE_SEL(pdesc, fw_qsel);
780		SET_TX_DESC_DATA_RATE_FB_LIMIT(pdesc, 0x1F);
781		SET_TX_DESC_RTS_RATE_FB_LIMIT(pdesc, 0xF);
782		SET_TX_DESC_DISABLE_FB(pdesc, ptcb_desc->disable_ratefallback ?
783				       1 : 0);
784		SET_TX_DESC_USE_RATE(pdesc, ptcb_desc->use_driver_rate ? 1 : 0);
785
786		/* Set TxRate and RTSRate in TxDesc  */
787		/* This prevent Tx initial rate of new-coming packets */
788		/* from being overwritten by retried  packet rate.*/
789		if (!ptcb_desc->use_driver_rate) {
790			SET_TX_DESC_RTS_RATE(pdesc, 0x08);
791			/* SET_TX_DESC_TX_RATE(pdesc, 0x0b); */
792		}
793		if (ieee80211_is_data_qos(fc)) {
794			if (mac->rdg_en) {
795				RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE,
796					("Enable RDG function.\n"));
797				SET_TX_DESC_RDG_ENABLE(pdesc, 1);
798				SET_TX_DESC_HTC(pdesc, 1);
799			}
800		}
801	}
802
803	SET_TX_DESC_FIRST_SEG(pdesc, (firstseg ? 1 : 0));
804	SET_TX_DESC_LAST_SEG(pdesc, (lastseg ? 1 : 0));
805	SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) buf_len);
806	SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping);
807	if (rtlpriv->dm.useramask) {
808		SET_TX_DESC_RATE_ID(pdesc, ptcb_desc->ratr_index);
809		SET_TX_DESC_MACID(pdesc, ptcb_desc->mac_id);
810	} else {
811		SET_TX_DESC_RATE_ID(pdesc, 0xC + ptcb_desc->ratr_index);
812		SET_TX_DESC_MACID(pdesc, ptcb_desc->ratr_index);
813	}
814	if (ieee80211_is_data_qos(fc))
815		SET_TX_DESC_QOS(pdesc, 1);
816
817	if ((!ieee80211_is_data_qos(fc)) && ppsc->fwctrl_lps) {
818		SET_TX_DESC_HWSEQ_EN(pdesc, 1);
819		SET_TX_DESC_PKT_ID(pdesc, 8);
820	}
821	SET_TX_DESC_MORE_FRAG(pdesc, (lastseg ? 0 : 1));
822	RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, ("\n"));
823}
824
825void rtl92de_tx_fill_cmddesc(struct ieee80211_hw *hw,
826			     u8 *pdesc, bool firstseg,
827			     bool lastseg, struct sk_buff *skb)
828{
829	struct rtl_priv *rtlpriv = rtl_priv(hw);
830	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
831	struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv);
832	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
833	u8 fw_queue = QSLT_BEACON;
834	dma_addr_t mapping = pci_map_single(rtlpci->pdev,
835		    skb->data, skb->len, PCI_DMA_TODEVICE);
836	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
837	__le16 fc = hdr->frame_control;
838
839	CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE);
840	if (firstseg)
841		SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN);
842	/* 5G have no CCK rate
843	 * Caution: The macros below are multi-line expansions.
844	 * The braces are needed no matter what checkpatch says
845	 */
846	if (rtlhal->current_bandtype == BAND_ON_5G) {
847		SET_TX_DESC_TX_RATE(pdesc, DESC92D_RATE6M);
848	} else {
849		SET_TX_DESC_TX_RATE(pdesc, DESC92D_RATE1M);
850	}
851	SET_TX_DESC_SEQ(pdesc, 0);
852	SET_TX_DESC_LINIP(pdesc, 0);
853	SET_TX_DESC_QUEUE_SEL(pdesc, fw_queue);
854	SET_TX_DESC_FIRST_SEG(pdesc, 1);
855	SET_TX_DESC_LAST_SEG(pdesc, 1);
856	SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) (skb->len));
857	SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, mapping);
858	SET_TX_DESC_RATE_ID(pdesc, 7);
859	SET_TX_DESC_MACID(pdesc, 0);
860	SET_TX_DESC_PKT_SIZE((u8 *) pdesc, (u16) (skb->len));
861	SET_TX_DESC_FIRST_SEG(pdesc, 1);
862	SET_TX_DESC_LAST_SEG(pdesc, 1);
863	SET_TX_DESC_OFFSET(pdesc, 0x20);
864	SET_TX_DESC_USE_RATE(pdesc, 1);
865
866	if (!ieee80211_is_data_qos(fc) && ppsc->fwctrl_lps) {
867		SET_TX_DESC_HWSEQ_EN(pdesc, 1);
868		SET_TX_DESC_PKT_ID(pdesc, 8);
869	}
870
871	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
872		      "H2C Tx Cmd Content\n", pdesc, TX_DESC_SIZE);
873	wmb();
874	SET_TX_DESC_OWN(pdesc, 1);
875}
876
877void rtl92de_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val)
878{
879	if (istx) {
880		switch (desc_name) {
881		case HW_DESC_OWN:
882			wmb();
883			SET_TX_DESC_OWN(pdesc, 1);
884			break;
885		case HW_DESC_TX_NEXTDESC_ADDR:
886			SET_TX_DESC_NEXT_DESC_ADDRESS(pdesc, *(u32 *) val);
887			break;
888		default:
889			RT_ASSERT(false, ("ERR txdesc :%d"
890					  " not process\n", desc_name));
891			break;
892		}
893	} else {
894		switch (desc_name) {
895		case HW_DESC_RXOWN:
896			wmb();
897			SET_RX_DESC_OWN(pdesc, 1);
898			break;
899		case HW_DESC_RXBUFF_ADDR:
900			SET_RX_DESC_BUFF_ADDR(pdesc, *(u32 *) val);
901			break;
902		case HW_DESC_RXPKT_LEN:
903			SET_RX_DESC_PKT_LEN(pdesc, *(u32 *) val);
904			break;
905		case HW_DESC_RXERO:
906			SET_RX_DESC_EOR(pdesc, 1);
907			break;
908		default:
909			RT_ASSERT(false, ("ERR rxdesc :%d "
910					  "not process\n", desc_name));
911			break;
912		}
913	}
914}
915
916u32 rtl92de_get_desc(u8 *p_desc, bool istx, u8 desc_name)
917{
918	u32 ret = 0;
919
920	if (istx) {
921		switch (desc_name) {
922		case HW_DESC_OWN:
923			ret = GET_TX_DESC_OWN(p_desc);
924			break;
925		case HW_DESC_TXBUFF_ADDR:
926			ret = GET_TX_DESC_TX_BUFFER_ADDRESS(p_desc);
927			break;
928		default:
929			RT_ASSERT(false, ("ERR txdesc :%d "
930					  "not process\n", desc_name));
931			break;
932		}
933	} else {
934		struct rx_desc_92c *pdesc = (struct rx_desc_92c *)p_desc;
935		switch (desc_name) {
936		case HW_DESC_OWN:
937			ret = GET_RX_DESC_OWN(pdesc);
938			break;
939		case HW_DESC_RXPKT_LEN:
940			ret = GET_RX_DESC_PKT_LEN(pdesc);
941			break;
942		default:
943			RT_ASSERT(false, ("ERR rxdesc :%d "
944					  "not process\n", desc_name));
945			break;
946		}
947	}
948	return ret;
949}
950
951void rtl92de_tx_polling(struct ieee80211_hw *hw, u8 hw_queue)
952{
953	struct rtl_priv *rtlpriv = rtl_priv(hw);
954	if (hw_queue == BEACON_QUEUE)
955		rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG, BIT(4));
956	else
957		rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG,
958			       BIT(0) << (hw_queue));
959}