Linux Audio

Check our new training course

Loading...
Note: File does not exist in v4.6.
  1/******************************************************************************
  2 *
  3 * Copyright(c) 2009-2010  Realtek Corporation.
  4 *
  5 * This program is free software; you can redistribute it and/or modify it
  6 * under the terms of version 2 of the GNU General Public License as
  7 * published by the Free Software Foundation.
  8 *
  9 * This program is distributed in the hope that it will be useful, but WITHOUT
 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 11 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
 12 * more details.
 13 *
 14 * You should have received a copy of the GNU General Public License along with
 15 * this program; if not, write to the Free Software Foundation, Inc.,
 16 * 51 Franklin Street, Fifth Floor, Boston, MA 02110, USA
 17 *
 18 * The full GNU General Public License is included in this distribution in the
 19 * file called LICENSE.
 20 *
 21 * Contact Information:
 22 * wlanfae <wlanfae@realtek.com>
 23 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
 24 * Hsinchu 300, Taiwan.
 25 *
 26 * Larry Finger <Larry.Finger@lwfinger.net>
 27 *
 28 *****************************************************************************/
 29
 30#include "../wifi.h"
 31#include "../pci.h"
 32#include "../base.h"
 33#include "reg.h"
 34#include "def.h"
 35#include "phy.h"
 36#include "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}