1 // SPDX-License-Identifier: GPL-2.0
2 /******************************************************************************
3 *
4 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
5 *
6 ******************************************************************************/
7 #define _RTL8723BS_XMIT_C_
8
9 #include <drv_types.h>
10 #include <rtw_debug.h>
11 #include <rtl8723b_hal.h>
12
rtw_sdio_wait_enough_TxOQT_space(struct adapter * padapter,u8 agg_num)13 static u8 rtw_sdio_wait_enough_TxOQT_space(struct adapter *padapter, u8 agg_num)
14 {
15 u32 n = 0;
16 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
17
18 while (pHalData->SdioTxOQTFreeSpace < agg_num) {
19 if (
20 (padapter->bSurpriseRemoved) ||
21 (padapter->bDriverStopped)
22 ) {
23 DBG_871X("%s: bSurpriseRemoved or bDriverStopped (wait TxOQT)\n", __func__);
24 return false;
25 }
26
27 HalQueryTxOQTBufferStatus8723BSdio(padapter);
28
29 if ((++n % 60) == 0) {
30 if ((n % 300) == 0) {
31 DBG_871X("%s(%d): QOT free space(%d), agg_num: %d\n",
32 __func__, n, pHalData->SdioTxOQTFreeSpace, agg_num);
33 }
34 msleep(1);
35 /* yield(); */
36 }
37 }
38
39 pHalData->SdioTxOQTFreeSpace -= agg_num;
40
41 /* if (n > 1) */
42 /* ++priv->pshare->nr_out_of_txoqt_space; */
43
44 return true;
45 }
46
rtl8723_dequeue_writeport(struct adapter * padapter)47 static s32 rtl8723_dequeue_writeport(struct adapter *padapter)
48 {
49 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
50 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
51 struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
52 struct xmit_buf *pxmitbuf;
53 struct adapter *pri_padapter = padapter;
54 s32 ret = 0;
55 u8 PageIdx = 0;
56 u32 deviceId;
57 u8 bUpdatePageNum = false;
58
59 ret = ret || check_fwstate(pmlmepriv, _FW_UNDER_SURVEY);
60
61 if (ret)
62 pxmitbuf = dequeue_pending_xmitbuf_under_survey(pxmitpriv);
63 else
64 pxmitbuf = dequeue_pending_xmitbuf(pxmitpriv);
65
66 if (!pxmitbuf)
67 return true;
68
69 deviceId = ffaddr2deviceId(pdvobjpriv, pxmitbuf->ff_hwaddr);
70
71 /* translate fifo addr to queue index */
72 switch (deviceId) {
73 case WLAN_TX_HIQ_DEVICE_ID:
74 PageIdx = HI_QUEUE_IDX;
75 break;
76
77 case WLAN_TX_MIQ_DEVICE_ID:
78 PageIdx = MID_QUEUE_IDX;
79 break;
80
81 case WLAN_TX_LOQ_DEVICE_ID:
82 PageIdx = LOW_QUEUE_IDX;
83 break;
84 }
85
86 query_free_page:
87 /* check if hardware tx fifo page is enough */
88 if (!rtw_hal_sdio_query_tx_freepage(pri_padapter, PageIdx, pxmitbuf->pg_num)) {
89 if (!bUpdatePageNum) {
90 /* Total number of page is NOT available, so update current FIFO status */
91 HalQueryTxBufferStatus8723BSdio(padapter);
92 bUpdatePageNum = true;
93 goto query_free_page;
94 } else {
95 bUpdatePageNum = false;
96 enqueue_pending_xmitbuf_to_head(pxmitpriv, pxmitbuf);
97 return true;
98 }
99 }
100
101 if (
102 (padapter->bSurpriseRemoved) ||
103 (padapter->bDriverStopped)
104 ) {
105 RT_TRACE(
106 _module_hal_xmit_c_,
107 _drv_notice_,
108 ("%s: bSurpriseRemoved(write port)\n", __func__)
109 );
110 goto free_xmitbuf;
111 }
112
113 if (rtw_sdio_wait_enough_TxOQT_space(padapter, pxmitbuf->agg_num) == false)
114 goto free_xmitbuf;
115
116 traffic_check_for_leave_lps(padapter, true, pxmitbuf->agg_num);
117
118 rtw_write_port(padapter, deviceId, pxmitbuf->len, (u8 *)pxmitbuf);
119
120 rtw_hal_sdio_update_tx_freepage(pri_padapter, PageIdx, pxmitbuf->pg_num);
121
122 free_xmitbuf:
123 /* rtw_free_xmitframe(pxmitpriv, pframe); */
124 /* pxmitbuf->priv_data = NULL; */
125 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
126
127 #ifdef CONFIG_SDIO_TX_TASKLET
128 tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
129 #endif
130
131 return _FAIL;
132 }
133
134 /*
135 * Description
136 *Transmit xmitbuf to hardware tx fifo
137 *
138 * Return
139 *_SUCCESS ok
140 *_FAIL something error
141 */
rtl8723bs_xmit_buf_handler(struct adapter * padapter)142 s32 rtl8723bs_xmit_buf_handler(struct adapter *padapter)
143 {
144 struct xmit_priv *pxmitpriv;
145 u8 queue_empty, queue_pending;
146 s32 ret;
147
148
149 pxmitpriv = &padapter->xmitpriv;
150
151 if (wait_for_completion_interruptible(&pxmitpriv->xmit_comp)) {
152 DBG_871X_LEVEL(_drv_emerg_, "%s: down SdioXmitBufSema fail!\n", __func__);
153 return _FAIL;
154 }
155
156 ret = (padapter->bDriverStopped) || (padapter->bSurpriseRemoved);
157 if (ret) {
158 RT_TRACE(
159 _module_hal_xmit_c_,
160 _drv_err_,
161 (
162 "%s: bDriverStopped(%d) bSurpriseRemoved(%d)!\n",
163 __func__,
164 padapter->bDriverStopped,
165 padapter->bSurpriseRemoved
166 )
167 );
168 return _FAIL;
169 }
170
171 queue_pending = check_pending_xmitbuf(pxmitpriv);
172
173 if (!queue_pending)
174 return _SUCCESS;
175
176 ret = rtw_register_tx_alive(padapter);
177 if (ret != _SUCCESS) {
178 return _SUCCESS;
179 }
180
181 do {
182 queue_empty = rtl8723_dequeue_writeport(padapter);
183 /* dump secondary adapter xmitbuf */
184 } while (!queue_empty);
185
186 rtw_unregister_tx_alive(padapter);
187
188 return _SUCCESS;
189 }
190
191 /*
192 * Description:
193 *Aggregation packets and send to hardware
194 *
195 * Return:
196 *0 Success
197 *-1 Hardware resource(TX FIFO) not ready
198 *-2 Software resource(xmitbuf) not ready
199 */
xmit_xmitframes(struct adapter * padapter,struct xmit_priv * pxmitpriv)200 static s32 xmit_xmitframes(struct adapter *padapter, struct xmit_priv *pxmitpriv)
201 {
202 s32 err, ret;
203 u32 k = 0;
204 struct hw_xmit *hwxmits, *phwxmit;
205 u8 idx, hwentry;
206 struct tx_servq *ptxservq;
207 struct list_head *sta_plist, *sta_phead, *frame_plist, *frame_phead;
208 struct xmit_frame *pxmitframe;
209 struct __queue *pframe_queue;
210 struct xmit_buf *pxmitbuf;
211 u32 txlen, max_xmit_len;
212 u8 txdesc_size = TXDESC_SIZE;
213 int inx[4];
214
215 err = 0;
216 hwxmits = pxmitpriv->hwxmits;
217 hwentry = pxmitpriv->hwxmit_entry;
218 ptxservq = NULL;
219 pxmitframe = NULL;
220 pframe_queue = NULL;
221 pxmitbuf = NULL;
222
223 if (padapter->registrypriv.wifi_spec == 1) {
224 for (idx = 0; idx < 4; idx++)
225 inx[idx] = pxmitpriv->wmm_para_seq[idx];
226 } else {
227 inx[0] = 0;
228 inx[1] = 1;
229 inx[2] = 2;
230 inx[3] = 3;
231 }
232
233 /* 0(VO), 1(VI), 2(BE), 3(BK) */
234 for (idx = 0; idx < hwentry; idx++) {
235 phwxmit = hwxmits + inx[idx];
236
237 if (
238 (check_pending_xmitbuf(pxmitpriv)) &&
239 (padapter->mlmepriv.LinkDetectInfo.bHigherBusyTxTraffic)
240 ) {
241 if ((phwxmit->accnt > 0) && (phwxmit->accnt < 5)) {
242 err = -2;
243 break;
244 }
245 }
246
247 max_xmit_len = rtw_hal_get_sdio_tx_max_length(padapter, inx[idx]);
248
249 spin_lock_bh(&pxmitpriv->lock);
250
251 sta_phead = get_list_head(phwxmit->sta_queue);
252 sta_plist = get_next(sta_phead);
253 /* because stop_sta_xmit may delete sta_plist at any time */
254 /* so we should add lock here, or while loop can not exit */
255 while (sta_phead != sta_plist) {
256 ptxservq = LIST_CONTAINOR(sta_plist, struct tx_servq, tx_pending);
257 sta_plist = get_next(sta_plist);
258
259 #ifdef DBG_XMIT_BUF
260 DBG_871X(
261 "%s idx:%d hwxmit_pkt_num:%d ptxservq_pkt_num:%d\n",
262 __func__,
263 idx,
264 phwxmit->accnt,
265 ptxservq->qcnt
266 );
267 DBG_871X(
268 "%s free_xmit_extbuf_cnt =%d free_xmitbuf_cnt =%d free_xmitframe_cnt =%d\n",
269 __func__,
270 pxmitpriv->free_xmit_extbuf_cnt,
271 pxmitpriv->free_xmitbuf_cnt,
272 pxmitpriv->free_xmitframe_cnt
273 );
274 #endif
275 pframe_queue = &ptxservq->sta_pending;
276
277 frame_phead = get_list_head(pframe_queue);
278
279 while (list_empty(frame_phead) == false) {
280 frame_plist = get_next(frame_phead);
281 pxmitframe = LIST_CONTAINOR(frame_plist, struct xmit_frame, list);
282
283 /* check xmit_buf size enough or not */
284 txlen = txdesc_size + rtw_wlan_pkt_size(pxmitframe);
285 if( !pxmitbuf ||
286 ((_RND(pxmitbuf->len, 8) + txlen) > max_xmit_len) ||
287 (k >= (rtw_hal_sdio_max_txoqt_free_space(padapter) - 1))
288 ) {
289 if (pxmitbuf) {
290 /* pxmitbuf->priv_data will be NULL, and will crash here */
291 if (pxmitbuf->len > 0 &&
292 pxmitbuf->priv_data) {
293 struct xmit_frame *pframe;
294 pframe = (struct xmit_frame *)pxmitbuf->priv_data;
295 pframe->agg_num = k;
296 pxmitbuf->agg_num = k;
297 rtl8723b_update_txdesc(pframe, pframe->buf_addr);
298 rtw_free_xmitframe(pxmitpriv, pframe);
299 pxmitbuf->priv_data = NULL;
300 enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
301 /* can not yield under lock */
302 /* yield(); */
303 } else
304 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
305 }
306
307 pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv);
308 if (!pxmitbuf) {
309 #ifdef DBG_XMIT_BUF
310 DBG_871X_LEVEL(_drv_err_, "%s: xmit_buf is not enough!\n", __func__);
311 #endif
312 err = -2;
313 complete(&(pxmitpriv->xmit_comp));
314 break;
315 }
316 k = 0;
317 }
318
319 /* ok to send, remove frame from queue */
320 if (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == true) {
321 if (
322 (pxmitframe->attrib.psta->state & WIFI_SLEEP_STATE) &&
323 (pxmitframe->attrib.triggered == 0)
324 ) {
325 DBG_871X(
326 "%s: one not triggered pkt in queue when this STA sleep,"
327 " break and goto next sta\n",
328 __func__
329 );
330 break;
331 }
332 }
333
334 list_del_init(&pxmitframe->list);
335 ptxservq->qcnt--;
336 phwxmit->accnt--;
337
338 if (k == 0) {
339 pxmitbuf->ff_hwaddr = rtw_get_ff_hwaddr(pxmitframe);
340 pxmitbuf->priv_data = (u8 *)pxmitframe;
341 }
342
343 /* coalesce the xmitframe to xmitbuf */
344 pxmitframe->pxmitbuf = pxmitbuf;
345 pxmitframe->buf_addr = pxmitbuf->ptail;
346
347 ret = rtw_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe);
348 if (ret == _FAIL) {
349 DBG_871X_LEVEL(_drv_err_, "%s: coalesce FAIL!", __func__);
350 /* Todo: error handler */
351 } else {
352 k++;
353 if (k != 1)
354 rtl8723b_update_txdesc(pxmitframe, pxmitframe->buf_addr);
355 rtw_count_tx_stats(padapter, pxmitframe, pxmitframe->attrib.last_txcmdsz);
356
357 txlen = txdesc_size + pxmitframe->attrib.last_txcmdsz;
358 pxmitframe->pg_num = (txlen + 127) / 128;
359 pxmitbuf->pg_num += (txlen + 127) / 128;
360 /* if (k != 1) */
361 /* ((struct xmit_frame*)pxmitbuf->priv_data)->pg_num += pxmitframe->pg_num; */
362 pxmitbuf->ptail += _RND(txlen, 8); /* round to 8 bytes alignment */
363 pxmitbuf->len = _RND(pxmitbuf->len, 8) + txlen;
364 }
365
366 if (k != 1)
367 rtw_free_xmitframe(pxmitpriv, pxmitframe);
368 pxmitframe = NULL;
369 }
370
371 if (list_empty(&pframe_queue->queue))
372 list_del_init(&ptxservq->tx_pending);
373
374 if (err)
375 break;
376 }
377 spin_unlock_bh(&pxmitpriv->lock);
378
379 /* dump xmit_buf to hw tx fifo */
380 if (pxmitbuf) {
381 RT_TRACE(_module_hal_xmit_c_, _drv_info_, ("pxmitbuf->len =%d enqueue\n", pxmitbuf->len));
382
383 if (pxmitbuf->len > 0) {
384 struct xmit_frame *pframe;
385 pframe = (struct xmit_frame *)pxmitbuf->priv_data;
386 pframe->agg_num = k;
387 pxmitbuf->agg_num = k;
388 rtl8723b_update_txdesc(pframe, pframe->buf_addr);
389 rtw_free_xmitframe(pxmitpriv, pframe);
390 pxmitbuf->priv_data = NULL;
391 enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
392 yield();
393 } else
394 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
395 pxmitbuf = NULL;
396 }
397
398 if (err)
399 break;
400 }
401
402 return err;
403 }
404
405 /*
406 * Description
407 *Transmit xmitframe from queue
408 *
409 * Return
410 *_SUCCESS ok
411 *_FAIL something error
412 */
rtl8723bs_xmit_handler(struct adapter * padapter)413 static s32 rtl8723bs_xmit_handler(struct adapter *padapter)
414 {
415 struct xmit_priv *pxmitpriv;
416 s32 ret;
417
418
419 pxmitpriv = &padapter->xmitpriv;
420
421 if (wait_for_completion_interruptible(&pxmitpriv->SdioXmitStart)) {
422 DBG_871X_LEVEL(_drv_emerg_, "%s: SdioXmitStart fail!\n", __func__);
423 return _FAIL;
424 }
425
426 next:
427 if (
428 (padapter->bDriverStopped) ||
429 (padapter->bSurpriseRemoved)
430 ) {
431 RT_TRACE(
432 _module_hal_xmit_c_,
433 _drv_notice_,
434 (
435 "%s: bDriverStopped(%d) bSurpriseRemoved(%d)\n",
436 __func__,
437 padapter->bDriverStopped,
438 padapter->bSurpriseRemoved
439 )
440 );
441 return _FAIL;
442 }
443
444 spin_lock_bh(&pxmitpriv->lock);
445 ret = rtw_txframes_pending(padapter);
446 spin_unlock_bh(&pxmitpriv->lock);
447 if (ret == 0) {
448 return _SUCCESS;
449 }
450
451 /* dequeue frame and write to hardware */
452
453 ret = xmit_xmitframes(padapter, pxmitpriv);
454 if (ret == -2) {
455 /* here sleep 1ms will cause big TP loss of TX */
456 /* from 50+ to 40+ */
457 if (padapter->registrypriv.wifi_spec)
458 msleep(1);
459 else
460 yield();
461 goto next;
462 }
463
464 spin_lock_bh(&pxmitpriv->lock);
465 ret = rtw_txframes_pending(padapter);
466 spin_unlock_bh(&pxmitpriv->lock);
467 if (ret == 1) {
468 goto next;
469 }
470
471 return _SUCCESS;
472 }
473
rtl8723bs_xmit_thread(void * context)474 int rtl8723bs_xmit_thread(void *context)
475 {
476 s32 ret;
477 struct adapter *padapter;
478 struct xmit_priv *pxmitpriv;
479 u8 thread_name[20] = "RTWHALXT";
480
481
482 ret = _SUCCESS;
483 padapter = context;
484 pxmitpriv = &padapter->xmitpriv;
485
486 rtw_sprintf(thread_name, 20, "%s-"ADPT_FMT, thread_name, ADPT_ARG(padapter));
487 thread_enter(thread_name);
488
489 DBG_871X("start "FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
490
491 do {
492 ret = rtl8723bs_xmit_handler(padapter);
493 if (signal_pending(current)) {
494 flush_signals(current);
495 }
496 } while (_SUCCESS == ret);
497
498 complete(&pxmitpriv->SdioXmitTerminate);
499
500 RT_TRACE(_module_hal_xmit_c_, _drv_notice_, ("-%s\n", __func__));
501
502 thread_exit();
503 }
504
rtl8723bs_mgnt_xmit(struct adapter * padapter,struct xmit_frame * pmgntframe)505 s32 rtl8723bs_mgnt_xmit(
506 struct adapter *padapter, struct xmit_frame *pmgntframe
507 )
508 {
509 s32 ret = _SUCCESS;
510 struct pkt_attrib *pattrib;
511 struct xmit_buf *pxmitbuf;
512 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
513 struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
514 u8 *pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
515 u8 txdesc_size = TXDESC_SIZE;
516
517 RT_TRACE(_module_hal_xmit_c_, _drv_info_, ("+%s\n", __func__));
518
519 pattrib = &pmgntframe->attrib;
520 pxmitbuf = pmgntframe->pxmitbuf;
521
522 rtl8723b_update_txdesc(pmgntframe, pmgntframe->buf_addr);
523
524 pxmitbuf->len = txdesc_size + pattrib->last_txcmdsz;
525 pxmitbuf->pg_num = (pxmitbuf->len + 127) / 128; /* 128 is tx page size */
526 pxmitbuf->ptail = pmgntframe->buf_addr + pxmitbuf->len;
527 pxmitbuf->ff_hwaddr = rtw_get_ff_hwaddr(pmgntframe);
528
529 rtw_count_tx_stats(padapter, pmgntframe, pattrib->last_txcmdsz);
530
531 rtw_free_xmitframe(pxmitpriv, pmgntframe);
532
533 pxmitbuf->priv_data = NULL;
534
535 if (GetFrameSubType(pframe) == WIFI_BEACON) { /* dump beacon directly */
536 ret = rtw_write_port(padapter, pdvobjpriv->Queue2Pipe[pxmitbuf->ff_hwaddr], pxmitbuf->len, (u8 *)pxmitbuf);
537 if (ret != _SUCCESS)
538 rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_WRITE_PORT_ERR);
539
540 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
541 } else
542 enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
543
544 return ret;
545 }
546
547 /*
548 * Description:
549 *Handle xmitframe(packet) come from rtw_xmit()
550 *
551 * Return:
552 *true dump packet directly ok
553 *false enqueue, temporary can't transmit packets to hardware
554 */
rtl8723bs_hal_xmit(struct adapter * padapter,struct xmit_frame * pxmitframe)555 s32 rtl8723bs_hal_xmit(
556 struct adapter *padapter, struct xmit_frame *pxmitframe
557 )
558 {
559 struct xmit_priv *pxmitpriv;
560 s32 err;
561
562
563 pxmitframe->attrib.qsel = pxmitframe->attrib.priority;
564 pxmitpriv = &padapter->xmitpriv;
565
566 if (
567 (pxmitframe->frame_tag == DATA_FRAMETAG) &&
568 (pxmitframe->attrib.ether_type != 0x0806) &&
569 (pxmitframe->attrib.ether_type != 0x888e) &&
570 (pxmitframe->attrib.dhcp_pkt != 1)
571 ) {
572 if (padapter->mlmepriv.LinkDetectInfo.bBusyTraffic)
573 rtw_issue_addbareq_cmd(padapter, pxmitframe);
574 }
575
576 spin_lock_bh(&pxmitpriv->lock);
577 err = rtw_xmitframe_enqueue(padapter, pxmitframe);
578 spin_unlock_bh(&pxmitpriv->lock);
579 if (err != _SUCCESS) {
580 RT_TRACE(_module_hal_xmit_c_, _drv_err_, ("rtl8723bs_hal_xmit: enqueue xmitframe fail\n"));
581 rtw_free_xmitframe(pxmitpriv, pxmitframe);
582
583 pxmitpriv->tx_drop++;
584 return true;
585 }
586
587 complete(&pxmitpriv->SdioXmitStart);
588
589 return false;
590 }
591
rtl8723bs_hal_xmitframe_enqueue(struct adapter * padapter,struct xmit_frame * pxmitframe)592 s32 rtl8723bs_hal_xmitframe_enqueue(
593 struct adapter *padapter, struct xmit_frame *pxmitframe
594 )
595 {
596 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
597 s32 err;
598
599 err = rtw_xmitframe_enqueue(padapter, pxmitframe);
600 if (err != _SUCCESS) {
601 rtw_free_xmitframe(pxmitpriv, pxmitframe);
602
603 pxmitpriv->tx_drop++;
604 } else {
605 #ifdef CONFIG_SDIO_TX_TASKLET
606 tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
607 #else
608 complete(&pxmitpriv->SdioXmitStart);
609 #endif
610 }
611
612 return err;
613
614 }
615
616 /*
617 * Return
618 *_SUCCESS start thread ok
619 *_FAIL start thread fail
620 *
621 */
rtl8723bs_init_xmit_priv(struct adapter * padapter)622 s32 rtl8723bs_init_xmit_priv(struct adapter *padapter)
623 {
624 struct xmit_priv *xmitpriv = &padapter->xmitpriv;
625 struct hal_com_data *phal;
626
627
628 phal = GET_HAL_DATA(padapter);
629
630 spin_lock_init(&phal->SdioTxFIFOFreePageLock);
631 init_completion(&xmitpriv->SdioXmitStart);
632 init_completion(&xmitpriv->SdioXmitTerminate);
633
634 return _SUCCESS;
635 }
636
rtl8723bs_free_xmit_priv(struct adapter * padapter)637 void rtl8723bs_free_xmit_priv(struct adapter *padapter)
638 {
639 struct xmit_priv *pxmitpriv;
640 struct xmit_buf *pxmitbuf;
641 struct __queue *pqueue;
642 struct list_head *plist, *phead;
643 struct list_head tmplist;
644
645
646 pxmitpriv = &padapter->xmitpriv;
647 pqueue = &pxmitpriv->pending_xmitbuf_queue;
648 phead = get_list_head(pqueue);
649 INIT_LIST_HEAD(&tmplist);
650
651 spin_lock_bh(&pqueue->lock);
652 if (!list_empty(&pqueue->queue)) {
653 /* Insert tmplist to end of queue, and delete phead */
654 /* then tmplist become head of queue. */
655 list_add_tail(&tmplist, phead);
656 list_del_init(phead);
657 }
658 spin_unlock_bh(&pqueue->lock);
659
660 phead = &tmplist;
661 while (list_empty(phead) == false) {
662 plist = get_next(phead);
663 list_del_init(plist);
664
665 pxmitbuf = LIST_CONTAINOR(plist, struct xmit_buf, list);
666 rtw_free_xmitframe(pxmitpriv, (struct xmit_frame *)pxmitbuf->priv_data);
667 pxmitbuf->priv_data = NULL;
668 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
669 }
670 }
671