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