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