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