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