trx.c 24.7 KB
Newer Older
1 2
// SPDX-License-Identifier: GPL-2.0
/* Copyright(c) 2009-2012  Realtek Corporation.*/
3 4 5 6

#include "../wifi.h"
#include "../pci.h"
#include "../base.h"
7
#include "../stats.h"
8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52
#include "reg.h"
#include "def.h"
#include "phy.h"
#include "trx.h"
#include "led.h"

static u8 _rtl92de_map_hwqueue_to_fwqueue(struct sk_buff *skb, u8 hw_queue)
{
	__le16 fc = rtl_get_fc(skb);

	if (unlikely(ieee80211_is_beacon(fc)))
		return QSLT_BEACON;
	if (ieee80211_is_mgmt(fc))
		return QSLT_MGNT;

	return skb->priority;
}

static long _rtl92de_translate_todbm(struct ieee80211_hw *hw,
				     u8 signal_strength_index)
{
	long signal_power;

	signal_power = (long)((signal_strength_index + 1) >> 1);
	signal_power -= 95;
	return signal_power;
}

static void _rtl92de_query_rxphystatus(struct ieee80211_hw *hw,
				       struct rtl_stats *pstats,
				       struct rx_desc_92d *pdesc,
				       struct rx_fwinfo_92d *p_drvinfo,
				       bool packet_match_bssid,
				       bool packet_toself,
				       bool packet_beacon)
{
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv);
	struct phy_sts_cck_8192d *cck_buf;
	s8 rx_pwr_all, rx_pwr[4];
	u8 rf_rx_num = 0, evm, pwdb_all;
	u8 i, max_spatial_stream;
	u32 rssi, total_rssi = 0;
	bool is_cck_rate;

53
	is_cck_rate = RX_HAL_IS_CCK_RATE(pdesc->rxmcs);
54 55 56 57
	pstats->packet_matchbssid = packet_match_bssid;
	pstats->packet_toself = packet_toself;
	pstats->packet_beacon = packet_beacon;
	pstats->is_cck = is_cck_rate;
58 59
	pstats->rx_mimo_sig_qual[0] = -1;
	pstats->rx_mimo_sig_qual[1] = -1;
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106

	if (is_cck_rate) {
		u8 report, cck_highpwr;
		cck_buf = (struct phy_sts_cck_8192d *)p_drvinfo;
		if (ppsc->rfpwr_state == ERFON)
			cck_highpwr = (u8) rtl_get_bbreg(hw,
						 RFPGA0_XA_HSSIPARAMETER2,
						 BIT(9));
		else
			cck_highpwr = false;
		if (!cck_highpwr) {
			u8 cck_agc_rpt = cck_buf->cck_agc_rpt;
			report = cck_buf->cck_agc_rpt & 0xc0;
			report = report >> 6;
			switch (report) {
			case 0x3:
				rx_pwr_all = -46 - (cck_agc_rpt & 0x3e);
				break;
			case 0x2:
				rx_pwr_all = -26 - (cck_agc_rpt & 0x3e);
				break;
			case 0x1:
				rx_pwr_all = -12 - (cck_agc_rpt & 0x3e);
				break;
			case 0x0:
				rx_pwr_all = 16 - (cck_agc_rpt & 0x3e);
				break;
			}
		} else {
			u8 cck_agc_rpt = cck_buf->cck_agc_rpt;
			report = p_drvinfo->cfosho[0] & 0x60;
			report = report >> 5;
			switch (report) {
			case 0x3:
				rx_pwr_all = -46 - ((cck_agc_rpt & 0x1f) << 1);
				break;
			case 0x2:
				rx_pwr_all = -26 - ((cck_agc_rpt & 0x1f) << 1);
				break;
			case 0x1:
				rx_pwr_all = -12 - ((cck_agc_rpt & 0x1f) << 1);
				break;
			case 0x0:
				rx_pwr_all = 16 - ((cck_agc_rpt & 0x1f) << 1);
				break;
			}
		}
107
		pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all);
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137
		/* CCK gain is smaller than OFDM/MCS gain,  */
		/* so we add gain diff by experiences, the val is 6 */
		pwdb_all += 6;
		if (pwdb_all > 100)
			pwdb_all = 100;
		/* modify the offset to make the same gain index with OFDM. */
		if (pwdb_all > 34 && pwdb_all <= 42)
			pwdb_all -= 2;
		else if (pwdb_all > 26 && pwdb_all <= 34)
			pwdb_all -= 6;
		else if (pwdb_all > 14 && pwdb_all <= 26)
			pwdb_all -= 8;
		else if (pwdb_all > 4 && pwdb_all <= 14)
			pwdb_all -= 4;
		pstats->rx_pwdb_all = pwdb_all;
		pstats->recvsignalpower = rx_pwr_all;
		if (packet_match_bssid) {
			u8 sq;
			if (pstats->rx_pwdb_all > 40) {
				sq = 100;
			} else {
				sq = cck_buf->sq_rpt;
				if (sq > 64)
					sq = 0;
				else if (sq < 20)
					sq = 100;
				else
					sq = ((64 - sq) * 100) / 44;
			}
			pstats->signalquality = sq;
138 139
			pstats->rx_mimo_sig_qual[0] = sq;
			pstats->rx_mimo_sig_qual[1] = -1;
140 141 142 143 144 145 146 147 148
		}
	} else {
		rtlpriv->dm.rfpath_rxenable[0] = true;
		rtlpriv->dm.rfpath_rxenable[1] = true;
		for (i = RF90_PATH_A; i < RF6052_MAX_PATH; i++) {
			if (rtlpriv->dm.rfpath_rxenable[i])
				rf_rx_num++;
			rx_pwr[i] = ((p_drvinfo->gain_trsw[i] & 0x3f) * 2)
				    - 110;
149
			rssi = rtl_query_rxpwrpercentage(rx_pwr[i]);
150 151 152 153 154 155 156
			total_rssi += rssi;
			rtlpriv->stats.rx_snr_db[i] =
					 (long)(p_drvinfo->rxsnr[i] / 2);
			if (packet_match_bssid)
				pstats->rx_mimo_signalstrength[i] = (u8) rssi;
		}
		rx_pwr_all = ((p_drvinfo->pwdb_all >> 1) & 0x7f) - 106;
157
		pwdb_all = rtl_query_rxpwrpercentage(rx_pwr_all);
158 159 160
		pstats->rx_pwdb_all = pwdb_all;
		pstats->rxpower = rx_pwr_all;
		pstats->recvsignalpower = rx_pwr_all;
161 162
		if (pdesc->rxht && pdesc->rxmcs >= DESC_RATEMCS8 &&
		    pdesc->rxmcs <= DESC_RATEMCS15)
163 164 165 166
			max_spatial_stream = 2;
		else
			max_spatial_stream = 1;
		for (i = 0; i < max_spatial_stream; i++) {
167
			evm = rtl_evm_db_to_percentage(p_drvinfo->rxevm[i]);
168 169 170 171
			if (packet_match_bssid) {
				if (i == 0)
					pstats->signalquality =
						 (u8)(evm & 0xff);
172
				pstats->rx_mimo_sig_qual[i] =
173 174 175 176 177
						 (u8)(evm & 0xff);
			}
		}
	}
	if (is_cck_rate)
178
		pstats->signalstrength = (u8)(rtl_signal_scale_mapping(hw,
179 180
				pwdb_all));
	else if (rf_rx_num != 0)
181
		pstats->signalstrength = (u8)(rtl_signal_scale_mapping(hw,
182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270
				total_rssi /= rf_rx_num));
}

static void rtl92d_loop_over_paths(struct ieee80211_hw *hw,
				   struct rtl_stats *pstats)
{
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	struct rtl_phy *rtlphy = &(rtlpriv->phy);
	u8 rfpath;

	for (rfpath = RF90_PATH_A; rfpath < rtlphy->num_total_rfpath;
	     rfpath++) {
		if (rtlpriv->stats.rx_rssi_percentage[rfpath] == 0) {
			rtlpriv->stats.rx_rssi_percentage[rfpath] =
			    pstats->rx_mimo_signalstrength[rfpath];

		}
		if (pstats->rx_mimo_signalstrength[rfpath] >
		    rtlpriv->stats.rx_rssi_percentage[rfpath]) {
			rtlpriv->stats.rx_rssi_percentage[rfpath] =
			    ((rtlpriv->stats.rx_rssi_percentage[rfpath] *
			      (RX_SMOOTH_FACTOR - 1)) +
			     (pstats->rx_mimo_signalstrength[rfpath])) /
			    (RX_SMOOTH_FACTOR);
			rtlpriv->stats.rx_rssi_percentage[rfpath] =
			    rtlpriv->stats.rx_rssi_percentage[rfpath] + 1;
		} else {
			rtlpriv->stats.rx_rssi_percentage[rfpath] =
			    ((rtlpriv->stats.rx_rssi_percentage[rfpath] *
			      (RX_SMOOTH_FACTOR - 1)) +
			     (pstats->rx_mimo_signalstrength[rfpath])) /
			    (RX_SMOOTH_FACTOR);
		}
	}
}

static void _rtl92de_process_ui_rssi(struct ieee80211_hw *hw,
				     struct rtl_stats *pstats)
{
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	u32 last_rssi, tmpval;

	if (pstats->packet_toself || pstats->packet_beacon) {
		rtlpriv->stats.rssi_calculate_cnt++;
		if (rtlpriv->stats.ui_rssi.total_num++ >=
		    PHY_RSSI_SLID_WIN_MAX) {
			rtlpriv->stats.ui_rssi.total_num =
						 PHY_RSSI_SLID_WIN_MAX;
			last_rssi = rtlpriv->stats.ui_rssi.elements[
				rtlpriv->stats.ui_rssi.index];
			rtlpriv->stats.ui_rssi.total_val -= last_rssi;
		}
		rtlpriv->stats.ui_rssi.total_val += pstats->signalstrength;
		rtlpriv->stats.ui_rssi.elements
			[rtlpriv->stats.ui_rssi.index++] =
			pstats->signalstrength;
		if (rtlpriv->stats.ui_rssi.index >= PHY_RSSI_SLID_WIN_MAX)
			rtlpriv->stats.ui_rssi.index = 0;
		tmpval = rtlpriv->stats.ui_rssi.total_val /
			rtlpriv->stats.ui_rssi.total_num;
		rtlpriv->stats.signal_strength = _rtl92de_translate_todbm(hw,
			(u8) tmpval);
		pstats->rssi = rtlpriv->stats.signal_strength;
	}
	if (!pstats->is_cck && pstats->packet_toself)
		rtl92d_loop_over_paths(hw, pstats);
}

static void _rtl92de_update_rxsignalstatistics(struct ieee80211_hw *hw,
					       struct rtl_stats *pstats)
{
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	int weighting = 0;

	if (rtlpriv->stats.recv_signal_power == 0)
		rtlpriv->stats.recv_signal_power = pstats->recvsignalpower;
	if (pstats->recvsignalpower > rtlpriv->stats.recv_signal_power)
		weighting = 5;
	else if (pstats->recvsignalpower < rtlpriv->stats.recv_signal_power)
		weighting = (-5);
	rtlpriv->stats.recv_signal_power = (rtlpriv->stats.recv_signal_power *
		5 + pstats->recvsignalpower + weighting) / 6;
}

static void _rtl92de_process_pwdb(struct ieee80211_hw *hw,
				  struct rtl_stats *pstats)
{
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
271
	long undec_sm_pwdb;
272 273 274 275 276

	if (mac->opmode == NL80211_IFTYPE_ADHOC	||
		mac->opmode == NL80211_IFTYPE_AP)
		return;
	else
277
		undec_sm_pwdb = rtlpriv->dm.undec_sm_pwdb;
278 279

	if (pstats->packet_toself || pstats->packet_beacon) {
280 281 282 283
		if (undec_sm_pwdb < 0)
			undec_sm_pwdb = pstats->rx_pwdb_all;
		if (pstats->rx_pwdb_all > (u32) undec_sm_pwdb) {
			undec_sm_pwdb = (((undec_sm_pwdb) *
284 285
			      (RX_SMOOTH_FACTOR - 1)) +
			      (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
286
			undec_sm_pwdb = undec_sm_pwdb + 1;
287
		} else {
288
			undec_sm_pwdb = (((undec_sm_pwdb) *
289 290 291
			      (RX_SMOOTH_FACTOR - 1)) +
			      (pstats->rx_pwdb_all)) / (RX_SMOOTH_FACTOR);
		}
292
		rtlpriv->dm.undec_sm_pwdb = undec_sm_pwdb;
293 294 295 296 297 298 299 300 301 302 303
		_rtl92de_update_rxsignalstatistics(hw, pstats);
	}
}

static void rtl92d_loop_over_streams(struct ieee80211_hw *hw,
				     struct rtl_stats *pstats)
{
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	int stream;

	for (stream = 0; stream < 2; stream++) {
304
		if (pstats->rx_mimo_sig_qual[stream] != -1) {
305 306
			if (rtlpriv->stats.rx_evm_percentage[stream] == 0) {
				rtlpriv->stats.rx_evm_percentage[stream] =
307
				    pstats->rx_mimo_sig_qual[stream];
308 309 310 311
			}
			rtlpriv->stats.rx_evm_percentage[stream] =
			    ((rtlpriv->stats.rx_evm_percentage[stream]
			      * (RX_SMOOTH_FACTOR - 1)) +
312
			     (pstats->rx_mimo_sig_qual[stream] * 1)) /
313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377
			    (RX_SMOOTH_FACTOR);
		}
	}
}

static void _rtl92de_process_ui_link_quality(struct ieee80211_hw *hw,
					     struct rtl_stats *pstats)
{
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	u32 last_evm, tmpval;

	if (pstats->signalquality == 0)
		return;
	if (pstats->packet_toself || pstats->packet_beacon) {
		if (rtlpriv->stats.ui_link_quality.total_num++ >=
		    PHY_LINKQUALITY_SLID_WIN_MAX) {
			rtlpriv->stats.ui_link_quality.total_num =
			    PHY_LINKQUALITY_SLID_WIN_MAX;
			last_evm = rtlpriv->stats.ui_link_quality.elements[
				rtlpriv->stats.ui_link_quality.index];
			rtlpriv->stats.ui_link_quality.total_val -= last_evm;
		}
		rtlpriv->stats.ui_link_quality.total_val +=
						 pstats->signalquality;
		rtlpriv->stats.ui_link_quality.elements[
			rtlpriv->stats.ui_link_quality.index++] =
						 pstats->signalquality;
		if (rtlpriv->stats.ui_link_quality.index >=
		    PHY_LINKQUALITY_SLID_WIN_MAX)
			rtlpriv->stats.ui_link_quality.index = 0;
		tmpval = rtlpriv->stats.ui_link_quality.total_val /
		    rtlpriv->stats.ui_link_quality.total_num;
		rtlpriv->stats.signal_quality = tmpval;
		rtlpriv->stats.last_sigstrength_inpercent = tmpval;
		rtl92d_loop_over_streams(hw, pstats);
	}
}

static void _rtl92de_process_phyinfo(struct ieee80211_hw *hw,
				     u8 *buffer,
				     struct rtl_stats *pcurrent_stats)
{

	if (!pcurrent_stats->packet_matchbssid &&
	    !pcurrent_stats->packet_beacon)
		return;

	_rtl92de_process_ui_rssi(hw, pcurrent_stats);
	_rtl92de_process_pwdb(hw, pcurrent_stats);
	_rtl92de_process_ui_link_quality(hw, pcurrent_stats);
}

static void _rtl92de_translate_rx_signal_stuff(struct ieee80211_hw *hw,
					       struct sk_buff *skb,
					       struct rtl_stats *pstats,
					       struct rx_desc_92d *pdesc,
					       struct rx_fwinfo_92d *p_drvinfo)
{
	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
	struct rtl_efuse *rtlefuse = rtl_efuse(rtl_priv(hw));
	struct ieee80211_hdr *hdr;
	u8 *tmp_buf;
	u8 *praddr;
	u16 type, cfc;
	__le16 fc;
378
	bool packet_matchbssid, packet_toself, packet_beacon = false;
379 380 381 382 383 384 385 386

	tmp_buf = skb->data + pstats->rx_drvinfo_size + pstats->rx_bufshift;
	hdr = (struct ieee80211_hdr *)tmp_buf;
	fc = hdr->frame_control;
	cfc = le16_to_cpu(fc);
	type = WLAN_FC_GET_TYPE(fc);
	praddr = hdr->addr1;
	packet_matchbssid = ((IEEE80211_FTYPE_CTL != type) &&
387 388 389 390 391
	     ether_addr_equal(mac->bssid,
			      (cfc & IEEE80211_FCTL_TODS) ? hdr->addr1 :
			      (cfc & IEEE80211_FCTL_FROMDS) ? hdr->addr2 :
			      hdr->addr3) &&
	     (!pstats->hwerror) && (!pstats->crc) && (!pstats->icv));
392
	packet_toself = packet_matchbssid &&
393
			ether_addr_equal(praddr, rtlefuse->dev_addr);
394 395 396 397 398 399 400 401 402 403
	if (ieee80211_is_beacon(fc))
		packet_beacon = true;
	_rtl92de_query_rxphystatus(hw, pstats, pdesc, p_drvinfo,
				   packet_matchbssid, packet_toself,
				   packet_beacon);
	_rtl92de_process_phyinfo(hw, tmp_buf, pstats);
}

bool rtl92de_rx_query_desc(struct ieee80211_hw *hw,	struct rtl_stats *stats,
		struct ieee80211_rx_status *rx_status,
404
		u8 *pdesc8, struct sk_buff *skb)
405
{
406
	__le32 *pdesc = (__le32 *)pdesc8;
407
	struct rx_fwinfo_92d *p_drvinfo;
408
	u32 phystatus = get_rx_desc_physt(pdesc);
409

410 411
	stats->length = (u16)get_rx_desc_pkt_len(pdesc);
	stats->rx_drvinfo_size = (u8)get_rx_desc_drv_info_size(pdesc) *
412
				 RX_DRV_INFO_SIZE_UNIT;
413 414 415
	stats->rx_bufshift = (u8)(get_rx_desc_shift(pdesc) & 0x03);
	stats->icv = (u16)get_rx_desc_icv(pdesc);
	stats->crc = (u16)get_rx_desc_crc32(pdesc);
416
	stats->hwerror = (stats->crc | stats->icv);
417 418 419 420 421 422 423 424 425
	stats->decrypted = !get_rx_desc_swdec(pdesc);
	stats->rate = (u8)get_rx_desc_rxmcs(pdesc);
	stats->shortpreamble = (u16)get_rx_desc_splcp(pdesc);
	stats->isampdu = (bool)(get_rx_desc_paggr(pdesc) == 1);
	stats->isfirst_ampdu = (bool)((get_rx_desc_paggr(pdesc) == 1) &&
				      (get_rx_desc_faggr(pdesc) == 1));
	stats->timestamp_low = get_rx_desc_tsfl(pdesc);
	stats->rx_is40mhzpacket = (bool)get_rx_desc_bw(pdesc);
	stats->is_ht = (bool)get_rx_desc_rxht(pdesc);
426 427
	rx_status->freq = hw->conf.chandef.chan->center_freq;
	rx_status->band = hw->conf.chandef.chan->band;
428
	if (get_rx_desc_crc32(pdesc))
429
		rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
430
	if (!get_rx_desc_swdec(pdesc))
431
		rx_status->flag |= RX_FLAG_DECRYPTED;
432
	if (get_rx_desc_bw(pdesc))
433
		rx_status->bw = RATE_INFO_BW_40;
434
	if (get_rx_desc_rxht(pdesc))
435
		rx_status->encoding = RX_ENC_HT;
436
	rx_status->flag |= RX_FLAG_MACTIME_START;
437 438
	if (stats->decrypted)
		rx_status->flag |= RX_FLAG_DECRYPTED;
439
	rx_status->rate_idx = rtlwifi_rate_mapping(hw, stats->is_ht,
440
						   false, stats->rate);
441
	rx_status->mactime = get_rx_desc_tsfl(pdesc);
442
	if (phystatus) {
443 444 445
		p_drvinfo = (struct rx_fwinfo_92d *)(skb->data +
						     stats->rx_bufshift);
		_rtl92de_translate_rx_signal_stuff(hw,
446 447
						   skb, stats,
						   (struct rx_desc_92d *)pdesc,
448 449 450
						   p_drvinfo);
	}
	/*rx_status->qual = stats->signal; */
451
	rx_status->signal = stats->recvsignalpower + 10;
452 453 454 455
	return true;
}

static void _rtl92de_insert_emcontent(struct rtl_tcb_desc *ptcb_desc,
456
				      u8 *virtualaddress8)
457
{
458 459
	__le32 *virtualaddress = (__le32 *)virtualaddress8;

460 461
	memset(virtualaddress, 0, 8);

462 463 464 465 466 467 468
	set_earlymode_pktnum(virtualaddress, ptcb_desc->empkt_num);
	set_earlymode_len0(virtualaddress, ptcb_desc->empkt_len[0]);
	set_earlymode_len1(virtualaddress, ptcb_desc->empkt_len[1]);
	set_earlymode_len2_1(virtualaddress, ptcb_desc->empkt_len[2] & 0xF);
	set_earlymode_len2_2(virtualaddress, ptcb_desc->empkt_len[2] >> 4);
	set_earlymode_len3(virtualaddress, ptcb_desc->empkt_len[3]);
	set_earlymode_len4(virtualaddress, ptcb_desc->empkt_len[4]);
469 470 471
}

void rtl92de_tx_fill_desc(struct ieee80211_hw *hw,
472
			  struct ieee80211_hdr *hdr, u8 *pdesc8,
473
			  u8 *pbd_desc_tx, struct ieee80211_tx_info *info,
474 475
			  struct ieee80211_sta *sta,
			  struct sk_buff *skb,
476 477 478 479 480 481 482
			  u8 hw_queue, struct rtl_tcb_desc *ptcb_desc)
{
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
483
	__le32 *pdesc = (__le32 *)pdesc8;
484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500
	u16 seq_number;
	__le16 fc = hdr->frame_control;
	unsigned int buf_len = 0;
	unsigned int skb_len = skb->len;
	u8 fw_qsel = _rtl92de_map_hwqueue_to_fwqueue(skb, hw_queue);
	bool firstseg = ((hdr->seq_ctrl &
			cpu_to_le16(IEEE80211_SCTL_FRAG)) == 0);
	bool lastseg = ((hdr->frame_control &
			cpu_to_le16(IEEE80211_FCTL_MOREFRAGS)) == 0);
	dma_addr_t mapping;
	u8 bw_40 = 0;

	if (mac->opmode == NL80211_IFTYPE_STATION) {
		bw_40 = mac->bw_40;
	} else if (mac->opmode == NL80211_IFTYPE_AP ||
		mac->opmode == NL80211_IFTYPE_ADHOC) {
		if (sta)
501
			bw_40 = sta->bandwidth >= IEEE80211_STA_RX_BW_40;
502 503 504 505 506 507 508 509 510 511 512
	}
	seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4;
	rtl_get_tcb_desc(hw, info, sta, skb, ptcb_desc);
	/* reserve 8 byte for AMPDU early mode */
	if (rtlhal->earlymode_enable) {
		skb_push(skb, EM_HDR_LEN);
		memset(skb->data, 0, EM_HDR_LEN);
	}
	buf_len = skb->len;
	mapping = pci_map_single(rtlpci->pdev, skb->data, skb->len,
				 PCI_DMA_TODEVICE);
513 514
	if (pci_dma_mapping_error(rtlpci->pdev, mapping)) {
		RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE,
515
			 "DMA mapping error\n");
516 517
		return;
	}
518
	clear_pci_tx_desc_content(pdesc, sizeof(struct tx_desc_92d));
519 520 521 522 523 524
	if (ieee80211_is_nullfunc(fc) || ieee80211_is_ctl(fc)) {
		firstseg = true;
		lastseg = true;
	}
	if (firstseg) {
		if (rtlhal->earlymode_enable) {
525 526
			set_tx_desc_pkt_offset(pdesc, 1);
			set_tx_desc_offset(pdesc, USB_HWDESC_HEADER_LEN +
527 528 529
					   EM_HDR_LEN);
			if (ptcb_desc->empkt_num) {
				RT_TRACE(rtlpriv, COMP_SEND, DBG_LOUD,
530 531
					 "Insert 8 byte.pTcb->EMPktNum:%d\n",
					 ptcb_desc->empkt_num);
532 533 534 535
				_rtl92de_insert_emcontent(ptcb_desc,
							  (u8 *)(skb->data));
			}
		} else {
536
			set_tx_desc_offset(pdesc, USB_HWDESC_HEADER_LEN);
537 538 539
		}
		/* 5G have no CCK rate */
		if (rtlhal->current_bandtype == BAND_ON_5G)
540 541
			if (ptcb_desc->hw_rate < DESC_RATE6M)
				ptcb_desc->hw_rate = DESC_RATE6M;
542
		set_tx_desc_tx_rate(pdesc, ptcb_desc->hw_rate);
543
		if (ptcb_desc->use_shortgi || ptcb_desc->use_shortpreamble)
544
			set_tx_desc_data_shortgi(pdesc, 1);
545 546

		if (rtlhal->macphymode == DUALMAC_DUALPHY &&
547
			ptcb_desc->hw_rate == DESC_RATEMCS7)
548
			set_tx_desc_data_shortgi(pdesc, 1);
549 550

		if (info->flags & IEEE80211_TX_CTL_AMPDU) {
551 552
			set_tx_desc_agg_enable(pdesc, 1);
			set_tx_desc_max_agg_num(pdesc, 0x14);
553
		}
554 555 556 557 558
		set_tx_desc_seq(pdesc, seq_number);
		set_tx_desc_rts_enable(pdesc,
				       ((ptcb_desc->rts_enable &&
					!ptcb_desc->cts_enable) ? 1 : 0));
		set_tx_desc_hw_rts_enable(pdesc, ((ptcb_desc->rts_enable
559
					  || ptcb_desc->cts_enable) ? 1 : 0));
560 561
		set_tx_desc_cts2self(pdesc, ((ptcb_desc->cts_enable) ? 1 : 0));
		set_tx_desc_rts_stbc(pdesc, ((ptcb_desc->rts_stbc) ? 1 : 0));
562 563
		/* 5G have no CCK rate */
		if (rtlhal->current_bandtype == BAND_ON_5G)
564 565
			if (ptcb_desc->rts_rate < DESC_RATE6M)
				ptcb_desc->rts_rate = DESC_RATE6M;
566 567 568 569
		set_tx_desc_rts_rate(pdesc, ptcb_desc->rts_rate);
		set_tx_desc_rts_bw(pdesc, 0);
		set_tx_desc_rts_sc(pdesc, ptcb_desc->rts_sc);
		set_tx_desc_rts_short(pdesc, ((ptcb_desc->rts_rate <=
570
			DESC_RATE54M) ?
571 572 573 574
			(ptcb_desc->rts_use_shortpreamble ? 1 : 0) :
			(ptcb_desc->rts_use_shortgi ? 1 : 0)));
		if (bw_40) {
			if (ptcb_desc->packet_bw) {
575 576
				set_tx_desc_data_bw(pdesc, 1);
				set_tx_desc_tx_sub_carrier(pdesc, 3);
577
			} else {
578 579
				set_tx_desc_data_bw(pdesc, 0);
				set_tx_desc_tx_sub_carrier(pdesc,
580 581 582
							mac->cur_40_prime_sc);
			}
		} else {
583 584
			set_tx_desc_data_bw(pdesc, 0);
			set_tx_desc_tx_sub_carrier(pdesc, 0);
585
		}
586 587
		set_tx_desc_linip(pdesc, 0);
		set_tx_desc_pkt_size(pdesc, (u16)skb_len);
588 589
		if (sta) {
			u8 ampdu_density = sta->ht_cap.ampdu_density;
590
			set_tx_desc_ampdu_density(pdesc, ampdu_density);
591 592 593 594 595 596 597 598 599
		}
		if (info->control.hw_key) {
			struct ieee80211_key_conf *keyconf;

			keyconf = info->control.hw_key;
			switch (keyconf->cipher) {
			case WLAN_CIPHER_SUITE_WEP40:
			case WLAN_CIPHER_SUITE_WEP104:
			case WLAN_CIPHER_SUITE_TKIP:
600
				set_tx_desc_sec_type(pdesc, 0x1);
601 602
				break;
			case WLAN_CIPHER_SUITE_CCMP:
603
				set_tx_desc_sec_type(pdesc, 0x3);
604 605
				break;
			default:
606
				set_tx_desc_sec_type(pdesc, 0x0);
607 608 609 610
				break;

			}
		}
611 612 613 614 615
		set_tx_desc_pkt_id(pdesc, 0);
		set_tx_desc_queue_sel(pdesc, fw_qsel);
		set_tx_desc_data_rate_fb_limit(pdesc, 0x1F);
		set_tx_desc_rts_rate_fb_limit(pdesc, 0xF);
		set_tx_desc_disable_fb(pdesc, ptcb_desc->disable_ratefallback ?
616
				       1 : 0);
617
		set_tx_desc_use_rate(pdesc, ptcb_desc->use_driver_rate ? 1 : 0);
618 619 620 621 622

		/* Set TxRate and RTSRate in TxDesc  */
		/* This prevent Tx initial rate of new-coming packets */
		/* from being overwritten by retried  packet rate.*/
		if (!ptcb_desc->use_driver_rate) {
623 624
			set_tx_desc_rts_rate(pdesc, 0x08);
			/* set_tx_desc_tx_rate(pdesc, 0x0b); */
625 626 627 628
		}
		if (ieee80211_is_data_qos(fc)) {
			if (mac->rdg_en) {
				RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE,
629
					 "Enable RDG function\n");
630 631
				set_tx_desc_rdg_enable(pdesc, 1);
				set_tx_desc_htc(pdesc, 1);
632 633 634 635
			}
		}
	}

636 637 638 639
	set_tx_desc_first_seg(pdesc, (firstseg ? 1 : 0));
	set_tx_desc_last_seg(pdesc, (lastseg ? 1 : 0));
	set_tx_desc_tx_buffer_size(pdesc, (u16)buf_len);
	set_tx_desc_tx_buffer_address(pdesc, mapping);
640
	if (rtlpriv->dm.useramask) {
641 642
		set_tx_desc_rate_id(pdesc, ptcb_desc->ratr_index);
		set_tx_desc_macid(pdesc, ptcb_desc->mac_id);
643
	} else {
644 645
		set_tx_desc_rate_id(pdesc, 0xC + ptcb_desc->ratr_index);
		set_tx_desc_macid(pdesc, ptcb_desc->ratr_index);
646 647
	}
	if (ieee80211_is_data_qos(fc))
648
		set_tx_desc_qos(pdesc, 1);
649 650

	if ((!ieee80211_is_data_qos(fc)) && ppsc->fwctrl_lps) {
651 652
		set_tx_desc_hwseq_en(pdesc, 1);
		set_tx_desc_pkt_id(pdesc, 8);
653
	}
654
	set_tx_desc_more_frag(pdesc, (lastseg ? 0 : 1));
655
	RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, "\n");
656 657 658
}

void rtl92de_tx_fill_cmddesc(struct ieee80211_hw *hw,
659
			     u8 *pdesc8, bool firstseg,
660 661 662 663 664 665 666 667 668 669 670
			     bool lastseg, struct sk_buff *skb)
{
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
	struct rtl_ps_ctl *ppsc = rtl_psc(rtlpriv);
	struct rtl_hal *rtlhal = rtl_hal(rtlpriv);
	u8 fw_queue = QSLT_BEACON;
	dma_addr_t mapping = pci_map_single(rtlpci->pdev,
		    skb->data, skb->len, PCI_DMA_TODEVICE);
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
	__le16 fc = hdr->frame_control;
671
	__le32 *pdesc = (__le32 *)pdesc8;
672

673 674
	if (pci_dma_mapping_error(rtlpci->pdev, mapping)) {
		RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE,
675
			 "DMA mapping error\n");
676 677
		return;
	}
678
	clear_pci_tx_desc_content(pdesc, TX_DESC_SIZE);
679
	if (firstseg)
680
		set_tx_desc_offset(pdesc, USB_HWDESC_HEADER_LEN);
681 682 683 684 685
	/* 5G have no CCK rate
	 * Caution: The macros below are multi-line expansions.
	 * The braces are needed no matter what checkpatch says
	 */
	if (rtlhal->current_bandtype == BAND_ON_5G) {
686
		set_tx_desc_tx_rate(pdesc, DESC_RATE6M);
687
	} else {
688
		set_tx_desc_tx_rate(pdesc, DESC_RATE1M);
689
	}
690 691 692 693 694 695 696 697 698 699 700 701 702 703
	set_tx_desc_seq(pdesc, 0);
	set_tx_desc_linip(pdesc, 0);
	set_tx_desc_queue_sel(pdesc, fw_queue);
	set_tx_desc_first_seg(pdesc, 1);
	set_tx_desc_last_seg(pdesc, 1);
	set_tx_desc_tx_buffer_size(pdesc, (u16)skb->len);
	set_tx_desc_tx_buffer_address(pdesc, mapping);
	set_tx_desc_rate_id(pdesc, 7);
	set_tx_desc_macid(pdesc, 0);
	set_tx_desc_pkt_size(pdesc, (u16)(skb->len));
	set_tx_desc_first_seg(pdesc, 1);
	set_tx_desc_last_seg(pdesc, 1);
	set_tx_desc_offset(pdesc, 0x20);
	set_tx_desc_use_rate(pdesc, 1);
704 705

	if (!ieee80211_is_data_qos(fc) && ppsc->fwctrl_lps) {
706 707
		set_tx_desc_hwseq_en(pdesc, 1);
		set_tx_desc_pkt_id(pdesc, 8);
708 709 710
	}

	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD,
711
		      "H2C Tx Cmd Content", pdesc, TX_DESC_SIZE);
712
	wmb();
713
	set_tx_desc_own(pdesc, 1);
714 715
}

716
void rtl92de_set_desc(struct ieee80211_hw *hw, u8 *pdesc8, bool istx,
717
		      u8 desc_name, u8 *val)
718
{
719 720
	__le32  *pdesc = (__le32 *)pdesc8;

721
	if (istx) {
722 723 724
		switch (desc_name) {
		case HW_DESC_OWN:
			wmb();
725
			set_tx_desc_own(pdesc, 1);
726 727
			break;
		case HW_DESC_TX_NEXTDESC_ADDR:
728
			set_tx_desc_next_desc_address(pdesc, *(u32 *)val);
729 730
			break;
		default:
731
			WARN_ONCE(true, "rtl8192de: ERR txdesc :%d not processed\n",
732
				  desc_name);
733 734 735 736 737 738
			break;
		}
	} else {
		switch (desc_name) {
		case HW_DESC_RXOWN:
			wmb();
739
			set_rx_desc_own(pdesc, 1);
740 741
			break;
		case HW_DESC_RXBUFF_ADDR:
742
			set_rx_desc_buff_addr(pdesc, *(u32 *)val);
743 744
			break;
		case HW_DESC_RXPKT_LEN:
745
			set_rx_desc_pkt_len(pdesc, *(u32 *)val);
746 747
			break;
		case HW_DESC_RXERO:
748
			set_rx_desc_eor(pdesc, 1);
749 750
			break;
		default:
751
			WARN_ONCE(true, "rtl8192de: ERR rxdesc :%d not processed\n",
752
				  desc_name);
753 754 755 756 757
			break;
		}
	}
}

758
u64 rtl92de_get_desc(struct ieee80211_hw *hw,
759
		     u8 *p_desc8, bool istx, u8 desc_name)
760
{
761
	__le32 *p_desc = (__le32 *)p_desc8;
762 763
	u32 ret = 0;

764
	if (istx) {
765 766
		switch (desc_name) {
		case HW_DESC_OWN:
767
			ret = get_tx_desc_own(p_desc);
768 769
			break;
		case HW_DESC_TXBUFF_ADDR:
770
			ret = get_tx_desc_tx_buffer_address(p_desc);
771 772
			break;
		default:
773
			WARN_ONCE(true, "rtl8192de: ERR txdesc :%d not processed\n",
774
				  desc_name);
775 776 777 778 779
			break;
		}
	} else {
		switch (desc_name) {
		case HW_DESC_OWN:
780
			ret = get_rx_desc_own(p_desc);
781 782
			break;
		case HW_DESC_RXPKT_LEN:
783 784
			ret = get_rx_desc_pkt_len(p_desc);
		break;
785
		case HW_DESC_RXBUFF_ADDR:
786
			ret = get_rx_desc_buff_addr(p_desc);
787 788
			break;
		default:
789
			WARN_ONCE(true, "rtl8192de: ERR rxdesc :%d not processed\n",
790
				  desc_name);
791 792 793 794 795 796
			break;
		}
	}
	return ret;
}

797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813
bool rtl92de_is_tx_desc_closed(struct ieee80211_hw *hw,
			       u8 hw_queue, u16 index)
{
	struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw));
	struct rtl8192_tx_ring *ring = &rtlpci->tx_ring[hw_queue];
	u8 *entry = (u8 *)(&ring->desc[ring->idx]);
	u8 own = (u8)rtl92de_get_desc(hw, entry, true, HW_DESC_OWN);

	/* a beacon packet will only use the first
	 * descriptor by defaut, and the own bit may not
	 * be cleared by the hardware
	 */
	if (own)
		return false;
	return true;
}

814 815 816 817 818 819 820 821 822
void rtl92de_tx_polling(struct ieee80211_hw *hw, u8 hw_queue)
{
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	if (hw_queue == BEACON_QUEUE)
		rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG, BIT(4));
	else
		rtl_write_word(rtlpriv, REG_PCIE_CTRL_REG,
			       BIT(0) << (hw_queue));
}