8723BU: Update 8723BU wifi driver to version v4.3.16_14189.20150519_BTCOEX2015119...
[firefly-linux-kernel-4.4.55.git] / drivers / net / wireless / rockchip_wlan / rtl8723au / hal / rtl8723a / sdio / rtl8723as_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 _RTL8723AS_XMIT_C_
21
22 #include <drv_conf.h>
23 #include <osdep_service.h>
24 #include <drv_types.h>
25 #include <sdio_ops.h>
26 #include <rtl8723a_hal.h>
27
28 #ifdef CONFIG_TX_AGGREGATION
29 #define SDIO_TX_AGG_MAX 5
30 #else
31 #define SDIO_TX_AGG_MAX 1
32 #endif
33
34 s32 rtl8723_dequeue_writeport(PADAPTER padapter, u8 *freePage)
35 {
36         struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
37         struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
38         struct dvobj_priv       *pdvobjpriv = adapter_to_dvobj(padapter);
39         struct xmit_buf *pxmitbuf;
40         //struct xmit_frame *pframe;
41         PADAPTER pri_padapter = padapter;
42         u32 deviceId;
43         u32 requiredPage;
44         u8 PageIdx;
45         _irqL irql;
46         u32 n;
47         s32 ret = 0;
48         //HAL_DATA_TYPE *pHalData = GET_HAL_DATA(padapter);
49 #ifdef CONFIG_CONCURRENT_MODE
50         s32 buddy_rm_stop = _FAIL;
51 #endif
52
53 #ifdef CONFIG_CONCURRENT_MODE
54         if(rtw_buddy_adapter_up(padapter))
55                 ret = check_buddy_fwstate( padapter,  _FW_UNDER_SURVEY);
56 #endif
57
58         ret = ret || check_fwstate(pmlmepriv, _FW_UNDER_SURVEY);
59
60         if (_TRUE == ret)
61                 pxmitbuf = dequeue_pending_xmitbuf_under_survey(pxmitpriv);
62         else
63                 pxmitbuf = dequeue_pending_xmitbuf(pxmitpriv);
64
65         if (pxmitbuf == NULL) 
66                 return _TRUE;
67
68         //pframe = (struct xmit_frame*)pxmitbuf->priv_data;
69         //requiredPage = pframe->pg_num;
70         requiredPage = pxmitbuf->pg_num;
71
72         //translate queue index to sdio fifo addr
73         deviceId = pdvobjpriv->Queue2Pipe[pxmitbuf->ff_hwaddr];
74
75         // translate sdio fifo addr to tx fifo page index
76         switch (deviceId)
77         {
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         // check if hardware tx fifo page is enough
92         n = 0;
93 //      _enter_critical_bh(&phal->SdioTxFIFOFreePageLock, &irql);
94         do {
95                 if (requiredPage <= freePage[PageIdx]) {
96                         freePage[PageIdx] -= requiredPage;
97                         break;
98                 }
99                 // The number of page which public page included is available.
100                 if ((freePage[PageIdx] + freePage[PUBLIC_QUEUE_IDX]) > (requiredPage + 1))
101                 {
102                         u8 requiredPublicPage;
103
104                         requiredPublicPage = requiredPage - freePage[PageIdx];
105                         freePage[PageIdx] = 0;
106                         freePage[PUBLIC_QUEUE_IDX] -= requiredPublicPage;
107                         break;
108                 }
109 //              _exit_critical_bh(&phal->SdioTxFIFOFreePageLock, &irql);
110
111                 ret = (padapter->bDriverStopped == _TRUE) || (padapter->bSurpriseRemoved == _TRUE)
112 #ifdef CONFIG_CONCURRENT_MODE
113                 ||((padapter->pbuddy_adapter) 
114                 && ((padapter->pbuddy_adapter->bSurpriseRemoved) ||(padapter->pbuddy_adapter->bDriverStopped)))
115 #endif
116                 ;
117
118                 if (ret) {
119                         RT_TRACE(_module_hal_xmit_c_, _drv_notice_,
120                                  ("%s: bSurpriseRemoved(update TX FIFO page)\n", __func__));
121                         goto free_xmitbuf;
122                 }
123
124                 n++;
125                 //if ((n & 0x3FF) == 0) 
126                 if ((n % 100) == 0) 
127                 {               
128                         if (n >= 5000) {
129                                 u8 reg_value_1 = 0;
130                                 u8 reg_value_2 = 0;
131                                 u8 reg_value_3 = 0;
132                                 
133                                 DBG_8192C(KERN_NOTICE "%s: FIFO starvation!(%d) len=%d agg=%d page=(R)%d(A)%d\n",
134                                         __func__, n, pxmitbuf->len, pxmitbuf->agg_num, pxmitbuf->pg_num, freePage[PageIdx] + freePage[PUBLIC_QUEUE_IDX]);
135
136                                 //try to recover the transmission
137                                 reg_value_1 = rtw_read8(padapter, REG_SYS_FUNC_EN);
138                                 reg_value_2 = rtw_read8(padapter, REG_CR);
139                                 reg_value_3 = rtw_read8(padapter, REG_TXPAUSE);
140                                 DBG_871X("Before recovery: REG_SYS_FUNC_EN = 0x%X, REG_CR = 0x%X, REG_TXPAUSE = 0x%X\n", reg_value_1, reg_value_2, reg_value_3);
141
142                                 rtw_write8(padapter, REG_SYS_FUNC_EN, reg_value_1 | 0x01);
143                                 rtw_write8(padapter, REG_CR, reg_value_2 | 0xC0);
144                                 rtw_write8(padapter, REG_TXPAUSE, 0);
145                                 DBG_871X("After recovery: REG_SYS_FUNC_EN = 0x%X, REG_CR = 0x%X, REG_TXPAUSE = 0x%X\n", 
146                                         rtw_read8(padapter, REG_SYS_FUNC_EN), rtw_read8(padapter, REG_CR), rtw_read8(padapter, REG_TXPAUSE));
147                         } else {
148                                 //RT_TRACE(_module_hal_xmit_c_, _drv_notice_,
149                                 //      ("%s: FIFO starvation!(%d) len=%d agg=%d page=(R)%d(A)%d\n",
150                                 //      __FUNCTION__, n, pxmitbuf->len, pxmitbuf->agg_num, pxmitbuf->pg_num, freePage[PageIdx] + freePage[PUBLIC_QUEUE_IDX]));
151                         }
152                         //rtw_yield_os();
153                         rtw_msleep_os(1);
154                 }
155
156                 // Total number of page is NOT available, so update current FIFO status
157 #ifdef CONFIG_CONCURRENT_MODE
158                 if (padapter->adapter_type > 0)
159                         pri_padapter = padapter->pbuddy_adapter;
160 #endif
161                 HalQueryTxBufferStatus8723ASdio(pri_padapter);
162
163         } while (1);
164
165         if ((padapter->bSurpriseRemoved == _TRUE)
166 #ifdef CONFIG_CONCURRENT_MODE
167                 ||((padapter->pbuddy_adapter)&& (padapter->pbuddy_adapter->bSurpriseRemoved))
168 #endif
169         ){
170                 RT_TRACE(_module_hal_xmit_c_, _drv_notice_,
171                          ("%s: bSurpriseRemoved(wirte port)\n", __FUNCTION__));
172                 goto free_xmitbuf;
173         }
174         rtw_write_port(padapter, deviceId, pxmitbuf->len, (u8 *)pxmitbuf);
175
176 free_xmitbuf:
177         //rtw_free_xmitframe(pxmitpriv, pframe);
178         //pxmitbuf->priv_data = NULL;
179         rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
180
181         return _FAIL;
182 }
183
184 /*
185  * Description
186  *      Transmit xmitbuf to hardware tx fifo
187  *
188  * Return
189  *      _SUCCESS        ok
190  *      _FAIL           something error
191  */
192 s32 rtl8723as_xmit_buf_handler(PADAPTER padapter)
193 {
194         PHAL_DATA_TYPE phal;
195         struct mlme_priv *pmlmepriv;
196         struct xmit_priv *pxmitpriv;
197         struct dvobj_priv       *pdvobjpriv;
198         struct xmit_buf *pxmitbuf;
199         struct xmit_frame *pframe;
200         u8 *freePage;
201         u32 deviceId;
202         u32 requiredPage;
203         u8 PageIdx, queue_empty;
204         _irqL irql;
205         u32 n;
206         s32 ret;
207
208
209         phal = GET_HAL_DATA(padapter);
210         pmlmepriv = &padapter->mlmepriv;
211         pxmitpriv = &padapter->xmitpriv;
212         pdvobjpriv = adapter_to_dvobj(padapter);
213         freePage = phal->SdioTxFIFOFreePage;
214
215         ret = _rtw_down_sema(&pxmitpriv->xmit_sema);
216         if (_FAIL == ret) {
217                 RT_TRACE(_module_hal_xmit_c_, _drv_emerg_,
218                                  ("%s: down SdioXmitBufSema fail!\n", __FUNCTION__));
219                 return _FAIL;
220         }
221
222         ret = (padapter->bDriverStopped == _TRUE) || (padapter->bSurpriseRemoved == _TRUE);
223         if (ret) {
224                 RT_TRACE(_module_hal_xmit_c_, _drv_err_,
225                                  ("%s: bDriverStopped(%d) bSurpriseRemoved(%d)!\n",
226                                   __FUNCTION__, padapter->bDriverStopped, padapter->bSurpriseRemoved));
227                 return _FAIL;
228         }
229
230 #ifdef CONFIG_LPS_LCLK
231         ret = rtw_register_tx_alive(padapter);
232         if (ret != _SUCCESS) {
233                 return _SUCCESS;
234         }
235 #endif
236
237         do {
238                 queue_empty = rtl8723_dequeue_writeport(padapter, freePage);
239 //      dump secondary adapter xmitbuf 
240 #ifdef CONFIG_CONCURRENT_MODE
241                 if(rtw_buddy_adapter_up(padapter))
242                         queue_empty &= rtl8723_dequeue_writeport(padapter->pbuddy_adapter, freePage);
243 #endif
244         } while ( !queue_empty);
245         
246 #ifdef CONFIG_LPS_LCLK
247         rtw_unregister_tx_alive(padapter);
248 #endif
249
250         return _SUCCESS;
251 }
252
253 /*
254  * Description:
255  *      Aggregation packets and send to hardware
256  *
257  * Return:
258  *      0       Success
259  *      -1      Hardware resource(TX FIFO) not ready
260  *      -2      Software resource(xmitbuf) not ready
261  */
262 static s32 xmit_xmitframes(PADAPTER padapter, struct xmit_priv *pxmitpriv)
263 {
264         s32 err, ret;
265         u32 k;
266         struct hw_xmit *hwxmits;
267         u8 no_res, idx, hwentry;
268         _irqL irql;
269 //      _irqL irqL0, irqL1;
270         struct tx_servq *ptxservq;
271         _list *sta_plist, *sta_phead, *frame_plist, *frame_phead;
272         struct xmit_frame *pxmitframe;
273         _queue *pframe_queue;
274         struct xmit_buf *pxmitbuf;
275         u32 txlen;
276
277
278         err = 0;
279         no_res = _FALSE;
280         hwxmits = pxmitpriv->hwxmits;
281         hwentry = pxmitpriv->hwxmit_entry;
282         ptxservq = NULL;
283         pxmitframe = NULL;
284         pframe_queue = NULL;
285         pxmitbuf = NULL;
286
287         // 0(VO), 1(VI), 2(BE), 3(BK)
288         for (idx = 0; idx < hwentry; idx++, hwxmits++)
289         {
290 //              _enter_critical(&hwxmits->sta_queue->lock, &irqL0);
291                 _enter_critical_bh(&pxmitpriv->lock, &irql);
292
293                 sta_phead = get_list_head(hwxmits->sta_queue);
294                 sta_plist = get_next(sta_phead);
295
296                 while (rtw_end_of_queue_search(sta_phead, sta_plist) == _FALSE)
297                 {
298                         ptxservq = LIST_CONTAINOR(sta_plist, struct tx_servq, tx_pending);
299                         sta_plist = get_next(sta_plist);
300
301                         pframe_queue = &ptxservq->sta_pending;
302
303 //                      _enter_critical(&pframe_queue->lock, &irqL1);
304                         //_enter_critical_bh(&pxmitpriv->lock, &irql);
305
306                         frame_phead = get_list_head(pframe_queue);
307
308                         while (rtw_is_list_empty(frame_phead) == _FALSE)
309                         {
310                                 frame_plist = get_next(frame_phead);
311                                 pxmitframe = LIST_CONTAINOR(frame_plist, struct xmit_frame, list);
312
313                                 // check xmit_buf size enough or not
314                                 txlen = TXDESC_SIZE + rtw_wlan_pkt_size(pxmitframe);
315                                 if ((NULL == pxmitbuf) ||
316                                         ((pxmitbuf->ptail + txlen) > pxmitbuf->pend)
317 #ifdef SDIO_TX_AGG_MAX
318                                         || (k >= SDIO_TX_AGG_MAX)
319 #endif
320                                         )
321                                 {
322                                         if (pxmitbuf) {
323                                                 struct xmit_frame *pframe;
324                                                 pframe = (struct xmit_frame*)pxmitbuf->priv_data;
325                                                 pframe->agg_num = k;
326                                                 pxmitbuf->agg_num = k;
327                                                 rtl8723a_update_txdesc(pframe, pframe->buf_addr);
328                                                 rtw_free_xmitframe(pxmitpriv, pframe);
329                                                 pxmitbuf->priv_data = NULL;
330                                                 enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
331                                                 //rtw_yield_os();
332                                         }
333
334                                         pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv);
335                                         if (pxmitbuf == NULL) {
336                                                 RT_TRACE(_module_hal_xmit_c_, _drv_err_, ("%s: xmit_buf is not enough!\n", __FUNCTION__));
337                                                 err = -2;
338                                                 break;
339                                         }
340                                         k = 0;
341                                 }
342
343                                 // ok to send, remove frame from queue
344                                 //_enter_critical_bh(&pxmitpriv->lock, &irql);
345 #ifdef CONFIG_AP_MODE
346                                 if (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == _TRUE)
347                                 {
348                                         if ((pxmitframe->attrib.psta->state & WIFI_SLEEP_STATE) &&
349                                                 (pxmitframe->attrib.triggered == 0))
350                                         {
351                                                 //_exit_critical_bh(&pxmitpriv->lock, &irql);
352                                                 
353                                                 DBG_8192C("%s: one not triggered pkt in queue when STA sleep\n", __func__);
354                                                 break;
355                                         }
356                                 }
357 #endif
358                                 rtw_list_delete(&pxmitframe->list);
359                                 ptxservq->qcnt--;
360                                 hwxmits->accnt--;
361                                 
362
363                                 if (k == 0) {
364                                         pxmitbuf->ff_hwaddr = rtw_get_ff_hwaddr(pxmitframe);
365                                         pxmitbuf->priv_data = (u8*)pxmitframe;
366                                 }
367
368                                 // coalesce the xmitframe to xmitbuf
369                                 pxmitframe->pxmitbuf = pxmitbuf;
370                                 pxmitframe->buf_addr = pxmitbuf->ptail;
371
372                                 ret = rtw_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe);
373                                 if (ret == _FAIL) {
374                                         RT_TRACE(_module_hal_xmit_c_, _drv_err_, ("%s: coalesce FAIL!", __FUNCTION__));
375                                         // Todo: error handler
376                                         DBG_871X("%s: coalesce FAIL!", __FUNCTION__);
377                                 } else {
378                                         k++;
379                                         if (k != 1)
380                                                 rtl8723a_update_txdesc(pxmitframe, pxmitframe->buf_addr);
381                                         rtw_count_tx_stats(padapter, pxmitframe, pxmitframe->attrib.last_txcmdsz);
382
383                                         txlen = TXDESC_SIZE + pxmitframe->attrib.last_txcmdsz;
384                                         pxmitframe->pg_num = (txlen + 127)/128;
385                                         pxmitbuf->pg_num += (txlen + 127)/128;                                  
386                                         //if (k != 1)
387                                         //      ((struct xmit_frame*)pxmitbuf->priv_data)->pg_num += pxmitframe->pg_num;
388                                         pxmitbuf->ptail += _RND(txlen, 8); // round to 8 bytes alignment
389                                         pxmitbuf->len = _RND(pxmitbuf->len, 8) + txlen;
390                                 }
391
392                                 if (k != 1)
393                                         rtw_free_xmitframe(pxmitpriv, pxmitframe);
394                                 pxmitframe = NULL;
395                         }
396
397                         //_enter_critical_bh(&pxmitpriv->lock, &irql);
398                         if (_rtw_queue_empty(pframe_queue) == _TRUE)
399                                 rtw_list_delete(&ptxservq->tx_pending);
400                         //_exit_critical_bh(&pxmitpriv->lock, &irql);
401
402 //                      _exit_critical(&pframe_queue->lock, &irqL1);
403                         //_exit_critical_bh(&pxmitpriv->lock, &irql);
404
405                         if (err) break;
406                 }
407
408 //              _exit_critical(&hwxmits->sta_queue->lock, &irqL0);
409                 _exit_critical_bh(&pxmitpriv->lock, &irql);
410
411                 // dump xmit_buf to hw tx fifo
412                 if (pxmitbuf)
413                 {
414                         RT_TRACE(_module_hal_xmit_c_, _drv_notice_, ("pxmitbuf->len=%d enqueue\n",pxmitbuf->len));
415
416                         if (pxmitbuf->len > 0) {
417                                 struct xmit_frame *pframe;
418                                 pframe = (struct xmit_frame*)pxmitbuf->priv_data;
419                                 pframe->agg_num = k;
420                                 pxmitbuf->agg_num = k;
421                                 rtl8723a_update_txdesc(pframe, pframe->buf_addr);
422                                 rtw_free_xmitframe(pxmitpriv, pframe);
423                                 pxmitbuf->priv_data = NULL;
424                                 enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
425                                 rtw_yield_os();
426                         }
427                         else
428                                 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
429                         
430                         pxmitbuf = NULL;
431                 }
432
433                 if (err) break;
434         }
435
436         return err;
437 }
438
439 /*
440  * Description
441  *      Transmit xmitframe from queue
442  *
443  * Return
444  *      _SUCCESS        ok
445  *      _FAIL           something error
446  */
447 s32 rtl8723as_xmit_handler(PADAPTER padapter)
448 {
449         struct xmit_priv *pxmitpriv;
450         s32 ret;
451         _irqL irql;
452
453
454         pxmitpriv = &padapter->xmitpriv;
455
456 wait:
457         ret = _rtw_down_sema(&pxmitpriv->SdioXmitSema);
458         if (_FAIL == ret) {
459                 RT_TRACE(_module_hal_xmit_c_, _drv_emerg_, ("%s: down sema fail!\n", __FUNCTION__));
460                 return _FAIL;
461         }
462
463 next:
464         if ((padapter->bDriverStopped == _TRUE) ||
465                 (padapter->bSurpriseRemoved == _TRUE)) {
466                 RT_TRACE(_module_hal_xmit_c_, _drv_notice_,
467                                  ("%s: bDriverStopped(%d) bSurpriseRemoved(%d)\n",
468                                   __FUNCTION__, padapter->bDriverStopped, padapter->bSurpriseRemoved));
469                 return _FAIL;
470         }
471
472         _enter_critical_bh(&pxmitpriv->lock, &irql);
473         ret = rtw_txframes_pending(padapter);
474         _exit_critical_bh(&pxmitpriv->lock, &irql);
475         if (ret == 0) {
476                 return _SUCCESS;
477         }
478
479         // dequeue frame and write to hardware
480
481         ret = xmit_xmitframes(padapter, pxmitpriv);
482         if (ret == -2) {
483                 rtw_msleep_os(1);
484                 goto next;
485         }
486
487         _enter_critical_bh(&pxmitpriv->lock, &irql);
488         ret = rtw_txframes_pending(padapter);
489         _exit_critical_bh(&pxmitpriv->lock, &irql);
490         if (ret == 1) {
491                 rtw_msleep_os(1);
492                 goto next;
493         }
494
495         return _SUCCESS;
496 }
497
498 thread_return rtl8723as_xmit_thread(thread_context context)
499 {
500         PADAPTER padapter;
501         struct xmit_priv *pxmitpriv;
502         s32 ret;
503
504
505         padapter = (PADAPTER)context;
506         pxmitpriv = &padapter->xmitpriv;
507         ret = _SUCCESS;
508
509         thread_enter("RTWHALXT");
510
511         do {
512                 ret = rtl8723as_xmit_handler(padapter);
513                 if (signal_pending(current)) {
514                         flush_signals(current);
515                 }
516         } while (_SUCCESS == ret);
517
518         _rtw_up_sema(&pxmitpriv->SdioXmitTerminateSema);
519
520         RT_TRACE(_module_hal_xmit_c_, _drv_notice_, ("-%s\n", __FUNCTION__));
521
522         thread_exit();
523 }
524
525 s32 rtl8723as_mgnt_xmit(PADAPTER padapter, struct xmit_frame *pmgntframe)
526 {
527         s32 ret = _SUCCESS;
528         struct pkt_attrib *pattrib;
529         struct xmit_buf *pxmitbuf;
530         struct xmit_priv        *pxmitpriv = &padapter->xmitpriv;
531         struct dvobj_priv       *pdvobjpriv = adapter_to_dvobj(padapter);
532         u8 *pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
533
534         RT_TRACE(_module_hal_xmit_c_, _drv_info_, ("+%s\n", __FUNCTION__));
535
536         pattrib = &pmgntframe->attrib;
537         pxmitbuf = pmgntframe->pxmitbuf;
538
539         rtl8723a_update_txdesc(pmgntframe, pmgntframe->buf_addr);
540
541         pxmitbuf->len = TXDESC_SIZE + pattrib->last_txcmdsz;
542         //pmgntframe->pg_num = (pxmitbuf->len + 127)/128; // 128 is tx page size
543         pxmitbuf->pg_num = (pxmitbuf->len + 127)/128; // 128 is tx page size
544         pxmitbuf->ptail = pmgntframe->buf_addr + pxmitbuf->len;
545         pxmitbuf->ff_hwaddr = rtw_get_ff_hwaddr(pmgntframe);
546
547         rtw_count_tx_stats(padapter, pmgntframe, pattrib->last_txcmdsz);
548
549         rtw_free_xmitframe(pxmitpriv, pmgntframe);
550
551         pxmitbuf->priv_data = NULL;
552
553         if(GetFrameSubType(pframe)==WIFI_BEACON) //dump beacon directly
554         {
555                 rtw_write_port(padapter, pdvobjpriv->Queue2Pipe[pxmitbuf->ff_hwaddr], pxmitbuf->len, (u8 *)pxmitbuf);
556                 
557                 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
558         }
559          else
560         {
561                 enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
562         }       
563
564         if  (ret != _SUCCESS)
565                 rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_UNKNOWN);
566
567         return ret;
568 }
569
570 /*
571  * Description:
572  *      Handle xmitframe(packet) come from rtw_xmit()
573  *
574  * Return:
575  *      _TRUE   dump packet directly ok
576  *      _FALSE  enqueue, temporary can't transmit packets to hardware
577  */
578 s32 rtl8723as_hal_xmit(PADAPTER padapter, struct xmit_frame *pxmitframe)
579 {
580         struct xmit_priv *pxmitpriv;
581         _irqL irql;
582         s32 err;
583
584
585         pxmitframe->attrib.qsel = pxmitframe->attrib.priority;
586         pxmitpriv = &padapter->xmitpriv;
587
588 #ifdef CONFIG_80211N_HT
589         if ((pxmitframe->frame_tag == DATA_FRAMETAG) &&
590                 (pxmitframe->attrib.ether_type != 0x0806) &&
591                 (pxmitframe->attrib.ether_type != 0x888e) &&
592                 (pxmitframe->attrib.dhcp_pkt != 1))
593         {
594                 if (padapter->mlmepriv.LinkDetectInfo.bBusyTraffic == _TRUE)
595                         rtw_issue_addbareq_cmd(padapter, pxmitframe);
596         }
597 #endif
598
599         _enter_critical_bh(&pxmitpriv->lock, &irql);
600         err = rtw_xmitframe_enqueue(padapter, pxmitframe);
601         _exit_critical_bh(&pxmitpriv->lock, &irql);
602         if (err != _SUCCESS) {
603                 RT_TRACE(_module_hal_xmit_c_, _drv_err_, ("rtl8723as_hal_xmit: enqueue xmitframe fail\n"));
604                 rtw_free_xmitframe(pxmitpriv, pxmitframe);
605
606                 // Trick, make the statistics correct
607                 pxmitpriv->tx_pkts--;
608                 pxmitpriv->tx_drop++;
609                 return _TRUE;
610         }
611
612         _rtw_up_sema(&pxmitpriv->SdioXmitSema);
613
614         return _FALSE;
615 }
616
617 s32     rtl8723as_hal_xmitframe_enqueue(_adapter *padapter, struct xmit_frame *pxmitframe)
618 {
619         struct xmit_priv        *pxmitpriv = &padapter->xmitpriv;
620         s32 err;
621         
622         if ((err=rtw_xmitframe_enqueue(padapter, pxmitframe)) != _SUCCESS) 
623         {
624                 rtw_free_xmitframe(pxmitpriv, pxmitframe);
625
626                 // Trick, make the statistics correct
627                 pxmitpriv->tx_pkts--;
628                 pxmitpriv->tx_drop++;                                   
629         }
630         else
631         {
632 #ifdef CONFIG_SDIO_TX_TASKLET
633                 tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);                                  
634 #else
635                 _rtw_up_sema(&pxmitpriv->SdioXmitSema);
636 #endif
637         }
638         
639         return err;
640         
641 }
642
643 /*
644  * Return
645  *      _SUCCESS        start thread ok
646  *      _FAIL           start thread fail
647  *
648  */
649 s32 rtl8723as_init_xmit_priv(PADAPTER padapter)
650 {
651         struct xmit_priv *xmitpriv = &padapter->xmitpriv;
652         PHAL_DATA_TYPE phal;
653
654
655         phal = GET_HAL_DATA(padapter);
656
657         _rtw_spinlock_init(&phal->SdioTxFIFOFreePageLock);
658         _rtw_init_sema(&xmitpriv->SdioXmitSema, 0);
659         _rtw_init_sema(&xmitpriv->SdioXmitTerminateSema, 0);
660
661         return _SUCCESS;
662 }
663
664 void rtl8723as_free_xmit_priv(PADAPTER padapter)
665 {
666         PHAL_DATA_TYPE phal;
667         struct xmit_priv *pxmitpriv;
668         struct xmit_buf *pxmitbuf;
669         _queue *pqueue;
670         _list *plist, *phead;
671         _list tmplist;
672         _irqL irql;
673
674
675         phal = GET_HAL_DATA(padapter);
676         pxmitpriv = &padapter->xmitpriv;
677         pqueue = &pxmitpriv->pending_xmitbuf_queue;
678         phead = get_list_head(pqueue);
679         _rtw_init_listhead(&tmplist);
680
681         _enter_critical_bh(&pqueue->lock, &irql);
682         if (_rtw_queue_empty(pqueue) == _FALSE)
683         {
684                 // Insert tmplist to end of queue, and delete phead
685                 // then tmplist become head of queue.
686                 rtw_list_insert_tail(&tmplist, phead);
687                 rtw_list_delete(phead);
688         }
689         _exit_critical_bh(&pqueue->lock, &irql);
690
691         phead = &tmplist;
692         while (rtw_is_list_empty(phead) == _FALSE)
693         {
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 }
705