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