1 /******************************************************************************
3 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 ******************************************************************************/
15 #define _RTL8723BS_XMIT_C_
17 #include <drv_types.h>
18 #include <rtw_debug.h>
19 #include <rtl8723b_hal.h>
21 static u8 rtw_sdio_wait_enough_TxOQT_space(struct adapter *padapter, u8 agg_num)
24 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
26 while (pHalData->SdioTxOQTFreeSpace < agg_num) {
28 (padapter->bSurpriseRemoved == true) ||
29 (padapter->bDriverStopped == true)
31 DBG_871X("%s: bSurpriseRemoved or bDriverStopped (wait TxOQT)\n", __func__);
35 HalQueryTxOQTBufferStatus8723BSdio(padapter);
37 if ((++n % 60) == 0) {
39 DBG_871X("%s(%d): QOT free space(%d), agg_num: %d\n",
40 __func__, n, pHalData->SdioTxOQTFreeSpace, agg_num);
47 pHalData->SdioTxOQTFreeSpace -= agg_num;
50 /* ++priv->pshare->nr_out_of_txoqt_space; */
55 static s32 rtl8723_dequeue_writeport(struct adapter *padapter)
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 struct adapter *pri_padapter = padapter;
65 u8 bUpdatePageNum = false;
67 ret = ret || check_fwstate(pmlmepriv, _FW_UNDER_SURVEY);
70 pxmitbuf = dequeue_pending_xmitbuf_under_survey(pxmitpriv);
72 pxmitbuf = dequeue_pending_xmitbuf(pxmitpriv);
77 deviceId = ffaddr2deviceId(pdvobjpriv, pxmitbuf->ff_hwaddr);
79 /* translate fifo addr to queue index */
81 case WLAN_TX_HIQ_DEVICE_ID:
82 PageIdx = HI_QUEUE_IDX;
85 case WLAN_TX_MIQ_DEVICE_ID:
86 PageIdx = MID_QUEUE_IDX;
89 case WLAN_TX_LOQ_DEVICE_ID:
90 PageIdx = LOW_QUEUE_IDX;
95 /* check if hardware tx fifo page is enough */
96 if (false == rtw_hal_sdio_query_tx_freepage(pri_padapter, PageIdx, pxmitbuf->pg_num)) {
97 if (!bUpdatePageNum) {
98 /* Total number of page is NOT available, so update current FIFO status */
99 HalQueryTxBufferStatus8723BSdio(padapter);
100 bUpdatePageNum = true;
101 goto query_free_page;
103 bUpdatePageNum = false;
104 enqueue_pending_xmitbuf_to_head(pxmitpriv, pxmitbuf);
110 (padapter->bSurpriseRemoved == true) ||
111 (padapter->bDriverStopped == true)
116 ("%s: bSurpriseRemoved(wirte port)\n", __func__)
121 if (rtw_sdio_wait_enough_TxOQT_space(padapter, pxmitbuf->agg_num) == false)
124 traffic_check_for_leave_lps(padapter, true, pxmitbuf->agg_num);
126 rtw_write_port(padapter, deviceId, pxmitbuf->len, (u8 *)pxmitbuf);
128 rtw_hal_sdio_update_tx_freepage(pri_padapter, PageIdx, pxmitbuf->pg_num);
131 /* rtw_free_xmitframe(pxmitpriv, pframe); */
132 /* pxmitbuf->priv_data = NULL; */
133 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
135 #ifdef CONFIG_SDIO_TX_TASKLET
136 tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
144 *Transmit xmitbuf to hardware tx fifo
148 *_FAIL something error
150 s32 rtl8723bs_xmit_buf_handler(struct adapter *padapter)
152 struct xmit_priv *pxmitpriv;
153 u8 queue_empty, queue_pending;
157 pxmitpriv = &padapter->xmitpriv;
159 if (down_interruptible(&pxmitpriv->xmit_sema)) {
160 DBG_871X_LEVEL(_drv_emerg_, "%s: down SdioXmitBufSema fail!\n", __func__);
164 ret = (padapter->bDriverStopped == true) || (padapter->bSurpriseRemoved == true);
170 "%s: bDriverStopped(%d) bSurpriseRemoved(%d)!\n",
172 padapter->bDriverStopped,
173 padapter->bSurpriseRemoved
179 queue_pending = check_pending_xmitbuf(pxmitpriv);
181 if (queue_pending == false)
184 ret = rtw_register_tx_alive(padapter);
185 if (ret != _SUCCESS) {
190 queue_empty = rtl8723_dequeue_writeport(padapter);
191 /* dump secondary adapter xmitbuf */
192 } while (!queue_empty);
194 rtw_unregister_tx_alive(padapter);
201 *Aggregation packets and send to hardware
205 *-1 Hardware resource(TX FIFO) not ready
206 *-2 Software resource(xmitbuf) not ready
208 static s32 xmit_xmitframes(struct adapter *padapter, struct xmit_priv *pxmitpriv)
212 struct hw_xmit *hwxmits, *phwxmit;
213 u8 no_res, idx, hwentry;
214 struct tx_servq *ptxservq;
215 struct list_head *sta_plist, *sta_phead, *frame_plist, *frame_phead;
216 struct xmit_frame *pxmitframe;
217 struct __queue *pframe_queue;
218 struct xmit_buf *pxmitbuf;
219 u32 txlen, max_xmit_len;
220 u8 txdesc_size = TXDESC_SIZE;
225 hwxmits = pxmitpriv->hwxmits;
226 hwentry = pxmitpriv->hwxmit_entry;
232 if (padapter->registrypriv.wifi_spec == 1) {
233 for (idx = 0; idx < 4; idx++)
234 inx[idx] = pxmitpriv->wmm_para_seq[idx];
242 /* 0(VO), 1(VI), 2(BE), 3(BK) */
243 for (idx = 0; idx < hwentry; idx++) {
244 phwxmit = hwxmits + inx[idx];
247 (check_pending_xmitbuf(pxmitpriv) == true) &&
248 (padapter->mlmepriv.LinkDetectInfo.bHigherBusyTxTraffic == true)
250 if ((phwxmit->accnt > 0) && (phwxmit->accnt < 5)) {
256 max_xmit_len = rtw_hal_get_sdio_tx_max_length(padapter, inx[idx]);
258 spin_lock_bh(&pxmitpriv->lock);
260 sta_phead = get_list_head(phwxmit->sta_queue);
261 sta_plist = get_next(sta_phead);
262 /* because stop_sta_xmit may delete sta_plist at any time */
263 /* so we should add lock here, or while loop can not exit */
264 while (sta_phead != sta_plist) {
265 ptxservq = LIST_CONTAINOR(sta_plist, struct tx_servq, tx_pending);
266 sta_plist = get_next(sta_plist);
270 "%s idx:%d hwxmit_pkt_num:%d ptxservq_pkt_num:%d\n",
277 "%s free_xmit_extbuf_cnt =%d free_xmitbuf_cnt =%d free_xmitframe_cnt =%d\n",
279 pxmitpriv->free_xmit_extbuf_cnt,
280 pxmitpriv->free_xmitbuf_cnt,
281 pxmitpriv->free_xmitframe_cnt
284 pframe_queue = &ptxservq->sta_pending;
286 frame_phead = get_list_head(pframe_queue);
288 while (list_empty(frame_phead) == false) {
289 frame_plist = get_next(frame_phead);
290 pxmitframe = LIST_CONTAINOR(frame_plist, struct xmit_frame, list);
292 /* check xmit_buf size enough or not */
293 txlen = txdesc_size + rtw_wlan_pkt_size(pxmitframe);
295 (NULL == pxmitbuf) ||
296 ((_RND(pxmitbuf->len, 8) + txlen) > max_xmit_len) ||
297 (k >= (rtw_hal_sdio_max_txoqt_free_space(padapter)-1))
300 /* pxmitbuf->priv_data will be NULL, and will crash here */
301 if (pxmitbuf->len > 0 &&
302 pxmitbuf->priv_data) {
303 struct xmit_frame *pframe;
304 pframe = (struct xmit_frame *)pxmitbuf->priv_data;
306 pxmitbuf->agg_num = k;
307 rtl8723b_update_txdesc(pframe, pframe->buf_addr);
308 rtw_free_xmitframe(pxmitpriv, pframe);
309 pxmitbuf->priv_data = NULL;
310 enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
311 /* can not yield under lock */
314 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
317 pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv);
318 if (pxmitbuf == NULL) {
320 DBG_871X_LEVEL(_drv_err_, "%s: xmit_buf is not enough!\n", __func__);
323 up(&(pxmitpriv->xmit_sema));
329 /* ok to send, remove frame from queue */
330 if (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == true) {
332 (pxmitframe->attrib.psta->state & WIFI_SLEEP_STATE) &&
333 (pxmitframe->attrib.triggered == 0)
336 "%s: one not triggered pkt in queue when this STA sleep,"
337 " break and goto next sta\n",
344 list_del_init(&pxmitframe->list);
349 pxmitbuf->ff_hwaddr = rtw_get_ff_hwaddr(pxmitframe);
350 pxmitbuf->priv_data = (u8 *)pxmitframe;
353 /* coalesce the xmitframe to xmitbuf */
354 pxmitframe->pxmitbuf = pxmitbuf;
355 pxmitframe->buf_addr = pxmitbuf->ptail;
357 ret = rtw_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe);
359 DBG_871X_LEVEL(_drv_err_, "%s: coalesce FAIL!", __func__);
360 /* Todo: error handler */
364 rtl8723b_update_txdesc(pxmitframe, pxmitframe->buf_addr);
365 rtw_count_tx_stats(padapter, pxmitframe, pxmitframe->attrib.last_txcmdsz);
367 txlen = txdesc_size + pxmitframe->attrib.last_txcmdsz;
368 pxmitframe->pg_num = (txlen + 127)/128;
369 pxmitbuf->pg_num += (txlen + 127)/128;
371 /* ((struct xmit_frame*)pxmitbuf->priv_data)->pg_num += pxmitframe->pg_num; */
372 pxmitbuf->ptail += _RND(txlen, 8); /* round to 8 bytes alignment */
373 pxmitbuf->len = _RND(pxmitbuf->len, 8) + txlen;
377 rtw_free_xmitframe(pxmitpriv, pxmitframe);
381 if (list_empty(&pframe_queue->queue))
382 list_del_init(&ptxservq->tx_pending);
387 spin_unlock_bh(&pxmitpriv->lock);
389 /* dump xmit_buf to hw tx fifo */
391 RT_TRACE(_module_hal_xmit_c_, _drv_info_, ("pxmitbuf->len =%d enqueue\n", pxmitbuf->len));
393 if (pxmitbuf->len > 0) {
394 struct xmit_frame *pframe;
395 pframe = (struct xmit_frame *)pxmitbuf->priv_data;
397 pxmitbuf->agg_num = k;
398 rtl8723b_update_txdesc(pframe, pframe->buf_addr);
399 rtw_free_xmitframe(pxmitpriv, pframe);
400 pxmitbuf->priv_data = NULL;
401 enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
404 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
417 *Transmit xmitframe from queue
421 *_FAIL something error
423 static s32 rtl8723bs_xmit_handler(struct adapter *padapter)
425 struct xmit_priv *pxmitpriv;
429 pxmitpriv = &padapter->xmitpriv;
431 if (down_interruptible(&pxmitpriv->SdioXmitSema)) {
432 DBG_871X_LEVEL(_drv_emerg_, "%s: down sema fail!\n", __func__);
438 (padapter->bDriverStopped == true) ||
439 (padapter->bSurpriseRemoved == true)
445 "%s: bDriverStopped(%d) bSurpriseRemoved(%d)\n",
447 padapter->bDriverStopped,
448 padapter->bSurpriseRemoved
454 spin_lock_bh(&pxmitpriv->lock);
455 ret = rtw_txframes_pending(padapter);
456 spin_unlock_bh(&pxmitpriv->lock);
461 /* dequeue frame and write to hardware */
463 ret = xmit_xmitframes(padapter, pxmitpriv);
465 /* here sleep 1ms will cause big TP loss of TX */
466 /* from 50+ to 40+ */
467 if (padapter->registrypriv.wifi_spec)
474 spin_lock_bh(&pxmitpriv->lock);
475 ret = rtw_txframes_pending(padapter);
476 spin_unlock_bh(&pxmitpriv->lock);
484 int rtl8723bs_xmit_thread(void *context)
487 struct adapter *padapter;
488 struct xmit_priv *pxmitpriv;
493 pxmitpriv = &padapter->xmitpriv;
495 rtw_sprintf(thread_name, 20, "RTWHALXT-" ADPT_FMT, ADPT_ARG(padapter));
496 thread_enter(thread_name);
498 DBG_871X("start "FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
500 /* For now, no one would down sema to check thread is running, */
501 /* so mark this temporary, Lucas@20130820 */
502 /* up(&pxmitpriv->SdioXmitTerminateSema); */
505 ret = rtl8723bs_xmit_handler(padapter);
506 if (signal_pending(current)) {
507 flush_signals(current);
509 } while (_SUCCESS == ret);
511 up(&pxmitpriv->SdioXmitTerminateSema);
513 RT_TRACE(_module_hal_xmit_c_, _drv_notice_, ("-%s\n", __func__));
518 s32 rtl8723bs_mgnt_xmit(
519 struct adapter *padapter, struct xmit_frame *pmgntframe
523 struct pkt_attrib *pattrib;
524 struct xmit_buf *pxmitbuf;
525 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
526 struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
527 u8 *pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
528 u8 txdesc_size = TXDESC_SIZE;
530 RT_TRACE(_module_hal_xmit_c_, _drv_info_, ("+%s\n", __func__));
532 pattrib = &pmgntframe->attrib;
533 pxmitbuf = pmgntframe->pxmitbuf;
535 rtl8723b_update_txdesc(pmgntframe, pmgntframe->buf_addr);
537 pxmitbuf->len = txdesc_size + pattrib->last_txcmdsz;
538 pxmitbuf->pg_num = (pxmitbuf->len + 127)/128; /* 128 is tx page size */
539 pxmitbuf->ptail = pmgntframe->buf_addr + pxmitbuf->len;
540 pxmitbuf->ff_hwaddr = rtw_get_ff_hwaddr(pmgntframe);
542 rtw_count_tx_stats(padapter, pmgntframe, pattrib->last_txcmdsz);
544 rtw_free_xmitframe(pxmitpriv, pmgntframe);
546 pxmitbuf->priv_data = NULL;
548 if (GetFrameSubType(pframe) == WIFI_BEACON) { /* dump beacon directly */
549 ret = rtw_write_port(padapter, pdvobjpriv->Queue2Pipe[pxmitbuf->ff_hwaddr], pxmitbuf->len, (u8 *)pxmitbuf);
551 rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_WRITE_PORT_ERR);
553 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
555 enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
562 *Handle xmitframe(packet) come from rtw_xmit()
565 *true dump packet directly ok
566 *false enqueue, temporary can't transmit packets to hardware
568 s32 rtl8723bs_hal_xmit(
569 struct adapter *padapter, struct xmit_frame *pxmitframe
572 struct xmit_priv *pxmitpriv;
576 pxmitframe->attrib.qsel = pxmitframe->attrib.priority;
577 pxmitpriv = &padapter->xmitpriv;
580 (pxmitframe->frame_tag == DATA_FRAMETAG) &&
581 (pxmitframe->attrib.ether_type != 0x0806) &&
582 (pxmitframe->attrib.ether_type != 0x888e) &&
583 (pxmitframe->attrib.dhcp_pkt != 1)
585 if (padapter->mlmepriv.LinkDetectInfo.bBusyTraffic == true)
586 rtw_issue_addbareq_cmd(padapter, pxmitframe);
589 spin_lock_bh(&pxmitpriv->lock);
590 err = rtw_xmitframe_enqueue(padapter, pxmitframe);
591 spin_unlock_bh(&pxmitpriv->lock);
592 if (err != _SUCCESS) {
593 RT_TRACE(_module_hal_xmit_c_, _drv_err_, ("rtl8723bs_hal_xmit: enqueue xmitframe fail\n"));
594 rtw_free_xmitframe(pxmitpriv, pxmitframe);
596 pxmitpriv->tx_drop++;
600 up(&pxmitpriv->SdioXmitSema);
605 s32 rtl8723bs_hal_xmitframe_enqueue(
606 struct adapter *padapter, struct xmit_frame *pxmitframe
609 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
612 err = rtw_xmitframe_enqueue(padapter, pxmitframe);
613 if (err != _SUCCESS) {
614 rtw_free_xmitframe(pxmitpriv, pxmitframe);
616 pxmitpriv->tx_drop++;
618 #ifdef CONFIG_SDIO_TX_TASKLET
619 tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
621 up(&pxmitpriv->SdioXmitSema);
631 *_SUCCESS start thread ok
632 *_FAIL start thread fail
635 s32 rtl8723bs_init_xmit_priv(struct adapter *padapter)
637 struct xmit_priv *xmitpriv = &padapter->xmitpriv;
638 struct hal_com_data *phal;
641 phal = GET_HAL_DATA(padapter);
643 spin_lock_init(&phal->SdioTxFIFOFreePageLock);
644 sema_init(&xmitpriv->SdioXmitSema, 0);
645 sema_init(&xmitpriv->SdioXmitTerminateSema, 0);
650 void rtl8723bs_free_xmit_priv(struct adapter *padapter)
652 struct hal_com_data *phal;
653 struct xmit_priv *pxmitpriv;
654 struct xmit_buf *pxmitbuf;
655 struct __queue *pqueue;
656 struct list_head *plist, *phead;
657 struct list_head tmplist;
660 phal = GET_HAL_DATA(padapter);
661 pxmitpriv = &padapter->xmitpriv;
662 pqueue = &pxmitpriv->pending_xmitbuf_queue;
663 phead = get_list_head(pqueue);
664 INIT_LIST_HEAD(&tmplist);
666 spin_lock_bh(&pqueue->lock);
667 if (!list_empty(&pqueue->queue)) {
668 /* Insert tmplist to end of queue, and delete phead */
669 /* then tmplist become head of queue. */
670 list_add_tail(&tmplist, phead);
671 list_del_init(phead);
673 spin_unlock_bh(&pqueue->lock);
676 while (list_empty(phead) == false) {
677 plist = get_next(phead);
678 list_del_init(plist);
680 pxmitbuf = LIST_CONTAINOR(plist, struct xmit_buf, list);
681 rtw_free_xmitframe(pxmitpriv, (struct xmit_frame *)pxmitbuf->priv_data);
682 pxmitbuf->priv_data = NULL;
683 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);