1 /******************************************************************************
3 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
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.
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
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
19 ******************************************************************************/
20 #define _RTL8723BS_XMIT_C_
22 #include <rtl8723b_hal.h>
24 static u8 rtw_sdio_wait_enough_TxOQT_space(PADAPTER padapter, u8 agg_num)
27 HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
29 while (pHalData->SdioTxOQTFreeSpace < agg_num)
31 if ((padapter->bSurpriseRemoved == _TRUE)
32 || (padapter->bDriverStopped == _TRUE)
33 #ifdef CONFIG_CONCURRENT_MODE
34 ||((padapter->pbuddy_adapter)
35 && ((padapter->pbuddy_adapter->bSurpriseRemoved) ||(padapter->pbuddy_adapter->bDriverStopped)))
38 DBG_871X("%s: bSurpriseRemoved or bDriverStopped (wait TxOQT)\n", __func__);
42 HalQueryTxOQTBufferStatus8723BSdio(padapter);
44 if ((++n % 60) == 0) {
46 DBG_871X("%s(%d): QOT free space(%d), agg_num: %d\n",
47 __func__, n, pHalData->SdioTxOQTFreeSpace, agg_num);
54 pHalData->SdioTxOQTFreeSpace -= agg_num;
57 // ++priv->pshare->nr_out_of_txoqt_space;
62 static s32 rtl8723_dequeue_writeport(PADAPTER padapter)
64 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
65 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
66 struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
67 struct xmit_buf *pxmitbuf;
68 PADAPTER pri_padapter = padapter;
72 #ifdef CONFIG_SDIO_TX_ENABLE_AVAL_INT
73 u8 bUpdatePageNum = _FALSE;
79 #ifdef CONFIG_CONCURRENT_MODE
80 if (padapter->adapter_type > 0)
81 pri_padapter = padapter->pbuddy_adapter;
83 if (rtw_buddy_adapter_up(padapter))
84 ret = check_buddy_fwstate(padapter, _FW_UNDER_SURVEY);
87 ret = ret || check_fwstate(pmlmepriv, _FW_UNDER_SURVEY);
90 pxmitbuf = dequeue_pending_xmitbuf_under_survey(pxmitpriv);
92 pxmitbuf = dequeue_pending_xmitbuf(pxmitpriv);
97 deviceId = ffaddr2deviceId(pdvobjpriv, pxmitbuf->ff_hwaddr);
99 // translate fifo addr to queue index
101 case WLAN_TX_HIQ_DEVICE_ID:
102 PageIdx = HI_QUEUE_IDX;
105 case WLAN_TX_MIQ_DEVICE_ID:
106 PageIdx = MID_QUEUE_IDX;
109 case WLAN_TX_LOQ_DEVICE_ID:
110 PageIdx = LOW_QUEUE_IDX;
115 // check if hardware tx fifo page is enough
116 if( _FALSE == rtw_hal_sdio_query_tx_freepage(pri_padapter, PageIdx, pxmitbuf->pg_num))
118 #ifdef CONFIG_SDIO_TX_ENABLE_AVAL_INT
119 if (!bUpdatePageNum) {
120 // Total number of page is NOT available, so update current FIFO status
121 HalQueryTxBufferStatus8723BSdio(padapter);
122 bUpdatePageNum = _TRUE;
123 goto query_free_page;
125 bUpdatePageNum = _FALSE;
126 enqueue_pending_xmitbuf_to_head(pxmitpriv, pxmitbuf);
129 #else //CONFIG_SDIO_TX_ENABLE_AVAL_INT
131 if ((polling_num % 0x7F) == 0) {//or 80
132 //DBG_871X("%s: FIFO starvation!(%d) len=%d agg=%d page=(R)%d(A)%d\n",
133 // __func__, polling_num, pxmitbuf->len, pxmitbuf->agg_num, pframe->pg_num, freePage[PageIdx] + freePage[PUBLIC_QUEUE_IDX]);
137 // Total number of page is NOT available, so update current FIFO status
138 HalQueryTxBufferStatus8723BSdio(padapter);
139 goto query_free_page;
140 #endif //CONFIG_SDIO_TX_ENABLE_AVAL_INT
143 if ((padapter->bSurpriseRemoved == _TRUE)
144 || (padapter->bDriverStopped == _TRUE)
145 #ifdef CONFIG_CONCURRENT_MODE
146 ||((padapter->pbuddy_adapter)
147 && ((padapter->pbuddy_adapter->bSurpriseRemoved) ||(padapter->pbuddy_adapter->bDriverStopped)))
150 RT_TRACE(_module_hal_xmit_c_, _drv_notice_,
151 ("%s: bSurpriseRemoved(wirte port)\n", __FUNCTION__));
155 if (rtw_sdio_wait_enough_TxOQT_space(padapter, pxmitbuf->agg_num) == _FALSE)
160 #ifdef CONFIG_CHECK_LEAVE_LPS
161 traffic_check_for_leave_lps(padapter, _TRUE, pxmitbuf->agg_num);
164 rtw_write_port(padapter, deviceId, pxmitbuf->len, (u8 *)pxmitbuf);
166 rtw_hal_sdio_update_tx_freepage(pri_padapter, PageIdx, pxmitbuf->pg_num);
169 //rtw_free_xmitframe(pxmitpriv, pframe);
170 //pxmitbuf->priv_data = NULL;
171 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
173 #if 0 // improve TX/RX throughput balance
176 struct sdio_func *func;
181 psdio = &adapter_to_dvobj(padapter)->intf_data;
189 sdio_hisr = SdioLocalCmd52Read1Byte(padapter, SDIO_REG_HISR);
190 sdio_hisr &= GET_HAL_DATA(padapter)->sdio_himr;
191 if (sdio_hisr & SDIO_HISR_RX_REQUEST)
193 sdio_claim_host(func);
194 sd_int_hdl(pri_padapter);
195 sdio_release_host(func);
212 #ifdef CONFIG_SDIO_TX_TASKLET
213 tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
221 * Transmit xmitbuf to hardware tx fifo
225 * _FAIL something error
227 s32 rtl8723bs_xmit_buf_handler(PADAPTER padapter)
229 struct xmit_priv *pxmitpriv;
230 u8 queue_empty, queue_pending;
234 pxmitpriv = &padapter->xmitpriv;
236 ret = _rtw_down_sema(&pxmitpriv->xmit_sema);
238 DBG_871X_LEVEL(_drv_emerg_, "%s: down SdioXmitBufSema fail!\n", __FUNCTION__);
242 ret = (padapter->bDriverStopped == _TRUE) || (padapter->bSurpriseRemoved == _TRUE);
244 RT_TRACE(_module_hal_xmit_c_, _drv_err_,
245 ("%s: bDriverStopped(%d) bSurpriseRemoved(%d)!\n",
246 __FUNCTION__, padapter->bDriverStopped, padapter->bSurpriseRemoved));
250 queue_pending = check_pending_xmitbuf(pxmitpriv);
252 #ifdef CONFIG_CONCURRENT_MODE
253 if(rtw_buddy_adapter_up(padapter))
254 queue_pending |= check_pending_xmitbuf(&padapter->pbuddy_adapter->xmitpriv);
257 if(queue_pending == _FALSE)
260 #ifdef CONFIG_LPS_LCLK
261 ret = rtw_register_tx_alive(padapter);
262 if (ret != _SUCCESS) {
268 queue_empty = rtl8723_dequeue_writeport(padapter);
269 // dump secondary adapter xmitbuf
270 #ifdef CONFIG_CONCURRENT_MODE
271 if(rtw_buddy_adapter_up(padapter))
272 queue_empty &= rtl8723_dequeue_writeport(padapter->pbuddy_adapter);
274 } while ( !queue_empty);
276 #ifdef CONFIG_LPS_LCLK
277 rtw_unregister_tx_alive(padapter);
285 * Aggregation packets and send to hardware
289 * -1 Hardware resource(TX FIFO) not ready
290 * -2 Software resource(xmitbuf) not ready
292 static s32 xmit_xmitframes(PADAPTER padapter, struct xmit_priv *pxmitpriv)
296 struct hw_xmit *hwxmits, *phwxmit;
297 u8 no_res, idx, hwentry;
299 struct tx_servq *ptxservq;
300 _list *sta_plist, *sta_phead, *frame_plist, *frame_phead;
301 struct xmit_frame *pxmitframe;
302 _queue *pframe_queue;
303 struct xmit_buf *pxmitbuf;
304 u32 txlen, max_xmit_len;
305 u8 txdesc_size = TXDESC_SIZE;
307 u8 pre_qsel=0xFF,next_qsel=0xFF;
310 hwxmits = pxmitpriv->hwxmits;
311 hwentry = pxmitpriv->hwxmit_entry;
317 if (padapter->registrypriv.wifi_spec == 1) {
318 for(idx=0; idx<4; idx++)
319 inx[idx] = pxmitpriv->wmm_para_seq[idx];
321 inx[0] = 0; inx[1] = 1; inx[2] = 2; inx[3] = 3;
324 // 0(VO), 1(VI), 2(BE), 3(BK)
325 for (idx = 0; idx < hwentry; idx++)
327 phwxmit = hwxmits + inx[idx];
329 if((check_pending_xmitbuf(pxmitpriv) == _TRUE) && (padapter->mlmepriv.LinkDetectInfo.bHigherBusyTxTraffic == _TRUE)) {
330 if ((phwxmit->accnt > 0) && (phwxmit->accnt < 5)) {
336 max_xmit_len = rtw_hal_get_sdio_tx_max_length(padapter, inx[idx]);
338 _enter_critical_bh(&pxmitpriv->lock, &irql);
340 sta_phead = get_list_head(phwxmit->sta_queue);
341 sta_plist = get_next(sta_phead);
342 //because stop_sta_xmit may delete sta_plist at any time
343 //so we should add lock here, or while loop can not exit
344 while (rtw_end_of_queue_search(sta_phead, sta_plist) == _FALSE)
346 ptxservq = LIST_CONTAINOR(sta_plist, struct tx_servq, tx_pending);
347 sta_plist = get_next(sta_plist);
350 DBG_871X("%s idx:%d hwxmit_pkt_num:%d ptxservq_pkt_num:%d\n", __func__, idx, phwxmit->accnt, ptxservq->qcnt);
351 DBG_871X("%s free_xmit_extbuf_cnt=%d free_xmitbuf_cnt=%d free_xmitframe_cnt=%d \n",
352 __func__, pxmitpriv->free_xmit_extbuf_cnt, pxmitpriv->free_xmitbuf_cnt,
353 pxmitpriv->free_xmitframe_cnt);
355 pframe_queue = &ptxservq->sta_pending;
357 frame_phead = get_list_head(pframe_queue);
359 while (rtw_is_list_empty(frame_phead) == _FALSE)
361 frame_plist = get_next(frame_phead);
362 pxmitframe = LIST_CONTAINOR(frame_plist, struct xmit_frame, list);
364 // check xmit_buf size enough or not
365 txlen = txdesc_size + rtw_wlan_pkt_size(pxmitframe);
366 next_qsel = pxmitframe->attrib.qsel;
367 if ((NULL == pxmitbuf) ||
368 ((_RND(pxmitbuf->len, 8) + txlen) > max_xmit_len)
369 || (k >= (rtw_hal_sdio_max_txoqt_free_space(padapter)-1))
370 || ((k!=0) && (_FAIL == rtw_hal_busagg_qsel_check(padapter,pre_qsel,next_qsel)))
375 //pxmitbuf->priv_data will be NULL, and will crash here
376 if (pxmitbuf->len > 0 && pxmitbuf->priv_data)
378 struct xmit_frame *pframe;
379 pframe = (struct xmit_frame*)pxmitbuf->priv_data;
381 pxmitbuf->agg_num = k;
382 rtl8723b_update_txdesc(pframe, pframe->buf_addr);
383 rtw_free_xmitframe(pxmitpriv, pframe);
384 pxmitbuf->priv_data = NULL;
385 enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
386 //can not yield under lock
389 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
393 pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv);
394 if (pxmitbuf == NULL) {
396 DBG_871X_LEVEL(_drv_err_, "%s: xmit_buf is not enough!\n", __FUNCTION__);
399 #ifdef CONFIG_SDIO_TX_ENABLE_AVAL_INT
400 #ifdef CONFIG_CONCURRENT_MODE
401 if (padapter->adapter_type > PRIMARY_ADAPTER)
402 _rtw_up_sema(&(padapter->pbuddy_adapter->xmitpriv.xmit_sema));
405 _rtw_up_sema(&(pxmitpriv->xmit_sema));
412 // ok to send, remove frame from queue
413 #ifdef CONFIG_AP_MODE
414 if (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == _TRUE) {
415 if ((pxmitframe->attrib.psta->state & WIFI_SLEEP_STATE) &&
416 (pxmitframe->attrib.triggered == 0)) {
417 DBG_871X("%s: one not triggered pkt in queue when this STA sleep,"
418 " break and goto next sta\n", __func__);
423 rtw_list_delete(&pxmitframe->list);
428 pxmitbuf->ff_hwaddr = rtw_get_ff_hwaddr(pxmitframe);
429 pxmitbuf->priv_data = (u8*)pxmitframe;
432 // coalesce the xmitframe to xmitbuf
433 pxmitframe->pxmitbuf = pxmitbuf;
434 pxmitframe->buf_addr = pxmitbuf->ptail;
436 ret = rtw_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe);
438 DBG_871X_LEVEL(_drv_err_, "%s: coalesce FAIL!", __FUNCTION__);
439 // Todo: error handler
443 rtl8723b_update_txdesc(pxmitframe, pxmitframe->buf_addr);
444 rtw_count_tx_stats(padapter, pxmitframe, pxmitframe->attrib.last_txcmdsz);
445 pre_qsel = pxmitframe->attrib.qsel;
446 txlen = txdesc_size + pxmitframe->attrib.last_txcmdsz;
447 pxmitframe->pg_num = (txlen + 127)/128;
448 pxmitbuf->pg_num += (txlen + 127)/128;
450 // ((struct xmit_frame*)pxmitbuf->priv_data)->pg_num += pxmitframe->pg_num;
451 pxmitbuf->ptail += _RND(txlen, 8); // round to 8 bytes alignment
452 pxmitbuf->len = _RND(pxmitbuf->len, 8) + txlen;
456 rtw_free_xmitframe(pxmitpriv, pxmitframe);
460 if (_rtw_queue_empty(pframe_queue) == _TRUE)
461 rtw_list_delete(&ptxservq->tx_pending);
465 _exit_critical_bh(&pxmitpriv->lock, &irql);
467 // dump xmit_buf to hw tx fifo
470 RT_TRACE(_module_hal_xmit_c_, _drv_info_, ("pxmitbuf->len=%d enqueue\n",pxmitbuf->len));
472 if (pxmitbuf->len > 0) {
473 struct xmit_frame *pframe;
474 pframe = (struct xmit_frame*)pxmitbuf->priv_data;
476 pxmitbuf->agg_num = k;
477 rtl8723b_update_txdesc(pframe, pframe->buf_addr);
478 rtw_free_xmitframe(pxmitpriv, pframe);
479 pxmitbuf->priv_data = NULL;
480 enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
484 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
496 * Transmit xmitframe from queue
500 * _FAIL something error
502 s32 rtl8723bs_xmit_handler(PADAPTER padapter)
504 struct xmit_priv *pxmitpriv;
509 pxmitpriv = &padapter->xmitpriv;
512 ret = _rtw_down_sema(&pxmitpriv->SdioXmitSema);
514 DBG_871X_LEVEL(_drv_emerg_, "%s: down sema fail!\n", __FUNCTION__);
519 if ((padapter->bDriverStopped == _TRUE) ||
520 (padapter->bSurpriseRemoved == _TRUE)) {
521 RT_TRACE(_module_hal_xmit_c_, _drv_notice_,
522 ("%s: bDriverStopped(%d) bSurpriseRemoved(%d)\n",
523 __FUNCTION__, padapter->bDriverStopped, padapter->bSurpriseRemoved));
527 _enter_critical_bh(&pxmitpriv->lock, &irql);
528 ret = rtw_txframes_pending(padapter);
529 _exit_critical_bh(&pxmitpriv->lock, &irql);
534 // dequeue frame and write to hardware
536 ret = xmit_xmitframes(padapter, pxmitpriv);
538 //here sleep 1ms will cause big TP loss of TX
540 if(padapter->registrypriv.wifi_spec)
543 #ifdef CONFIG_REDUCE_TX_CPU_LOADING
551 _enter_critical_bh(&pxmitpriv->lock, &irql);
552 ret = rtw_txframes_pending(padapter);
553 _exit_critical_bh(&pxmitpriv->lock, &irql);
555 #ifdef CONFIG_REDUCE_TX_CPU_LOADING
564 thread_return rtl8723bs_xmit_thread(thread_context context)
568 struct xmit_priv *pxmitpriv;
569 u8 thread_name[20] = "RTWHALXT";
573 padapter = (PADAPTER)context;
574 pxmitpriv = &padapter->xmitpriv;
576 rtw_sprintf(thread_name, 20, "%s-"ADPT_FMT, thread_name, ADPT_ARG(padapter));
577 thread_enter(thread_name);
579 DBG_871X("start "FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
581 // For now, no one would down sema to check thread is running,
582 // so mark this temporary, Lucas@20130820
583 // _rtw_up_sema(&pxmitpriv->SdioXmitTerminateSema);
586 ret = rtl8723bs_xmit_handler(padapter);
587 if (signal_pending(current)) {
588 flush_signals(current);
590 } while (_SUCCESS == ret);
592 _rtw_up_sema(&pxmitpriv->SdioXmitTerminateSema);
594 RT_TRACE(_module_hal_xmit_c_, _drv_notice_, ("-%s\n", __FUNCTION__));
599 s32 rtl8723bs_mgnt_xmit(PADAPTER padapter, struct xmit_frame *pmgntframe)
602 struct pkt_attrib *pattrib;
603 struct xmit_buf *pxmitbuf;
604 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
605 struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
606 u8 *pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
607 u8 txdesc_size = TXDESC_SIZE;
609 RT_TRACE(_module_hal_xmit_c_, _drv_info_, ("+%s\n", __FUNCTION__));
611 pattrib = &pmgntframe->attrib;
612 pxmitbuf = pmgntframe->pxmitbuf;
614 rtl8723b_update_txdesc(pmgntframe, pmgntframe->buf_addr);
616 pxmitbuf->len = txdesc_size + pattrib->last_txcmdsz;
617 //pmgntframe->pg_num = (pxmitbuf->len + 127)/128; // 128 is tx page size
618 pxmitbuf->pg_num = (pxmitbuf->len + 127)/128; // 128 is tx page size
619 pxmitbuf->ptail = pmgntframe->buf_addr + pxmitbuf->len;
620 pxmitbuf->ff_hwaddr = rtw_get_ff_hwaddr(pmgntframe);
622 rtw_count_tx_stats(padapter, pmgntframe, pattrib->last_txcmdsz);
624 rtw_free_xmitframe(pxmitpriv, pmgntframe);
626 pxmitbuf->priv_data = NULL;
628 if(GetFrameSubType(pframe)==WIFI_BEACON) //dump beacon directly
630 ret = rtw_write_port(padapter, pdvobjpriv->Queue2Pipe[pxmitbuf->ff_hwaddr], pxmitbuf->len, (u8 *)pxmitbuf);
632 rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_WRITE_PORT_ERR);
634 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
638 enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
646 * Handle xmitframe(packet) come from rtw_xmit()
649 * _TRUE dump packet directly ok
650 * _FALSE enqueue, temporary can't transmit packets to hardware
652 s32 rtl8723bs_hal_xmit(PADAPTER padapter, struct xmit_frame *pxmitframe)
654 struct xmit_priv *pxmitpriv;
659 pxmitframe->attrib.qsel = pxmitframe->attrib.priority;
660 pxmitpriv = &padapter->xmitpriv;
662 #ifdef CONFIG_80211N_HT
663 if ((pxmitframe->frame_tag == DATA_FRAMETAG) &&
664 (pxmitframe->attrib.ether_type != 0x0806) &&
665 (pxmitframe->attrib.ether_type != 0x888e) &&
666 (pxmitframe->attrib.dhcp_pkt != 1))
668 if (padapter->mlmepriv.LinkDetectInfo.bBusyTraffic == _TRUE)
669 rtw_issue_addbareq_cmd(padapter, pxmitframe);
673 _enter_critical_bh(&pxmitpriv->lock, &irql);
674 err = rtw_xmitframe_enqueue(padapter, pxmitframe);
675 _exit_critical_bh(&pxmitpriv->lock, &irql);
676 if (err != _SUCCESS) {
677 RT_TRACE(_module_hal_xmit_c_, _drv_err_, ("rtl8723bs_hal_xmit: enqueue xmitframe fail\n"));
678 rtw_free_xmitframe(pxmitpriv, pxmitframe);
680 pxmitpriv->tx_drop++;
684 _rtw_up_sema(&pxmitpriv->SdioXmitSema);
689 s32 rtl8723bs_hal_xmitframe_enqueue(_adapter *padapter, struct xmit_frame *pxmitframe)
691 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
694 if ((err=rtw_xmitframe_enqueue(padapter, pxmitframe)) != _SUCCESS)
696 rtw_free_xmitframe(pxmitpriv, pxmitframe);
698 pxmitpriv->tx_drop++;
702 #ifdef CONFIG_SDIO_TX_TASKLET
703 tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
705 _rtw_up_sema(&pxmitpriv->SdioXmitSema);
715 * _SUCCESS start thread ok
716 * _FAIL start thread fail
719 s32 rtl8723bs_init_xmit_priv(PADAPTER padapter)
721 struct xmit_priv *xmitpriv = &padapter->xmitpriv;
725 phal = GET_HAL_DATA(padapter);
727 _rtw_spinlock_init(&phal->SdioTxFIFOFreePageLock);
728 _rtw_init_sema(&xmitpriv->SdioXmitSema, 0);
729 _rtw_init_sema(&xmitpriv->SdioXmitTerminateSema, 0);
734 void rtl8723bs_free_xmit_priv(PADAPTER padapter)
737 struct xmit_priv *pxmitpriv;
738 struct xmit_buf *pxmitbuf;
740 _list *plist, *phead;
745 phal = GET_HAL_DATA(padapter);
746 pxmitpriv = &padapter->xmitpriv;
747 pqueue = &pxmitpriv->pending_xmitbuf_queue;
748 phead = get_list_head(pqueue);
749 _rtw_init_listhead(&tmplist);
751 _enter_critical_bh(&pqueue->lock, &irql);
752 if (_rtw_queue_empty(pqueue) == _FALSE)
754 // Insert tmplist to end of queue, and delete phead
755 // then tmplist become head of queue.
756 rtw_list_insert_tail(&tmplist, phead);
757 rtw_list_delete(phead);
759 _exit_critical_bh(&pqueue->lock, &irql);
762 while (rtw_is_list_empty(phead) == _FALSE)
764 plist = get_next(phead);
765 rtw_list_delete(plist);
767 pxmitbuf = LIST_CONTAINOR(plist, struct xmit_buf, list);
768 rtw_free_xmitframe(pxmitpriv, (struct xmit_frame*)pxmitbuf->priv_data);
769 pxmitbuf->priv_data = NULL;
770 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
773 _rtw_spinlock_free(&phal->SdioTxFIFOFreePageLock);