trx.c revision 6ebacbb79d2d05978ba50a24d8cbe2a76ff2014c
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 enum rtl_desc_qsel _rtl92ce_map_hwqueue_to_fwqueue(__le16 fc,
40							  unsigned int
41							  skb_queue)
42{
43	enum rtl_desc_qsel qsel;
44
45	if (unlikely(ieee80211_is_beacon(fc))) {
46		qsel = QSLT_BEACON;
47		return qsel;
48	}
49
50	if (ieee80211_is_mgmt(fc)) {
51		qsel = QSLT_MGNT;
52		return qsel;
53	}
54
55	switch (skb_queue) {
56	case VO_QUEUE:
57		qsel = QSLT_VO;
58		break;
59	case VI_QUEUE:
60		qsel = QSLT_VI;
61		break;
62	case BE_QUEUE:
63		qsel = QSLT_BE;
64		break;
65	case BK_QUEUE:
66		qsel = QSLT_BK;
67		break;
68	default:
69		qsel = QSLT_BE;
70		RT_ASSERT(false, ("BE queue, skb_queue:%d,"
71				  " set qsel = 0x%X\n", skb_queue, QSLT_BE));
72		break;
73	}
74	return qsel;
75}
76
77static int _rtl92ce_rate_mapping(bool isht, u8 desc_rate, bool first_ampdu)
78{
79	int rate_idx;
80
81	if (first_ampdu) {
82		if (false == isht) {
83			switch (desc_rate) {
84			case DESC92C_RATE1M:
85				rate_idx = 0;
86				break;
87			case DESC92C_RATE2M:
88				rate_idx = 1;
89				break;
90			case DESC92C_RATE5_5M:
91				rate_idx = 2;
92				break;
93			case DESC92C_RATE11M:
94				rate_idx = 3;
95				break;
96			case DESC92C_RATE6M:
97				rate_idx = 4;
98				break;
99			case DESC92C_RATE9M:
100				rate_idx = 5;
101				break;
102			case DESC92C_RATE12M:
103				rate_idx = 6;
104				break;
105			case DESC92C_RATE18M:
106				rate_idx = 7;
107				break;
108			case DESC92C_RATE24M:
109				rate_idx = 8;
110				break;
111			case DESC92C_RATE36M:
112				rate_idx = 9;
113				break;
114			case DESC92C_RATE48M:
115				rate_idx = 10;
116				break;
117			case DESC92C_RATE54M:
118				rate_idx = 11;
119				break;
120			default:
121				rate_idx = 0;
122				break;
123			}
124		} else {
125			rate_idx = 11;
126		}
127
128		return rate_idx;
129	}
130
131	switch (desc_rate) {
132	case DESC92C_RATE1M:
133		rate_idx = 0;
134		break;
135	case DESC92C_RATE2M:
136		rate_idx = 1;
137		break;
138	case DESC92C_RATE5_5M:
139		rate_idx = 2;
140		break;
141	case DESC92C_RATE11M:
142		rate_idx = 3;
143		break;
144	case DESC92C_RATE6M:
145		rate_idx = 4;
146		break;
147	case DESC92C_RATE9M:
148		rate_idx = 5;
149		break;
150	case DESC92C_RATE12M:
151		rate_idx = 6;
152		break;
153	case DESC92C_RATE18M:
154		rate_idx = 7;
155		break;
156	case DESC92C_RATE24M:
157		rate_idx = 8;
158		break;
159	case DESC92C_RATE36M:
160		rate_idx = 9;
161		break;
162	case DESC92C_RATE48M:
163		rate_idx = 10;
164		break;
165	case DESC92C_RATE54M:
166		rate_idx = 11;
167		break;
168	default:
169		rate_idx = 11;
170		break;
171	}
172	return rate_idx;
173}
174
175static u8 _rtl92c_query_rxpwrpercentage(char antpower)
176{
177	if ((antpower <= -100) || (antpower >= 20))
178		return 0;
179	else if (antpower >= 0)
180		return 100;
181	else
182		return 100 + antpower;
183}
184
185static u8 _rtl92c_evm_db_to_percentage(char value)
186{
187	char ret_val;
188	ret_val = value;
189
190	if (ret_val >= 0)
191		ret_val = 0;
192
193	if (ret_val <= -33)
194		ret_val = -33;
195
196	ret_val = 0 - ret_val;
197	ret_val *= 3;
198
199	if (ret_val == 99)
200		ret_val = 100;
201
202	return ret_val;
203}
204
205static long _rtl92ce_translate_todbm(struct ieee80211_hw *hw,
206				     u8 signal_strength_index)
207{
208	long signal_power;
209
210	signal_power = (long)((signal_strength_index + 1) >> 1);
211	signal_power -= 95;
212	return signal_power;
213}
214
215static long _rtl92ce_signal_scale_mapping(struct ieee80211_hw *hw,
216		long currsig)
217{
218	long retsig;
219
220	if (currsig >= 61 && currsig <= 100)
221		retsig = 90 + ((currsig - 60) / 4);
222	else if (currsig >= 41 && currsig <= 60)
223		retsig = 78 + ((currsig - 40) / 2);
224	else if (currsig >= 31 && currsig <= 40)
225		retsig = 66 + (currsig - 30);
226	else if (currsig >= 21 && currsig <= 30)
227		retsig = 54 + (currsig - 20);
228	else if (currsig >= 5 && currsig <= 20)
229		retsig = 42 + (((currsig - 5) * 2) / 3);
230	else if (currsig == 4)
231		retsig = 36;
232	else if (currsig == 3)
233		retsig = 27;
234	else if (currsig == 2)
235		retsig = 18;
236	else if (currsig == 1)
237		retsig = 9;
238	else
239		retsig = currsig;
240
241	return retsig;
242}
243
244static void _rtl92ce_query_rxphystatus(struct ieee80211_hw *hw,
245				       struct rtl_stats *pstats,
246				       struct rx_desc_92c *pdesc,
247				       struct rx_fwinfo_92c *p_drvinfo,
248				       bool packet_match_bssid,
249				       bool packet_toself,
250				       bool packet_beacon)
251{
252	struct rtl_priv *rtlpriv = rtl_priv(hw);
253	struct phy_sts_cck_8192s_t *cck_buf;
254	s8 rx_pwr_all, rx_pwr[4];
255	u8 rf_rx_num, evm, pwdb_all;
256	u8 i, max_spatial_stream;
257	u32 rssi, total_rssi;
258	bool is_cck_rate;
259
260	is_cck_rate = RX_HAL_IS_CCK_RATE(pdesc);
261	pstats->packet_matchbssid = packet_match_bssid;
262	pstats->packet_toself = packet_toself;
263	pstats->is_cck = is_cck_rate;
264	pstats->packet_beacon = packet_beacon;
265	pstats->is_cck = is_cck_rate;
266	pstats->rx_mimo_signalquality[0] = -1;
267	pstats->rx_mimo_signalquality[1] = -1;
268
269	if (is_cck_rate) {
270		u8 report, cck_highpwr;
271		cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo;
272
273		cck_highpwr = (u8) rtl_get_bbreg(hw,
274					 RFPGA0_XA_HSSIPARAMETER2,
275					 BIT(9));
276		if (!cck_highpwr) {
277			u8 cck_agc_rpt = cck_buf->cck_agc_rpt;
278			report = cck_buf->cck_agc_rpt & 0xc0;
279			report = report >> 6;
280			switch (report) {
281			case 0x3:
282				rx_pwr_all = -46 - (cck_agc_rpt & 0x3e);
283				break;
284			case 0x2:
285				rx_pwr_all = -26 - (cck_agc_rpt & 0x3e);
286				break;
287			case 0x1:
288				rx_pwr_all = -12 - (cck_agc_rpt & 0x3e);
289				break;
290			case 0x0:
291				rx_pwr_all = 16 - (cck_agc_rpt & 0x3e);
292				break;
293			}
294		} else {
295			u8 cck_agc_rpt = cck_buf->cck_agc_rpt;
296			report = p_drvinfo->cfosho[0] & 0x60;
297			report = report >> 5;
298			switch (report) {
299			case 0x3:
300				rx_pwr_all = -46 - ((cck_agc_rpt & 0x1f) << 1);
301				break;
302			case 0x2:
303				rx_pwr_all = -26 - ((cck_agc_rpt & 0x1f) << 1);
304				break;
305			case 0x1:
306				rx_pwr_all = -12 - ((cck_agc_rpt & 0x1f) << 1);
307				break;
308			case 0x0:
309				rx_pwr_all = 16 - ((cck_agc_rpt & 0x1f) << 1);
310				break;
311			}
312		}
313
314		pwdb_all = _rtl92c_query_rxpwrpercentage(rx_pwr_all);
315		pstats->rx_pwdb_all = pwdb_all;
316		pstats->recvsignalpower = rx_pwr_all;
317
318		if (packet_match_bssid) {
319			u8 sq;
320			if (pstats->rx_pwdb_all > 40)
321				sq = 100;
322			else {
323				sq = cck_buf->sq_rpt;
324				if (sq > 64)
325					sq = 0;
326				else if (sq < 20)
327					sq = 100;
328				else
329					sq = ((64 - sq) * 100) / 44;
330			}
331
332			pstats->signalquality = sq;
333			pstats->rx_mimo_signalquality[0] = sq;
334			pstats->rx_mimo_signalquality[1] = -1;
335		}
336	} else {
337		rtlpriv->dm.rfpath_rxenable[0] =
338		    rtlpriv->dm.rfpath_rxenable[1] = true;
339		for (i = RF90_PATH_A; i < RF90_PATH_MAX; i++) {
340			if (rtlpriv->dm.rfpath_rxenable[i])
341				rf_rx_num++;
342
343			rx_pwr[i] =
344			    ((p_drvinfo->gain_trsw[i] & 0x3f) * 2) - 110;
345			rssi = _rtl92c_query_rxpwrpercentage(rx_pwr[i]);
346			total_rssi += rssi;
347			rtlpriv->stats.rx_snr_db[i] =
348			    (long)(p_drvinfo->rxsnr[i] / 2);
349
350			if (packet_match_bssid)
351				pstats->rx_mimo_signalstrength[i] = (u8) rssi;
352		}
353
354		rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 110;
355		pwdb_all = _rtl92c_query_rxpwrpercentage(rx_pwr_all);
356		pstats->rx_pwdb_all = pwdb_all;
357		pstats->rxpower = rx_pwr_all;
358		pstats->recvsignalpower = rx_pwr_all;
359
360		if (pdesc->rxht && pdesc->rxmcs >= DESC92C_RATEMCS8 &&
361		    pdesc->rxmcs <= DESC92C_RATEMCS15)
362			max_spatial_stream = 2;
363		else
364			max_spatial_stream = 1;
365
366		for (i = 0; i < max_spatial_stream; i++) {
367			evm = _rtl92c_evm_db_to_percentage(p_drvinfo->rxevm[i]);
368
369			if (packet_match_bssid) {
370				if (i == 0)
371					pstats->signalquality =
372					    (u8) (evm & 0xff);
373				pstats->rx_mimo_signalquality[i] =
374				    (u8) (evm & 0xff);
375			}
376		}
377	}
378
379	if (is_cck_rate)
380		pstats->signalstrength =
381		    (u8) (_rtl92ce_signal_scale_mapping(hw, pwdb_all));
382	else if (rf_rx_num != 0)
383		pstats->signalstrength =
384		    (u8) (_rtl92ce_signal_scale_mapping
385			  (hw, total_rssi /= rf_rx_num));
386}
387
388static void _rtl92ce_process_ui_rssi(struct ieee80211_hw *hw,
389		struct rtl_stats *pstats)
390{
391	struct rtl_priv *rtlpriv = rtl_priv(hw);
392	struct rtl_phy *rtlphy = &(rtlpriv->phy);
393	u8 rfpath;
394	u32 last_rssi, tmpval;
395
396	if (pstats->packet_toself || pstats->packet_beacon) {
397		rtlpriv->stats.rssi_calculate_cnt++;
398
399		if (rtlpriv->stats.ui_rssi.total_num++ >=
400		    PHY_RSSI_SLID_WIN_MAX) {
401			rtlpriv->stats.ui_rssi.total_num =
402			    PHY_RSSI_SLID_WIN_MAX;
403			last_rssi =
404			    rtlpriv->stats.ui_rssi.elements[rtlpriv->
405						    stats.ui_rssi.index];
406			rtlpriv->stats.ui_rssi.total_val -= last_rssi;
407		}
408
409		rtlpriv->stats.ui_rssi.total_val += pstats->signalstrength;
410		rtlpriv->stats.ui_rssi.elements[rtlpriv->stats.ui_rssi.
411						index++] =
412		    pstats->signalstrength;
413
414		if (rtlpriv->stats.ui_rssi.index >= PHY_RSSI_SLID_WIN_MAX)
415			rtlpriv->stats.ui_rssi.index = 0;
416
417		tmpval = rtlpriv->stats.ui_rssi.total_val /
418		    rtlpriv->stats.ui_rssi.total_num;
419		rtlpriv->stats.signal_strength =
420		    _rtl92ce_translate_todbm(hw, (u8) tmpval);
421		pstats->rssi = rtlpriv->stats.signal_strength;
422	}
423
424	if (!pstats->is_cck && pstats->packet_toself) {
425		for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath;
426		     rfpath++) {
427
428			if (!rtl8192_phy_check_is_legal_rfpath(hw, rfpath))
429				continue;
430
431			if (rtlpriv->stats.rx_rssi_percentage[rfpath] == 0) {
432				rtlpriv->stats.rx_rssi_percentage[rfpath] =
433				    pstats->rx_mimo_signalstrength[rfpath];
434
435			}
436
437			if (pstats->rx_mimo_signalstrength[rfpath] >
438			    rtlpriv->stats.rx_rssi_percentage[rfpath]) {
439				rtlpriv->stats.rx_rssi_percentage[rfpath] =
440				    ((rtlpriv->stats.
441				      rx_rssi_percentage[rfpath] *
442				      (RX_SMOOTH_FACTOR - 1)) +
443				     (pstats->rx_mimo_signalstrength[rfpath])) /
444				    (RX_SMOOTH_FACTOR);
445
446				rtlpriv->stats.rx_rssi_percentage[rfpath] =
447				    rtlpriv->stats.rx_rssi_percentage[rfpath] +
448				    1;
449			} else {
450				rtlpriv->stats.rx_rssi_percentage[rfpath] =
451				    ((rtlpriv->stats.
452				      rx_rssi_percentage[rfpath] *
453				      (RX_SMOOTH_FACTOR - 1)) +
454				     (pstats->rx_mimo_signalstrength[rfpath])) /
455				    (RX_SMOOTH_FACTOR);
456			}
457
458		}
459	}
460}
461
462static void _rtl92ce_update_rxsignalstatistics(struct ieee80211_hw *hw,
463					       struct rtl_stats *pstats)
464{
465	struct rtl_priv *rtlpriv = rtl_priv(hw);
466	int weighting;
467
468	if (rtlpriv->stats.recv_signal_power == 0)
469		rtlpriv->stats.recv_signal_power = pstats->recvsignalpower;
470
471	if (pstats->recvsignalpower > rtlpriv->stats.recv_signal_power)
472		weighting = 5;
473
474	else if (pstats->recvsignalpower < rtlpriv->stats.recv_signal_power)
475		weighting = (-5);
476
477	rtlpriv->stats.recv_signal_power =
478	    (rtlpriv->stats.recv_signal_power * 5 +
479	     pstats->recvsignalpower + weighting) / 6;
480}
481
482static void _rtl92ce_process_pwdb(struct ieee80211_hw *hw,
483		struct rtl_stats *pstats)
484{
485	struct rtl_priv *rtlpriv = rtl_priv(hw);
486	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
487	long undecorated_smoothed_pwdb;
488
489	if (mac->opmode == NL80211_IFTYPE_ADHOC) {
490		return;
491	} else {
492		undecorated_smoothed_pwdb =
493		    rtlpriv->dm.undecorated_smoothed_pwdb;
494	}
495
496	if (pstats->packet_toself || pstats->packet_beacon) {
497		if (undecorated_smoothed_pwdb < 0)
498			undecorated_smoothed_pwdb = pstats->rx_pwdb_all;
499
500		if (pstats->rx_pwdb_all > (u32) undecorated_smoothed_pwdb) {
501			undecorated_smoothed_pwdb =
502			    (((undecorated_smoothed_pwdb) *
503			      (RX_SMOOTH_FACTOR - 1)) +
504			     (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
505
506			undecorated_smoothed_pwdb = undecorated_smoothed_pwdb
507			    + 1;
508		} else {
509			undecorated_smoothed_pwdb =
510			    (((undecorated_smoothed_pwdb) *
511			      (RX_SMOOTH_FACTOR - 1)) +
512			     (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
513		}
514
515		rtlpriv->dm.undecorated_smoothed_pwdb =
516		    undecorated_smoothed_pwdb;
517		_rtl92ce_update_rxsignalstatistics(hw, pstats);
518	}
519}
520
521static void _rtl92ce_process_ui_link_quality(struct ieee80211_hw *hw,
522					     struct rtl_stats *pstats)
523{
524	struct rtl_priv *rtlpriv = rtl_priv(hw);
525	u32 last_evm, n_spatialstream, tmpval;
526
527	if (pstats->signalquality != 0) {
528		if (pstats->packet_toself || pstats->packet_beacon) {
529
530			if (rtlpriv->stats.ui_link_quality.total_num++ >=
531			    PHY_LINKQUALITY_SLID_WIN_MAX) {
532				rtlpriv->stats.ui_link_quality.total_num =
533				    PHY_LINKQUALITY_SLID_WIN_MAX;
534				last_evm =
535				    rtlpriv->stats.
536				    ui_link_quality.elements[rtlpriv->
537							  stats.ui_link_quality.
538							  index];
539				rtlpriv->stats.ui_link_quality.total_val -=
540				    last_evm;
541			}
542
543			rtlpriv->stats.ui_link_quality.total_val +=
544			    pstats->signalquality;
545			rtlpriv->stats.ui_link_quality.elements[rtlpriv->stats.
546								ui_link_quality.
547								index++] =
548			    pstats->signalquality;
549
550			if (rtlpriv->stats.ui_link_quality.index >=
551			    PHY_LINKQUALITY_SLID_WIN_MAX)
552				rtlpriv->stats.ui_link_quality.index = 0;
553
554			tmpval = rtlpriv->stats.ui_link_quality.total_val /
555			    rtlpriv->stats.ui_link_quality.total_num;
556			rtlpriv->stats.signal_quality = tmpval;
557
558			rtlpriv->stats.last_sigstrength_inpercent = tmpval;
559
560			for (n_spatialstream = 0; n_spatialstream < 2;
561			     n_spatialstream++) {
562				if (pstats->
563				    rx_mimo_signalquality[n_spatialstream] !=
564				    -1) {
565					if (rtlpriv->stats.
566					    rx_evm_percentage[n_spatialstream]
567					    == 0) {
568						rtlpriv->stats.
569						   rx_evm_percentage
570						   [n_spatialstream] =
571						   pstats->rx_mimo_signalquality
572						   [n_spatialstream];
573					}
574
575					rtlpriv->stats.
576					    rx_evm_percentage[n_spatialstream] =
577					    ((rtlpriv->
578					      stats.rx_evm_percentage
579					      [n_spatialstream] *
580					      (RX_SMOOTH_FACTOR - 1)) +
581					     (pstats->
582					      rx_mimo_signalquality
583					      [n_spatialstream] * 1)) /
584					    (RX_SMOOTH_FACTOR);
585				}
586			}
587		}
588	} else {
589		;
590	}
591}
592
593static void _rtl92ce_process_phyinfo(struct ieee80211_hw *hw,
594				     u8 *buffer,
595				     struct rtl_stats *pcurrent_stats)
596{
597
598	if (!pcurrent_stats->packet_matchbssid &&
599	    !pcurrent_stats->packet_beacon)
600		return;
601
602	_rtl92ce_process_ui_rssi(hw, pcurrent_stats);
603	_rtl92ce_process_pwdb(hw, pcurrent_stats);
604	_rtl92ce_process_ui_link_quality(hw, pcurrent_stats);
605}
606
607static void _rtl92ce_translate_rx_signal_stuff(struct ieee80211_hw *hw,
608					       struct sk_buff *skb,
609					       struct rtl_stats *pstats,
610					       struct rx_desc_92c *pdesc,
611					       struct rx_fwinfo_92c *p_drvinfo)
612{
613	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
614	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
615
616	struct ieee80211_hdr *hdr;
617	u8 *tmp_buf;
618	u8 *praddr;
619	u8 *psaddr;
620	__le16 fc;
621	u16 type, c_fc;
622	bool packet_matchbssid, packet_toself, packet_beacon;
623
624	tmp_buf = skb->data + pstats->rx_drvinfo_size + pstats->rx_bufshift;
625
626	hdr = (struct ieee80211_hdr *)tmp_buf;
627	fc = hdr->frame_control;
628	c_fc = le16_to_cpu(fc);
629	type = WLAN_FC_GET_TYPE(fc);
630	praddr = hdr->addr1;
631	psaddr = hdr->addr2;
632
633	packet_matchbssid =
634	    ((IEEE80211_FTYPE_CTL != type) &&
635	     (!compare_ether_addr(mac->bssid,
636				  (c_fc & IEEE80211_FCTL_TODS) ?
637				  hdr->addr1 : (c_fc & IEEE80211_FCTL_FROMDS) ?
638				  hdr->addr2 : hdr->addr3)) &&
639	     (!pstats->hwerror) && (!pstats->crc) && (!pstats->icv));
640
641	packet_toself = packet_matchbssid &&
642	    (!compare_ether_addr(praddr, rtlefuse->dev_addr));
643
644	if (ieee80211_is_beacon(fc))
645		packet_beacon = true;
646
647	_rtl92ce_query_rxphystatus(hw, pstats, pdesc, p_drvinfo,
648				   packet_matchbssid, packet_toself,
649				   packet_beacon);
650
651	_rtl92ce_process_phyinfo(hw, tmp_buf, pstats);
652}
653
654bool rtl92ce_rx_query_desc(struct ieee80211_hw *hw,
655			   struct rtl_stats *stats,
656			   struct ieee80211_rx_status *rx_status,
657			   u8 *p_desc, struct sk_buff *skb)
658{
659	struct rx_fwinfo_92c *p_drvinfo;
660	struct rx_desc_92c *pdesc = (struct rx_desc_92c *)p_desc;
661
662	u32 phystatus = GET_RX_DESC_PHYST(pdesc);
663	stats->length = (u16) GET_RX_DESC_PKT_LEN(pdesc);
664	stats->rx_drvinfo_size = (u8) GET_RX_DESC_DRV_INFO_SIZE(pdesc) *
665	    RX_DRV_INFO_SIZE_UNIT;
666	stats->rx_bufshift = (u8) (GET_RX_DESC_SHIFT(pdesc) & 0x03);
667	stats->icv = (u16) GET_RX_DESC_ICV(pdesc);
668	stats->crc = (u16) GET_RX_DESC_CRC32(pdesc);
669	stats->hwerror = (stats->crc | stats->icv);
670	stats->decrypted = !GET_RX_DESC_SWDEC(pdesc);
671	stats->rate = (u8) GET_RX_DESC_RXMCS(pdesc);
672	stats->shortpreamble = (u16) GET_RX_DESC_SPLCP(pdesc);
673	stats->isampdu = (bool) (GET_RX_DESC_PAGGR(pdesc) == 1);
674	stats->isampdu = (bool) ((GET_RX_DESC_PAGGR(pdesc) == 1)
675				   && (GET_RX_DESC_FAGGR(pdesc) == 1));
676	stats->timestamp_low = GET_RX_DESC_TSFL(pdesc);
677	stats->rx_is40Mhzpacket = (bool) GET_RX_DESC_BW(pdesc);
678
679	rx_status->freq = hw->conf.channel->center_freq;
680	rx_status->band = hw->conf.channel->band;
681
682	if (GET_RX_DESC_CRC32(pdesc))
683		rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
684
685	if (!GET_RX_DESC_SWDEC(pdesc))
686		rx_status->flag |= RX_FLAG_DECRYPTED;
687
688	if (GET_RX_DESC_BW(pdesc))
689		rx_status->flag |= RX_FLAG_40MHZ;
690
691	if (GET_RX_DESC_RXHT(pdesc))
692		rx_status->flag |= RX_FLAG_HT;
693
694	rx_status->flag |= RX_FLAG_MACTIME_MPDU;
695
696	if (stats->decrypted)
697		rx_status->flag |= RX_FLAG_DECRYPTED;
698
699	rx_status->rate_idx = _rtl92ce_rate_mapping((bool)
700						    GET_RX_DESC_RXHT(pdesc),
701						    (u8)
702						    GET_RX_DESC_RXMCS(pdesc),
703						    (bool)
704						    GET_RX_DESC_PAGGR(pdesc));
705
706	rx_status->mactime = GET_RX_DESC_TSFL(pdesc);
707	if (phystatus == true) {
708		p_drvinfo = (struct rx_fwinfo_92c *)(skb->data +
709						     stats->rx_bufshift);
710
711		_rtl92ce_translate_rx_signal_stuff(hw,
712						   skb, stats, pdesc,
713						   p_drvinfo);
714	}
715
716	/*rx_status->qual = stats->signal; */
717	rx_status->signal = stats->rssi + 10;
718	/*rx_status->noise = -stats->noise; */
719
720	return true;
721}
722
723void rtl92ce_tx_fill_desc(struct ieee80211_hw *hw,
724			  struct ieee80211_hdr *hdr, u8 *pdesc_tx,
725			  struct ieee80211_tx_info *info, struct sk_buff *skb,
726			  unsigned int queue_index)
727{
728	struct rtl_priv *rtlpriv = rtl_priv(hw);
729	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
730	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
731	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
732	bool defaultadapter = true;
733	struct ieee80211_sta *sta = ieee80211_find_sta(mac->vif, mac->bssid);
734	u8 *pdesc = (u8 *) pdesc_tx;
735	struct rtl_tcb_desc tcb_desc;
736	u8 *qc = ieee80211_get_qos_ctl(hdr);
737	u8 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
738	u16 seq_number;
739	__le16 fc = hdr->frame_control;
740	u8 rate_flag = info->control.rates[0].flags;
741
742	enum rtl_desc_qsel fw_qsel =
743	    _rtl92ce_map_hwqueue_to_fwqueue(fc, queue_index);
744
745	bool firstseg = ((hdr->seq_ctrl &
746			  cpu_to_le16(IEEE80211_SCTL_FRAG)) == 0);
747
748	bool lastseg = ((hdr->frame_control &
749			 cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)) == 0);
750
751	dma_addr_t mapping = pci_map_single(rtlpci->pdev,
752					    skb->data, skb->len,
753					    PCI_DMA_TODEVICE);
754
755	seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4;
756
757	rtl_get_tcb_desc(hw, info, skb, &tcb_desc);
758
759	CLEAR_PCI_TX_DESC_CONTENT(pdesc, sizeof(struct tx_desc_92c));
760
761	if (firstseg) {
762		SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN);
763
764		SET_TX_DESC_TX_RATE(pdesc, tcb_desc.hw_rate);
765
766		if (tcb_desc.use_shortgi || tcb_desc.use_shortpreamble)
767			SET_TX_DESC_DATA_SHORTGI(pdesc, 1);
768
769		if (mac->tids[tid].agg.agg_state == RTL_AGG_ON &&
770		    info->flags & IEEE80211_TX_CTL_AMPDU) {
771			SET_TX_DESC_AGG_BREAK(pdesc, 1);
772			SET_TX_DESC_MAX_AGG_NUM(pdesc, 0x14);
773		}
774		SET_TX_DESC_SEQ(pdesc, seq_number);
775
776		SET_TX_DESC_RTS_ENABLE(pdesc, ((tcb_desc.rts_enable &&
777						!tcb_desc.
778						cts_enable) ? 1 : 0));
779		SET_TX_DESC_HW_RTS_ENABLE(pdesc,
780					  ((tcb_desc.rts_enable
781					    || tcb_desc.cts_enable) ? 1 : 0));
782		SET_TX_DESC_CTS2SELF(pdesc, ((tcb_desc.cts_enable) ? 1 : 0));
783		SET_TX_DESC_RTS_STBC(pdesc, ((tcb_desc.rts_stbc) ? 1 : 0));
784
785		SET_TX_DESC_RTS_RATE(pdesc, tcb_desc.rts_rate);
786		SET_TX_DESC_RTS_BW(pdesc, 0);
787		SET_TX_DESC_RTS_SC(pdesc, tcb_desc.rts_sc);
788		SET_TX_DESC_RTS_SHORT(pdesc,
789				      ((tcb_desc.rts_rate <= DESC92C_RATE54M) ?
790				      (tcb_desc.rts_use_shortpreamble ? 1 : 0)
791				      : (tcb_desc.rts_use_shortgi ? 1 : 0)));
792
793		if (mac->bw_40) {
794			if (tcb_desc.packet_bw) {
795				SET_TX_DESC_DATA_BW(pdesc, 1);
796				SET_TX_DESC_TX_SUB_CARRIER(pdesc, 3);
797			} else {
798				SET_TX_DESC_DATA_BW(pdesc, 0);
799
800				if (rate_flag & IEEE80211_TX_RC_DUP_DATA) {
801					SET_TX_DESC_TX_SUB_CARRIER(pdesc,
802							mac->cur_40_prime_sc);
803				}
804			}
805		} else {
806			SET_TX_DESC_DATA_BW(pdesc, 0);
807			SET_TX_DESC_TX_SUB_CARRIER(pdesc, 0);
808		}
809
810		SET_TX_DESC_LINIP(pdesc, 0);
811		SET_TX_DESC_PKT_SIZE(pdesc, (u16) skb->len);
812
813		if (sta) {
814			u8 ampdu_density = sta->ht_cap.ampdu_density;
815			SET_TX_DESC_AMPDU_DENSITY(pdesc, ampdu_density);
816		}
817
818		if (info->control.hw_key) {
819			struct ieee80211_key_conf *keyconf =
820			    info->control.hw_key;
821
822			switch (keyconf->cipher) {
823			case WLAN_CIPHER_SUITE_WEP40:
824			case WLAN_CIPHER_SUITE_WEP104:
825			case WLAN_CIPHER_SUITE_TKIP:
826				SET_TX_DESC_SEC_TYPE(pdesc, 0x1);
827				break;
828			case WLAN_CIPHER_SUITE_CCMP:
829				SET_TX_DESC_SEC_TYPE(pdesc, 0x3);
830				break;
831			default:
832				SET_TX_DESC_SEC_TYPE(pdesc, 0x0);
833				break;
834
835			}
836		}
837
838		SET_TX_DESC_PKT_ID(pdesc, 0);
839		SET_TX_DESC_QUEUE_SEL(pdesc, fw_qsel);
840
841		SET_TX_DESC_DATA_RATE_FB_LIMIT(pdesc, 0x1F);
842		SET_TX_DESC_RTS_RATE_FB_LIMIT(pdesc, 0xF);
843		SET_TX_DESC_DISABLE_FB(pdesc, 0);
844		SET_TX_DESC_USE_RATE(pdesc, tcb_desc.use_driver_rate ? 1 : 0);
845
846		if (ieee80211_is_data_qos(fc)) {
847			if (mac->rdg_en) {
848				RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE,
849					 ("Enable RDG function.\n"));
850				SET_TX_DESC_RDG_ENABLE(pdesc, 1);
851				SET_TX_DESC_HTC(pdesc, 1);
852			}
853		}
854	}
855
856	SET_TX_DESC_FIRST_SEG(pdesc, (firstseg ? 1 : 0));
857	SET_TX_DESC_LAST_SEG(pdesc, (lastseg ? 1 : 0));
858
859	SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) skb->len);
860
861	SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, cpu_to_le32(mapping));
862
863	if (rtlpriv->dm.useramask) {
864		SET_TX_DESC_RATE_ID(pdesc, tcb_desc.ratr_index);
865		SET_TX_DESC_MACID(pdesc, tcb_desc.mac_id);
866	} else {
867		SET_TX_DESC_RATE_ID(pdesc, 0xC + tcb_desc.ratr_index);
868		SET_TX_DESC_MACID(pdesc, tcb_desc.ratr_index);
869	}
870
871	if ((!ieee80211_is_data_qos(fc)) && ppsc->leisure_ps &&
872	    ppsc->fwctrl_lps) {
873		SET_TX_DESC_HWSEQ_EN(pdesc, 1);
874		SET_TX_DESC_PKT_ID(pdesc, 8);
875
876		if (!defaultadapter)
877			SET_TX_DESC_QOS(pdesc, 1);
878	}
879
880	SET_TX_DESC_MORE_FRAG(pdesc, (lastseg ? 0 : 1));
881
882	if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) ||
883	    is_broadcast_ether_addr(ieee80211_get_DA(hdr))) {
884		SET_TX_DESC_BMC(pdesc, 1);
885	}
886
887	RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, ("\n"));
888}
889
890void rtl92ce_tx_fill_cmddesc(struct ieee80211_hw *hw,
891			     u8 *pdesc, bool firstseg,
892			     bool lastseg, struct sk_buff *skb)
893{
894	struct rtl_priv *rtlpriv = rtl_priv(hw);
895	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
896	u8 fw_queue = QSLT_BEACON;
897
898	dma_addr_t mapping = pci_map_single(rtlpci->pdev,
899					    skb->data, skb->len,
900					    PCI_DMA_TODEVICE);
901
902	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
903	__le16 fc = hdr->frame_control;
904
905	CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE);
906
907	if (firstseg)
908		SET_TX_DESC_OFFSET(pdesc, USB_HWDESC_HEADER_LEN);
909
910	SET_TX_DESC_TX_RATE(pdesc, DESC92C_RATE1M);
911
912	SET_TX_DESC_SEQ(pdesc, 0);
913
914	SET_TX_DESC_LINIP(pdesc, 0);
915
916	SET_TX_DESC_QUEUE_SEL(pdesc, fw_queue);
917
918	SET_TX_DESC_FIRST_SEG(pdesc, 1);
919	SET_TX_DESC_LAST_SEG(pdesc, 1);
920
921	SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) (skb->len));
922
923	SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, cpu_to_le32(mapping));
924
925	SET_TX_DESC_RATE_ID(pdesc, 7);
926	SET_TX_DESC_MACID(pdesc, 0);
927
928	SET_TX_DESC_OWN(pdesc, 1);
929
930	SET_TX_DESC_PKT_SIZE((u8 *) pdesc, (u16) (skb->len));
931
932	SET_TX_DESC_FIRST_SEG(pdesc, 1);
933	SET_TX_DESC_LAST_SEG(pdesc, 1);
934
935	SET_TX_DESC_OFFSET(pdesc, 0x20);
936
937	SET_TX_DESC_USE_RATE(pdesc, 1);
938
939	if (!ieee80211_is_data_qos(fc)) {
940		SET_TX_DESC_HWSEQ_EN(pdesc, 1);
941		SET_TX_DESC_PKT_ID(pdesc, 8);
942	}
943
944	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
945		      "H2C Tx Cmd Content\n",
946		      pdesc, TX_DESC_SIZE);
947}
948
949void rtl92ce_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val)
950{
951	if (istx == true) {
952		switch (desc_name) {
953		case HW_DESC_OWN:
954			SET_TX_DESC_OWN(pdesc, 1);
955			break;
956		case HW_DESC_TX_NEXTDESC_ADDR:
957			SET_TX_DESC_NEXT_DESC_ADDRESS(pdesc, *(u32 *) val);
958			break;
959		default:
960			RT_ASSERT(false, ("ERR txdesc :%d"
961					  " not process\n", desc_name));
962			break;
963		}
964	} else {
965		switch (desc_name) {
966		case HW_DESC_RXOWN:
967			SET_RX_DESC_OWN(pdesc, 1);
968			break;
969		case HW_DESC_RXBUFF_ADDR:
970			SET_RX_DESC_BUFF_ADDR(pdesc, *(u32 *) val);
971			break;
972		case HW_DESC_RXPKT_LEN:
973			SET_RX_DESC_PKT_LEN(pdesc, *(u32 *) val);
974			break;
975		case HW_DESC_RXERO:
976			SET_RX_DESC_EOR(pdesc, 1);
977			break;
978		default:
979			RT_ASSERT(false, ("ERR rxdesc :%d "
980					  "not process\n", desc_name));
981			break;
982		}
983	}
984}
985
986u32 rtl92ce_get_desc(u8 *p_desc, bool istx, u8 desc_name)
987{
988	u32 ret = 0;
989
990	if (istx == true) {
991		switch (desc_name) {
992		case HW_DESC_OWN:
993			ret = GET_TX_DESC_OWN(p_desc);
994			break;
995		case HW_DESC_TXBUFF_ADDR:
996			ret = GET_TX_DESC_TX_BUFFER_ADDRESS(p_desc);
997			break;
998		default:
999			RT_ASSERT(false, ("ERR txdesc :%d "
1000					  "not process\n", desc_name));
1001			break;
1002		}
1003	} else {
1004		struct rx_desc_92c *pdesc = (struct rx_desc_92c *)p_desc;
1005		switch (desc_name) {
1006		case HW_DESC_OWN:
1007			ret = GET_RX_DESC_OWN(pdesc);
1008			break;
1009		case HW_DESC_RXPKT_LEN:
1010			ret = GET_RX_DESC_PKT_LEN(pdesc);
1011			break;
1012		default:
1013			RT_ASSERT(false, ("ERR rxdesc :%d "
1014					  "not process\n", desc_name));
1015			break;
1016		}
1017	}
1018	return ret;
1019}
1020
1021void rtl92ce_tx_polling(struct ieee80211_hw *hw, unsigned int hw_queue)
1022{
1023	struct rtl_priv *rtlpriv = rtl_priv(hw);
1024	if (hw_queue == BEACON_QUEUE) {
1025		rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG, BIT(4));
1026	} else {
1027		rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG,
1028			       BIT(0) << (hw_queue));
1029	}
1030}
1031
1032bool _rtl92c_cmd_send_packet(struct ieee80211_hw *hw,
1033			     struct sk_buff *skb)
1034{
1035	struct rtl_priv *rtlpriv = rtl_priv(hw);
1036	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
1037	struct rtl8192_tx_ring *ring;
1038	struct rtl_tx_desc *pdesc;
1039	u8 own;
1040	unsigned long flags;
1041	struct sk_buff *pskb = NULL;
1042
1043	ring = &rtlpci->tx_ring[BEACON_QUEUE];
1044
1045	spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags);
1046
1047	pskb = __skb_dequeue(&ring->queue);
1048	if (pskb)
1049		kfree_skb(pskb);
1050
1051	pdesc = &ring->desc[0];
1052	own = (u8) rtlpriv->cfg->ops->get_desc((u8 *) pdesc, true, HW_DESC_OWN);
1053
1054	rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *) pdesc, 1, 1, skb);
1055
1056	__skb_queue_tail(&ring->queue, skb);
1057
1058	spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags);
1059
1060	rtlpriv->cfg->ops->tx_polling(hw, BEACON_QUEUE);
1061
1062	return true;
1063}
1064