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