1 // SPDX-License-Identifier: GPL-2.0
2 /******************************************************************************
3 *
4 * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
5 *
6 ******************************************************************************/
7
8 #include <drv_types.h>
9 #include <rtl8723b_hal.h>
10
rtw_sdio_wait_enough_TxOQT_space(struct adapter * padapter,u8 agg_num)11 static u8 rtw_sdio_wait_enough_TxOQT_space(struct adapter *padapter, u8 agg_num)
12 {
13 u32 n = 0;
14 struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
15
16 while (pHalData->SdioTxOQTFreeSpace < agg_num) {
17 if (
18 (padapter->bSurpriseRemoved) ||
19 (padapter->bDriverStopped)
20 )
21 return false;
22
23 HalQueryTxOQTBufferStatus8723BSdio(padapter);
24
25 if ((++n % 60) == 0) {
26 msleep(1);
27 /* yield(); */
28 }
29 }
30
31 pHalData->SdioTxOQTFreeSpace -= agg_num;
32
33 return true;
34 }
35
rtl8723_dequeue_writeport(struct adapter * padapter)36 static s32 rtl8723_dequeue_writeport(struct adapter *padapter)
37 {
38 struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
39 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
40 struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
41 struct xmit_buf *pxmitbuf;
42 struct adapter *pri_padapter = padapter;
43 s32 ret = 0;
44 u8 PageIdx = 0;
45 u32 deviceId;
46 u8 bUpdatePageNum = false;
47
48 ret = ret || check_fwstate(pmlmepriv, _FW_UNDER_SURVEY);
49
50 if (ret)
51 pxmitbuf = dequeue_pending_xmitbuf_under_survey(pxmitpriv);
52 else
53 pxmitbuf = dequeue_pending_xmitbuf(pxmitpriv);
54
55 if (!pxmitbuf)
56 return true;
57
58 deviceId = ffaddr2deviceId(pdvobjpriv, pxmitbuf->ff_hwaddr);
59
60 /* translate fifo addr to queue index */
61 switch (deviceId) {
62 case WLAN_TX_HIQ_DEVICE_ID:
63 PageIdx = HI_QUEUE_IDX;
64 break;
65
66 case WLAN_TX_MIQ_DEVICE_ID:
67 PageIdx = MID_QUEUE_IDX;
68 break;
69
70 case WLAN_TX_LOQ_DEVICE_ID:
71 PageIdx = LOW_QUEUE_IDX;
72 break;
73 }
74
75 query_free_page:
76 /* check if hardware tx fifo page is enough */
77 if (!rtw_hal_sdio_query_tx_freepage(pri_padapter, PageIdx, pxmitbuf->pg_num)) {
78 if (!bUpdatePageNum) {
79 /* Total number of page is NOT available, so update current FIFO status */
80 HalQueryTxBufferStatus8723BSdio(padapter);
81 bUpdatePageNum = true;
82 goto query_free_page;
83 } else {
84 bUpdatePageNum = false;
85 enqueue_pending_xmitbuf_to_head(pxmitpriv, pxmitbuf);
86 return true;
87 }
88 }
89
90 if (
91 (padapter->bSurpriseRemoved) ||
92 (padapter->bDriverStopped)
93 )
94 goto free_xmitbuf;
95
96 if (rtw_sdio_wait_enough_TxOQT_space(padapter, pxmitbuf->agg_num) == false)
97 goto free_xmitbuf;
98
99 traffic_check_for_leave_lps(padapter, true, pxmitbuf->agg_num);
100
101 rtw_write_port(padapter, deviceId, pxmitbuf->len, (u8 *)pxmitbuf);
102
103 rtw_hal_sdio_update_tx_freepage(pri_padapter, PageIdx, pxmitbuf->pg_num);
104
105 free_xmitbuf:
106 /* rtw_free_xmitframe(pxmitpriv, pframe); */
107 /* pxmitbuf->priv_data = NULL; */
108 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
109
110 return _FAIL;
111 }
112
113 /*
114 * Description
115 *Transmit xmitbuf to hardware tx fifo
116 *
117 * Return
118 *_SUCCESS ok
119 *_FAIL something error
120 */
rtl8723bs_xmit_buf_handler(struct adapter * padapter)121 s32 rtl8723bs_xmit_buf_handler(struct adapter *padapter)
122 {
123 struct xmit_priv *pxmitpriv;
124 u8 queue_empty, queue_pending;
125 s32 ret;
126
127
128 pxmitpriv = &padapter->xmitpriv;
129
130 if (wait_for_completion_interruptible(&pxmitpriv->xmit_comp)) {
131 netdev_emerg(padapter->pnetdev,
132 "%s: down SdioXmitBufSema fail!\n", __func__);
133 return _FAIL;
134 }
135
136 ret = (padapter->bDriverStopped) || (padapter->bSurpriseRemoved);
137 if (ret)
138 return _FAIL;
139
140 queue_pending = check_pending_xmitbuf(pxmitpriv);
141
142 if (!queue_pending)
143 return _SUCCESS;
144
145 ret = rtw_register_tx_alive(padapter);
146 if (ret != _SUCCESS) {
147 return _SUCCESS;
148 }
149
150 do {
151 queue_empty = rtl8723_dequeue_writeport(padapter);
152 /* dump secondary adapter xmitbuf */
153 } while (!queue_empty);
154
155 rtw_unregister_tx_alive(padapter);
156
157 return _SUCCESS;
158 }
159
160 /*
161 * Description:
162 *Aggregation packets and send to hardware
163 *
164 * Return:
165 *0 Success
166 *-1 Hardware resource(TX FIFO) not ready
167 *-2 Software resource(xmitbuf) not ready
168 */
xmit_xmitframes(struct adapter * padapter,struct xmit_priv * pxmitpriv)169 static s32 xmit_xmitframes(struct adapter *padapter, struct xmit_priv *pxmitpriv)
170 {
171 s32 err, ret;
172 u32 k = 0;
173 struct hw_xmit *hwxmits, *phwxmit;
174 u8 idx, hwentry;
175 struct tx_servq *ptxservq;
176 struct list_head *sta_plist, *sta_phead, *frame_plist, *frame_phead, *tmp;
177 struct xmit_frame *pxmitframe;
178 struct __queue *pframe_queue;
179 struct xmit_buf *pxmitbuf;
180 u32 txlen, max_xmit_len;
181 u8 txdesc_size = TXDESC_SIZE;
182 int inx[4];
183
184 err = 0;
185 hwxmits = pxmitpriv->hwxmits;
186 hwentry = pxmitpriv->hwxmit_entry;
187 ptxservq = NULL;
188 pxmitframe = NULL;
189 pframe_queue = NULL;
190 pxmitbuf = NULL;
191
192 if (padapter->registrypriv.wifi_spec == 1) {
193 for (idx = 0; idx < 4; idx++)
194 inx[idx] = pxmitpriv->wmm_para_seq[idx];
195 } else {
196 inx[0] = 0;
197 inx[1] = 1;
198 inx[2] = 2;
199 inx[3] = 3;
200 }
201
202 /* 0(VO), 1(VI), 2(BE), 3(BK) */
203 for (idx = 0; idx < hwentry; idx++) {
204 phwxmit = hwxmits + inx[idx];
205
206 if (
207 (check_pending_xmitbuf(pxmitpriv)) &&
208 (padapter->mlmepriv.LinkDetectInfo.bHigherBusyTxTraffic)
209 ) {
210 if ((phwxmit->accnt > 0) && (phwxmit->accnt < 5)) {
211 err = -2;
212 break;
213 }
214 }
215
216 max_xmit_len = rtw_hal_get_sdio_tx_max_length(padapter, inx[idx]);
217
218 spin_lock_bh(&pxmitpriv->lock);
219
220 sta_phead = get_list_head(phwxmit->sta_queue);
221 /* because stop_sta_xmit may delete sta_plist at any time */
222 /* so we should add lock here, or while loop can not exit */
223 list_for_each_safe(sta_plist, tmp, sta_phead) {
224 ptxservq = list_entry(sta_plist, struct tx_servq,
225 tx_pending);
226
227 pframe_queue = &ptxservq->sta_pending;
228
229 frame_phead = get_list_head(pframe_queue);
230
231 while (list_empty(frame_phead) == false) {
232 frame_plist = get_next(frame_phead);
233 pxmitframe = container_of(frame_plist, struct xmit_frame, list);
234
235 /* check xmit_buf size enough or not */
236 txlen = txdesc_size + rtw_wlan_pkt_size(pxmitframe);
237 if (!pxmitbuf ||
238 ((_RND(pxmitbuf->len, 8) + txlen) > max_xmit_len) ||
239 (k >= (rtw_hal_sdio_max_txoqt_free_space(padapter) - 1))
240 ) {
241 if (pxmitbuf) {
242 /* pxmitbuf->priv_data will be NULL, and will crash here */
243 if (pxmitbuf->len > 0 &&
244 pxmitbuf->priv_data) {
245 struct xmit_frame *pframe;
246 pframe = (struct xmit_frame *)pxmitbuf->priv_data;
247 pframe->agg_num = k;
248 pxmitbuf->agg_num = k;
249 rtl8723b_update_txdesc(pframe, pframe->buf_addr);
250 rtw_free_xmitframe(pxmitpriv, pframe);
251 pxmitbuf->priv_data = NULL;
252 enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
253 /* can not yield under lock */
254 /* yield(); */
255 } else
256 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
257 }
258
259 pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv);
260 if (!pxmitbuf) {
261 #ifdef DBG_XMIT_BUF
262 netdev_err(padapter->pnetdev,
263 "%s: xmit_buf is not enough!\n",
264 __func__);
265 #endif
266 err = -2;
267 complete(&(pxmitpriv->xmit_comp));
268 break;
269 }
270 k = 0;
271 }
272
273 /* ok to send, remove frame from queue */
274 if (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == true)
275 if (
276 (pxmitframe->attrib.psta->state & WIFI_SLEEP_STATE) &&
277 (pxmitframe->attrib.triggered == 0)
278 )
279 break;
280
281 list_del_init(&pxmitframe->list);
282 ptxservq->qcnt--;
283 phwxmit->accnt--;
284
285 if (k == 0) {
286 pxmitbuf->ff_hwaddr = rtw_get_ff_hwaddr(pxmitframe);
287 pxmitbuf->priv_data = (u8 *)pxmitframe;
288 }
289
290 /* coalesce the xmitframe to xmitbuf */
291 pxmitframe->pxmitbuf = pxmitbuf;
292 pxmitframe->buf_addr = pxmitbuf->ptail;
293
294 ret = rtw_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe);
295 if (ret == _FAIL) {
296 netdev_err(padapter->pnetdev,
297 "%s: coalesce FAIL!",
298 __func__);
299 /* Todo: error handler */
300 } else {
301 k++;
302 if (k != 1)
303 rtl8723b_update_txdesc(pxmitframe, pxmitframe->buf_addr);
304 rtw_count_tx_stats(padapter, pxmitframe, pxmitframe->attrib.last_txcmdsz);
305
306 txlen = txdesc_size + pxmitframe->attrib.last_txcmdsz;
307 pxmitframe->pg_num = (txlen + 127) / 128;
308 pxmitbuf->pg_num += (txlen + 127) / 128;
309 pxmitbuf->ptail += _RND(txlen, 8); /* round to 8 bytes alignment */
310 pxmitbuf->len = _RND(pxmitbuf->len, 8) + txlen;
311 }
312
313 if (k != 1)
314 rtw_free_xmitframe(pxmitpriv, pxmitframe);
315 pxmitframe = NULL;
316 }
317
318 if (list_empty(&pframe_queue->queue))
319 list_del_init(&ptxservq->tx_pending);
320
321 if (err)
322 break;
323 }
324 spin_unlock_bh(&pxmitpriv->lock);
325
326 /* dump xmit_buf to hw tx fifo */
327 if (pxmitbuf) {
328 if (pxmitbuf->len > 0) {
329 struct xmit_frame *pframe;
330 pframe = (struct xmit_frame *)pxmitbuf->priv_data;
331 pframe->agg_num = k;
332 pxmitbuf->agg_num = k;
333 rtl8723b_update_txdesc(pframe, pframe->buf_addr);
334 rtw_free_xmitframe(pxmitpriv, pframe);
335 pxmitbuf->priv_data = NULL;
336 enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
337 yield();
338 } else
339 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
340 pxmitbuf = NULL;
341 }
342
343 if (err)
344 break;
345 }
346
347 return err;
348 }
349
350 /*
351 * Description
352 *Transmit xmitframe from queue
353 *
354 * Return
355 *_SUCCESS ok
356 *_FAIL something error
357 */
rtl8723bs_xmit_handler(struct adapter * padapter)358 static s32 rtl8723bs_xmit_handler(struct adapter *padapter)
359 {
360 struct xmit_priv *pxmitpriv;
361 s32 ret;
362
363
364 pxmitpriv = &padapter->xmitpriv;
365
366 if (wait_for_completion_interruptible(&pxmitpriv->SdioXmitStart)) {
367 netdev_emerg(padapter->pnetdev, "%s: SdioXmitStart fail!\n",
368 __func__);
369 return _FAIL;
370 }
371
372 next:
373 if (
374 (padapter->bDriverStopped) ||
375 (padapter->bSurpriseRemoved)
376 )
377 return _FAIL;
378
379 spin_lock_bh(&pxmitpriv->lock);
380 ret = rtw_txframes_pending(padapter);
381 spin_unlock_bh(&pxmitpriv->lock);
382 if (ret == 0) {
383 return _SUCCESS;
384 }
385
386 /* dequeue frame and write to hardware */
387
388 ret = xmit_xmitframes(padapter, pxmitpriv);
389 if (ret == -2) {
390 /* here sleep 1ms will cause big TP loss of TX */
391 /* from 50+ to 40+ */
392 if (padapter->registrypriv.wifi_spec)
393 msleep(1);
394 else
395 yield();
396 goto next;
397 }
398
399 spin_lock_bh(&pxmitpriv->lock);
400 ret = rtw_txframes_pending(padapter);
401 spin_unlock_bh(&pxmitpriv->lock);
402 if (ret == 1) {
403 goto next;
404 }
405
406 return _SUCCESS;
407 }
408
rtl8723bs_xmit_thread(void * context)409 int rtl8723bs_xmit_thread(void *context)
410 {
411 s32 ret;
412 struct adapter *padapter;
413 struct xmit_priv *pxmitpriv;
414 u8 thread_name[20];
415
416 ret = _SUCCESS;
417 padapter = context;
418 pxmitpriv = &padapter->xmitpriv;
419
420 rtw_sprintf(thread_name, 20, "RTWHALXT-%s", ADPT_ARG(padapter));
421 thread_enter(thread_name);
422
423 do {
424 ret = rtl8723bs_xmit_handler(padapter);
425 if (signal_pending(current)) {
426 flush_signals(current);
427 }
428 } while (_SUCCESS == ret);
429
430 complete(&pxmitpriv->SdioXmitTerminate);
431
432 return 0;
433 }
434
rtl8723bs_mgnt_xmit(struct adapter * padapter,struct xmit_frame * pmgntframe)435 s32 rtl8723bs_mgnt_xmit(
436 struct adapter *padapter, struct xmit_frame *pmgntframe
437 )
438 {
439 s32 ret = _SUCCESS;
440 struct pkt_attrib *pattrib;
441 struct xmit_buf *pxmitbuf;
442 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
443 struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
444 u8 *pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
445 u8 txdesc_size = TXDESC_SIZE;
446
447 pattrib = &pmgntframe->attrib;
448 pxmitbuf = pmgntframe->pxmitbuf;
449
450 rtl8723b_update_txdesc(pmgntframe, pmgntframe->buf_addr);
451
452 pxmitbuf->len = txdesc_size + pattrib->last_txcmdsz;
453 pxmitbuf->pg_num = (pxmitbuf->len + 127) / 128; /* 128 is tx page size */
454 pxmitbuf->ptail = pmgntframe->buf_addr + pxmitbuf->len;
455 pxmitbuf->ff_hwaddr = rtw_get_ff_hwaddr(pmgntframe);
456
457 rtw_count_tx_stats(padapter, pmgntframe, pattrib->last_txcmdsz);
458
459 rtw_free_xmitframe(pxmitpriv, pmgntframe);
460
461 pxmitbuf->priv_data = NULL;
462
463 if (GetFrameSubType(pframe) == WIFI_BEACON) { /* dump beacon directly */
464 ret = rtw_write_port(padapter, pdvobjpriv->Queue2Pipe[pxmitbuf->ff_hwaddr], pxmitbuf->len, (u8 *)pxmitbuf);
465 if (ret != _SUCCESS)
466 rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_WRITE_PORT_ERR);
467
468 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
469 } else
470 enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
471
472 return ret;
473 }
474
475 /*
476 * Description:
477 *Handle xmitframe(packet) come from rtw_xmit()
478 *
479 * Return:
480 *true dump packet directly ok
481 *false enqueue, temporary can't transmit packets to hardware
482 */
rtl8723bs_hal_xmit(struct adapter * padapter,struct xmit_frame * pxmitframe)483 s32 rtl8723bs_hal_xmit(
484 struct adapter *padapter, struct xmit_frame *pxmitframe
485 )
486 {
487 struct xmit_priv *pxmitpriv;
488 s32 err;
489
490
491 pxmitframe->attrib.qsel = pxmitframe->attrib.priority;
492 pxmitpriv = &padapter->xmitpriv;
493
494 if (
495 (pxmitframe->frame_tag == DATA_FRAMETAG) &&
496 (pxmitframe->attrib.ether_type != 0x0806) &&
497 (pxmitframe->attrib.ether_type != 0x888e) &&
498 (pxmitframe->attrib.dhcp_pkt != 1)
499 ) {
500 if (padapter->mlmepriv.LinkDetectInfo.bBusyTraffic)
501 rtw_issue_addbareq_cmd(padapter, pxmitframe);
502 }
503
504 spin_lock_bh(&pxmitpriv->lock);
505 err = rtw_xmitframe_enqueue(padapter, pxmitframe);
506 spin_unlock_bh(&pxmitpriv->lock);
507 if (err != _SUCCESS) {
508 rtw_free_xmitframe(pxmitpriv, pxmitframe);
509
510 pxmitpriv->tx_drop++;
511 return true;
512 }
513
514 complete(&pxmitpriv->SdioXmitStart);
515
516 return false;
517 }
518
rtl8723bs_hal_xmitframe_enqueue(struct adapter * padapter,struct xmit_frame * pxmitframe)519 s32 rtl8723bs_hal_xmitframe_enqueue(
520 struct adapter *padapter, struct xmit_frame *pxmitframe
521 )
522 {
523 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
524 s32 err;
525
526 err = rtw_xmitframe_enqueue(padapter, pxmitframe);
527 if (err != _SUCCESS) {
528 rtw_free_xmitframe(pxmitpriv, pxmitframe);
529
530 pxmitpriv->tx_drop++;
531 } else {
532 complete(&pxmitpriv->SdioXmitStart);
533 }
534
535 return err;
536
537 }
538
539 /*
540 * Return
541 *_SUCCESS start thread ok
542 *_FAIL start thread fail
543 *
544 */
rtl8723bs_init_xmit_priv(struct adapter * padapter)545 s32 rtl8723bs_init_xmit_priv(struct adapter *padapter)
546 {
547 struct xmit_priv *xmitpriv = &padapter->xmitpriv;
548 struct hal_com_data *phal;
549
550
551 phal = GET_HAL_DATA(padapter);
552
553 spin_lock_init(&phal->SdioTxFIFOFreePageLock);
554 init_completion(&xmitpriv->SdioXmitStart);
555 init_completion(&xmitpriv->SdioXmitTerminate);
556
557 return _SUCCESS;
558 }
559
rtl8723bs_free_xmit_priv(struct adapter * padapter)560 void rtl8723bs_free_xmit_priv(struct adapter *padapter)
561 {
562 struct xmit_priv *pxmitpriv;
563 struct xmit_buf *pxmitbuf;
564 struct __queue *pqueue;
565 struct list_head *plist, *phead;
566 struct list_head tmplist;
567
568
569 pxmitpriv = &padapter->xmitpriv;
570 pqueue = &pxmitpriv->pending_xmitbuf_queue;
571 phead = get_list_head(pqueue);
572 INIT_LIST_HEAD(&tmplist);
573
574 spin_lock_bh(&pqueue->lock);
575 if (!list_empty(&pqueue->queue)) {
576 /* Insert tmplist to end of queue, and delete phead */
577 /* then tmplist become head of queue. */
578 list_add_tail(&tmplist, phead);
579 list_del_init(phead);
580 }
581 spin_unlock_bh(&pqueue->lock);
582
583 phead = &tmplist;
584 while (list_empty(phead) == false) {
585 plist = get_next(phead);
586 list_del_init(plist);
587
588 pxmitbuf = container_of(plist, struct xmit_buf, list);
589 rtw_free_xmitframe(pxmitpriv, (struct xmit_frame *)pxmitbuf->priv_data);
590 pxmitbuf->priv_data = NULL;
591 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
592 }
593 }
594