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 = &padapter->xmitpriv;
124 u8 queue_empty, queue_pending;
125 s32 ret;
126
127 if (wait_for_completion_interruptible(&pxmitpriv->xmit_comp)) {
128 netdev_emerg(padapter->pnetdev,
129 "%s: down SdioXmitBufSema fail!\n", __func__);
130 return _FAIL;
131 }
132
133 ret = (padapter->bDriverStopped) || (padapter->bSurpriseRemoved);
134 if (ret)
135 return _FAIL;
136
137 queue_pending = check_pending_xmitbuf(pxmitpriv);
138
139 if (!queue_pending)
140 return _SUCCESS;
141
142 ret = rtw_register_tx_alive(padapter);
143 if (ret != _SUCCESS) {
144 return _SUCCESS;
145 }
146
147 do {
148 queue_empty = rtl8723_dequeue_writeport(padapter);
149 /* dump secondary adapter xmitbuf */
150 } while (!queue_empty);
151
152 rtw_unregister_tx_alive(padapter);
153
154 return _SUCCESS;
155 }
156
157 /*
158 * Description:
159 *Aggregation packets and send to hardware
160 *
161 * Return:
162 *0 Success
163 *-1 Hardware resource(TX FIFO) not ready
164 *-2 Software resource(xmitbuf) not ready
165 */
xmit_xmitframes(struct adapter * padapter,struct xmit_priv * pxmitpriv)166 static s32 xmit_xmitframes(struct adapter *padapter, struct xmit_priv *pxmitpriv)
167 {
168 s32 err, ret;
169 u32 k = 0;
170 struct hw_xmit *hwxmits, *phwxmit;
171 u8 idx, hwentry;
172 struct tx_servq *ptxservq;
173 struct list_head *sta_plist, *sta_phead, *frame_plist, *frame_phead, *tmp;
174 struct xmit_frame *pxmitframe;
175 struct __queue *pframe_queue;
176 struct xmit_buf *pxmitbuf;
177 u32 txlen, max_xmit_len;
178 u8 txdesc_size = TXDESC_SIZE;
179 int inx[4];
180
181 err = 0;
182 hwxmits = pxmitpriv->hwxmits;
183 hwentry = pxmitpriv->hwxmit_entry;
184 ptxservq = NULL;
185 pxmitframe = NULL;
186 pframe_queue = NULL;
187 pxmitbuf = NULL;
188
189 if (padapter->registrypriv.wifi_spec == 1) {
190 for (idx = 0; idx < 4; idx++)
191 inx[idx] = pxmitpriv->wmm_para_seq[idx];
192 } else {
193 inx[0] = 0;
194 inx[1] = 1;
195 inx[2] = 2;
196 inx[3] = 3;
197 }
198
199 /* 0(VO), 1(VI), 2(BE), 3(BK) */
200 for (idx = 0; idx < hwentry; idx++) {
201 phwxmit = hwxmits + inx[idx];
202
203 if (
204 (check_pending_xmitbuf(pxmitpriv)) &&
205 (padapter->mlmepriv.LinkDetectInfo.bHigherBusyTxTraffic)
206 ) {
207 if ((phwxmit->accnt > 0) && (phwxmit->accnt < 5)) {
208 err = -2;
209 break;
210 }
211 }
212
213 max_xmit_len = rtw_hal_get_sdio_tx_max_length(padapter, inx[idx]);
214
215 spin_lock_bh(&pxmitpriv->lock);
216
217 sta_phead = get_list_head(phwxmit->sta_queue);
218 /* because stop_sta_xmit may delete sta_plist at any time */
219 /* so we should add lock here, or while loop can not exit */
220 list_for_each_safe(sta_plist, tmp, sta_phead) {
221 ptxservq = list_entry(sta_plist, struct tx_servq,
222 tx_pending);
223
224 pframe_queue = &ptxservq->sta_pending;
225
226 frame_phead = get_list_head(pframe_queue);
227
228 while (list_empty(frame_phead) == false) {
229 frame_plist = get_next(frame_phead);
230 pxmitframe = container_of(frame_plist, struct xmit_frame, list);
231
232 /* check xmit_buf size enough or not */
233 txlen = txdesc_size + rtw_wlan_pkt_size(pxmitframe);
234 if (!pxmitbuf ||
235 ((_RND(pxmitbuf->len, 8) + txlen) > max_xmit_len) ||
236 (k >= (rtw_hal_sdio_max_txoqt_free_space(padapter) - 1))
237 ) {
238 if (pxmitbuf) {
239 /* pxmitbuf->priv_data will be NULL, and will crash here */
240 if (pxmitbuf->len > 0 &&
241 pxmitbuf->priv_data) {
242 struct xmit_frame *pframe;
243 pframe = (struct xmit_frame *)pxmitbuf->priv_data;
244 pframe->agg_num = k;
245 pxmitbuf->agg_num = k;
246 rtl8723b_update_txdesc(pframe, pframe->buf_addr);
247 rtw_free_xmitframe(pxmitpriv, pframe);
248 pxmitbuf->priv_data = NULL;
249 enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
250 /* can not yield under lock */
251 /* yield(); */
252 } else
253 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
254 }
255
256 pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv);
257 if (!pxmitbuf) {
258 #ifdef DBG_XMIT_BUF
259 netdev_err(padapter->pnetdev,
260 "%s: xmit_buf is not enough!\n",
261 __func__);
262 #endif
263 err = -2;
264 complete(&(pxmitpriv->xmit_comp));
265 break;
266 }
267 k = 0;
268 }
269
270 /* ok to send, remove frame from queue */
271 if (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == true)
272 if (
273 (pxmitframe->attrib.psta->state & WIFI_SLEEP_STATE) &&
274 (pxmitframe->attrib.triggered == 0)
275 )
276 break;
277
278 list_del_init(&pxmitframe->list);
279 ptxservq->qcnt--;
280 phwxmit->accnt--;
281
282 if (k == 0) {
283 pxmitbuf->ff_hwaddr = rtw_get_ff_hwaddr(pxmitframe);
284 pxmitbuf->priv_data = (u8 *)pxmitframe;
285 }
286
287 /* coalesce the xmitframe to xmitbuf */
288 pxmitframe->pxmitbuf = pxmitbuf;
289 pxmitframe->buf_addr = pxmitbuf->ptail;
290
291 ret = rtw_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe);
292 if (ret == _FAIL) {
293 netdev_err(padapter->pnetdev,
294 "%s: coalesce FAIL!",
295 __func__);
296 /* Todo: error handler */
297 } else {
298 k++;
299 if (k != 1)
300 rtl8723b_update_txdesc(pxmitframe, pxmitframe->buf_addr);
301 rtw_count_tx_stats(padapter, pxmitframe, pxmitframe->attrib.last_txcmdsz);
302
303 txlen = txdesc_size + pxmitframe->attrib.last_txcmdsz;
304 pxmitframe->pg_num = (txlen + 127) / 128;
305 pxmitbuf->pg_num += (txlen + 127) / 128;
306 pxmitbuf->ptail += _RND(txlen, 8); /* round to 8 bytes alignment */
307 pxmitbuf->len = _RND(pxmitbuf->len, 8) + txlen;
308 }
309
310 if (k != 1)
311 rtw_free_xmitframe(pxmitpriv, pxmitframe);
312 pxmitframe = NULL;
313 }
314
315 if (list_empty(&pframe_queue->queue))
316 list_del_init(&ptxservq->tx_pending);
317
318 if (err)
319 break;
320 }
321 spin_unlock_bh(&pxmitpriv->lock);
322
323 /* dump xmit_buf to hw tx fifo */
324 if (pxmitbuf) {
325 if (pxmitbuf->len > 0) {
326 struct xmit_frame *pframe;
327 pframe = (struct xmit_frame *)pxmitbuf->priv_data;
328 pframe->agg_num = k;
329 pxmitbuf->agg_num = k;
330 rtl8723b_update_txdesc(pframe, pframe->buf_addr);
331 rtw_free_xmitframe(pxmitpriv, pframe);
332 pxmitbuf->priv_data = NULL;
333 enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
334 yield();
335 } else
336 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
337 pxmitbuf = NULL;
338 }
339
340 if (err)
341 break;
342 }
343
344 return err;
345 }
346
347 /*
348 * Description
349 *Transmit xmitframe from queue
350 *
351 * Return
352 *_SUCCESS ok
353 *_FAIL something error
354 */
rtl8723bs_xmit_handler(struct adapter * padapter)355 static s32 rtl8723bs_xmit_handler(struct adapter *padapter)
356 {
357 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
358 s32 ret;
359
360 if (wait_for_completion_interruptible(&pxmitpriv->SdioXmitStart)) {
361 netdev_emerg(padapter->pnetdev, "%s: SdioXmitStart fail!\n",
362 __func__);
363 return _FAIL;
364 }
365
366 next:
367 if (
368 (padapter->bDriverStopped) ||
369 (padapter->bSurpriseRemoved)
370 )
371 return _FAIL;
372
373 spin_lock_bh(&pxmitpriv->lock);
374 ret = rtw_txframes_pending(padapter);
375 spin_unlock_bh(&pxmitpriv->lock);
376 if (ret == 0) {
377 return _SUCCESS;
378 }
379
380 /* dequeue frame and write to hardware */
381
382 ret = xmit_xmitframes(padapter, pxmitpriv);
383 if (ret == -2) {
384 /* here sleep 1ms will cause big TP loss of TX */
385 /* from 50+ to 40+ */
386 if (padapter->registrypriv.wifi_spec)
387 msleep(1);
388 else
389 yield();
390 goto next;
391 }
392
393 spin_lock_bh(&pxmitpriv->lock);
394 ret = rtw_txframes_pending(padapter);
395 spin_unlock_bh(&pxmitpriv->lock);
396 if (ret == 1) {
397 goto next;
398 }
399
400 return _SUCCESS;
401 }
402
rtl8723bs_xmit_thread(void * context)403 int rtl8723bs_xmit_thread(void *context)
404 {
405 s32 ret = _SUCCESS;
406 struct adapter *padapter = context;
407 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
408
409 allow_signal(SIGTERM);
410
411 do {
412 ret = rtl8723bs_xmit_handler(padapter);
413 if (signal_pending(current)) {
414 flush_signals(current);
415 }
416 } while (_SUCCESS == ret);
417
418 complete(&pxmitpriv->SdioXmitTerminate);
419
420 return 0;
421 }
422
rtl8723bs_mgnt_xmit(struct adapter * padapter,struct xmit_frame * pmgntframe)423 s32 rtl8723bs_mgnt_xmit(
424 struct adapter *padapter, struct xmit_frame *pmgntframe
425 )
426 {
427 s32 ret = _SUCCESS;
428 struct pkt_attrib *pattrib = &pmgntframe->attrib;
429 struct xmit_buf *pxmitbuf = pmgntframe->pxmitbuf;
430 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
431 struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
432 u8 *pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
433 u8 txdesc_size = TXDESC_SIZE;
434
435 rtl8723b_update_txdesc(pmgntframe, pmgntframe->buf_addr);
436
437 pxmitbuf->len = txdesc_size + pattrib->last_txcmdsz;
438 pxmitbuf->pg_num = (pxmitbuf->len + 127) / 128; /* 128 is tx page size */
439 pxmitbuf->ptail = pmgntframe->buf_addr + pxmitbuf->len;
440 pxmitbuf->ff_hwaddr = rtw_get_ff_hwaddr(pmgntframe);
441
442 rtw_count_tx_stats(padapter, pmgntframe, pattrib->last_txcmdsz);
443
444 rtw_free_xmitframe(pxmitpriv, pmgntframe);
445
446 pxmitbuf->priv_data = NULL;
447
448 if (GetFrameSubType(pframe) == WIFI_BEACON) { /* dump beacon directly */
449 ret = rtw_write_port(padapter, pdvobjpriv->Queue2Pipe[pxmitbuf->ff_hwaddr], pxmitbuf->len, (u8 *)pxmitbuf);
450 if (ret != _SUCCESS)
451 rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_WRITE_PORT_ERR);
452
453 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
454 } else
455 enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
456
457 return ret;
458 }
459
460 /*
461 * Description:
462 *Handle xmitframe(packet) come from rtw_xmit()
463 *
464 * Return:
465 *true dump packet directly ok
466 *false enqueue, temporary can't transmit packets to hardware
467 */
rtl8723bs_hal_xmit(struct adapter * padapter,struct xmit_frame * pxmitframe)468 s32 rtl8723bs_hal_xmit(
469 struct adapter *padapter, struct xmit_frame *pxmitframe
470 )
471 {
472 struct xmit_priv *pxmitpriv;
473 s32 err;
474
475
476 pxmitframe->attrib.qsel = pxmitframe->attrib.priority;
477 pxmitpriv = &padapter->xmitpriv;
478
479 if (
480 (pxmitframe->frame_tag == DATA_FRAMETAG) &&
481 (pxmitframe->attrib.ether_type != 0x0806) &&
482 (pxmitframe->attrib.ether_type != 0x888e) &&
483 (pxmitframe->attrib.dhcp_pkt != 1)
484 ) {
485 if (padapter->mlmepriv.LinkDetectInfo.bBusyTraffic)
486 rtw_issue_addbareq_cmd(padapter, pxmitframe);
487 }
488
489 spin_lock_bh(&pxmitpriv->lock);
490 err = rtw_xmitframe_enqueue(padapter, pxmitframe);
491 spin_unlock_bh(&pxmitpriv->lock);
492 if (err != _SUCCESS) {
493 rtw_free_xmitframe(pxmitpriv, pxmitframe);
494
495 pxmitpriv->tx_drop++;
496 return true;
497 }
498
499 complete(&pxmitpriv->SdioXmitStart);
500
501 return false;
502 }
503
rtl8723bs_hal_xmitframe_enqueue(struct adapter * padapter,struct xmit_frame * pxmitframe)504 s32 rtl8723bs_hal_xmitframe_enqueue(
505 struct adapter *padapter, struct xmit_frame *pxmitframe
506 )
507 {
508 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
509 s32 err;
510
511 err = rtw_xmitframe_enqueue(padapter, pxmitframe);
512 if (err != _SUCCESS) {
513 rtw_free_xmitframe(pxmitpriv, pxmitframe);
514
515 pxmitpriv->tx_drop++;
516 } else {
517 complete(&pxmitpriv->SdioXmitStart);
518 }
519
520 return err;
521
522 }
523
524 /*
525 * Return
526 *_SUCCESS start thread ok
527 *_FAIL start thread fail
528 *
529 */
rtl8723bs_init_xmit_priv(struct adapter * padapter)530 s32 rtl8723bs_init_xmit_priv(struct adapter *padapter)
531 {
532 struct xmit_priv *xmitpriv = &padapter->xmitpriv;
533 struct hal_com_data *phal;
534
535
536 phal = GET_HAL_DATA(padapter);
537
538 spin_lock_init(&phal->SdioTxFIFOFreePageLock);
539 init_completion(&xmitpriv->SdioXmitStart);
540 init_completion(&xmitpriv->SdioXmitTerminate);
541
542 return _SUCCESS;
543 }
544
rtl8723bs_free_xmit_priv(struct adapter * padapter)545 void rtl8723bs_free_xmit_priv(struct adapter *padapter)
546 {
547 struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
548 struct xmit_buf *pxmitbuf;
549 struct __queue *pqueue = &pxmitpriv->pending_xmitbuf_queue;
550 struct list_head *plist, *phead;
551 struct list_head tmplist;
552
553
554 phead = get_list_head(pqueue);
555 INIT_LIST_HEAD(&tmplist);
556
557 spin_lock_bh(&pqueue->lock);
558 if (!list_empty(&pqueue->queue)) {
559 /* Insert tmplist to end of queue, and delete phead */
560 /* then tmplist become head of queue. */
561 list_add_tail(&tmplist, phead);
562 list_del_init(phead);
563 }
564 spin_unlock_bh(&pqueue->lock);
565
566 phead = &tmplist;
567 while (list_empty(phead) == false) {
568 plist = get_next(phead);
569 list_del_init(plist);
570
571 pxmitbuf = container_of(plist, struct xmit_buf, list);
572 rtw_free_xmitframe(pxmitpriv, (struct xmit_frame *)pxmitbuf->priv_data);
573 pxmitbuf->priv_data = NULL;
574 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
575 }
576 }
577