trx.c 19.6 KB
Newer Older
1 2
// SPDX-License-Identifier: GPL-2.0
/* Copyright(c) 2009-2012  Realtek Corporation.*/
G
George 已提交
3 4 5 6 7 8 9 10 11 12 13 14

#include "../wifi.h"
#include "../usb.h"
#include "../ps.h"
#include "../base.h"
#include "reg.h"
#include "def.h"
#include "phy.h"
#include "rf.h"
#include "dm.h"
#include "mac.h"
#include "trx.h"
15
#include "../rtl8192c/fw_common.h"
G
George 已提交
16

17
static int configvertoutep(struct ieee80211_hw *hw)
G
George 已提交
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
{
	u8 ep_cfg, txqsele;
	u8 ep_nums = 0;

	struct rtl_priv *rtlpriv = rtl_priv(hw);
	struct rtl_usb_priv *usb_priv = rtl_usbpriv(hw);
	struct rtl_usb *rtlusb = rtl_usbdev(usb_priv);

	rtlusb->out_queue_sel = 0;
	ep_cfg = rtl_read_byte(rtlpriv, REG_TEST_SIE_OPTIONAL);
	ep_cfg = (ep_cfg & USB_TEST_EP_MASK) >> USB_TEST_EP_SHIFT;
	switch (ep_cfg)	{
	case 0:		/* 2 bulk OUT, 1 bulk IN */
	case 3:
		rtlusb->out_queue_sel  = TX_SELE_HQ | TX_SELE_LQ;
		ep_nums = 2;
		break;
	case 1:	/* 1 bulk IN/OUT => map all endpoint to Low queue */
	case 2:	/* 1 bulk IN, 1 bulk OUT => map all endpoint to High queue */
		txqsele = rtl_read_byte(rtlpriv, REG_TEST_USB_TXQS);
		if (txqsele & 0x0F) /* /map all endpoint to High queue */
			rtlusb->out_queue_sel =  TX_SELE_HQ;
		else if (txqsele&0xF0) /* map all endpoint to Low queue */
			rtlusb->out_queue_sel =  TX_SELE_LQ;
		ep_nums = 1;
		break;
	default:
		break;
	}
	return (rtlusb->out_ep_nums == ep_nums) ? 0 : -EINVAL;
}

50
static int configvernoutep(struct ieee80211_hw *hw)
G
George 已提交
51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78
{
	u8 ep_cfg;
	u8 ep_nums = 0;

	struct rtl_priv *rtlpriv = rtl_priv(hw);
	struct rtl_usb_priv *usb_priv = rtl_usbpriv(hw);
	struct rtl_usb *rtlusb = rtl_usbdev(usb_priv);

	rtlusb->out_queue_sel = 0;
	/* Normal and High queue */
	ep_cfg =  rtl_read_byte(rtlpriv, (REG_NORMAL_SIE_EP + 1));
	if (ep_cfg & USB_NORMAL_SIE_EP_MASK) {
		rtlusb->out_queue_sel |= TX_SELE_HQ;
		ep_nums++;
	}
	if ((ep_cfg >> USB_NORMAL_SIE_EP_SHIFT) & USB_NORMAL_SIE_EP_MASK) {
		rtlusb->out_queue_sel |= TX_SELE_NQ;
		ep_nums++;
	}
	/* Low queue */
	ep_cfg =  rtl_read_byte(rtlpriv, (REG_NORMAL_SIE_EP + 2));
	if (ep_cfg & USB_NORMAL_SIE_EP_MASK) {
		rtlusb->out_queue_sel |= TX_SELE_LQ;
		ep_nums++;
	}
	return (rtlusb->out_ep_nums == ep_nums) ? 0 : -EINVAL;
}

79
static void twooutepmapping(struct ieee80211_hw *hw, bool is_chip8,
G
George 已提交
80 81 82 83 84 85
			     bool  bwificfg, struct rtl_ep_map *ep_map)
{
	struct rtl_priv *rtlpriv = rtl_priv(hw);

	if (bwificfg) { /* for WMM */
		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
86
			 "USB Chip-B & WMM Setting.....\n");
G
George 已提交
87 88 89 90 91 92 93 94 95
		ep_map->ep_mapping[RTL_TXQ_BE]	= 2;
		ep_map->ep_mapping[RTL_TXQ_BK]	= 3;
		ep_map->ep_mapping[RTL_TXQ_VI]	= 3;
		ep_map->ep_mapping[RTL_TXQ_VO] = 2;
		ep_map->ep_mapping[RTL_TXQ_MGT] = 2;
		ep_map->ep_mapping[RTL_TXQ_BCN] = 2;
		ep_map->ep_mapping[RTL_TXQ_HI]	= 2;
	} else { /* typical setting */
		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
96
			 "USB typical Setting.....\n");
G
George 已提交
97 98 99 100 101 102 103 104 105 106
		ep_map->ep_mapping[RTL_TXQ_BE]	= 3;
		ep_map->ep_mapping[RTL_TXQ_BK]	= 3;
		ep_map->ep_mapping[RTL_TXQ_VI]	= 2;
		ep_map->ep_mapping[RTL_TXQ_VO]	= 2;
		ep_map->ep_mapping[RTL_TXQ_MGT] = 2;
		ep_map->ep_mapping[RTL_TXQ_BCN] = 2;
		ep_map->ep_mapping[RTL_TXQ_HI]	= 2;
	}
}

107
static void threeoutepmapping(struct ieee80211_hw *hw, bool  bwificfg,
G
George 已提交
108 109 110
			       struct rtl_ep_map *ep_map)
{
	struct rtl_priv *rtlpriv = rtl_priv(hw);
111

G
George 已提交
112 113
	if (bwificfg) { /* for WMM */
		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
114
			 "USB 3EP Setting for WMM.....\n");
G
George 已提交
115 116 117 118 119 120 121 122 123
		ep_map->ep_mapping[RTL_TXQ_BE]	= 5;
		ep_map->ep_mapping[RTL_TXQ_BK]	= 3;
		ep_map->ep_mapping[RTL_TXQ_VI]	= 3;
		ep_map->ep_mapping[RTL_TXQ_VO]	= 2;
		ep_map->ep_mapping[RTL_TXQ_MGT] = 2;
		ep_map->ep_mapping[RTL_TXQ_BCN] = 2;
		ep_map->ep_mapping[RTL_TXQ_HI]	= 2;
	} else { /* typical setting */
		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
124
			 "USB 3EP Setting for typical.....\n");
G
George 已提交
125 126 127 128 129 130 131 132 133 134
		ep_map->ep_mapping[RTL_TXQ_BE]	= 5;
		ep_map->ep_mapping[RTL_TXQ_BK]	= 5;
		ep_map->ep_mapping[RTL_TXQ_VI]	= 3;
		ep_map->ep_mapping[RTL_TXQ_VO]	= 2;
		ep_map->ep_mapping[RTL_TXQ_MGT] = 2;
		ep_map->ep_mapping[RTL_TXQ_BCN] = 2;
		ep_map->ep_mapping[RTL_TXQ_HI]	= 2;
	}
}

135
static void oneoutepmapping(struct ieee80211_hw *hw, struct rtl_ep_map *ep_map)
G
George 已提交
136 137 138 139 140 141 142 143 144
{
	ep_map->ep_mapping[RTL_TXQ_BE]	= 2;
	ep_map->ep_mapping[RTL_TXQ_BK]	= 2;
	ep_map->ep_mapping[RTL_TXQ_VI]	= 2;
	ep_map->ep_mapping[RTL_TXQ_VO] = 2;
	ep_map->ep_mapping[RTL_TXQ_MGT] = 2;
	ep_map->ep_mapping[RTL_TXQ_BCN] = 2;
	ep_map->ep_mapping[RTL_TXQ_HI]	= 2;
}
145

G
George 已提交
146 147 148
static int _out_ep_mapping(struct ieee80211_hw *hw)
{
	int err = 0;
149
	bool ischipn, bwificfg = false;
G
George 已提交
150 151 152 153 154
	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
	struct rtl_usb_priv *usb_priv = rtl_usbpriv(hw);
	struct rtl_usb *rtlusb = rtl_usbdev(usb_priv);
	struct rtl_ep_map *ep_map = &(rtlusb->ep_map);

155
	ischipn = IS_NORMAL_CHIP(rtlhal->version);
G
George 已提交
156 157
	switch (rtlusb->out_ep_nums) {
	case 2:
158
		twooutepmapping(hw, ischipn, bwificfg, ep_map);
G
George 已提交
159 160 161
		break;
	case 3:
		/* Test chip doesn't support three out EPs. */
162
		if (!ischipn) {
G
George 已提交
163 164 165
			err  =  -EINVAL;
			goto err_out;
		}
166
		threeoutepmapping(hw, ischipn, ep_map);
G
George 已提交
167 168
		break;
	case 1:
169
		oneoutepmapping(hw, ep_map);
G
George 已提交
170 171 172 173 174 175 176 177 178
		break;
	default:
		err  =  -EINVAL;
		break;
	}
err_out:
	return err;

}
179

G
George 已提交
180 181 182 183 184
/* endpoint mapping */
int  rtl8192cu_endpoint_mapping(struct ieee80211_hw *hw)
{
	struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw));
	int error = 0;
185

G
George 已提交
186
	if (likely(IS_NORMAL_CHIP(rtlhal->version)))
187
		error = configvernoutep(hw);
G
George 已提交
188
	else
189
		error = configvertoutep(hw);
G
George 已提交
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
	if (error)
		goto err_out;
	error = _out_ep_mapping(hw);
	if (error)
		goto err_out;
err_out:
	return error;
}

u16 rtl8192cu_mq_to_hwq(__le16 fc, u16 mac80211_queue_index)
{
	u16 hw_queue_index;

	if (unlikely(ieee80211_is_beacon(fc))) {
		hw_queue_index = RTL_TXQ_BCN;
		goto out;
	}
	if (ieee80211_is_mgmt(fc)) {
		hw_queue_index = RTL_TXQ_MGT;
		goto out;
	}
	switch (mac80211_queue_index) {
	case 0:
		hw_queue_index = RTL_TXQ_VO;
		break;
	case 1:
		hw_queue_index = RTL_TXQ_VI;
		break;
	case 2:
		hw_queue_index = RTL_TXQ_BE;
		break;
	case 3:
		hw_queue_index = RTL_TXQ_BK;
		break;
	default:
		hw_queue_index = RTL_TXQ_BE;
226
		WARN_ONCE(true, "rtl8192cu: QSLT_BE queue, skb_queue:%d\n",
227
			  mac80211_queue_index);
G
George 已提交
228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251
		break;
	}
out:
	return hw_queue_index;
}

static enum rtl_desc_qsel _rtl8192cu_mq_to_descq(struct ieee80211_hw *hw,
					 __le16 fc, u16 mac80211_queue_index)
{
	enum rtl_desc_qsel qsel;
	struct rtl_priv *rtlpriv = rtl_priv(hw);

	if (unlikely(ieee80211_is_beacon(fc))) {
		qsel = QSLT_BEACON;
		goto out;
	}
	if (ieee80211_is_mgmt(fc)) {
		qsel = QSLT_MGNT;
		goto out;
	}
	switch (mac80211_queue_index) {
	case 0:	/* VO */
		qsel = QSLT_VO;
		RT_TRACE(rtlpriv, COMP_USB, DBG_DMESG,
252
			 "VO queue, set qsel = 0x%x\n", QSLT_VO);
G
George 已提交
253 254 255 256
		break;
	case 1:	/* VI */
		qsel = QSLT_VI;
		RT_TRACE(rtlpriv, COMP_USB, DBG_DMESG,
257
			 "VI queue, set qsel = 0x%x\n", QSLT_VI);
G
George 已提交
258 259 260 261
		break;
	case 3:	/* BK */
		qsel = QSLT_BK;
		RT_TRACE(rtlpriv, COMP_USB, DBG_DMESG,
262
			 "BK queue, set qsel = 0x%x\n", QSLT_BK);
G
George 已提交
263 264 265 266 267
		break;
	case 2:	/* BE */
	default:
		qsel = QSLT_BE;
		RT_TRACE(rtlpriv, COMP_USB, DBG_DMESG,
268
			 "BE queue, set qsel = 0x%x\n", QSLT_BE);
G
George 已提交
269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284
		break;
	}
out:
	return qsel;
}

/* =============================================================== */

/*----------------------------------------------------------------------
 *
 *	Rx handler
 *
 *---------------------------------------------------------------------- */
bool rtl92cu_rx_query_desc(struct ieee80211_hw *hw,
			   struct rtl_stats *stats,
			   struct ieee80211_rx_status *rx_status,
285
			   u8 *pdesc, struct sk_buff *skb)
G
George 已提交
286 287
{
	struct rx_fwinfo_92c *p_drvinfo;
288
	struct rx_desc_92c *p_desc = (struct rx_desc_92c *)pdesc;
G
George 已提交
289 290 291 292 293 294 295 296 297 298 299 300 301
	u32 phystatus = GET_RX_DESC_PHY_STATUS(pdesc);

	stats->length = (u16) GET_RX_DESC_PKT_LEN(pdesc);
	stats->rx_drvinfo_size = (u8)GET_RX_DESC_DRVINFO_SIZE(pdesc) *
				 RX_DRV_INFO_SIZE_UNIT;
	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);
	stats->hwerror = (stats->crc | stats->icv);
	stats->decrypted = !GET_RX_DESC_SWDEC(pdesc);
	stats->rate = (u8) GET_RX_DESC_RX_MCS(pdesc);
	stats->shortpreamble = (u16) GET_RX_DESC_SPLCP(pdesc);
	stats->isampdu = (bool) (GET_RX_DESC_PAGGR(pdesc) == 1);
302
	stats->isfirst_ampdu = (bool)((GET_RX_DESC_PAGGR(pdesc) == 1)
G
George 已提交
303 304
				   && (GET_RX_DESC_FAGGR(pdesc) == 1));
	stats->timestamp_low = GET_RX_DESC_TSFL(pdesc);
305
	stats->rx_is40mhzpacket = (bool)GET_RX_DESC_BW(pdesc);
306
	stats->is_ht = (bool)GET_RX_DESC_RX_HT(pdesc);
307 308
	rx_status->freq = hw->conf.chandef.chan->center_freq;
	rx_status->band = hw->conf.chandef.chan->band;
G
George 已提交
309 310 311 312 313
	if (GET_RX_DESC_CRC32(pdesc))
		rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
	if (!GET_RX_DESC_SWDEC(pdesc))
		rx_status->flag |= RX_FLAG_DECRYPTED;
	if (GET_RX_DESC_BW(pdesc))
314
		rx_status->bw = RATE_INFO_BW_40;
G
George 已提交
315
	if (GET_RX_DESC_RX_HT(pdesc))
316
		rx_status->encoding = RX_ENC_HT;
317
	rx_status->flag |= RX_FLAG_MACTIME_START;
G
George 已提交
318 319
	if (stats->decrypted)
		rx_status->flag |= RX_FLAG_DECRYPTED;
320
	rx_status->rate_idx = rtlwifi_rate_mapping(hw, stats->is_ht,
321
						   false, stats->rate);
G
George 已提交
322
	rx_status->mactime = GET_RX_DESC_TSFL(pdesc);
323
	if (phystatus) {
324 325
		p_drvinfo = (struct rx_fwinfo_92c *)(skb->data +
						     stats->rx_bufshift);
326
		rtl92c_translate_rx_signal_stuff(hw, skb, stats, p_desc,
G
George 已提交
327 328 329
						 p_drvinfo);
	}
	/*rx_status->qual = stats->signal; */
330
	rx_status->signal = stats->recvsignalpower + 10;
G
George 已提交
331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351
	return true;
}

#define RTL_RX_DRV_INFO_UNIT		8

static void _rtl_rx_process(struct ieee80211_hw *hw, struct sk_buff *skb)
{
	struct ieee80211_rx_status *rx_status =
		 (struct ieee80211_rx_status *)IEEE80211_SKB_RXCB(skb);
	u32 skb_len, pkt_len, drvinfo_len;
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	u8 *rxdesc;
	struct rtl_stats stats = {
		.signal = 0,
		.rate = 0,
	};
	struct rx_fwinfo_92c *p_drvinfo;
	bool bv;
	__le16 fc;
	struct ieee80211_hdr *hdr;

352
	memset(rx_status, 0, sizeof(*rx_status));
G
George 已提交
353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371
	rxdesc	= skb->data;
	skb_len	= skb->len;
	drvinfo_len = (GET_RX_DESC_DRVINFO_SIZE(rxdesc) * RTL_RX_DRV_INFO_UNIT);
	pkt_len		= GET_RX_DESC_PKT_LEN(rxdesc);
	/* TODO: Error recovery. drop this skb or something. */
	WARN_ON(skb_len < (pkt_len + RTL_RX_DESC_SIZE + drvinfo_len));
	stats.length = (u16) GET_RX_DESC_PKT_LEN(rxdesc);
	stats.rx_drvinfo_size = (u8)GET_RX_DESC_DRVINFO_SIZE(rxdesc) *
				RX_DRV_INFO_SIZE_UNIT;
	stats.rx_bufshift = (u8) (GET_RX_DESC_SHIFT(rxdesc) & 0x03);
	stats.icv = (u16) GET_RX_DESC_ICV(rxdesc);
	stats.crc = (u16) GET_RX_DESC_CRC32(rxdesc);
	stats.hwerror = (stats.crc | stats.icv);
	stats.decrypted = !GET_RX_DESC_SWDEC(rxdesc);
	stats.rate = (u8) GET_RX_DESC_RX_MCS(rxdesc);
	stats.shortpreamble = (u16) GET_RX_DESC_SPLCP(rxdesc);
	stats.isampdu = (bool) ((GET_RX_DESC_PAGGR(rxdesc) == 1)
				   && (GET_RX_DESC_FAGGR(rxdesc) == 1));
	stats.timestamp_low = GET_RX_DESC_TSFL(rxdesc);
372
	stats.rx_is40mhzpacket = (bool)GET_RX_DESC_BW(rxdesc);
373
	stats.is_ht = (bool)GET_RX_DESC_RX_HT(rxdesc);
G
George 已提交
374 375
	/* TODO: is center_freq changed when doing scan? */
	/* TODO: Shall we add protection or just skip those two step? */
376 377
	rx_status->freq = hw->conf.chandef.chan->center_freq;
	rx_status->band = hw->conf.chandef.chan->band;
G
George 已提交
378 379 380 381 382
	if (GET_RX_DESC_CRC32(rxdesc))
		rx_status->flag |= RX_FLAG_FAILED_FCS_CRC;
	if (!GET_RX_DESC_SWDEC(rxdesc))
		rx_status->flag |= RX_FLAG_DECRYPTED;
	if (GET_RX_DESC_BW(rxdesc))
383
		rx_status->bw = RATE_INFO_BW_40;
G
George 已提交
384
	if (GET_RX_DESC_RX_HT(rxdesc))
385
		rx_status->encoding = RX_ENC_HT;
G
George 已提交
386
	/* Data rate */
387
	rx_status->rate_idx = rtlwifi_rate_mapping(hw, stats.is_ht,
388
						   false, stats.rate);
G
George 已提交
389 390 391 392 393 394 395 396 397 398 399 400
	/*  There is a phy status after this rx descriptor. */
	if (GET_RX_DESC_PHY_STATUS(rxdesc)) {
		p_drvinfo = (struct rx_fwinfo_92c *)(rxdesc + RTL_RX_DESC_SIZE);
		rtl92c_translate_rx_signal_stuff(hw, skb, &stats,
				 (struct rx_desc_92c *)rxdesc, p_drvinfo);
	}
	skb_pull(skb, (drvinfo_len + RTL_RX_DESC_SIZE));
	hdr = (struct ieee80211_hdr *)(skb->data);
	fc = hdr->frame_control;
	bv = ieee80211_is_probe_resp(fc);
	if (bv)
		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
401
			 "Got probe response frame\n");
G
George 已提交
402
	if (ieee80211_is_beacon(fc))
403
		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Got beacon frame\n");
G
George 已提交
404
	if (ieee80211_is_data(fc))
405
		RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG, "Got data frame\n");
G
George 已提交
406
	RT_TRACE(rtlpriv, COMP_INIT, DBG_DMESG,
407 408 409 410 411
		 "Fram: fc = 0x%X addr1 = 0x%02X:0x%02X:0x%02X:0x%02X:0x%02X:0x%02X\n",
		 fc,
		 (u32)hdr->addr1[0], (u32)hdr->addr1[1],
		 (u32)hdr->addr1[2], (u32)hdr->addr1[3],
		 (u32)hdr->addr1[4], (u32)hdr->addr1[5]);
412
	ieee80211_rx(hw, skb);
G
George 已提交
413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448
}

void  rtl8192cu_rx_hdl(struct ieee80211_hw *hw, struct sk_buff * skb)
{
	_rtl_rx_process(hw, skb);
}

/*----------------------------------------------------------------------
 *
 *	Tx handler
 *
 *---------------------------------------------------------------------- */
void rtl8192c_tx_cleanup(struct ieee80211_hw *hw, struct sk_buff  *skb)
{
}

int rtl8192c_tx_post_hdl(struct ieee80211_hw *hw, struct urb *urb,
			 struct sk_buff *skb)
{
	return 0;
}

struct sk_buff *rtl8192c_tx_aggregate_hdl(struct ieee80211_hw *hw,
					   struct sk_buff_head *list)
{
	return skb_dequeue(list);
}

/*======================================== trx ===============================*/

static void _rtl_fill_usb_tx_desc(u8 *txdesc)
{
	SET_TX_DESC_OWN(txdesc, 1);
	SET_TX_DESC_LAST_SEG(txdesc, 1);
	SET_TX_DESC_FIRST_SEG(txdesc, 1);
}
449

G
George 已提交
450 451 452 453 454
/**
 *	For HW recovery information
 */
static void _rtl_tx_desc_checksum(u8 *txdesc)
{
455
	__le16 *ptr = (__le16 *)txdesc;
G
George 已提交
456 457 458 459 460 461
	u16	checksum = 0;
	u32 index;

	/* Clear first */
	SET_TX_DESC_TX_DESC_CHECKSUM(txdesc, 0);
	for (index = 0; index < 16; index++)
462
		checksum = checksum ^ le16_to_cpu(*(ptr + index));
463
	SET_TX_DESC_TX_DESC_CHECKSUM(txdesc, checksum);
G
George 已提交
464 465 466 467
}

void rtl92cu_tx_fill_desc(struct ieee80211_hw *hw,
			  struct ieee80211_hdr *hdr, u8 *pdesc_tx,
468
			  u8 *pbd_desc_tx, struct ieee80211_tx_info *info,
469 470
			  struct ieee80211_sta *sta,
			  struct sk_buff *skb,
471 472
			  u8 queue_index,
			  struct rtl_tcb_desc *tcb_desc)
G
George 已提交
473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488
{
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	struct rtl_mac *mac = rtl_mac(rtl_priv(hw));
	struct rtl_ps_ctl *ppsc = rtl_psc(rtl_priv(hw));
	bool defaultadapter = true;
	u8 *qc = ieee80211_get_qos_ctl(hdr);
	u8 tid = qc[0] & IEEE80211_QOS_CTL_TID_MASK;
	u16 seq_number;
	__le16 fc = hdr->frame_control;
	u8 rate_flag = info->control.rates[0].flags;
	u16 pktlen = skb->len;
	enum rtl_desc_qsel fw_qsel = _rtl8192cu_mq_to_descq(hw, fc,
						skb_get_queue_mapping(skb));
	u8 *txdesc;

	seq_number = (le16_to_cpu(hdr->seq_ctrl) & IEEE80211_SCTL_SEQ) >> 4;
489
	rtl_get_tcb_desc(hw, info, sta, skb, tcb_desc);
490
	txdesc = skb_push(skb, RTL_TX_HEADER_SIZE);
G
George 已提交
491 492 493 494 495
	memset(txdesc, 0, RTL_TX_HEADER_SIZE);
	SET_TX_DESC_PKT_SIZE(txdesc, pktlen);
	SET_TX_DESC_LINIP(txdesc, 0);
	SET_TX_DESC_PKT_OFFSET(txdesc, RTL_DUMMY_OFFSET);
	SET_TX_DESC_OFFSET(txdesc, RTL_TX_HEADER_SIZE);
496 497
	SET_TX_DESC_TX_RATE(txdesc, tcb_desc->hw_rate);
	if (tcb_desc->use_shortgi || tcb_desc->use_shortpreamble)
G
George 已提交
498 499 500 501 502 503 504 505 506
		SET_TX_DESC_DATA_SHORTGI(txdesc, 1);
	if (mac->tids[tid].agg.agg_state == RTL_AGG_ON &&
		    info->flags & IEEE80211_TX_CTL_AMPDU) {
		SET_TX_DESC_AGG_ENABLE(txdesc, 1);
		SET_TX_DESC_MAX_AGG_NUM(txdesc, 0x14);
	} else {
		SET_TX_DESC_AGG_BREAK(txdesc, 1);
	}
	SET_TX_DESC_SEQ(txdesc, seq_number);
507 508 509 510 511 512 513
	SET_TX_DESC_RTS_ENABLE(txdesc, ((tcb_desc->rts_enable &&
			       !tcb_desc->cts_enable) ? 1 : 0));
	SET_TX_DESC_HW_RTS_ENABLE(txdesc, ((tcb_desc->rts_enable ||
				  tcb_desc->cts_enable) ? 1 : 0));
	SET_TX_DESC_CTS2SELF(txdesc, ((tcb_desc->cts_enable) ? 1 : 0));
	SET_TX_DESC_RTS_STBC(txdesc, ((tcb_desc->rts_stbc) ? 1 : 0));
	SET_TX_DESC_RTS_RATE(txdesc, tcb_desc->rts_rate);
G
George 已提交
514
	SET_TX_DESC_RTS_BW(txdesc, 0);
515
	SET_TX_DESC_RTS_SC(txdesc, tcb_desc->rts_sc);
G
George 已提交
516
	SET_TX_DESC_RTS_SHORT(txdesc,
517
			      ((tcb_desc->rts_rate <= DESC_RATE54M) ?
518 519
			       (tcb_desc->rts_use_shortpreamble ? 1 : 0)
			       : (tcb_desc->rts_use_shortgi ? 1 : 0)));
G
George 已提交
520
	if (mac->bw_40) {
521
		if (rate_flag & IEEE80211_TX_RC_DUP_DATA) {
G
George 已提交
522 523
			SET_TX_DESC_DATA_BW(txdesc, 1);
			SET_TX_DESC_DATA_SC(txdesc, 3);
524 525 526
		} else if(rate_flag & IEEE80211_TX_RC_40_MHZ_WIDTH){
			SET_TX_DESC_DATA_BW(txdesc, 1);
			SET_TX_DESC_DATA_SC(txdesc, mac->cur_40_prime_sc);
G
George 已提交
527 528
		} else {
			SET_TX_DESC_DATA_BW(txdesc, 0);
529 530
			SET_TX_DESC_DATA_SC(txdesc, 0);
		}
G
George 已提交
531 532 533 534
	} else {
		SET_TX_DESC_DATA_BW(txdesc, 0);
		SET_TX_DESC_DATA_SC(txdesc, 0);
	}
535 536
	rcu_read_lock();
	sta = ieee80211_find_sta(mac->vif, mac->bssid);
G
George 已提交
537 538
	if (sta) {
		u8 ampdu_density = sta->ht_cap.ampdu_density;
539

G
George 已提交
540 541
		SET_TX_DESC_AMPDU_DENSITY(txdesc, ampdu_density);
	}
542
	rcu_read_unlock();
G
George 已提交
543 544
	if (info->control.hw_key) {
		struct ieee80211_key_conf *keyconf = info->control.hw_key;
545

G
George 已提交
546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564
		switch (keyconf->cipher) {
		case WLAN_CIPHER_SUITE_WEP40:
		case WLAN_CIPHER_SUITE_WEP104:
		case WLAN_CIPHER_SUITE_TKIP:
			SET_TX_DESC_SEC_TYPE(txdesc, 0x1);
			break;
		case WLAN_CIPHER_SUITE_CCMP:
			SET_TX_DESC_SEC_TYPE(txdesc, 0x3);
			break;
		default:
			SET_TX_DESC_SEC_TYPE(txdesc, 0x0);
			break;
		}
	}
	SET_TX_DESC_PKT_ID(txdesc, 0);
	SET_TX_DESC_QUEUE_SEL(txdesc, fw_qsel);
	SET_TX_DESC_DATA_RATE_FB_LIMIT(txdesc, 0x1F);
	SET_TX_DESC_RTS_RATE_FB_LIMIT(txdesc, 0xF);
	SET_TX_DESC_DISABLE_FB(txdesc, 0);
565
	SET_TX_DESC_USE_RATE(txdesc, tcb_desc->use_driver_rate ? 1 : 0);
G
George 已提交
566 567 568
	if (ieee80211_is_data_qos(fc)) {
		if (mac->rdg_en) {
			RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE,
569
				 "Enable RDG function\n");
G
George 已提交
570 571 572 573 574
			SET_TX_DESC_RDG_ENABLE(txdesc, 1);
			SET_TX_DESC_HTC(txdesc, 1);
		}
	}
	if (rtlpriv->dm.useramask) {
575 576
		SET_TX_DESC_RATE_ID(txdesc, tcb_desc->ratr_index);
		SET_TX_DESC_MACID(txdesc, tcb_desc->mac_id);
G
George 已提交
577
	} else {
578 579
		SET_TX_DESC_RATE_ID(txdesc, 0xC + tcb_desc->ratr_index);
		SET_TX_DESC_MACID(txdesc, tcb_desc->ratr_index);
G
George 已提交
580 581 582 583 584 585 586 587 588 589 590 591 592 593 594
	}
	if ((!ieee80211_is_data_qos(fc)) && ppsc->leisure_ps &&
	      ppsc->fwctrl_lps) {
		SET_TX_DESC_HWSEQ_EN(txdesc, 1);
		SET_TX_DESC_PKT_ID(txdesc, 8);
		if (!defaultadapter)
			SET_TX_DESC_QOS(txdesc, 1);
	}
	if (ieee80211_has_morefrags(fc))
		SET_TX_DESC_MORE_FRAG(txdesc, 1);
	if (is_multicast_ether_addr(ieee80211_get_DA(hdr)) ||
	    is_broadcast_ether_addr(ieee80211_get_DA(hdr)))
		SET_TX_DESC_BMC(txdesc, 1);
	_rtl_fill_usb_tx_desc(txdesc);
	_rtl_tx_desc_checksum(txdesc);
J
Joe Perches 已提交
595
	RT_TRACE(rtlpriv, COMP_SEND, DBG_TRACE, "==>\n");
G
George 已提交
596 597
}

598 599
void rtl92cu_fill_fake_txdesc(struct ieee80211_hw *hw, u8 *pdesc,
			      u32 buffer_len, bool is_pspoll)
G
George 已提交
600 601
{
	/* Clear all status */
602 603 604 605 606 607
	memset(pdesc, 0, RTL_TX_HEADER_SIZE);
	SET_TX_DESC_FIRST_SEG(pdesc, 1); /* bFirstSeg; */
	SET_TX_DESC_LAST_SEG(pdesc, 1); /* bLastSeg; */
	SET_TX_DESC_OFFSET(pdesc, RTL_TX_HEADER_SIZE); /* Offset = 32 */
	SET_TX_DESC_PKT_SIZE(pdesc, buffer_len); /* Buffer size + command hdr */
	SET_TX_DESC_QUEUE_SEL(pdesc, QSLT_MGNT); /* Fixed queue of Mgnt queue */
G
George 已提交
608 609
	/* Set NAVUSEHDR to prevent Ps-poll AId filed to be changed to error
	 * vlaue by Hw. */
610 611
	if (is_pspoll) {
		SET_TX_DESC_NAV_USE_HDR(pdesc, 1);
G
George 已提交
612
	} else {
613 614
		SET_TX_DESC_HWSEQ_EN(pdesc, 1); /* Hw set sequence number */
		SET_TX_DESC_PKT_ID(pdesc, 0x100); /* set bit3 to 1. */
G
George 已提交
615
	}
616 617 618 619
	SET_TX_DESC_USE_RATE(pdesc, 1); /* use data rate which is set by Sw */
	SET_TX_DESC_OWN(pdesc, 1);
	SET_TX_DESC_TX_RATE(pdesc, DESC_RATE1M);
	_rtl_tx_desc_checksum(pdesc);
G
George 已提交
620 621 622 623 624 625 626 627 628 629 630
}

void rtl92cu_tx_fill_cmddesc(struct ieee80211_hw *hw,
			     u8 *pdesc, bool firstseg,
			     bool lastseg, struct sk_buff *skb)
{
	struct rtl_priv *rtlpriv = rtl_priv(hw);
	u8 fw_queue = QSLT_BEACON;
	struct ieee80211_hdr *hdr = (struct ieee80211_hdr *)(skb->data);
	__le16 fc = hdr->frame_control;

631
	memset((void *)pdesc, 0, RTL_TX_HEADER_SIZE);
G
George 已提交
632 633
	if (firstseg)
		SET_TX_DESC_OFFSET(pdesc, RTL_TX_HEADER_SIZE);
634
	SET_TX_DESC_TX_RATE(pdesc, DESC_RATE1M);
G
George 已提交
635 636 637 638 639 640 641 642
	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_RATE_ID(pdesc, 7);
	SET_TX_DESC_MACID(pdesc, 0);
	SET_TX_DESC_OWN(pdesc, 1);
643
	SET_TX_DESC_PKT_SIZE(pdesc, (u16)skb->len);
G
George 已提交
644 645 646 647 648 649 650 651
	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);
	if (!ieee80211_is_data_qos(fc)) {
		SET_TX_DESC_HWSEQ_EN(pdesc, 1);
		SET_TX_DESC_PKT_ID(pdesc, 8);
	}
652
	RT_PRINT_DATA(rtlpriv, COMP_CMD, DBG_LOUD, "H2C Tx Cmd Content",
G
George 已提交
653 654
		      pdesc, RTL_TX_DESC_SIZE);
}