1 // SPDX-License-Identifier: GPL-2.0
2 /******************************************************************************
4 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
6 ******************************************************************************/
10 #include <rtl8723b_hal.h>
12 static u8 rtw_sdio_wait_enough_TxOQT_space(struct adapter *padapter, u8 agg_num)
15 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
17 while (pHalData->SdioTxOQTFreeSpace < agg_num) {
19 (padapter->bSurpriseRemoved) ||
20 (padapter->bDriverStopped)
24 HalQueryTxOQTBufferStatus8723BSdio(padapter);
26 if ((++n % 60) == 0) {
32 pHalData->SdioTxOQTFreeSpace -= agg_num;
37 static s32 rtl8723_dequeue_writeport(struct adapter *padapter)
39 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
40 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
41 struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
42 struct xmit_buf *pxmitbuf;
43 struct adapter *pri_padapter = padapter;
47 u8 bUpdatePageNum = false;
49 ret = ret || check_fwstate(pmlmepriv, _FW_UNDER_SURVEY);
52 pxmitbuf = dequeue_pending_xmitbuf_under_survey(pxmitpriv);
54 pxmitbuf = dequeue_pending_xmitbuf(pxmitpriv);
59 deviceId = ffaddr2deviceId(pdvobjpriv, pxmitbuf->ff_hwaddr);
61 /* translate fifo addr to queue index */
63 case WLAN_TX_HIQ_DEVICE_ID:
64 PageIdx = HI_QUEUE_IDX;
67 case WLAN_TX_MIQ_DEVICE_ID:
68 PageIdx = MID_QUEUE_IDX;
71 case WLAN_TX_LOQ_DEVICE_ID:
72 PageIdx = LOW_QUEUE_IDX;
77 /* check if hardware tx fifo page is enough */
78 if (!rtw_hal_sdio_query_tx_freepage(pri_padapter, PageIdx, pxmitbuf->pg_num)) {
79 if (!bUpdatePageNum) {
80 /* Total number of page is NOT available, so update current FIFO status */
81 HalQueryTxBufferStatus8723BSdio(padapter);
82 bUpdatePageNum = true;
85 bUpdatePageNum = false;
86 enqueue_pending_xmitbuf_to_head(pxmitpriv, pxmitbuf);
92 (padapter->bSurpriseRemoved) ||
93 (padapter->bDriverStopped)
97 if (rtw_sdio_wait_enough_TxOQT_space(padapter, pxmitbuf->agg_num) == false)
100 traffic_check_for_leave_lps(padapter, true, pxmitbuf->agg_num);
102 rtw_write_port(padapter, deviceId, pxmitbuf->len, (u8 *)pxmitbuf);
104 rtw_hal_sdio_update_tx_freepage(pri_padapter, PageIdx, pxmitbuf->pg_num);
107 /* rtw_free_xmitframe(pxmitpriv, pframe); */
108 /* pxmitbuf->priv_data = NULL; */
109 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
116 *Transmit xmitbuf to hardware tx fifo
120 *_FAIL something error
122 s32 rtl8723bs_xmit_buf_handler(struct adapter *padapter)
124 struct xmit_priv *pxmitpriv;
125 u8 queue_empty, queue_pending;
129 pxmitpriv = &padapter->xmitpriv;
131 if (wait_for_completion_interruptible(&pxmitpriv->xmit_comp)) {
132 netdev_emerg(padapter->pnetdev,
133 "%s: down SdioXmitBufSema fail!\n", __func__);
137 ret = (padapter->bDriverStopped) || (padapter->bSurpriseRemoved);
141 queue_pending = check_pending_xmitbuf(pxmitpriv);
146 ret = rtw_register_tx_alive(padapter);
147 if (ret != _SUCCESS) {
152 queue_empty = rtl8723_dequeue_writeport(padapter);
153 /* dump secondary adapter xmitbuf */
154 } while (!queue_empty);
156 rtw_unregister_tx_alive(padapter);
163 *Aggregation packets and send to hardware
167 *-1 Hardware resource(TX FIFO) not ready
168 *-2 Software resource(xmitbuf) not ready
170 static s32 xmit_xmitframes(struct adapter *padapter, struct xmit_priv *pxmitpriv)
174 struct hw_xmit *hwxmits, *phwxmit;
176 struct tx_servq *ptxservq;
177 struct list_head *sta_plist, *sta_phead, *frame_plist, *frame_phead, *tmp;
178 struct xmit_frame *pxmitframe;
179 struct __queue *pframe_queue;
180 struct xmit_buf *pxmitbuf;
181 u32 txlen, max_xmit_len;
182 u8 txdesc_size = TXDESC_SIZE;
186 hwxmits = pxmitpriv->hwxmits;
187 hwentry = pxmitpriv->hwxmit_entry;
193 if (padapter->registrypriv.wifi_spec == 1) {
194 for (idx = 0; idx < 4; idx++)
195 inx[idx] = pxmitpriv->wmm_para_seq[idx];
203 /* 0(VO), 1(VI), 2(BE), 3(BK) */
204 for (idx = 0; idx < hwentry; idx++) {
205 phwxmit = hwxmits + inx[idx];
208 (check_pending_xmitbuf(pxmitpriv)) &&
209 (padapter->mlmepriv.LinkDetectInfo.bHigherBusyTxTraffic)
211 if ((phwxmit->accnt > 0) && (phwxmit->accnt < 5)) {
217 max_xmit_len = rtw_hal_get_sdio_tx_max_length(padapter, inx[idx]);
219 spin_lock_bh(&pxmitpriv->lock);
221 sta_phead = get_list_head(phwxmit->sta_queue);
222 /* because stop_sta_xmit may delete sta_plist at any time */
223 /* so we should add lock here, or while loop can not exit */
224 list_for_each_safe(sta_plist, tmp, sta_phead) {
225 ptxservq = list_entry(sta_plist, struct tx_servq,
228 pframe_queue = &ptxservq->sta_pending;
230 frame_phead = get_list_head(pframe_queue);
232 while (list_empty(frame_phead) == false) {
233 frame_plist = get_next(frame_phead);
234 pxmitframe = container_of(frame_plist, struct xmit_frame, list);
236 /* check xmit_buf size enough or not */
237 txlen = txdesc_size + rtw_wlan_pkt_size(pxmitframe);
239 ((_RND(pxmitbuf->len, 8) + txlen) > max_xmit_len) ||
240 (k >= (rtw_hal_sdio_max_txoqt_free_space(padapter) - 1))
243 /* pxmitbuf->priv_data will be NULL, and will crash here */
244 if (pxmitbuf->len > 0 &&
245 pxmitbuf->priv_data) {
246 struct xmit_frame *pframe;
247 pframe = (struct xmit_frame *)pxmitbuf->priv_data;
249 pxmitbuf->agg_num = k;
250 rtl8723b_update_txdesc(pframe, pframe->buf_addr);
251 rtw_free_xmitframe(pxmitpriv, pframe);
252 pxmitbuf->priv_data = NULL;
253 enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
254 /* can not yield under lock */
257 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
260 pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv);
263 netdev_err(padapter->pnetdev,
264 "%s: xmit_buf is not enough!\n",
268 complete(&(pxmitpriv->xmit_comp));
274 /* ok to send, remove frame from queue */
275 if (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == true)
277 (pxmitframe->attrib.psta->state & WIFI_SLEEP_STATE) &&
278 (pxmitframe->attrib.triggered == 0)
282 list_del_init(&pxmitframe->list);
287 pxmitbuf->ff_hwaddr = rtw_get_ff_hwaddr(pxmitframe);
288 pxmitbuf->priv_data = (u8 *)pxmitframe;
291 /* coalesce the xmitframe to xmitbuf */
292 pxmitframe->pxmitbuf = pxmitbuf;
293 pxmitframe->buf_addr = pxmitbuf->ptail;
295 ret = rtw_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe);
297 netdev_err(padapter->pnetdev,
298 "%s: coalesce FAIL!",
300 /* Todo: error handler */
304 rtl8723b_update_txdesc(pxmitframe, pxmitframe->buf_addr);
305 rtw_count_tx_stats(padapter, pxmitframe, pxmitframe->attrib.last_txcmdsz);
307 txlen = txdesc_size + pxmitframe->attrib.last_txcmdsz;
308 pxmitframe->pg_num = (txlen + 127) / 128;
309 pxmitbuf->pg_num += (txlen + 127) / 128;
310 pxmitbuf->ptail += _RND(txlen, 8); /* round to 8 bytes alignment */
311 pxmitbuf->len = _RND(pxmitbuf->len, 8) + txlen;
315 rtw_free_xmitframe(pxmitpriv, pxmitframe);
319 if (list_empty(&pframe_queue->queue))
320 list_del_init(&ptxservq->tx_pending);
325 spin_unlock_bh(&pxmitpriv->lock);
327 /* dump xmit_buf to hw tx fifo */
329 if (pxmitbuf->len > 0) {
330 struct xmit_frame *pframe;
331 pframe = (struct xmit_frame *)pxmitbuf->priv_data;
333 pxmitbuf->agg_num = k;
334 rtl8723b_update_txdesc(pframe, pframe->buf_addr);
335 rtw_free_xmitframe(pxmitpriv, pframe);
336 pxmitbuf->priv_data = NULL;
337 enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
340 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
353 *Transmit xmitframe from queue
357 *_FAIL something error
359 static s32 rtl8723bs_xmit_handler(struct adapter *padapter)
361 struct xmit_priv *pxmitpriv;
365 pxmitpriv = &padapter->xmitpriv;
367 if (wait_for_completion_interruptible(&pxmitpriv->SdioXmitStart)) {
368 netdev_emerg(padapter->pnetdev, "%s: SdioXmitStart fail!\n",
375 (padapter->bDriverStopped) ||
376 (padapter->bSurpriseRemoved)
380 spin_lock_bh(&pxmitpriv->lock);
381 ret = rtw_txframes_pending(padapter);
382 spin_unlock_bh(&pxmitpriv->lock);
387 /* dequeue frame and write to hardware */
389 ret = xmit_xmitframes(padapter, pxmitpriv);
391 /* here sleep 1ms will cause big TP loss of TX */
392 /* from 50+ to 40+ */
393 if (padapter->registrypriv.wifi_spec)
400 spin_lock_bh(&pxmitpriv->lock);
401 ret = rtw_txframes_pending(padapter);
402 spin_unlock_bh(&pxmitpriv->lock);
410 int rtl8723bs_xmit_thread(void *context)
413 struct adapter *padapter;
414 struct xmit_priv *pxmitpriv;
419 pxmitpriv = &padapter->xmitpriv;
421 rtw_sprintf(thread_name, 20, "RTWHALXT-%s", ADPT_ARG(padapter));
422 thread_enter(thread_name);
425 ret = rtl8723bs_xmit_handler(padapter);
426 if (signal_pending(current)) {
427 flush_signals(current);
429 } while (_SUCCESS == ret);
431 complete(&pxmitpriv->SdioXmitTerminate);
436 s32 rtl8723bs_mgnt_xmit(
437 struct adapter *padapter, struct xmit_frame *pmgntframe
441 struct pkt_attrib *pattrib;
442 struct xmit_buf *pxmitbuf;
443 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
444 struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
445 u8 *pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
446 u8 txdesc_size = TXDESC_SIZE;
448 pattrib = &pmgntframe->attrib;
449 pxmitbuf = pmgntframe->pxmitbuf;
451 rtl8723b_update_txdesc(pmgntframe, pmgntframe->buf_addr);
453 pxmitbuf->len = txdesc_size + pattrib->last_txcmdsz;
454 pxmitbuf->pg_num = (pxmitbuf->len + 127) / 128; /* 128 is tx page size */
455 pxmitbuf->ptail = pmgntframe->buf_addr + pxmitbuf->len;
456 pxmitbuf->ff_hwaddr = rtw_get_ff_hwaddr(pmgntframe);
458 rtw_count_tx_stats(padapter, pmgntframe, pattrib->last_txcmdsz);
460 rtw_free_xmitframe(pxmitpriv, pmgntframe);
462 pxmitbuf->priv_data = NULL;
464 if (GetFrameSubType(pframe) == WIFI_BEACON) { /* dump beacon directly */
465 ret = rtw_write_port(padapter, pdvobjpriv->Queue2Pipe[pxmitbuf->ff_hwaddr], pxmitbuf->len, (u8 *)pxmitbuf);
467 rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_WRITE_PORT_ERR);
469 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
471 enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
478 *Handle xmitframe(packet) come from rtw_xmit()
481 *true dump packet directly ok
482 *false enqueue, temporary can't transmit packets to hardware
484 s32 rtl8723bs_hal_xmit(
485 struct adapter *padapter, struct xmit_frame *pxmitframe
488 struct xmit_priv *pxmitpriv;
492 pxmitframe->attrib.qsel = pxmitframe->attrib.priority;
493 pxmitpriv = &padapter->xmitpriv;
496 (pxmitframe->frame_tag == DATA_FRAMETAG) &&
497 (pxmitframe->attrib.ether_type != 0x0806) &&
498 (pxmitframe->attrib.ether_type != 0x888e) &&
499 (pxmitframe->attrib.dhcp_pkt != 1)
501 if (padapter->mlmepriv.LinkDetectInfo.bBusyTraffic)
502 rtw_issue_addbareq_cmd(padapter, pxmitframe);
505 spin_lock_bh(&pxmitpriv->lock);
506 err = rtw_xmitframe_enqueue(padapter, pxmitframe);
507 spin_unlock_bh(&pxmitpriv->lock);
508 if (err != _SUCCESS) {
509 rtw_free_xmitframe(pxmitpriv, pxmitframe);
511 pxmitpriv->tx_drop++;
515 complete(&pxmitpriv->SdioXmitStart);
520 s32 rtl8723bs_hal_xmitframe_enqueue(
521 struct adapter *padapter, struct xmit_frame *pxmitframe
524 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
527 err = rtw_xmitframe_enqueue(padapter, pxmitframe);
528 if (err != _SUCCESS) {
529 rtw_free_xmitframe(pxmitpriv, pxmitframe);
531 pxmitpriv->tx_drop++;
533 complete(&pxmitpriv->SdioXmitStart);
542 *_SUCCESS start thread ok
543 *_FAIL start thread fail
546 s32 rtl8723bs_init_xmit_priv(struct adapter *padapter)
548 struct xmit_priv *xmitpriv = &padapter->xmitpriv;
549 struct hal_com_data *phal;
552 phal = GET_HAL_DATA(padapter);
554 spin_lock_init(&phal->SdioTxFIFOFreePageLock);
555 init_completion(&xmitpriv->SdioXmitStart);
556 init_completion(&xmitpriv->SdioXmitTerminate);
561 void rtl8723bs_free_xmit_priv(struct adapter *padapter)
563 struct xmit_priv *pxmitpriv;
564 struct xmit_buf *pxmitbuf;
565 struct __queue *pqueue;
566 struct list_head *plist, *phead;
567 struct list_head tmplist;
570 pxmitpriv = &padapter->xmitpriv;
571 pqueue = &pxmitpriv->pending_xmitbuf_queue;
572 phead = get_list_head(pqueue);
573 INIT_LIST_HEAD(&tmplist);
575 spin_lock_bh(&pqueue->lock);
576 if (!list_empty(&pqueue->queue)) {
577 /* Insert tmplist to end of queue, and delete phead */
578 /* then tmplist become head of queue. */
579 list_add_tail(&tmplist, phead);
580 list_del_init(phead);
582 spin_unlock_bh(&pqueue->lock);
585 while (list_empty(phead) == false) {
586 plist = get_next(phead);
587 list_del_init(plist);
589 pxmitbuf = container_of(plist, struct xmit_buf, list);
590 rtw_free_xmitframe(pxmitpriv, (struct xmit_frame *)pxmitbuf->priv_data);
591 pxmitbuf->priv_data = NULL;
592 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);