• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /******************************************************************************
2  *
3  * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
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  ******************************************************************************/
15 #define _RTL8192C_XMIT_C_
16 #include <osdep_service.h>
17 #include <drv_types.h>
18 #include <wifi.h>
19 #include <osdep_intf.h>
20 #include <usb_ops.h>
21 /* include <rtl8192c_hal.h> */
22 #include <rtl8723a_hal.h>
23 
do_queue_select(struct rtw_adapter * padapter,struct pkt_attrib * pattrib)24 static void do_queue_select(struct rtw_adapter	*padapter, struct pkt_attrib *pattrib)
25 {
26 	u8 qsel;
27 
28 	qsel = pattrib->priority;
29 	RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
30 		 ("### do_queue_select priority =%d , qsel = %d\n",
31 		  pattrib->priority, qsel));
32 
33 	pattrib->qsel = qsel;
34 }
35 
urb_zero_packet_chk(struct rtw_adapter * padapter,int sz)36 static int urb_zero_packet_chk(struct rtw_adapter *padapter, int sz)
37 {
38 	int blnSetTxDescOffset;
39 	struct dvobj_priv	*pdvobj = adapter_to_dvobj(padapter);
40 
41 	if (pdvobj->ishighspeed) {
42 		if (((sz + TXDESC_SIZE) % 512) == 0)
43 			blnSetTxDescOffset = 1;
44 		else
45 			blnSetTxDescOffset = 0;
46 	} else {
47 		if (((sz + TXDESC_SIZE) % 64) == 0)
48 			blnSetTxDescOffset = 1;
49 		else
50 			blnSetTxDescOffset = 0;
51 	}
52 	return blnSetTxDescOffset;
53 }
54 
rtl8192cu_cal_txdesc_chksum(struct tx_desc * ptxdesc)55 static void rtl8192cu_cal_txdesc_chksum(struct tx_desc	*ptxdesc)
56 {
57 		u16	*usPtr = (u16 *)ptxdesc;
58 		u32 count = 16;		/*  (32 bytes / 2 bytes per XOR) => 16 times */
59 		u32 index;
60 		u16 checksum = 0;
61 
62 		/* Clear first */
63 		ptxdesc->txdw7 &= cpu_to_le32(0xffff0000);
64 
65 		for (index = 0 ; index < count ; index++)
66 			checksum = checksum ^ le16_to_cpu(*(usPtr + index));
67 
68 		ptxdesc->txdw7 |= cpu_to_le32(0x0000ffff&checksum);
69 }
70 
fill_txdesc_sectype(struct pkt_attrib * pattrib,struct tx_desc * ptxdesc)71 static void fill_txdesc_sectype(struct pkt_attrib *pattrib, struct tx_desc *ptxdesc)
72 {
73 	if ((pattrib->encrypt > 0) && !pattrib->bswenc) {
74 		switch (pattrib->encrypt) {
75 		/* SEC_TYPE */
76 		case WLAN_CIPHER_SUITE_WEP40:
77 		case WLAN_CIPHER_SUITE_WEP104:
78 			ptxdesc->txdw1 |= cpu_to_le32((0x01<<22)&0x00c00000);
79 			break;
80 		case WLAN_CIPHER_SUITE_TKIP:
81 			/* ptxdesc->txdw1 |= cpu_to_le32((0x02<<22)&0x00c00000); */
82 			ptxdesc->txdw1 |= cpu_to_le32((0x01<<22)&0x00c00000);
83 			break;
84 		case WLAN_CIPHER_SUITE_CCMP:
85 			ptxdesc->txdw1 |= cpu_to_le32((0x03<<22)&0x00c00000);
86 			break;
87 		case 0:
88 		default:
89 			break;
90 		}
91 	}
92 }
93 
fill_txdesc_vcs(struct pkt_attrib * pattrib,u32 * pdw)94 static void fill_txdesc_vcs(struct pkt_attrib *pattrib, u32 *pdw)
95 {
96 	/* DBG_8723A("cvs_mode =%d\n", pattrib->vcs_mode); */
97 
98 	switch (pattrib->vcs_mode) {
99 	case RTS_CTS:
100 		*pdw |= cpu_to_le32(BIT(12));
101 		break;
102 	case CTS_TO_SELF:
103 		*pdw |= cpu_to_le32(BIT(11));
104 		break;
105 	case NONE_VCS:
106 	default:
107 		break;
108 	}
109 
110 	if (pattrib->vcs_mode) {
111 		*pdw |= cpu_to_le32(BIT(13));
112 
113 		/*  Set RTS BW */
114 		if (pattrib->ht_en) {
115 			*pdw |= (pattrib->bwmode&HT_CHANNEL_WIDTH_40) ?	cpu_to_le32(BIT(27)) : 0;
116 
117 			if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER)
118 				*pdw |= cpu_to_le32((0x01<<28)&0x30000000);
119 			else if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_UPPER)
120 				*pdw |= cpu_to_le32((0x02<<28)&0x30000000);
121 			else if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE)
122 				*pdw |= 0;
123 			else
124 				*pdw |= cpu_to_le32((0x03<<28)&0x30000000);
125 		}
126 	}
127 }
128 
fill_txdesc_phy(struct pkt_attrib * pattrib,u32 * pdw)129 static void fill_txdesc_phy(struct pkt_attrib *pattrib, u32 *pdw)
130 {
131 	if (pattrib->ht_en) {
132 		*pdw |= (pattrib->bwmode&HT_CHANNEL_WIDTH_40) ? cpu_to_le32(BIT(25)) : 0;
133 
134 		if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_LOWER)
135 			*pdw |= cpu_to_le32((0x01<<20)&0x003f0000);
136 		else if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_UPPER)
137 			*pdw |= cpu_to_le32((0x02<<20)&0x003f0000);
138 		else if (pattrib->ch_offset == HAL_PRIME_CHNL_OFFSET_DONT_CARE)
139 			*pdw |= 0;
140 		else
141 			*pdw |= cpu_to_le32((0x03<<20)&0x003f0000);
142 	}
143 }
144 
update_txdesc(struct xmit_frame * pxmitframe,u8 * pmem,s32 sz,u8 bagg_pkt)145 static s32 update_txdesc(struct xmit_frame *pxmitframe, u8 *pmem, s32 sz, u8 bagg_pkt)
146 {
147 	int	pull = 0;
148 	uint	qsel;
149 	struct rtw_adapter	*padapter = pxmitframe->padapter;
150 	struct pkt_attrib	*pattrib = &pxmitframe->attrib;
151 	struct hal_data_8723a	*pHalData = GET_HAL_DATA(padapter);
152 	struct dm_priv	*pdmpriv = &pHalData->dmpriv;
153 	struct tx_desc	*ptxdesc = (struct tx_desc *)pmem;
154 	struct mlme_ext_priv	*pmlmeext = &padapter->mlmeextpriv;
155 	struct mlme_ext_info	*pmlmeinfo = &pmlmeext->mlmext_info;
156 	int	bmcst = is_multicast_ether_addr(pattrib->ra);
157 
158 	if ((!bagg_pkt) && (urb_zero_packet_chk(padapter, sz) == 0)) {
159 		ptxdesc = (struct tx_desc *)(pmem+PACKET_OFFSET_SZ);
160 		pull = 1;
161 		pxmitframe->pkt_offset--;
162 	}
163 
164 	memset(ptxdesc, 0, sizeof(struct tx_desc));
165 
166 	if ((pxmitframe->frame_tag&0x0f) == DATA_FRAMETAG) {
167 		/* offset 4 */
168 		ptxdesc->txdw1 |= cpu_to_le32(pattrib->mac_id&0x1f);
169 
170 		qsel = (uint)(pattrib->qsel & 0x0000001f);
171 		ptxdesc->txdw1 |= cpu_to_le32((qsel << QSEL_SHT) & 0x00001f00);
172 
173 		ptxdesc->txdw1 |= cpu_to_le32((pattrib->raid<<16) & 0x000f0000);
174 
175 		fill_txdesc_sectype(pattrib, ptxdesc);
176 
177 		if (pattrib->ampdu_en)
178 			ptxdesc->txdw1 |= cpu_to_le32(BIT(5));/* AGG EN */
179 		else
180 			ptxdesc->txdw1 |= cpu_to_le32(BIT(6));/* AGG BK */
181 
182 		/* offset 8 */
183 
184 		/* offset 12 */
185 		ptxdesc->txdw3 |= cpu_to_le32((pattrib->seqnum<<16)&0xffff0000);
186 
187 		/* offset 16 , offset 20 */
188 		if (pattrib->qos_en)
189 			ptxdesc->txdw4 |= cpu_to_le32(BIT(6));/* QoS */
190 
191 		if ((pattrib->ether_type != 0x888e) &&
192 		    (pattrib->ether_type != 0x0806) &&
193 		    (pattrib->dhcp_pkt != 1)) {
194 			/* Non EAP & ARP & DHCP type data packet */
195 
196 			fill_txdesc_vcs(pattrib, &ptxdesc->txdw4);
197 			fill_txdesc_phy(pattrib, &ptxdesc->txdw4);
198 
199 			ptxdesc->txdw4 |= cpu_to_le32(0x00000008);/* RTS Rate = 24M */
200 			ptxdesc->txdw5 |= cpu_to_le32(0x0001ff00);/*  */
201 
202 			/* use REG_INIDATA_RATE_SEL value */
203 			ptxdesc->txdw5 |= cpu_to_le32(pdmpriv->INIDATA_RATE[pattrib->mac_id]);
204 		} else {
205 			/*  EAP data packet and ARP packet. */
206 			/*  Use the 1M data rate to send the EAP/ARP packet. */
207 			/*  This will maybe make the handshake smooth. */
208 
209 			ptxdesc->txdw1 |= cpu_to_le32(BIT(6));/* AGG BK */
210 
211 			ptxdesc->txdw4 |= cpu_to_le32(BIT(8));/* driver uses rate */
212 
213 			if (pmlmeinfo->preamble_mode == PREAMBLE_SHORT)
214 				ptxdesc->txdw4 |= cpu_to_le32(BIT(24));/*  DATA_SHORT */
215 
216 			ptxdesc->txdw5 |= cpu_to_le32(MRateToHwRate23a(pmlmeext->tx_rate));
217 		}
218 	} else if ((pxmitframe->frame_tag&0x0f) == MGNT_FRAMETAG) {
219 		/* offset 4 */
220 		ptxdesc->txdw1 |= cpu_to_le32(pattrib->mac_id&0x1f);
221 
222 		qsel = (uint)(pattrib->qsel&0x0000001f);
223 		ptxdesc->txdw1 |= cpu_to_le32((qsel<<QSEL_SHT)&0x00001f00);
224 
225 		ptxdesc->txdw1 |= cpu_to_le32((pattrib->raid<<16) & 0x000f0000);
226 
227 		/* offset 8 */
228 		/* CCX-TXRPT ack for xmit mgmt frames. */
229 		if (pxmitframe->ack_report)
230 			ptxdesc->txdw2 |= cpu_to_le32(BIT(19));
231 
232 		/* offset 12 */
233 		ptxdesc->txdw3 |= cpu_to_le32((pattrib->seqnum<<16)&0xffff0000);
234 
235 		/* offset 16 */
236 		ptxdesc->txdw4 |= cpu_to_le32(BIT(8));/* driver uses rate */
237 
238 		/* offset 20 */
239 		ptxdesc->txdw5 |= cpu_to_le32(BIT(17));/* retry limit enable */
240 		ptxdesc->txdw5 |= cpu_to_le32(0x00180000);/* retry limit = 6 */
241 
242 		ptxdesc->txdw5 |= cpu_to_le32(MRateToHwRate23a(pmlmeext->tx_rate));
243 	} else if ((pxmitframe->frame_tag&0x0f) == TXAGG_FRAMETAG) {
244 		DBG_8723A("pxmitframe->frame_tag == TXAGG_FRAMETAG\n");
245 	} else {
246 		DBG_8723A("pxmitframe->frame_tag = %d\n", pxmitframe->frame_tag);
247 
248 		/* offset 4 */
249 		ptxdesc->txdw1 |= cpu_to_le32((4)&0x1f);/* CAM_ID(MAC_ID) */
250 
251 		ptxdesc->txdw1 |= cpu_to_le32((6<<16) & 0x000f0000);/* raid */
252 
253 		/* offset 8 */
254 
255 		/* offset 12 */
256 		ptxdesc->txdw3 |= cpu_to_le32((pattrib->seqnum<<16)&0xffff0000);
257 
258 		/* offset 16 */
259 		ptxdesc->txdw4 |= cpu_to_le32(BIT(8));/* driver uses rate */
260 
261 		/* offset 20 */
262 		ptxdesc->txdw5 |= cpu_to_le32(MRateToHwRate23a(pmlmeext->tx_rate));
263 	}
264 
265 	/*  (1) The sequence number of each non-Qos frame / broadcast / multicast / */
266 	/*  mgnt frame should be controled by Hw because Fw will also send null data */
267 	/*  which we cannot control when Fw LPS enable. */
268 	/*  --> default enable non-Qos data sequense number. 2010.06.23. by tynli. */
269 	/*  (2) Enable HW SEQ control for beacon packet, because we use Hw beacon. */
270 	/*  (3) Use HW Qos SEQ to control the seq num of Ext port non-Qos packets. */
271 	if (!pattrib->qos_en) {
272 		/*  Hw set sequence number */
273 		ptxdesc->txdw4 |= cpu_to_le32(BIT(7));
274 		/* set bit3 to 1. */
275 		ptxdesc->txdw3 |= cpu_to_le32((8 << 28));
276 	}
277 
278 	/* offset 0 */
279 	ptxdesc->txdw0 |= cpu_to_le32(sz&0x0000ffff);
280 	ptxdesc->txdw0 |= cpu_to_le32(OWN | FSG | LSG);
281 	ptxdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE+OFFSET_SZ)<<OFFSET_SHT)&0x00ff0000);/* 32 bytes for TX Desc */
282 
283 	if (bmcst)
284 		ptxdesc->txdw0 |= cpu_to_le32(BIT(24));
285 
286 	RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("offset0-txdesc = 0x%x\n", ptxdesc->txdw0));
287 
288 	/* offset 4 */
289 	/*  pkt_offset, unit:8 bytes padding */
290 	if (pxmitframe->pkt_offset > 0)
291 		ptxdesc->txdw1 |= cpu_to_le32((pxmitframe->pkt_offset << 26) & 0x7c000000);
292 
293 	rtl8192cu_cal_txdesc_chksum(ptxdesc);
294 	return pull;
295 }
296 
rtw_dump_xframe(struct rtw_adapter * padapter,struct xmit_frame * pxmitframe)297 static int rtw_dump_xframe(struct rtw_adapter *padapter,
298 			   struct xmit_frame *pxmitframe)
299 {
300 	int ret = _SUCCESS;
301 	int inner_ret = _SUCCESS;
302 	int t, sz, w_sz, pull = 0;
303 	u8 *mem_addr;
304 	u32 ff_hwaddr;
305 	struct xmit_buf *pxmitbuf = pxmitframe->pxmitbuf;
306 	struct pkt_attrib *pattrib = &pxmitframe->attrib;
307 	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
308 
309 	if ((pxmitframe->frame_tag == DATA_FRAMETAG) &&
310 	    (pxmitframe->attrib.ether_type != 0x0806) &&
311 	    (pxmitframe->attrib.ether_type != 0x888e) &&
312 	    (pxmitframe->attrib.dhcp_pkt != 1))
313 		rtw_issue_addbareq_cmd23a(padapter, pxmitframe);
314 
315 	mem_addr = pxmitframe->buf_addr;
316 
317 	RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("rtw_dump_xframe()\n"));
318 
319 	for (t = 0; t < pattrib->nr_frags; t++) {
320 		if (inner_ret != _SUCCESS && ret == _SUCCESS)
321 			ret = _FAIL;
322 
323 		if (t != (pattrib->nr_frags - 1)) {
324 			RT_TRACE(_module_rtl871x_xmit_c_, _drv_err_,
325 				 ("pattrib->nr_frags =%d\n", pattrib->nr_frags));
326 
327 			sz = pxmitpriv->frag_len;
328 			sz = sz - 4 - pattrib->icv_len;
329 		} else {
330 			/* no frag */
331 			sz = pattrib->last_txcmdsz;
332 		}
333 
334 		pull = update_txdesc(pxmitframe, mem_addr, sz, false);
335 
336 		if (pull) {
337 			mem_addr += PACKET_OFFSET_SZ; /* pull txdesc head */
338 
339 			pxmitframe->buf_addr = mem_addr;
340 
341 			w_sz = sz + TXDESC_SIZE;
342 		} else {
343 			w_sz = sz + TXDESC_SIZE + PACKET_OFFSET_SZ;
344 		}
345 
346 		ff_hwaddr = rtw_get_ff_hwaddr23a(pxmitframe);
347 		inner_ret = rtl8723au_write_port(padapter, ff_hwaddr,
348 						 w_sz, pxmitbuf);
349 		rtw_count_tx_stats23a(padapter, pxmitframe, sz);
350 
351 		RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_,
352 			 ("rtw_write_port, w_sz =%d\n", w_sz));
353 
354 		mem_addr += w_sz;
355 
356 		mem_addr = PTR_ALIGN(mem_addr, 4);
357 	}
358 
359 	rtw_free_xmitframe23a(pxmitpriv, pxmitframe);
360 
361 	if  (ret != _SUCCESS)
362 		rtw23a_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_UNKNOWN);
363 
364 	return ret;
365 }
366 
rtl8723au_xmitframe_complete(struct rtw_adapter * padapter,struct xmit_priv * pxmitpriv,struct xmit_buf * pxmitbuf)367 bool rtl8723au_xmitframe_complete(struct rtw_adapter *padapter,
368 				  struct xmit_priv *pxmitpriv,
369 				  struct xmit_buf *pxmitbuf)
370 {
371 	struct hw_xmit *phwxmits;
372 	struct xmit_frame *pxmitframe;
373 	int hwentry;
374 	int res = _SUCCESS, xcnt = 0;
375 
376 	phwxmits = pxmitpriv->hwxmits;
377 	hwentry = pxmitpriv->hwxmit_entry;
378 
379 	RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("xmitframe_complete()\n"));
380 
381 	if (pxmitbuf == NULL) {
382 		pxmitbuf = rtw_alloc_xmitbuf23a(pxmitpriv);
383 		if (!pxmitbuf)
384 			return false;
385 	}
386 	pxmitframe =  rtw_dequeue_xframe23a(pxmitpriv, phwxmits, hwentry);
387 
388 	if (pxmitframe) {
389 		pxmitframe->pxmitbuf = pxmitbuf;
390 
391 		pxmitframe->buf_addr = pxmitbuf->pbuf;
392 
393 		pxmitbuf->priv_data = pxmitframe;
394 
395 		if ((pxmitframe->frame_tag&0x0f) == DATA_FRAMETAG) {
396 			if (pxmitframe->attrib.priority <= 15)/* TID0~15 */
397 				res = rtw_xmitframe_coalesce23a(padapter, pxmitframe->pkt, pxmitframe);
398 
399 			rtw_os_xmit_complete23a(padapter, pxmitframe);/* always return ndis_packet after rtw_xmitframe_coalesce23a */
400 		}
401 
402 		RT_TRACE(_module_rtl871x_xmit_c_, _drv_info_, ("xmitframe_complete(): rtw_dump_xframe\n"));
403 
404 		if (res == _SUCCESS) {
405 			rtw_dump_xframe(padapter, pxmitframe);
406 		} else {
407 			rtw_free_xmitbuf23a(pxmitpriv, pxmitbuf);
408 			rtw_free_xmitframe23a(pxmitpriv, pxmitframe);
409 		}
410 		xcnt++;
411 	} else {
412 		rtw_free_xmitbuf23a(pxmitpriv, pxmitbuf);
413 		return false;
414 	}
415 	return true;
416 }
417 
xmitframe_direct(struct rtw_adapter * padapter,struct xmit_frame * pxmitframe)418 static int xmitframe_direct(struct rtw_adapter *padapter,
419 			    struct xmit_frame *pxmitframe)
420 {
421 	int res;
422 
423 	res = rtw_xmitframe_coalesce23a(padapter, pxmitframe->pkt, pxmitframe);
424 	if (res == _SUCCESS)
425 		rtw_dump_xframe(padapter, pxmitframe);
426 	return res;
427 }
428 
429 /*
430  * Return
431  *	true	dump packet directly
432  *	false	enqueue packet
433  */
rtl8723au_hal_xmit(struct rtw_adapter * padapter,struct xmit_frame * pxmitframe)434 bool rtl8723au_hal_xmit(struct rtw_adapter *padapter,
435 			struct xmit_frame *pxmitframe)
436 {
437 	int res;
438 	struct xmit_buf *pxmitbuf = NULL;
439 	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
440 	struct pkt_attrib *pattrib = &pxmitframe->attrib;
441 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
442 
443 	do_queue_select(padapter, pattrib);
444 	spin_lock_bh(&pxmitpriv->lock);
445 
446 #ifdef CONFIG_8723AU_AP_MODE
447 	if (xmitframe_enqueue_for_sleeping_sta23a(padapter, pxmitframe)) {
448 		struct sta_info *psta;
449 		struct sta_priv *pstapriv = &padapter->stapriv;
450 
451 		spin_unlock_bh(&pxmitpriv->lock);
452 
453 		if (pattrib->psta)
454 			psta = pattrib->psta;
455 		else
456 			psta = rtw_get_stainfo23a(pstapriv, pattrib->ra);
457 
458 		if (psta) {
459 			if (psta->sleepq_len > (NR_XMITFRAME>>3))
460 				wakeup_sta_to_xmit23a(padapter, psta);
461 		}
462 
463 		return false;
464 	}
465 #endif
466 
467 	if (rtw_txframes_sta_ac_pending23a(padapter, pattrib) > 0)
468 		goto enqueue;
469 
470 	if (check_fwstate(pmlmepriv, _FW_UNDER_SURVEY|_FW_UNDER_LINKING) == true)
471 		goto enqueue;
472 
473 	pxmitbuf = rtw_alloc_xmitbuf23a(pxmitpriv);
474 	if (pxmitbuf == NULL)
475 		goto enqueue;
476 
477 	spin_unlock_bh(&pxmitpriv->lock);
478 
479 	pxmitframe->pxmitbuf = pxmitbuf;
480 	pxmitframe->buf_addr = pxmitbuf->pbuf;
481 	pxmitbuf->priv_data = pxmitframe;
482 
483 	if (xmitframe_direct(padapter, pxmitframe) != _SUCCESS) {
484 		rtw_free_xmitbuf23a(pxmitpriv, pxmitbuf);
485 		rtw_free_xmitframe23a(pxmitpriv, pxmitframe);
486 	}
487 	return true;
488 
489 enqueue:
490 	res = rtw_xmitframe_enqueue23a(padapter, pxmitframe);
491 	spin_unlock_bh(&pxmitpriv->lock);
492 
493 	if (res != _SUCCESS) {
494 		RT_TRACE(_module_xmit_osdep_c_, _drv_err_,
495 			 ("pre_xmitframe: enqueue xmitframe fail\n"));
496 		rtw_free_xmitframe23a(pxmitpriv, pxmitframe);
497 
498 		/*  Trick, make the statistics correct */
499 		pxmitpriv->tx_pkts--;
500 		pxmitpriv->tx_drop++;
501 		return true;
502 	}
503 	return false;
504 }
505 
rtl8723au_mgnt_xmit(struct rtw_adapter * padapter,struct xmit_frame * pmgntframe)506 int rtl8723au_mgnt_xmit(struct rtw_adapter *padapter,
507 			struct xmit_frame *pmgntframe)
508 {
509 	return rtw_dump_xframe(padapter, pmgntframe);
510 }
511 
rtl8723au_hal_xmitframe_enqueue(struct rtw_adapter * padapter,struct xmit_frame * pxmitframe)512 int rtl8723au_hal_xmitframe_enqueue(struct rtw_adapter *padapter,
513 				    struct xmit_frame *pxmitframe)
514 {
515 	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
516 	int err;
517 
518 	err = rtw_xmitframe_enqueue23a(padapter, pxmitframe);
519 	if (err != _SUCCESS) {
520 		rtw_free_xmitframe23a(pxmitpriv, pxmitframe);
521 
522 		/*  Trick, make the statistics correct */
523 		pxmitpriv->tx_pkts--;
524 		pxmitpriv->tx_drop++;
525 	} else {
526 		tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
527 	}
528 	return err;
529 }
530