Linux Audio

Check our new training course

Buildroot integration, development and maintenance

Need a Buildroot system for your embedded project?
Loading...
v3.1
  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 "fw.h"
 37#include "trx.h"
 38#include "led.h"
 39
 40static u8 _rtl92se_map_hwqueue_to_fwqueue(struct sk_buff *skb,	u8 skb_queue)
 41{
 42	__le16 fc = rtl_get_fc(skb);
 43
 44	if (unlikely(ieee80211_is_beacon(fc)))
 45		return QSLT_BEACON;
 46	if (ieee80211_is_mgmt(fc))
 47		return QSLT_MGNT;
 48	if (ieee80211_is_nullfunc(fc))
 49		return QSLT_HIGH;
 50
 51	return skb->priority;
 52}
 53
 54static int _rtl92se_rate_mapping(bool isht, u8 desc_rate, bool first_ampdu)
 55{
 56	int rate_idx = 0;
 57
 58	if (first_ampdu) {
 59		if (false == isht) {
 60			switch (desc_rate) {
 61			case DESC92S_RATE1M:
 62				rate_idx = 0;
 63				break;
 64			case DESC92S_RATE2M:
 65				rate_idx = 1;
 66				break;
 67			case DESC92S_RATE5_5M:
 68				rate_idx = 2;
 69				break;
 70			case DESC92S_RATE11M:
 71				rate_idx = 3;
 72				break;
 73			case DESC92S_RATE6M:
 74				rate_idx = 4;
 75				break;
 76			case DESC92S_RATE9M:
 77				rate_idx = 5;
 78				break;
 79			case DESC92S_RATE12M:
 80				rate_idx = 6;
 81				break;
 82			case DESC92S_RATE18M:
 83				rate_idx = 7;
 84				break;
 85			case DESC92S_RATE24M:
 86				rate_idx = 8;
 87				break;
 88			case DESC92S_RATE36M:
 89				rate_idx = 9;
 90				break;
 91			case DESC92S_RATE48M:
 92				rate_idx = 10;
 93				break;
 94			case DESC92S_RATE54M:
 95				rate_idx = 11;
 96				break;
 97			default:
 98				rate_idx = 0;
 99				break;
100			}
101		} else {
102			rate_idx = 11;
103		}
104
105		return rate_idx;
106	}
107
108	switch (desc_rate) {
109	case DESC92S_RATE1M:
110		rate_idx = 0;
111		break;
112	case DESC92S_RATE2M:
113		rate_idx = 1;
114		break;
115	case DESC92S_RATE5_5M:
116		rate_idx = 2;
117		break;
118	case DESC92S_RATE11M:
119		rate_idx = 3;
120		break;
121	case DESC92S_RATE6M:
122		rate_idx = 4;
123		break;
124	case DESC92S_RATE9M:
125		rate_idx = 5;
126		break;
127	case DESC92S_RATE12M:
128		rate_idx = 6;
129		break;
130	case DESC92S_RATE18M:
131		rate_idx = 7;
132		break;
133	case DESC92S_RATE24M:
134		rate_idx = 8;
135		break;
136	case DESC92S_RATE36M:
137		rate_idx = 9;
138		break;
139	case DESC92S_RATE48M:
140		rate_idx = 10;
141		break;
142	case DESC92S_RATE54M:
143		rate_idx = 11;
144		break;
145	default:
146		rate_idx = 11;
147		break;
148	}
149	return rate_idx;
150}
151
152static u8 _rtl92s_query_rxpwrpercentage(char antpower)
153{
154	if ((antpower <= -100) || (antpower >= 20))
155		return 0;
156	else if (antpower >= 0)
157		return 100;
158	else
159		return 100 + antpower;
160}
161
162static u8 _rtl92s_evm_db_to_percentage(char value)
163{
164	char ret_val;
165	ret_val = value;
166
167	if (ret_val >= 0)
168		ret_val = 0;
169
170	if (ret_val <= -33)
171		ret_val = -33;
172
173	ret_val = 0 - ret_val;
174	ret_val *= 3;
175
176	if (ret_val == 99)
177		ret_val = 100;
178
179	return ret_val;
180}
181
182static long _rtl92se_translate_todbm(struct ieee80211_hw *hw,
183				     u8 signal_strength_index)
184{
185	long signal_power;
186
187	signal_power = (long)((signal_strength_index + 1) >> 1);
188	signal_power -= 95;
189	return signal_power;
190}
191
192static long _rtl92se_signal_scale_mapping(struct ieee80211_hw *hw,
193		long currsig)
194{
195	long retsig = 0;
196
197	/* Step 1. Scale mapping. */
198	if (currsig > 47)
199		retsig = 100;
200	else if (currsig > 14 && currsig <= 47)
201		retsig = 100 - ((47 - currsig) * 3) / 2;
202	else if (currsig > 2 && currsig <= 14)
203		retsig = 48 - ((14 - currsig) * 15) / 7;
204	else if (currsig >= 0)
205		retsig = currsig * 9 + 1;
206
207	return retsig;
208}
209
210
211static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw,
212				       struct rtl_stats *pstats, u8 *pdesc,
213				       struct rx_fwinfo *p_drvinfo,
214				       bool packet_match_bssid,
215				       bool packet_toself,
216				       bool packet_beacon)
217{
218	struct rtl_priv *rtlpriv = rtl_priv(hw);
219	struct phy_sts_cck_8192s_t *cck_buf;
220	s8 rx_pwr_all = 0, rx_pwr[4];
221	u8 rf_rx_num = 0, evm, pwdb_all;
222	u8 i, max_spatial_stream;
223	u32 rssi, total_rssi = 0;
224	bool in_powersavemode = false;
225	bool is_cck_rate;
226
227	is_cck_rate = RX_HAL_IS_CCK_RATE(pdesc);
228	pstats->packet_matchbssid = packet_match_bssid;
229	pstats->packet_toself = packet_toself;
230	pstats->is_cck = is_cck_rate;
231	pstats->packet_beacon = packet_beacon;
232	pstats->is_cck = is_cck_rate;
233	pstats->rx_mimo_signalquality[0] = -1;
234	pstats->rx_mimo_signalquality[1] = -1;
235
236	if (is_cck_rate) {
237		u8 report, cck_highpwr;
238		cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo;
239
240		if (!in_powersavemode)
241			cck_highpwr = (u8) rtl_get_bbreg(hw,
242						RFPGA0_XA_HSSIPARAMETER2,
243						0x200);
244		else
245			cck_highpwr = false;
246
247		if (!cck_highpwr) {
248			u8 cck_agc_rpt = cck_buf->cck_agc_rpt;
249			report = cck_buf->cck_agc_rpt & 0xc0;
250			report = report >> 6;
251			switch (report) {
252			case 0x3:
253				rx_pwr_all = -40 - (cck_agc_rpt & 0x3e);
254				break;
255			case 0x2:
256				rx_pwr_all = -20 - (cck_agc_rpt & 0x3e);
257				break;
258			case 0x1:
259				rx_pwr_all = -2 - (cck_agc_rpt & 0x3e);
260				break;
261			case 0x0:
262				rx_pwr_all = 14 - (cck_agc_rpt & 0x3e);
263				break;
264			}
265		} else {
266			u8 cck_agc_rpt = cck_buf->cck_agc_rpt;
267			report = p_drvinfo->cfosho[0] & 0x60;
268			report = report >> 5;
269			switch (report) {
270			case 0x3:
271				rx_pwr_all = -40 - ((cck_agc_rpt & 0x1f) << 1);
272				break;
273			case 0x2:
274				rx_pwr_all = -20 - ((cck_agc_rpt & 0x1f) << 1);
275				break;
276			case 0x1:
277				rx_pwr_all = -2 - ((cck_agc_rpt & 0x1f) << 1);
278				break;
279			case 0x0:
280				rx_pwr_all = 14 - ((cck_agc_rpt & 0x1f) << 1);
281				break;
282			}
283		}
284
285		pwdb_all = _rtl92s_query_rxpwrpercentage(rx_pwr_all);
286
287		/* CCK gain is smaller than OFDM/MCS gain,  */
288		/* so we add gain diff by experiences, the val is 6 */
289		pwdb_all += 6;
290		if (pwdb_all > 100)
291			pwdb_all = 100;
292		/* modify the offset to make the same gain index with OFDM. */
293		if (pwdb_all > 34 && pwdb_all <= 42)
294			pwdb_all -= 2;
295		else if (pwdb_all > 26 && pwdb_all <= 34)
296			pwdb_all -= 6;
297		else if (pwdb_all > 14 && pwdb_all <= 26)
298			pwdb_all -= 8;
299		else if (pwdb_all > 4 && pwdb_all <= 14)
300			pwdb_all -= 4;
301
302		pstats->rx_pwdb_all = pwdb_all;
303		pstats->recvsignalpower = rx_pwr_all;
304
305		if (packet_match_bssid) {
306			u8 sq;
307			if (pstats->rx_pwdb_all > 40) {
308				sq = 100;
309			} else {
310				sq = cck_buf->sq_rpt;
311				if (sq > 64)
312					sq = 0;
313				else if (sq < 20)
314					sq = 100;
315				else
316					sq = ((64 - sq) * 100) / 44;
317			}
318
319			pstats->signalquality = sq;
320			pstats->rx_mimo_signalquality[0] = sq;
321			pstats->rx_mimo_signalquality[1] = -1;
322		}
323	} else {
324		rtlpriv->dm.rfpath_rxenable[0] =
325		    rtlpriv->dm.rfpath_rxenable[1] = true;
326		for (i = RF90_PATH_A; i < RF90_PATH_MAX; i++) {
327			if (rtlpriv->dm.rfpath_rxenable[i])
328				rf_rx_num++;
329
330			rx_pwr[i] = ((p_drvinfo->gain_trsw[i] &
331				    0x3f) * 2) - 110;
332			rssi = _rtl92s_query_rxpwrpercentage(rx_pwr[i]);
333			total_rssi += rssi;
334			rtlpriv->stats.rx_snr_db[i] =
335					 (long)(p_drvinfo->rxsnr[i] / 2);
336
337			if (packet_match_bssid)
338				pstats->rx_mimo_signalstrength[i] = (u8) rssi;
339		}
340
341		rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 110;
342		pwdb_all = _rtl92s_query_rxpwrpercentage(rx_pwr_all);
343		pstats->rx_pwdb_all = pwdb_all;
344		pstats->rxpower = rx_pwr_all;
345		pstats->recvsignalpower = rx_pwr_all;
346
347		if (GET_RX_STATUS_DESC_RX_HT(pdesc) &&
348			GET_RX_STATUS_DESC_RX_MCS(pdesc) >= DESC92S_RATEMCS8 &&
349		    GET_RX_STATUS_DESC_RX_MCS(pdesc) <= DESC92S_RATEMCS15)
350			max_spatial_stream = 2;
351		else
352			max_spatial_stream = 1;
353
354		for (i = 0; i < max_spatial_stream; i++) {
355			evm = _rtl92s_evm_db_to_percentage(p_drvinfo->rxevm[i]);
356
357			if (packet_match_bssid) {
358				if (i == 0)
359					pstats->signalquality = (u8)(evm &
360								 0xff);
361				pstats->rx_mimo_signalquality[i] =
362							 (u8) (evm & 0xff);
363			}
364		}
365	}
366
367	if (is_cck_rate)
368		pstats->signalstrength = (u8)(_rtl92se_signal_scale_mapping(hw,
369					 pwdb_all));
370	else if (rf_rx_num != 0)
371		pstats->signalstrength = (u8) (_rtl92se_signal_scale_mapping(hw,
372				total_rssi /= rf_rx_num));
373}
374
375static void _rtl92se_process_ui_rssi(struct ieee80211_hw *hw,
376				     struct rtl_stats *pstats)
377{
378	struct rtl_priv *rtlpriv = rtl_priv(hw);
379	struct rtl_phy *rtlphy = &(rtlpriv->phy);
380	u8 rfpath;
381	u32 last_rssi, tmpval;
382
383	if (pstats->packet_toself || pstats->packet_beacon) {
384		rtlpriv->stats.rssi_calculate_cnt++;
385
386		if (rtlpriv->stats.ui_rssi.total_num++ >=
387		    PHY_RSSI_SLID_WIN_MAX) {
388			rtlpriv->stats.ui_rssi.total_num =
389					 PHY_RSSI_SLID_WIN_MAX;
390			last_rssi = rtlpriv->stats.ui_rssi.elements[
391				rtlpriv->stats.ui_rssi.index];
392			rtlpriv->stats.ui_rssi.total_val -= last_rssi;
393		}
394
395		rtlpriv->stats.ui_rssi.total_val += pstats->signalstrength;
396		rtlpriv->stats.ui_rssi.elements[rtlpriv->stats.ui_rssi.index++]
397			 = pstats->signalstrength;
398
399		if (rtlpriv->stats.ui_rssi.index >= PHY_RSSI_SLID_WIN_MAX)
400			rtlpriv->stats.ui_rssi.index = 0;
401
402		tmpval = rtlpriv->stats.ui_rssi.total_val /
403			rtlpriv->stats.ui_rssi.total_num;
404		rtlpriv->stats.signal_strength = _rtl92se_translate_todbm(hw,
405								(u8) tmpval);
406		pstats->rssi = rtlpriv->stats.signal_strength;
407	}
408
409	if (!pstats->is_cck && pstats->packet_toself) {
410		for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath;
411		     rfpath++) {
412			if (rtlpriv->stats.rx_rssi_percentage[rfpath] == 0) {
413				rtlpriv->stats.rx_rssi_percentage[rfpath] =
414				    pstats->rx_mimo_signalstrength[rfpath];
415
416			}
417
418			if (pstats->rx_mimo_signalstrength[rfpath] >
419			    rtlpriv->stats.rx_rssi_percentage[rfpath]) {
420				rtlpriv->stats.rx_rssi_percentage[rfpath] =
421				    ((rtlpriv->stats.rx_rssi_percentage[rfpath]
422				    * (RX_SMOOTH_FACTOR - 1)) +
423				    (pstats->rx_mimo_signalstrength[rfpath])) /
424				    (RX_SMOOTH_FACTOR);
425
426				rtlpriv->stats.rx_rssi_percentage[rfpath] =
427				    rtlpriv->stats.rx_rssi_percentage[rfpath]
428				    + 1;
429			} else {
430				rtlpriv->stats.rx_rssi_percentage[rfpath] =
431				    ((rtlpriv->stats.rx_rssi_percentage[rfpath]
432				    * (RX_SMOOTH_FACTOR - 1)) +
433				    (pstats->rx_mimo_signalstrength[rfpath])) /
434				    (RX_SMOOTH_FACTOR);
435			}
436
437		}
438	}
439}
440
441static void _rtl92se_update_rxsignalstatistics(struct ieee80211_hw *hw,
442					       struct rtl_stats *pstats)
443{
444	struct rtl_priv *rtlpriv = rtl_priv(hw);
445	int weighting = 0;
446
447	if (rtlpriv->stats.recv_signal_power == 0)
448		rtlpriv->stats.recv_signal_power = pstats->recvsignalpower;
449
450	if (pstats->recvsignalpower > rtlpriv->stats.recv_signal_power)
451		weighting = 5;
452	else if (pstats->recvsignalpower < rtlpriv->stats.recv_signal_power)
453		weighting = (-5);
454
455	rtlpriv->stats.recv_signal_power = (rtlpriv->stats.recv_signal_power * 5
456					   + pstats->recvsignalpower +
457					   weighting) / 6;
458}
459
460static void _rtl92se_process_pwdb(struct ieee80211_hw *hw,
461				  struct rtl_stats *pstats)
462{
463	struct rtl_priv *rtlpriv = rtl_priv(hw);
464	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
465	long undec_sm_pwdb = 0;
466
467	if (mac->opmode == NL80211_IFTYPE_ADHOC) {
468		return;
469	} else {
470		undec_sm_pwdb =
471		    rtlpriv->dm.undecorated_smoothed_pwdb;
472	}
473
474	if (pstats->packet_toself || pstats->packet_beacon) {
475		if (undec_sm_pwdb < 0)
476			undec_sm_pwdb = pstats->rx_pwdb_all;
477
478		if (pstats->rx_pwdb_all > (u32) undec_sm_pwdb) {
479			undec_sm_pwdb =
480			    (((undec_sm_pwdb) *
481			    (RX_SMOOTH_FACTOR - 1)) +
482			    (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
483
484			undec_sm_pwdb = undec_sm_pwdb + 1;
485		} else {
486			undec_sm_pwdb = (((undec_sm_pwdb) *
487			      (RX_SMOOTH_FACTOR - 1)) + (pstats->rx_pwdb_all)) /
488			      (RX_SMOOTH_FACTOR);
489		}
490
491		rtlpriv->dm.undecorated_smoothed_pwdb = undec_sm_pwdb;
492		_rtl92se_update_rxsignalstatistics(hw, pstats);
493	}
494}
495
496static void rtl_92s_process_streams(struct ieee80211_hw *hw,
497				    struct rtl_stats *pstats)
498{
499	struct rtl_priv *rtlpriv = rtl_priv(hw);
500	u32 stream;
501
502	for (stream = 0; stream < 2; stream++) {
503		if (pstats->rx_mimo_signalquality[stream] != -1) {
504			if (rtlpriv->stats.rx_evm_percentage[stream] == 0) {
505				rtlpriv->stats.rx_evm_percentage[stream] =
506				    pstats->rx_mimo_signalquality[stream];
507			}
508
509			rtlpriv->stats.rx_evm_percentage[stream] =
510			    ((rtlpriv->stats.rx_evm_percentage[stream] *
511					(RX_SMOOTH_FACTOR - 1)) +
512			     (pstats->rx_mimo_signalquality[stream] *
513					1)) / (RX_SMOOTH_FACTOR);
514		}
515	}
516}
517
518static void _rtl92se_process_ui_link_quality(struct ieee80211_hw *hw,
519					     struct rtl_stats *pstats)
520{
521	struct rtl_priv *rtlpriv = rtl_priv(hw);
522	u32 last_evm = 0, tmpval;
523
524	if (pstats->signalquality != 0) {
525		if (pstats->packet_toself || pstats->packet_beacon) {
526
527			if (rtlpriv->stats.ui_link_quality.total_num++ >=
528			    PHY_LINKQUALITY_SLID_WIN_MAX) {
529				rtlpriv->stats.ui_link_quality.total_num =
530				    PHY_LINKQUALITY_SLID_WIN_MAX;
531				last_evm =
532				    rtlpriv->stats.ui_link_quality.elements[
533				    rtlpriv->stats.ui_link_quality.index];
534				rtlpriv->stats.ui_link_quality.total_val -=
535				    last_evm;
536			}
537
538			rtlpriv->stats.ui_link_quality.total_val +=
539			    pstats->signalquality;
540			rtlpriv->stats.ui_link_quality.elements[
541				rtlpriv->stats.ui_link_quality.index++] =
542			    pstats->signalquality;
543
544			if (rtlpriv->stats.ui_link_quality.index >=
545			    PHY_LINKQUALITY_SLID_WIN_MAX)
546				rtlpriv->stats.ui_link_quality.index = 0;
547
548			tmpval = rtlpriv->stats.ui_link_quality.total_val /
549			    rtlpriv->stats.ui_link_quality.total_num;
550			rtlpriv->stats.signal_quality = tmpval;
551
552			rtlpriv->stats.last_sigstrength_inpercent = tmpval;
553
554			rtl_92s_process_streams(hw, pstats);
555
556		}
557	}
558}
559
560static void _rtl92se_process_phyinfo(struct ieee80211_hw *hw,
561				     u8 *buffer,
562				     struct rtl_stats *pcurrent_stats)
563{
564
565	if (!pcurrent_stats->packet_matchbssid &&
566	    !pcurrent_stats->packet_beacon)
567		return;
568
569	_rtl92se_process_ui_rssi(hw, pcurrent_stats);
570	_rtl92se_process_pwdb(hw, pcurrent_stats);
571	_rtl92se_process_ui_link_quality(hw, pcurrent_stats);
572}
573
574static void _rtl92se_translate_rx_signal_stuff(struct ieee80211_hw *hw,
575		struct sk_buff *skb, struct rtl_stats *pstats,
576		u8 *pdesc, struct rx_fwinfo *p_drvinfo)
577{
578	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
579	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
580
581	struct ieee80211_hdr *hdr;
582	u8 *tmp_buf;
583	u8 *praddr;
584	__le16 fc;
585	u16 type, cfc;
586	bool packet_matchbssid, packet_toself, packet_beacon;
587
588	tmp_buf = skb->data + pstats->rx_drvinfo_size + pstats->rx_bufshift;
589
590	hdr = (struct ieee80211_hdr *)tmp_buf;
591	fc = hdr->frame_control;
592	cfc = le16_to_cpu(fc);
593	type = WLAN_FC_GET_TYPE(fc);
594	praddr = hdr->addr1;
595
596	packet_matchbssid = ((IEEE80211_FTYPE_CTL != type) &&
597	     (!compare_ether_addr(mac->bssid, (cfc & IEEE80211_FCTL_TODS) ?
598			hdr->addr1 : (cfc & IEEE80211_FCTL_FROMDS) ?
599			hdr->addr2 : hdr->addr3)) && (!pstats->hwerror) &&
600			(!pstats->crc) && (!pstats->icv));
 
601
602	packet_toself = packet_matchbssid &&
603	    (!compare_ether_addr(praddr, rtlefuse->dev_addr));
604
605	if (ieee80211_is_beacon(fc))
606		packet_beacon = true;
607
608	_rtl92se_query_rxphystatus(hw, pstats, pdesc, p_drvinfo,
609			packet_matchbssid, packet_toself, packet_beacon);
610	_rtl92se_process_phyinfo(hw, tmp_buf, pstats);
611}
612
613bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats,
614			   struct ieee80211_rx_status *rx_status, u8 *pdesc,
615			   struct sk_buff *skb)
616{
617	struct rx_fwinfo *p_drvinfo;
618	u32 phystatus = (u32)GET_RX_STATUS_DESC_PHY_STATUS(pdesc);
 
 
619
620	stats->length = (u16)GET_RX_STATUS_DESC_PKT_LEN(pdesc);
621	stats->rx_drvinfo_size = (u8)GET_RX_STATUS_DESC_DRVINFO_SIZE(pdesc) * 8;
622	stats->rx_bufshift = (u8)(GET_RX_STATUS_DESC_SHIFT(pdesc) & 0x03);
623	stats->icv = (u16)GET_RX_STATUS_DESC_ICV(pdesc);
624	stats->crc = (u16)GET_RX_STATUS_DESC_CRC32(pdesc);
625	stats->hwerror = (u16)(stats->crc | stats->icv);
626	stats->decrypted = !GET_RX_STATUS_DESC_SWDEC(pdesc);
627
628	stats->rate = (u8)GET_RX_STATUS_DESC_RX_MCS(pdesc);
629	stats->shortpreamble = (u16)GET_RX_STATUS_DESC_SPLCP(pdesc);
630	stats->isampdu = (bool)(GET_RX_STATUS_DESC_PAGGR(pdesc) == 1);
 
 
631	stats->timestamp_low = GET_RX_STATUS_DESC_TSFL(pdesc);
632	stats->rx_is40Mhzpacket = (bool)GET_RX_STATUS_DESC_BW(pdesc);
 
 
633
634	if (stats->hwerror)
635		return false;
636
637	rx_status->freq = hw->conf.channel->center_freq;
638	rx_status->band = hw->conf.channel->band;
639
640	if (GET_RX_STATUS_DESC_CRC32(pdesc))
641		rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
642
643	if (!GET_RX_STATUS_DESC_SWDEC(pdesc))
644		rx_status->flag |= RX_FLAG_DECRYPTED;
645
646	if (GET_RX_STATUS_DESC_BW(pdesc))
647		rx_status->flag |= RX_FLAG_40MHZ;
648
649	if (GET_RX_STATUS_DESC_RX_HT(pdesc))
650		rx_status->flag |= RX_FLAG_HT;
651
652	rx_status->flag |= RX_FLAG_MACTIME_MPDU;
653
654	if (stats->decrypted)
655		rx_status->flag |= RX_FLAG_DECRYPTED;
656
657	rx_status->rate_idx = _rtl92se_rate_mapping((bool)
658			GET_RX_STATUS_DESC_RX_HT(pdesc),
659			(u8)GET_RX_STATUS_DESC_RX_MCS(pdesc),
660			(bool)GET_RX_STATUS_DESC_PAGGR(pdesc));
 
 
 
 
 
 
 
661
 
 
662
663	rx_status->mactime = GET_RX_STATUS_DESC_TSFL(pdesc);
664	if (phystatus) {
665		p_drvinfo = (struct rx_fwinfo *)(skb->data +
666						 stats->rx_bufshift);
667		_rtl92se_translate_rx_signal_stuff(hw, skb, stats, pdesc,
668						   p_drvinfo);
669	}
670
671	/*rx_status->qual = stats->signal; */
672	rx_status->signal = stats->rssi + 10;
673	/*rx_status->noise = -stats->noise; */
674
675	return true;
676}
677
678void rtl92se_tx_fill_desc(struct ieee80211_hw *hw,
679		struct ieee80211_hdr *hdr, u8 *pdesc_tx,
680		struct ieee80211_tx_info *info, struct sk_buff *skb,
681		u8 hw_queue, struct rtl_tcb_desc *ptcb_desc)
682{
683	struct rtl_priv *rtlpriv = rtl_priv(hw);
684	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
685	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
686	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
687	struct ieee80211_sta *sta = info->control.sta;
688	u8 *pdesc = (u8 *) pdesc_tx;
689	u16 seq_number;
690	__le16 fc = hdr->frame_control;
691	u8 reserved_macid = 0;
692	u8 fw_qsel = _rtl92se_map_hwqueue_to_fwqueue(skb, hw_queue);
693	bool firstseg = (!(hdr->seq_ctrl & cpu_to_le16(IEEE80211_SCTL_FRAG)));
694	bool lastseg = (!(hdr->frame_control &
695			cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)));
696	dma_addr_t mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len,
697		    PCI_DMA_TODEVICE);
698	u8 bw_40 = 0;
699
700	if (mac->opmode == NL80211_IFTYPE_STATION) {
701		bw_40 = mac->bw_40;
702	} else if (mac->opmode == NL80211_IFTYPE_AP ||
703		mac->opmode == NL80211_IFTYPE_ADHOC) {
704		if (sta)
705			bw_40 = sta->ht_cap.cap &
706				    IEEE80211_HT_CAP_SUP_WIDTH_20_40;
707	}
708
709	seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4;
710
711	rtl_get_tcb_desc(hw, info, sta, skb, ptcb_desc);
712
713	CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE_RTL8192S);
714
715	if (firstseg) {
716		if (rtlpriv->dm.useramask) {
717			/* set txdesc macId */
718			if (ptcb_desc->mac_id < 32) {
719				SET_TX_DESC_MACID(pdesc, ptcb_desc->mac_id);
720				reserved_macid |= ptcb_desc->mac_id;
721			}
722		}
723		SET_TX_DESC_RSVD_MACID(pdesc, reserved_macid);
724
725		SET_TX_DESC_TXHT(pdesc, ((ptcb_desc->hw_rate >=
726				 DESC92S_RATEMCS0) ? 1 : 0));
727
728		if (rtlhal->version == VERSION_8192S_ACUT) {
729			if (ptcb_desc->hw_rate == DESC92S_RATE1M ||
730				ptcb_desc->hw_rate  == DESC92S_RATE2M ||
731				ptcb_desc->hw_rate == DESC92S_RATE5_5M ||
732				ptcb_desc->hw_rate == DESC92S_RATE11M) {
733				ptcb_desc->hw_rate = DESC92S_RATE12M;
734			}
735		}
736
737		SET_TX_DESC_TX_RATE(pdesc, ptcb_desc->hw_rate);
738
739		if (ptcb_desc->use_shortgi || ptcb_desc->use_shortpreamble)
740			SET_TX_DESC_TX_SHORT(pdesc, 0);
741
742		/* Aggregation related */
743		if (info->flags & IEEE80211_TX_CTL_AMPDU)
744			SET_TX_DESC_AGG_ENABLE(pdesc, 1);
745
746		/* For AMPDU, we must insert SSN into TX_DESC */
747		SET_TX_DESC_SEQ(pdesc, seq_number);
748
749		/* Protection mode related */
750		/* For 92S, if RTS/CTS are set, HW will execute RTS. */
751		/* We choose only one protection mode to execute */
752		SET_TX_DESC_RTS_ENABLE(pdesc, ((ptcb_desc->rts_enable &&
753				!ptcb_desc->cts_enable) ? 1 : 0));
754		SET_TX_DESC_CTS_ENABLE(pdesc, ((ptcb_desc->cts_enable) ?
755				       1 : 0));
756		SET_TX_DESC_RTS_STBC(pdesc, ((ptcb_desc->rts_stbc) ? 1 : 0));
757
758		SET_TX_DESC_RTS_RATE(pdesc, ptcb_desc->rts_rate);
759		SET_TX_DESC_RTS_BANDWIDTH(pdesc, 0);
760		SET_TX_DESC_RTS_SUB_CARRIER(pdesc, ptcb_desc->rts_sc);
761		SET_TX_DESC_RTS_SHORT(pdesc, ((ptcb_desc->rts_rate <=
762		       DESC92S_RATE54M) ?
763		       (ptcb_desc->rts_use_shortpreamble ? 1 : 0)
764		       : (ptcb_desc->rts_use_shortgi ? 1 : 0)));
765
766
767		/* Set Bandwidth and sub-channel settings. */
768		if (bw_40) {
769			if (ptcb_desc->packet_bw) {
770				SET_TX_DESC_TX_BANDWIDTH(pdesc, 1);
771				/* use duplicated mode */
772				SET_TX_DESC_TX_SUB_CARRIER(pdesc, 0);
773			} else {
774				SET_TX_DESC_TX_BANDWIDTH(pdesc, 0);
775				SET_TX_DESC_TX_SUB_CARRIER(pdesc,
776						   mac->cur_40_prime_sc);
777			}
778		} else {
779			SET_TX_DESC_TX_BANDWIDTH(pdesc, 0);
780			SET_TX_DESC_TX_SUB_CARRIER(pdesc, 0);
781		}
782
783		/* 3 Fill necessary field in First Descriptor */
784		/*DWORD 0*/
785		SET_TX_DESC_LINIP(pdesc, 0);
786		SET_TX_DESC_OFFSET(pdesc, 32);
787		SET_TX_DESC_PKT_SIZE(pdesc, (u16) skb->len);
788
789		/*DWORD 1*/
790		SET_TX_DESC_RA_BRSR_ID(pdesc, ptcb_desc->ratr_index);
791
792		/* Fill security related */
793		if (info->control.hw_key) {
794			struct ieee80211_key_conf *keyconf;
795
796			keyconf = info->control.hw_key;
797			switch (keyconf->cipher) {
798			case WLAN_CIPHER_SUITE_WEP40:
799			case WLAN_CIPHER_SUITE_WEP104:
800				SET_TX_DESC_SEC_TYPE(pdesc, 0x1);
801				break;
802			case WLAN_CIPHER_SUITE_TKIP:
803				SET_TX_DESC_SEC_TYPE(pdesc, 0x2);
804				break;
805			case WLAN_CIPHER_SUITE_CCMP:
806				SET_TX_DESC_SEC_TYPE(pdesc, 0x3);
807				break;
808			default:
809				SET_TX_DESC_SEC_TYPE(pdesc, 0x0);
810				break;
811
812			}
813		}
814
815		/* Set Packet ID */
816		SET_TX_DESC_PACKET_ID(pdesc, 0);
817
818		/* We will assign magement queue to BK. */
819		SET_TX_DESC_QUEUE_SEL(pdesc, fw_qsel);
820
821		/* Alwasy enable all rate fallback range */
822		SET_TX_DESC_DATA_RATE_FB_LIMIT(pdesc, 0x1F);
823
824		/* Fix: I don't kown why hw use 6.5M to tx when set it */
825		SET_TX_DESC_USER_RATE(pdesc,
826				      ptcb_desc->use_driver_rate ? 1 : 0);
827
828		/* Set NON_QOS bit. */
829		if (!ieee80211_is_data_qos(fc))
830			SET_TX_DESC_NON_QOS(pdesc, 1);
831
832	}
833
834	/* Fill fields that are required to be initialized
835	 * in all of the descriptors */
836	/*DWORD 0 */
837	SET_TX_DESC_FIRST_SEG(pdesc, (firstseg ? 1 : 0));
838	SET_TX_DESC_LAST_SEG(pdesc, (lastseg ? 1 : 0));
839
840	/* DWORD 7 */
841	SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) skb->len);
842
843	/* DOWRD 8 */
844	SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, cpu_to_le32(mapping));
845
846	RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, ("\n"));
847}
848
849void rtl92se_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc,
850	bool firstseg, bool lastseg, struct sk_buff *skb)
851{
852	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
853	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
854	struct rtl_tcb_desc *tcb_desc = (struct rtl_tcb_desc *)(skb->cb);
855
856	dma_addr_t mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len,
857			PCI_DMA_TODEVICE);
858
859    /* Clear all status	*/
860	CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_CMDDESC_SIZE_RTL8192S);
861
862	/* This bit indicate this packet is used for FW download. */
863	if (tcb_desc->cmd_or_init == DESC_PACKET_TYPE_INIT) {
864		/* For firmware downlaod we only need to set LINIP */
865		SET_TX_DESC_LINIP(pdesc, tcb_desc->last_inipkt);
866
867		/* 92SE must set as 1 for firmware download HW DMA error */
868		SET_TX_DESC_FIRST_SEG(pdesc, 1);
869		SET_TX_DESC_LAST_SEG(pdesc, 1);
870
871		/* 92SE need not to set TX packet size when firmware download */
872		SET_TX_DESC_PKT_SIZE(pdesc, (u16)(skb->len));
873		SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16)(skb->len));
874		SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, cpu_to_le32(mapping));
875
876		wmb();
877		SET_TX_DESC_OWN(pdesc, 1);
878	} else { /* H2C Command Desc format (Host TXCMD) */
879		/* 92SE must set as 1 for firmware download HW DMA error */
880		SET_TX_DESC_FIRST_SEG(pdesc, 1);
881		SET_TX_DESC_LAST_SEG(pdesc, 1);
882
883		SET_TX_DESC_OFFSET(pdesc, 0x20);
884
885		/* Buffer size + command header */
886		SET_TX_DESC_PKT_SIZE(pdesc, (u16)(skb->len));
887		/* Fixed queue of H2C command */
888		SET_TX_DESC_QUEUE_SEL(pdesc, 0x13);
889
890		SET_BITS_TO_LE_4BYTE(skb->data, 24, 7, rtlhal->h2c_txcmd_seq);
891
892		SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16)(skb->len));
893		SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, cpu_to_le32(mapping));
894
895		wmb();
896		SET_TX_DESC_OWN(pdesc, 1);
897
898	}
899}
900
901void rtl92se_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val)
902{
903	if (istx) {
904		switch (desc_name) {
905		case HW_DESC_OWN:
906			wmb();
907			SET_TX_DESC_OWN(pdesc, 1);
908			break;
909		case HW_DESC_TX_NEXTDESC_ADDR:
910			SET_TX_DESC_NEXT_DESC_ADDRESS(pdesc, *(u32 *) val);
911			break;
912		default:
913			RT_ASSERT(false, ("ERR txdesc :%d not process\n",
914				  desc_name));
915			break;
916		}
917	} else {
918		switch (desc_name) {
919		case HW_DESC_RXOWN:
920			wmb();
921			SET_RX_STATUS_DESC_OWN(pdesc, 1);
922			break;
923		case HW_DESC_RXBUFF_ADDR:
924			SET_RX_STATUS__DESC_BUFF_ADDR(pdesc, *(u32 *) val);
925			break;
926		case HW_DESC_RXPKT_LEN:
927			SET_RX_STATUS_DESC_PKT_LEN(pdesc, *(u32 *) val);
928			break;
929		case HW_DESC_RXERO:
930			SET_RX_STATUS_DESC_EOR(pdesc, 1);
931			break;
932		default:
933			RT_ASSERT(false, ("ERR rxdesc :%d not process\n",
934				  desc_name));
935			break;
936		}
937	}
938}
939
940u32 rtl92se_get_desc(u8 *desc, bool istx, u8 desc_name)
941{
942	u32 ret = 0;
943
944	if (istx) {
945		switch (desc_name) {
946		case HW_DESC_OWN:
947			ret = GET_TX_DESC_OWN(desc);
948			break;
949		case HW_DESC_TXBUFF_ADDR:
950			ret = GET_TX_DESC_TX_BUFFER_ADDRESS(desc);
951			break;
952		default:
953			RT_ASSERT(false, ("ERR txdesc :%d not process\n",
954				  desc_name));
955			break;
956		}
957	} else {
958		switch (desc_name) {
959		case HW_DESC_OWN:
960			ret = GET_RX_STATUS_DESC_OWN(desc);
961			break;
962		case HW_DESC_RXPKT_LEN:
963			ret = GET_RX_STATUS_DESC_PKT_LEN(desc);
964			break;
965		default:
966			RT_ASSERT(false, ("ERR rxdesc :%d not process\n",
967				  desc_name));
968			break;
969		}
970	}
971	return ret;
972}
973
974void rtl92se_tx_polling(struct ieee80211_hw *hw, u8 hw_queue)
975{
976	struct rtl_priv *rtlpriv = rtl_priv(hw);
977	rtl_write_word(rtlpriv, TP_POLL, BIT(0) << (hw_queue));
978}
v3.5.6
  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 "fw.h"
 37#include "trx.h"
 38#include "led.h"
 39
 40static u8 _rtl92se_map_hwqueue_to_fwqueue(struct sk_buff *skb,	u8 skb_queue)
 41{
 42	__le16 fc = rtl_get_fc(skb);
 43
 44	if (unlikely(ieee80211_is_beacon(fc)))
 45		return QSLT_BEACON;
 46	if (ieee80211_is_mgmt(fc))
 47		return QSLT_MGNT;
 48	if (ieee80211_is_nullfunc(fc))
 49		return QSLT_HIGH;
 50
 51	return skb->priority;
 52}
 53
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 54static u8 _rtl92s_query_rxpwrpercentage(char antpower)
 55{
 56	if ((antpower <= -100) || (antpower >= 20))
 57		return 0;
 58	else if (antpower >= 0)
 59		return 100;
 60	else
 61		return 100 + antpower;
 62}
 63
 64static u8 _rtl92s_evm_db_to_percentage(char value)
 65{
 66	char ret_val;
 67	ret_val = value;
 68
 69	if (ret_val >= 0)
 70		ret_val = 0;
 71
 72	if (ret_val <= -33)
 73		ret_val = -33;
 74
 75	ret_val = 0 - ret_val;
 76	ret_val *= 3;
 77
 78	if (ret_val == 99)
 79		ret_val = 100;
 80
 81	return ret_val;
 82}
 83
 84static long _rtl92se_translate_todbm(struct ieee80211_hw *hw,
 85				     u8 signal_strength_index)
 86{
 87	long signal_power;
 88
 89	signal_power = (long)((signal_strength_index + 1) >> 1);
 90	signal_power -= 95;
 91	return signal_power;
 92}
 93
 94static long _rtl92se_signal_scale_mapping(struct ieee80211_hw *hw,
 95		long currsig)
 96{
 97	long retsig = 0;
 98
 99	/* Step 1. Scale mapping. */
100	if (currsig > 47)
101		retsig = 100;
102	else if (currsig > 14 && currsig <= 47)
103		retsig = 100 - ((47 - currsig) * 3) / 2;
104	else if (currsig > 2 && currsig <= 14)
105		retsig = 48 - ((14 - currsig) * 15) / 7;
106	else if (currsig >= 0)
107		retsig = currsig * 9 + 1;
108
109	return retsig;
110}
111
112
113static void _rtl92se_query_rxphystatus(struct ieee80211_hw *hw,
114				       struct rtl_stats *pstats, u8 *pdesc,
115				       struct rx_fwinfo *p_drvinfo,
116				       bool packet_match_bssid,
117				       bool packet_toself,
118				       bool packet_beacon)
119{
120	struct rtl_priv *rtlpriv = rtl_priv(hw);
121	struct phy_sts_cck_8192s_t *cck_buf;
122	s8 rx_pwr_all = 0, rx_pwr[4];
123	u8 rf_rx_num = 0, evm, pwdb_all;
124	u8 i, max_spatial_stream;
125	u32 rssi, total_rssi = 0;
126	bool in_powersavemode = false;
127	bool is_cck = pstats->is_cck;
128
 
129	pstats->packet_matchbssid = packet_match_bssid;
130	pstats->packet_toself = packet_toself;
 
131	pstats->packet_beacon = packet_beacon;
 
132	pstats->rx_mimo_signalquality[0] = -1;
133	pstats->rx_mimo_signalquality[1] = -1;
134
135	if (is_cck) {
136		u8 report, cck_highpwr;
137		cck_buf = (struct phy_sts_cck_8192s_t *)p_drvinfo;
138
139		if (!in_powersavemode)
140			cck_highpwr = (u8) rtl_get_bbreg(hw,
141						RFPGA0_XA_HSSIPARAMETER2,
142						0x200);
143		else
144			cck_highpwr = false;
145
146		if (!cck_highpwr) {
147			u8 cck_agc_rpt = cck_buf->cck_agc_rpt;
148			report = cck_buf->cck_agc_rpt & 0xc0;
149			report = report >> 6;
150			switch (report) {
151			case 0x3:
152				rx_pwr_all = -40 - (cck_agc_rpt & 0x3e);
153				break;
154			case 0x2:
155				rx_pwr_all = -20 - (cck_agc_rpt & 0x3e);
156				break;
157			case 0x1:
158				rx_pwr_all = -2 - (cck_agc_rpt & 0x3e);
159				break;
160			case 0x0:
161				rx_pwr_all = 14 - (cck_agc_rpt & 0x3e);
162				break;
163			}
164		} else {
165			u8 cck_agc_rpt = cck_buf->cck_agc_rpt;
166			report = p_drvinfo->cfosho[0] & 0x60;
167			report = report >> 5;
168			switch (report) {
169			case 0x3:
170				rx_pwr_all = -40 - ((cck_agc_rpt & 0x1f) << 1);
171				break;
172			case 0x2:
173				rx_pwr_all = -20 - ((cck_agc_rpt & 0x1f) << 1);
174				break;
175			case 0x1:
176				rx_pwr_all = -2 - ((cck_agc_rpt & 0x1f) << 1);
177				break;
178			case 0x0:
179				rx_pwr_all = 14 - ((cck_agc_rpt & 0x1f) << 1);
180				break;
181			}
182		}
183
184		pwdb_all = _rtl92s_query_rxpwrpercentage(rx_pwr_all);
185
186		/* CCK gain is smaller than OFDM/MCS gain,  */
187		/* so we add gain diff by experiences, the val is 6 */
188		pwdb_all += 6;
189		if (pwdb_all > 100)
190			pwdb_all = 100;
191		/* modify the offset to make the same gain index with OFDM. */
192		if (pwdb_all > 34 && pwdb_all <= 42)
193			pwdb_all -= 2;
194		else if (pwdb_all > 26 && pwdb_all <= 34)
195			pwdb_all -= 6;
196		else if (pwdb_all > 14 && pwdb_all <= 26)
197			pwdb_all -= 8;
198		else if (pwdb_all > 4 && pwdb_all <= 14)
199			pwdb_all -= 4;
200
201		pstats->rx_pwdb_all = pwdb_all;
202		pstats->recvsignalpower = rx_pwr_all;
203
204		if (packet_match_bssid) {
205			u8 sq;
206			if (pstats->rx_pwdb_all > 40) {
207				sq = 100;
208			} else {
209				sq = cck_buf->sq_rpt;
210				if (sq > 64)
211					sq = 0;
212				else if (sq < 20)
213					sq = 100;
214				else
215					sq = ((64 - sq) * 100) / 44;
216			}
217
218			pstats->signalquality = sq;
219			pstats->rx_mimo_signalquality[0] = sq;
220			pstats->rx_mimo_signalquality[1] = -1;
221		}
222	} else {
223		rtlpriv->dm.rfpath_rxenable[0] =
224		    rtlpriv->dm.rfpath_rxenable[1] = true;
225		for (i = RF90_PATH_A; i < RF90_PATH_MAX; i++) {
226			if (rtlpriv->dm.rfpath_rxenable[i])
227				rf_rx_num++;
228
229			rx_pwr[i] = ((p_drvinfo->gain_trsw[i] &
230				    0x3f) * 2) - 110;
231			rssi = _rtl92s_query_rxpwrpercentage(rx_pwr[i]);
232			total_rssi += rssi;
233			rtlpriv->stats.rx_snr_db[i] =
234					 (long)(p_drvinfo->rxsnr[i] / 2);
235
236			if (packet_match_bssid)
237				pstats->rx_mimo_signalstrength[i] = (u8) rssi;
238		}
239
240		rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 110;
241		pwdb_all = _rtl92s_query_rxpwrpercentage(rx_pwr_all);
242		pstats->rx_pwdb_all = pwdb_all;
243		pstats->rxpower = rx_pwr_all;
244		pstats->recvsignalpower = rx_pwr_all;
245
246		if (pstats->is_ht && pstats->rate >= DESC92_RATEMCS8 &&
247		    pstats->rate <= DESC92_RATEMCS15)
 
248			max_spatial_stream = 2;
249		else
250			max_spatial_stream = 1;
251
252		for (i = 0; i < max_spatial_stream; i++) {
253			evm = _rtl92s_evm_db_to_percentage(p_drvinfo->rxevm[i]);
254
255			if (packet_match_bssid) {
256				if (i == 0)
257					pstats->signalquality = (u8)(evm &
258								 0xff);
259				pstats->rx_mimo_signalquality[i] =
260							 (u8) (evm & 0xff);
261			}
262		}
263	}
264
265	if (is_cck)
266		pstats->signalstrength = (u8)(_rtl92se_signal_scale_mapping(hw,
267					 pwdb_all));
268	else if (rf_rx_num != 0)
269		pstats->signalstrength = (u8) (_rtl92se_signal_scale_mapping(hw,
270				total_rssi /= rf_rx_num));
271}
272
273static void _rtl92se_process_ui_rssi(struct ieee80211_hw *hw,
274				     struct rtl_stats *pstats)
275{
276	struct rtl_priv *rtlpriv = rtl_priv(hw);
277	struct rtl_phy *rtlphy = &(rtlpriv->phy);
278	u8 rfpath;
279	u32 last_rssi, tmpval;
280
281	if (pstats->packet_toself || pstats->packet_beacon) {
282		rtlpriv->stats.rssi_calculate_cnt++;
283
284		if (rtlpriv->stats.ui_rssi.total_num++ >=
285		    PHY_RSSI_SLID_WIN_MAX) {
286			rtlpriv->stats.ui_rssi.total_num =
287					 PHY_RSSI_SLID_WIN_MAX;
288			last_rssi = rtlpriv->stats.ui_rssi.elements[
289				rtlpriv->stats.ui_rssi.index];
290			rtlpriv->stats.ui_rssi.total_val -= last_rssi;
291		}
292
293		rtlpriv->stats.ui_rssi.total_val += pstats->signalstrength;
294		rtlpriv->stats.ui_rssi.elements[rtlpriv->stats.ui_rssi.index++]
295			 = pstats->signalstrength;
296
297		if (rtlpriv->stats.ui_rssi.index >= PHY_RSSI_SLID_WIN_MAX)
298			rtlpriv->stats.ui_rssi.index = 0;
299
300		tmpval = rtlpriv->stats.ui_rssi.total_val /
301			rtlpriv->stats.ui_rssi.total_num;
302		rtlpriv->stats.signal_strength = _rtl92se_translate_todbm(hw,
303								(u8) tmpval);
304		pstats->rssi = rtlpriv->stats.signal_strength;
305	}
306
307	if (!pstats->is_cck && pstats->packet_toself) {
308		for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath;
309		     rfpath++) {
310			if (rtlpriv->stats.rx_rssi_percentage[rfpath] == 0) {
311				rtlpriv->stats.rx_rssi_percentage[rfpath] =
312				    pstats->rx_mimo_signalstrength[rfpath];
313
314			}
315
316			if (pstats->rx_mimo_signalstrength[rfpath] >
317			    rtlpriv->stats.rx_rssi_percentage[rfpath]) {
318				rtlpriv->stats.rx_rssi_percentage[rfpath] =
319				    ((rtlpriv->stats.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.rx_rssi_percentage[rfpath]
330				    * (RX_SMOOTH_FACTOR - 1)) +
331				    (pstats->rx_mimo_signalstrength[rfpath])) /
332				    (RX_SMOOTH_FACTOR);
333			}
334
335		}
336	}
337}
338
339static void _rtl92se_update_rxsignalstatistics(struct ieee80211_hw *hw,
340					       struct rtl_stats *pstats)
341{
342	struct rtl_priv *rtlpriv = rtl_priv(hw);
343	int weighting = 0;
344
345	if (rtlpriv->stats.recv_signal_power == 0)
346		rtlpriv->stats.recv_signal_power = pstats->recvsignalpower;
347
348	if (pstats->recvsignalpower > rtlpriv->stats.recv_signal_power)
349		weighting = 5;
350	else if (pstats->recvsignalpower < rtlpriv->stats.recv_signal_power)
351		weighting = (-5);
352
353	rtlpriv->stats.recv_signal_power = (rtlpriv->stats.recv_signal_power * 5
354					   + pstats->recvsignalpower +
355					   weighting) / 6;
356}
357
358static void _rtl92se_process_pwdb(struct ieee80211_hw *hw,
359				  struct rtl_stats *pstats)
360{
361	struct rtl_priv *rtlpriv = rtl_priv(hw);
362	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
363	long undec_sm_pwdb = 0;
364
365	if (mac->opmode == NL80211_IFTYPE_ADHOC) {
366		return;
367	} else {
368		undec_sm_pwdb =
369		    rtlpriv->dm.undecorated_smoothed_pwdb;
370	}
371
372	if (pstats->packet_toself || pstats->packet_beacon) {
373		if (undec_sm_pwdb < 0)
374			undec_sm_pwdb = pstats->rx_pwdb_all;
375
376		if (pstats->rx_pwdb_all > (u32) undec_sm_pwdb) {
377			undec_sm_pwdb =
378			    (((undec_sm_pwdb) *
379			    (RX_SMOOTH_FACTOR - 1)) +
380			    (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
381
382			undec_sm_pwdb = undec_sm_pwdb + 1;
383		} else {
384			undec_sm_pwdb = (((undec_sm_pwdb) *
385			      (RX_SMOOTH_FACTOR - 1)) + (pstats->rx_pwdb_all)) /
386			      (RX_SMOOTH_FACTOR);
387		}
388
389		rtlpriv->dm.undecorated_smoothed_pwdb = undec_sm_pwdb;
390		_rtl92se_update_rxsignalstatistics(hw, pstats);
391	}
392}
393
394static void rtl_92s_process_streams(struct ieee80211_hw *hw,
395				    struct rtl_stats *pstats)
396{
397	struct rtl_priv *rtlpriv = rtl_priv(hw);
398	u32 stream;
399
400	for (stream = 0; stream < 2; stream++) {
401		if (pstats->rx_mimo_signalquality[stream] != -1) {
402			if (rtlpriv->stats.rx_evm_percentage[stream] == 0) {
403				rtlpriv->stats.rx_evm_percentage[stream] =
404				    pstats->rx_mimo_signalquality[stream];
405			}
406
407			rtlpriv->stats.rx_evm_percentage[stream] =
408			    ((rtlpriv->stats.rx_evm_percentage[stream] *
409					(RX_SMOOTH_FACTOR - 1)) +
410			     (pstats->rx_mimo_signalquality[stream] *
411					1)) / (RX_SMOOTH_FACTOR);
412		}
413	}
414}
415
416static void _rtl92se_process_ui_link_quality(struct ieee80211_hw *hw,
417					     struct rtl_stats *pstats)
418{
419	struct rtl_priv *rtlpriv = rtl_priv(hw);
420	u32 last_evm = 0, tmpval;
421
422	if (pstats->signalquality != 0) {
423		if (pstats->packet_toself || pstats->packet_beacon) {
424
425			if (rtlpriv->stats.ui_link_quality.total_num++ >=
426			    PHY_LINKQUALITY_SLID_WIN_MAX) {
427				rtlpriv->stats.ui_link_quality.total_num =
428				    PHY_LINKQUALITY_SLID_WIN_MAX;
429				last_evm =
430				    rtlpriv->stats.ui_link_quality.elements[
431				    rtlpriv->stats.ui_link_quality.index];
432				rtlpriv->stats.ui_link_quality.total_val -=
433				    last_evm;
434			}
435
436			rtlpriv->stats.ui_link_quality.total_val +=
437			    pstats->signalquality;
438			rtlpriv->stats.ui_link_quality.elements[
439				rtlpriv->stats.ui_link_quality.index++] =
440			    pstats->signalquality;
441
442			if (rtlpriv->stats.ui_link_quality.index >=
443			    PHY_LINKQUALITY_SLID_WIN_MAX)
444				rtlpriv->stats.ui_link_quality.index = 0;
445
446			tmpval = rtlpriv->stats.ui_link_quality.total_val /
447			    rtlpriv->stats.ui_link_quality.total_num;
448			rtlpriv->stats.signal_quality = tmpval;
449
450			rtlpriv->stats.last_sigstrength_inpercent = tmpval;
451
452			rtl_92s_process_streams(hw, pstats);
453
454		}
455	}
456}
457
458static void _rtl92se_process_phyinfo(struct ieee80211_hw *hw,
459				     u8 *buffer,
460				     struct rtl_stats *pcurrent_stats)
461{
462
463	if (!pcurrent_stats->packet_matchbssid &&
464	    !pcurrent_stats->packet_beacon)
465		return;
466
467	_rtl92se_process_ui_rssi(hw, pcurrent_stats);
468	_rtl92se_process_pwdb(hw, pcurrent_stats);
469	_rtl92se_process_ui_link_quality(hw, pcurrent_stats);
470}
471
472static void _rtl92se_translate_rx_signal_stuff(struct ieee80211_hw *hw,
473		struct sk_buff *skb, struct rtl_stats *pstats,
474		u8 *pdesc, struct rx_fwinfo *p_drvinfo)
475{
476	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
477	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
478
479	struct ieee80211_hdr *hdr;
480	u8 *tmp_buf;
481	u8 *praddr;
482	__le16 fc;
483	u16 type, cfc;
484	bool packet_matchbssid, packet_toself, packet_beacon;
485
486	tmp_buf = skb->data + pstats->rx_drvinfo_size + pstats->rx_bufshift;
487
488	hdr = (struct ieee80211_hdr *)tmp_buf;
489	fc = hdr->frame_control;
490	cfc = le16_to_cpu(fc);
491	type = WLAN_FC_GET_TYPE(fc);
492	praddr = hdr->addr1;
493
494	packet_matchbssid = ((IEEE80211_FTYPE_CTL != type) &&
495	     ether_addr_equal(mac->bssid,
496			      (cfc & IEEE80211_FCTL_TODS) ? hdr->addr1 :
497			      (cfc & IEEE80211_FCTL_FROMDS) ? hdr->addr2 :
498			      hdr->addr3) &&
499	     (!pstats->hwerror) && (!pstats->crc) && (!pstats->icv));
500
501	packet_toself = packet_matchbssid &&
502	    ether_addr_equal(praddr, rtlefuse->dev_addr);
503
504	if (ieee80211_is_beacon(fc))
505		packet_beacon = true;
506
507	_rtl92se_query_rxphystatus(hw, pstats, pdesc, p_drvinfo,
508			packet_matchbssid, packet_toself, packet_beacon);
509	_rtl92se_process_phyinfo(hw, tmp_buf, pstats);
510}
511
512bool rtl92se_rx_query_desc(struct ieee80211_hw *hw, struct rtl_stats *stats,
513			   struct ieee80211_rx_status *rx_status, u8 *pdesc,
514			   struct sk_buff *skb)
515{
516	struct rx_fwinfo *p_drvinfo;
517	u32 phystatus = (u32)GET_RX_STATUS_DESC_PHY_STATUS(pdesc);
518	struct ieee80211_hdr *hdr;
519	bool first_ampdu = false;
520
521	stats->length = (u16)GET_RX_STATUS_DESC_PKT_LEN(pdesc);
522	stats->rx_drvinfo_size = (u8)GET_RX_STATUS_DESC_DRVINFO_SIZE(pdesc) * 8;
523	stats->rx_bufshift = (u8)(GET_RX_STATUS_DESC_SHIFT(pdesc) & 0x03);
524	stats->icv = (u16)GET_RX_STATUS_DESC_ICV(pdesc);
525	stats->crc = (u16)GET_RX_STATUS_DESC_CRC32(pdesc);
526	stats->hwerror = (u16)(stats->crc | stats->icv);
527	stats->decrypted = !GET_RX_STATUS_DESC_SWDEC(pdesc);
528
529	stats->rate = (u8)GET_RX_STATUS_DESC_RX_MCS(pdesc);
530	stats->shortpreamble = (u16)GET_RX_STATUS_DESC_SPLCP(pdesc);
531	stats->isampdu = (bool)(GET_RX_STATUS_DESC_PAGGR(pdesc) == 1);
532	stats->isfirst_ampdu = (bool) ((GET_RX_STATUS_DESC_PAGGR(pdesc) == 1)
533			       && (GET_RX_STATUS_DESC_FAGGR(pdesc) == 1));
534	stats->timestamp_low = GET_RX_STATUS_DESC_TSFL(pdesc);
535	stats->rx_is40Mhzpacket = (bool)GET_RX_STATUS_DESC_BW(pdesc);
536	stats->is_ht = (bool)GET_RX_STATUS_DESC_RX_HT(pdesc);
537	stats->is_cck = SE_RX_HAL_IS_CCK_RATE(pdesc);
538
539	if (stats->hwerror)
540		return false;
541
542	rx_status->freq = hw->conf.channel->center_freq;
543	rx_status->band = hw->conf.channel->band;
544
545	hdr = (struct ieee80211_hdr *)(skb->data + stats->rx_drvinfo_size
546	      + stats->rx_bufshift);
547
548	if (stats->crc)
549		rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
550
551	if (stats->rx_is40Mhzpacket)
552		rx_status->flag |= RX_FLAG_40MHZ;
553
554	if (stats->is_ht)
555		rx_status->flag |= RX_FLAG_HT;
556
557	rx_status->flag |= RX_FLAG_MACTIME_MPDU;
558
559	/* hw will set stats->decrypted true, if it finds the
560	 * frame is open data frame or mgmt frame,
561	 * hw will not decrypt robust managment frame
562	 * for IEEE80211w but still set stats->decrypted
563	 * true, so here we should set it back to undecrypted
564	 * for IEEE80211w frame, and mac80211 sw will help
565	 * to decrypt it */
566	if (stats->decrypted) {
567		if ((ieee80211_is_robust_mgmt_frame(hdr)) &&
568			(ieee80211_has_protected(hdr->frame_control)))
569			rx_status->flag &= ~RX_FLAG_DECRYPTED;
570		else
571			rx_status->flag |= RX_FLAG_DECRYPTED;
572	}
573
574	rx_status->rate_idx = rtlwifi_rate_mapping(hw,
575			      stats->is_ht, stats->rate, first_ampdu);
576
577	rx_status->mactime = stats->timestamp_low;
578	if (phystatus) {
579		p_drvinfo = (struct rx_fwinfo *)(skb->data +
580						 stats->rx_bufshift);
581		_rtl92se_translate_rx_signal_stuff(hw, skb, stats, pdesc,
582						   p_drvinfo);
583	}
584
585	/*rx_status->qual = stats->signal; */
586	rx_status->signal = stats->rssi + 10;
587	/*rx_status->noise = -stats->noise; */
588
589	return true;
590}
591
592void rtl92se_tx_fill_desc(struct ieee80211_hw *hw,
593		struct ieee80211_hdr *hdr, u8 *pdesc_tx,
594		struct ieee80211_tx_info *info, struct sk_buff *skb,
595		u8 hw_queue, struct rtl_tcb_desc *ptcb_desc)
596{
597	struct rtl_priv *rtlpriv = rtl_priv(hw);
598	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
599	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
600	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
601	struct ieee80211_sta *sta = info->control.sta;
602	u8 *pdesc = (u8 *) pdesc_tx;
603	u16 seq_number;
604	__le16 fc = hdr->frame_control;
605	u8 reserved_macid = 0;
606	u8 fw_qsel = _rtl92se_map_hwqueue_to_fwqueue(skb, hw_queue);
607	bool firstseg = (!(hdr->seq_ctrl & cpu_to_le16(IEEE80211_SCTL_FRAG)));
608	bool lastseg = (!(hdr->frame_control &
609			cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)));
610	dma_addr_t mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len,
611		    PCI_DMA_TODEVICE);
612	u8 bw_40 = 0;
613
614	if (mac->opmode == NL80211_IFTYPE_STATION) {
615		bw_40 = mac->bw_40;
616	} else if (mac->opmode == NL80211_IFTYPE_AP ||
617		mac->opmode == NL80211_IFTYPE_ADHOC) {
618		if (sta)
619			bw_40 = sta->ht_cap.cap &
620				    IEEE80211_HT_CAP_SUP_WIDTH_20_40;
621	}
622
623	seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4;
624
625	rtl_get_tcb_desc(hw, info, sta, skb, ptcb_desc);
626
627	CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_DESC_SIZE_RTL8192S);
628
629	if (firstseg) {
630		if (rtlpriv->dm.useramask) {
631			/* set txdesc macId */
632			if (ptcb_desc->mac_id < 32) {
633				SET_TX_DESC_MACID(pdesc, ptcb_desc->mac_id);
634				reserved_macid |= ptcb_desc->mac_id;
635			}
636		}
637		SET_TX_DESC_RSVD_MACID(pdesc, reserved_macid);
638
639		SET_TX_DESC_TXHT(pdesc, ((ptcb_desc->hw_rate >=
640				 DESC92_RATEMCS0) ? 1 : 0));
641
642		if (rtlhal->version == VERSION_8192S_ACUT) {
643			if (ptcb_desc->hw_rate == DESC92_RATE1M ||
644				ptcb_desc->hw_rate  == DESC92_RATE2M ||
645				ptcb_desc->hw_rate == DESC92_RATE5_5M ||
646				ptcb_desc->hw_rate == DESC92_RATE11M) {
647				ptcb_desc->hw_rate = DESC92_RATE12M;
648			}
649		}
650
651		SET_TX_DESC_TX_RATE(pdesc, ptcb_desc->hw_rate);
652
653		if (ptcb_desc->use_shortgi || ptcb_desc->use_shortpreamble)
654			SET_TX_DESC_TX_SHORT(pdesc, 0);
655
656		/* Aggregation related */
657		if (info->flags & IEEE80211_TX_CTL_AMPDU)
658			SET_TX_DESC_AGG_ENABLE(pdesc, 1);
659
660		/* For AMPDU, we must insert SSN into TX_DESC */
661		SET_TX_DESC_SEQ(pdesc, seq_number);
662
663		/* Protection mode related */
664		/* For 92S, if RTS/CTS are set, HW will execute RTS. */
665		/* We choose only one protection mode to execute */
666		SET_TX_DESC_RTS_ENABLE(pdesc, ((ptcb_desc->rts_enable &&
667				!ptcb_desc->cts_enable) ? 1 : 0));
668		SET_TX_DESC_CTS_ENABLE(pdesc, ((ptcb_desc->cts_enable) ?
669				       1 : 0));
670		SET_TX_DESC_RTS_STBC(pdesc, ((ptcb_desc->rts_stbc) ? 1 : 0));
671
672		SET_TX_DESC_RTS_RATE(pdesc, ptcb_desc->rts_rate);
673		SET_TX_DESC_RTS_BANDWIDTH(pdesc, 0);
674		SET_TX_DESC_RTS_SUB_CARRIER(pdesc, ptcb_desc->rts_sc);
675		SET_TX_DESC_RTS_SHORT(pdesc, ((ptcb_desc->rts_rate <=
676		       DESC92_RATE54M) ?
677		       (ptcb_desc->rts_use_shortpreamble ? 1 : 0)
678		       : (ptcb_desc->rts_use_shortgi ? 1 : 0)));
679
680
681		/* Set Bandwidth and sub-channel settings. */
682		if (bw_40) {
683			if (ptcb_desc->packet_bw) {
684				SET_TX_DESC_TX_BANDWIDTH(pdesc, 1);
685				/* use duplicated mode */
686				SET_TX_DESC_TX_SUB_CARRIER(pdesc, 0);
687			} else {
688				SET_TX_DESC_TX_BANDWIDTH(pdesc, 0);
689				SET_TX_DESC_TX_SUB_CARRIER(pdesc,
690						   mac->cur_40_prime_sc);
691			}
692		} else {
693			SET_TX_DESC_TX_BANDWIDTH(pdesc, 0);
694			SET_TX_DESC_TX_SUB_CARRIER(pdesc, 0);
695		}
696
697		/* 3 Fill necessary field in First Descriptor */
698		/*DWORD 0*/
699		SET_TX_DESC_LINIP(pdesc, 0);
700		SET_TX_DESC_OFFSET(pdesc, 32);
701		SET_TX_DESC_PKT_SIZE(pdesc, (u16) skb->len);
702
703		/*DWORD 1*/
704		SET_TX_DESC_RA_BRSR_ID(pdesc, ptcb_desc->ratr_index);
705
706		/* Fill security related */
707		if (info->control.hw_key) {
708			struct ieee80211_key_conf *keyconf;
709
710			keyconf = info->control.hw_key;
711			switch (keyconf->cipher) {
712			case WLAN_CIPHER_SUITE_WEP40:
713			case WLAN_CIPHER_SUITE_WEP104:
714				SET_TX_DESC_SEC_TYPE(pdesc, 0x1);
715				break;
716			case WLAN_CIPHER_SUITE_TKIP:
717				SET_TX_DESC_SEC_TYPE(pdesc, 0x2);
718				break;
719			case WLAN_CIPHER_SUITE_CCMP:
720				SET_TX_DESC_SEC_TYPE(pdesc, 0x3);
721				break;
722			default:
723				SET_TX_DESC_SEC_TYPE(pdesc, 0x0);
724				break;
725
726			}
727		}
728
729		/* Set Packet ID */
730		SET_TX_DESC_PACKET_ID(pdesc, 0);
731
732		/* We will assign magement queue to BK. */
733		SET_TX_DESC_QUEUE_SEL(pdesc, fw_qsel);
734
735		/* Alwasy enable all rate fallback range */
736		SET_TX_DESC_DATA_RATE_FB_LIMIT(pdesc, 0x1F);
737
738		/* Fix: I don't kown why hw use 6.5M to tx when set it */
739		SET_TX_DESC_USER_RATE(pdesc,
740				      ptcb_desc->use_driver_rate ? 1 : 0);
741
742		/* Set NON_QOS bit. */
743		if (!ieee80211_is_data_qos(fc))
744			SET_TX_DESC_NON_QOS(pdesc, 1);
745
746	}
747
748	/* Fill fields that are required to be initialized
749	 * in all of the descriptors */
750	/*DWORD 0 */
751	SET_TX_DESC_FIRST_SEG(pdesc, (firstseg ? 1 : 0));
752	SET_TX_DESC_LAST_SEG(pdesc, (lastseg ? 1 : 0));
753
754	/* DWORD 7 */
755	SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16) skb->len);
756
757	/* DOWRD 8 */
758	SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, cpu_to_le32(mapping));
759
760	RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, "\n");
761}
762
763void rtl92se_tx_fill_cmddesc(struct ieee80211_hw *hw, u8 *pdesc,
764	bool firstseg, bool lastseg, struct sk_buff *skb)
765{
766	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
767	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
768	struct rtl_tcb_desc *tcb_desc = (struct rtl_tcb_desc *)(skb->cb);
769
770	dma_addr_t mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len,
771			PCI_DMA_TODEVICE);
772
773    /* Clear all status	*/
774	CLEAR_PCI_TX_DESC_CONTENT(pdesc, TX_CMDDESC_SIZE_RTL8192S);
775
776	/* This bit indicate this packet is used for FW download. */
777	if (tcb_desc->cmd_or_init == DESC_PACKET_TYPE_INIT) {
778		/* For firmware downlaod we only need to set LINIP */
779		SET_TX_DESC_LINIP(pdesc, tcb_desc->last_inipkt);
780
781		/* 92SE must set as 1 for firmware download HW DMA error */
782		SET_TX_DESC_FIRST_SEG(pdesc, 1);
783		SET_TX_DESC_LAST_SEG(pdesc, 1);
784
785		/* 92SE need not to set TX packet size when firmware download */
786		SET_TX_DESC_PKT_SIZE(pdesc, (u16)(skb->len));
787		SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16)(skb->len));
788		SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, cpu_to_le32(mapping));
789
790		wmb();
791		SET_TX_DESC_OWN(pdesc, 1);
792	} else { /* H2C Command Desc format (Host TXCMD) */
793		/* 92SE must set as 1 for firmware download HW DMA error */
794		SET_TX_DESC_FIRST_SEG(pdesc, 1);
795		SET_TX_DESC_LAST_SEG(pdesc, 1);
796
797		SET_TX_DESC_OFFSET(pdesc, 0x20);
798
799		/* Buffer size + command header */
800		SET_TX_DESC_PKT_SIZE(pdesc, (u16)(skb->len));
801		/* Fixed queue of H2C command */
802		SET_TX_DESC_QUEUE_SEL(pdesc, 0x13);
803
804		SET_BITS_TO_LE_4BYTE(skb->data, 24, 7, rtlhal->h2c_txcmd_seq);
805
806		SET_TX_DESC_TX_BUFFER_SIZE(pdesc, (u16)(skb->len));
807		SET_TX_DESC_TX_BUFFER_ADDRESS(pdesc, cpu_to_le32(mapping));
808
809		wmb();
810		SET_TX_DESC_OWN(pdesc, 1);
811
812	}
813}
814
815void rtl92se_set_desc(u8 *pdesc, bool istx, u8 desc_name, u8 *val)
816{
817	if (istx) {
818		switch (desc_name) {
819		case HW_DESC_OWN:
820			wmb();
821			SET_TX_DESC_OWN(pdesc, 1);
822			break;
823		case HW_DESC_TX_NEXTDESC_ADDR:
824			SET_TX_DESC_NEXT_DESC_ADDRESS(pdesc, *(u32 *) val);
825			break;
826		default:
827			RT_ASSERT(false, "ERR txdesc :%d not process\n",
828				  desc_name);
829			break;
830		}
831	} else {
832		switch (desc_name) {
833		case HW_DESC_RXOWN:
834			wmb();
835			SET_RX_STATUS_DESC_OWN(pdesc, 1);
836			break;
837		case HW_DESC_RXBUFF_ADDR:
838			SET_RX_STATUS__DESC_BUFF_ADDR(pdesc, *(u32 *) val);
839			break;
840		case HW_DESC_RXPKT_LEN:
841			SET_RX_STATUS_DESC_PKT_LEN(pdesc, *(u32 *) val);
842			break;
843		case HW_DESC_RXERO:
844			SET_RX_STATUS_DESC_EOR(pdesc, 1);
845			break;
846		default:
847			RT_ASSERT(false, "ERR rxdesc :%d not process\n",
848				  desc_name);
849			break;
850		}
851	}
852}
853
854u32 rtl92se_get_desc(u8 *desc, bool istx, u8 desc_name)
855{
856	u32 ret = 0;
857
858	if (istx) {
859		switch (desc_name) {
860		case HW_DESC_OWN:
861			ret = GET_TX_DESC_OWN(desc);
862			break;
863		case HW_DESC_TXBUFF_ADDR:
864			ret = GET_TX_DESC_TX_BUFFER_ADDRESS(desc);
865			break;
866		default:
867			RT_ASSERT(false, "ERR txdesc :%d not process\n",
868				  desc_name);
869			break;
870		}
871	} else {
872		switch (desc_name) {
873		case HW_DESC_OWN:
874			ret = GET_RX_STATUS_DESC_OWN(desc);
875			break;
876		case HW_DESC_RXPKT_LEN:
877			ret = GET_RX_STATUS_DESC_PKT_LEN(desc);
878			break;
879		default:
880			RT_ASSERT(false, "ERR rxdesc :%d not process\n",
881				  desc_name);
882			break;
883		}
884	}
885	return ret;
886}
887
888void rtl92se_tx_polling(struct ieee80211_hw *hw, u8 hw_queue)
889{
890	struct rtl_priv *rtlpriv = rtl_priv(hw);
891	rtl_write_word(rtlpriv, TP_POLL, BIT(0) << (hw_queue));
892}