1 /******************************************************************************
2 *
3 * Copyright(c) 2015 - 2017 Realtek Corporation.
4 *
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
8 *
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
12 * more details.
13 *
14 *****************************************************************************/
15 #define _RTL8822CS_XMIT_C_
16
17 #include <drv_types.h> /* PADAPTER, rtw_xmit.h and etc. */
18 #include <hal_data.h> /* HAL_DATA_TYPE */
19 #include "../../hal_halmac.h" /* rtw_halmac_sdio_tx_allowed() and etc. */
20 #include "../rtl8822c.h" /* rtl8822c_update_txdesc() and etc. */
21
22
dequeue_writeport(PADAPTER adapter)23 static s32 dequeue_writeport(PADAPTER adapter)
24 {
25 struct mlme_priv *pmlmepriv = &adapter->mlmepriv;
26 struct xmit_priv *pxmitpriv = &adapter->xmitpriv;
27 struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(adapter);
28 struct xmit_buf *pxmitbuf;
29 u32 polling_num = 0;
30
31 #ifdef CONFIG_SDIO_MULTI_FUNCTION_COEX
32 if (!ex_hal_sdio_multi_if_bus_available(adapter)) {
33 #if DBG_SDIO_MULTI_FUNCTION_COEX
34 RTW_INFO("%s: TX, SDIO_MULTI_BT\n", __FUNCTION__);
35 #endif
36 /* wait signal instead of sleep? */
37 rtw_usleep_os(10);
38 return _FALSE;
39 }
40 #endif
41
42 pxmitbuf = select_and_dequeue_pending_xmitbuf(adapter);
43
44 if (pxmitbuf == NULL)
45 return _TRUE;
46
47 /* check if hardware tx fifo page is enough */
48 while (rtw_halmac_sdio_tx_allowed(pdvobjpriv, pxmitbuf->pdata, pxmitbuf->len)) {
49 if (RTW_CANNOT_RUN(adapter)) {
50 RTW_INFO("%s: bSurpriseRemoved(write port)\n", __func__);
51 goto free_xmitbuf;
52 }
53
54 polling_num++;
55 /* Only polling (0x7F / 10) times here, since rtw_halmac_sdio_tx_allowed() has polled 10 times within */
56 if (((polling_num % (0x7F / 10))) == 0) {
57 enqueue_pending_xmitbuf_to_head(pxmitpriv, pxmitbuf);
58 rtw_msleep_os(1);
59 return _FALSE;
60 }
61 }
62
63 #ifdef CONFIG_CHECK_LEAVE_LPS
64 #ifdef CONFIG_LPS_CHK_BY_TP
65 if (!adapter_to_pwrctl(adapter)->lps_chk_by_tp)
66 #endif
67 traffic_check_for_leave_lps(adapter, _TRUE, pxmitbuf->agg_num);
68 #endif
69
70 rtw_write_port(adapter, 0, pxmitbuf->len, (u8 *)pxmitbuf);
71
72 free_xmitbuf:
73 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
74 #ifdef SDIO_FREE_XMIT_BUF_SEMA
75 if (pxmitbuf->buf_tag == XMITBUF_DATA)
76 rtw_sdio_free_xmitbuf_sema_up(pxmitpriv);
77 #endif
78
79 #ifdef CONFIG_SDIO_TX_TASKLET
80 tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
81 #endif
82
83 return _FALSE;
84 }
85
86 /*
87 * Description
88 * For MI call.
89 */
rtl8822cs_dequeue_writeport(PADAPTER adapter)90 s32 rtl8822cs_dequeue_writeport(PADAPTER adapter)
91 {
92 return dequeue_writeport(adapter);
93 }
94
95 /*
96 * Description
97 * Transmit xmitbuf to hardware tx fifo
98 *
99 * Return
100 * _SUCCESS ok
101 * _FAIL something error
102 */
rtl8822cs_xmit_buf_handler(PADAPTER adapter)103 s32 rtl8822cs_xmit_buf_handler(PADAPTER adapter)
104 {
105 struct xmit_priv *pxmitpriv;
106 u8 queue_empty, queue_pending;
107 s32 ret;
108
109
110 pxmitpriv = &adapter->xmitpriv;
111
112 ret = _rtw_down_sema(&pxmitpriv->xmit_sema);
113 if (_FAIL == ret) {
114 RTW_ERR("%s: down SdioXmitBufSema fail!\n", __FUNCTION__);
115 return _FAIL;
116 }
117
118 if (RTW_CANNOT_RUN(adapter)) {
119 RTW_DBG(FUNC_ADPT_FMT "- bDriverStopped(%s) bSurpriseRemoved(%s)\n",
120 FUNC_ADPT_ARG(adapter),
121 rtw_is_drv_stopped(adapter) ? "True" : "False",
122 rtw_is_surprise_removed(adapter) ? "True" : "False");
123 return _FAIL;
124 }
125
126 if (rtw_mi_check_pending_xmitbuf(adapter) == 0)
127 return _SUCCESS;
128
129 #ifdef CONFIG_LPS_LCLK
130 ret = rtw_register_tx_alive(adapter);
131 if (ret != _SUCCESS)
132 return _SUCCESS;
133 #endif
134
135 do {
136 queue_empty = rtw_mi_dequeue_writeport(adapter);
137 } while (!queue_empty);
138
139 #ifdef CONFIG_LPS_LCLK
140 rtw_unregister_tx_alive(adapter);
141 #endif
142
143 return _SUCCESS;
144 }
145
146 /*
147 * Description:
148 * Aggregation packets and send to hardware
149 *
150 * Return:
151 * 0 Success
152 * -1 Hardware resource(TX FIFO) not ready
153 * -2 Software resource(xmitbuf) not ready
154 */
xmit_xmitframes(PADAPTER adapter,struct xmit_priv * pxmitpriv)155 static s32 xmit_xmitframes(PADAPTER adapter, struct xmit_priv *pxmitpriv)
156 {
157 s32 err, ret;
158 u32 k = 0;
159 u8 max_agg_num;
160 struct hw_xmit *hwxmits, *phwxmit;
161 u8 no_res, idx, hwentry;
162 _irqL irql;
163 struct tx_servq *ptxservq;
164 _list *sta_plist, *sta_phead, *frame_plist, *frame_phead;
165 struct xmit_frame *pxmitframe;
166 _queue *pframe_queue;
167 struct xmit_buf *pxmitbuf;
168 u32 txlen, max_txbuf_len, max_pg_num;
169 u32 page_size, desc_size;
170 int inx[4];
171 u8 pre_qsel = 0xFF, next_qsel = 0xFF;
172 u8 single_sta_in_queue = _FALSE;
173 #ifdef SDIO_FREE_XMIT_BUF_SEMA
174 u32 consume;
175 #endif
176
177 err = 0;
178 no_res = _FALSE;
179 hwxmits = pxmitpriv->hwxmits;
180 hwentry = pxmitpriv->hwxmit_entry;
181 ptxservq = NULL;
182 pxmitframe = NULL;
183 pframe_queue = NULL;
184 pxmitbuf = NULL;
185 max_txbuf_len = MAX_XMITBUF_SZ;
186 max_agg_num = 0xFF;
187 rtw_halmac_get_oqt_size(adapter_to_dvobj(adapter), &max_agg_num);
188 rtw_hal_get_def_var(adapter, HAL_DEF_TX_PAGE_SIZE, &page_size);
189 desc_size = rtl8822c_get_tx_desc_size(adapter);
190
191 #ifdef CONFIG_RTW_MGMT_QUEUE
192 /* dump management frame directly */
193 do {
194 pxmitframe = rtw_dequeue_mgmt_xframe(pxmitpriv);
195 if (pxmitframe)
196 adapter->hal_func.mgnt_xmit(adapter, pxmitframe);
197 } while (pxmitframe != NULL);
198
199 hwentry--;
200 #endif
201
202 if (adapter->registrypriv.wifi_spec == 1) {
203 for (idx = 0; idx < 4; idx++)
204 inx[idx] = pxmitpriv->wmm_para_seq[idx];
205 } else {
206 inx[0] = 0;
207 inx[1] = 1;
208 inx[2] = 2;
209 inx[3] = 3;
210 }
211
212 /* 0(VO), 1(VI), 2(BE), 3(BK) */
213 for (idx = 0; idx < hwentry; idx++) {
214 phwxmit = hwxmits + inx[idx];
215 #ifdef SDIO_FREE_XMIT_BUF_SEMA
216 consume = 0;
217 #endif
218
219 if ((check_pending_xmitbuf(pxmitpriv) == _TRUE)
220 && (adapter->mlmepriv.LinkDetectInfo.bHigherBusyTxTraffic == _TRUE)) {
221 if ((phwxmit->accnt > 0) && (phwxmit->accnt < 5)) {
222 err = RTW_TX_WAIT_MORE_FRAME;
223 break;
224 }
225 }
226
227 rtw_halmac_get_tx_queue_page_num(adapter_to_dvobj(adapter), inx[idx], &max_pg_num);
228
229 _enter_critical_bh(&pxmitpriv->lock, &irql);
230
231 sta_phead = get_list_head(phwxmit->sta_queue);
232 sta_plist = get_next(sta_phead);
233 /*
234 * Because stop_sta_xmit may delete sta_plist at any time,
235 * so we should add lock here, or while loop can not exit
236 */
237
238 single_sta_in_queue = rtw_end_of_queue_search(sta_phead, get_next(sta_plist));
239
240 while (rtw_end_of_queue_search(sta_phead, sta_plist) == _FALSE) {
241 ptxservq = LIST_CONTAINOR(sta_plist, struct tx_servq, tx_pending);
242 sta_plist = get_next(sta_plist);
243
244 #ifdef DBG_XMIT_BUF
245 RTW_INFO("%s idx:%d hwxmit_pkt_num:%d ptxservq_pkt_num:%d\n", __FUNCTION__, idx, phwxmit->accnt, ptxservq->qcnt);
246 RTW_INFO("%s free_xmit_extbuf_cnt=%d free_xmitbuf_cnt=%d free_xmitframe_cnt=%d\n",
247 __FUNCTION__, pxmitpriv->free_xmit_extbuf_cnt, pxmitpriv->free_xmitbuf_cnt,
248 pxmitpriv->free_xmitframe_cnt);
249 #endif
250 pframe_queue = &ptxservq->sta_pending;
251
252 frame_phead = get_list_head(pframe_queue);
253
254 while (rtw_is_list_empty(frame_phead) == _FALSE) {
255 frame_plist = get_next(frame_phead);
256 pxmitframe = LIST_CONTAINOR(frame_plist, struct xmit_frame, list);
257
258 /* check xmit_buf size enough or not */
259 txlen = desc_size + rtw_wlan_pkt_size(pxmitframe);
260 next_qsel = pxmitframe->attrib.qsel;
261 if ((NULL == pxmitbuf)
262 || ((_RND(pxmitbuf->len, 8) + txlen) > max_txbuf_len)
263 || ((pxmitbuf->pg_num + PageNum(txlen, page_size)) > max_pg_num)
264 || (k == max_agg_num)
265 || ((k != 0) && (_FAIL == rtw_hal_busagg_qsel_check(adapter, pre_qsel, next_qsel)))) {
266 if (pxmitbuf) {
267 if (pxmitbuf->len > 0 && pxmitbuf->priv_data) {
268 struct xmit_frame *pframe;
269
270 pframe = (struct xmit_frame *)pxmitbuf->priv_data;
271 pframe->agg_num = k;
272 pxmitbuf->agg_num = k;
273 rtl8822c_update_txdesc(pframe, pframe->buf_addr);
274 rtw_free_xmitframe(pxmitpriv, pframe);
275 pxmitbuf->priv_data = NULL;
276 enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
277
278 if (single_sta_in_queue == _FALSE) {
279 /* break the loop in case there is more than one sta in this ac queue */
280 pxmitbuf = NULL;
281 err = RTW_TX_BALANCE;
282 break;
283 }
284 } else {
285 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
286 #ifdef SDIO_FREE_XMIT_BUF_SEMA
287 consume--;
288 #endif
289 }
290 }
291
292 pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv);
293 if (pxmitbuf == NULL) {
294 #ifdef DBG_XMIT_BUF
295 RTW_ERR("%s: xmit_buf is not enough!\n", __FUNCTION__);
296 #endif
297 err = RTW_XBUF_UNAVAIL;
298 #ifdef CONFIG_SDIO_TX_ENABLE_AVAL_INT
299 _rtw_up_sema(&GET_PRIMARY_ADAPTER(adapter)->xmitpriv.xmit_sema);
300 #endif
301 break;
302 }
303
304 #ifdef SDIO_FREE_XMIT_BUF_SEMA
305 consume++;
306 #endif
307 k = 0;
308 }
309
310 /* ok to send, remove frame from queue */
311 #ifdef CONFIG_AP_MODE
312 if (MLME_IS_AP(adapter) || MLME_IS_MESH(adapter)) {
313 if ((pxmitframe->attrib.psta->state & WIFI_SLEEP_STATE)
314 && (pxmitframe->attrib.triggered == 0)) {
315 RTW_INFO("%s: one not triggered pkt in queue when this STA sleep, break and goto next sta\n", __FUNCTION__);
316 break;
317 }
318 }
319 #endif
320 rtw_list_delete(&pxmitframe->list);
321 ptxservq->qcnt--;
322 phwxmit->accnt--;
323
324 if (k == 0) {
325 pxmitbuf->ff_hwaddr = rtw_get_ff_hwaddr(pxmitframe);
326 pxmitbuf->priv_data = (u8 *)pxmitframe;
327 }
328
329 /* coalesce the xmitframe to xmitbuf */
330 pxmitframe->pxmitbuf = pxmitbuf;
331 pxmitframe->buf_addr = pxmitbuf->ptail;
332
333 ret = rtw_xmitframe_coalesce(adapter, pxmitframe->pkt, pxmitframe);
334 if (ret == _FAIL) {
335 RTW_ERR("%s: coalesce FAIL!", __FUNCTION__);
336 /* Todo: error handler */
337 } else {
338 k++;
339 if (k != 1)
340 rtl8822c_update_txdesc(pxmitframe, pxmitframe->buf_addr);
341 rtw_count_tx_stats(adapter, pxmitframe, pxmitframe->attrib.last_txcmdsz);
342 pre_qsel = pxmitframe->attrib.qsel;
343 txlen = desc_size + pxmitframe->attrib.last_txcmdsz;
344 pxmitframe->pg_num = PageNum(txlen, page_size);
345 pxmitbuf->pg_num += pxmitframe->pg_num;
346 pxmitbuf->ptail += _RND(txlen, 8); /* round to 8 bytes alignment */
347 pxmitbuf->len = _RND(pxmitbuf->len, 8) + txlen;
348 }
349
350 if (k != 1)
351 rtw_free_xmitframe(pxmitpriv, pxmitframe);
352 pxmitframe = NULL;
353 }
354 #if 0
355 /* dump xmit_buf to hw tx fifo */
356 if (pxmitbuf && (pxmitbuf->len > 0)) {
357 struct xmit_frame *pframe;
358
359 RTW_INFO("STA pxmitbuf->len=%d enqueue\n", pxmitbuf->len);
360
361 pframe = (struct xmit_frame *)pxmitbuf->priv_data;
362 pframe->agg_num = k;
363 pxmitbuf->agg_num = k;
364 rtl8822c_update_txdesc(pframe, pframe->buf_addr);
365 rtw_free_xmitframe(pxmitpriv, pframe);
366 pxmitbuf->priv_data = NULL;
367 enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
368
369 pxmitbuf = NULL;
370 }
371 #endif
372 if (_rtw_queue_empty(pframe_queue) == _TRUE)
373 rtw_list_delete(&ptxservq->tx_pending);
374 else if (err == RTW_TX_BALANCE) {
375 /* Re-arrange the order of stations in this ac queue to balance the service for these stations */
376 rtw_list_delete(&ptxservq->tx_pending);
377 rtw_list_insert_tail(&ptxservq->tx_pending, get_list_head(phwxmit->sta_queue));
378 err = 0;
379 }
380
381 if (err)
382 break;
383 }
384 _exit_critical_bh(&pxmitpriv->lock, &irql);
385
386
387 #ifdef SDIO_FREE_XMIT_BUF_SEMA
388 #ifdef DBG_SDIO_FREE_XMIT_BUF_SEMA
389 if (consume)
390 RTW_INFO(FUNC_ADPT_FMT" acq[%u], consume:%u\n", FUNC_ADPT_ARG(adapter), inx[idx], consume);
391 #endif
392 while (consume--)
393 rtw_sdio_free_xmitbuf_sema_down(pxmitpriv);
394 #endif
395
396 /* dump xmit_buf to hw tx fifo */
397 if (pxmitbuf) {
398 if (pxmitbuf->len > 0) {
399 struct xmit_frame *pframe;
400
401 pframe = (struct xmit_frame *)pxmitbuf->priv_data;
402 pframe->agg_num = k;
403 pxmitbuf->agg_num = k;
404 rtl8822c_update_txdesc(pframe, pframe->buf_addr);
405 rtw_free_xmitframe(pxmitpriv, pframe);
406 pxmitbuf->priv_data = NULL;
407 enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
408 rtw_yield_os();
409 } else {
410 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
411 #ifdef SDIO_FREE_XMIT_BUF_SEMA
412 rtw_sdio_free_xmitbuf_sema_up(pxmitpriv);
413 #endif
414 }
415
416 pxmitbuf = NULL;
417 }
418
419 if (err == RTW_XBUF_UNAVAIL)
420 break;
421 }
422
423 return err;
424 }
425
426 /*
427 * Description
428 * Transmit xmitframe from queue
429 *
430 * Return
431 * _SUCCESS ok
432 * _FAIL something error
433 */
xmit_handler(PADAPTER adapter)434 static s32 xmit_handler(PADAPTER adapter)
435 {
436 struct xmit_priv *pxmitpriv;
437 s32 ret;
438 _irqL irql;
439
440
441 pxmitpriv = &adapter->xmitpriv;
442
443 ret = _rtw_down_sema(&pxmitpriv->SdioXmitSema);
444 if (_FAIL == ret) {
445 RTW_ERR("%s: down sema fail!\n", __FUNCTION__);
446 return _FAIL;
447 }
448
449 next:
450 if (RTW_CANNOT_RUN(adapter)) {
451 RTW_DBG(FUNC_ADPT_FMT "- bDriverStopped(%s) bSurpriseRemoved(%s)\n",
452 FUNC_ADPT_ARG(adapter),
453 rtw_is_drv_stopped(adapter) ? "True" : "False",
454 rtw_is_surprise_removed(adapter) ? "True" : "False");
455 return _FAIL;
456 }
457
458 _enter_critical_bh(&pxmitpriv->lock, &irql);
459 ret = rtw_txframes_pending(adapter);
460 _exit_critical_bh(&pxmitpriv->lock, &irql);
461 /* All queues are empty! */
462 if (!ret)
463 return _SUCCESS;
464
465 /* Dequeue frame and write to hardware */
466 ret = xmit_xmitframes(adapter, pxmitpriv);
467 if ((ret == RTW_XBUF_UNAVAIL) ||
468 (ret == RTW_TX_WAIT_MORE_FRAME)) {
469 #ifdef SDIO_FREE_XMIT_BUF_SEMA
470 if (ret == RTW_XBUF_UNAVAIL) {
471 rtw_sdio_free_xmitbuf_sema_down(pxmitpriv);
472 rtw_sdio_free_xmitbuf_sema_up(pxmitpriv);
473 goto next;
474 }
475 #endif
476
477 /* _rtw_up_sema(&pxmitpriv->SdioXmitSema); */
478 /*
479 * here sleep 1ms will cause big TP loss of TX
480 * from 50+ to 40+
481 */
482 if (adapter->registrypriv.wifi_spec)
483 rtw_msleep_os(1);
484 else
485 #ifdef CONFIG_REDUCE_TX_CPU_LOADING
486 rtw_msleep_os(1);
487 #else
488 #ifdef RTW_XMIT_THREAD_HIGH_PRIORITY_AGG
489 rtw_usleep_os(10);
490 #else
491 rtw_yield_os();
492 #endif
493 #endif
494 goto next;
495 }
496
497 return _SUCCESS;
498 }
499
rtl8822cs_xmit_thread(thread_context context)500 thread_return rtl8822cs_xmit_thread(thread_context context)
501 {
502 s32 ret;
503 PADAPTER adapter;
504 struct xmit_priv *pxmitpriv;
505 u8 thread_name[20] = {0};
506 #ifdef RTW_XMIT_THREAD_HIGH_PRIORITY_AGG
507 #ifdef PLATFORM_LINUX
508 #if (LINUX_VERSION_CODE >= KERNEL_VERSION(5, 9, 0))
509 sched_set_fifo_low(current);
510 #else
511 struct sched_param param = { .sched_priority = 1 };
512
513 sched_setscheduler(current, SCHED_FIFO, ¶m);
514 #endif
515 #endif /* PLATFORM_LINUX */
516 #endif /* RTW_XMIT_THREAD_HIGH_PRIORITY_AGG */
517
518 ret = _SUCCESS;
519 adapter = (PADAPTER)context;
520 pxmitpriv = &adapter->xmitpriv;
521
522 rtw_sprintf(thread_name, 20, "RTWHALXT-"ADPT_FMT, ADPT_ARG(adapter));
523 thread_enter(thread_name);
524
525 RTW_INFO("start "FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(adapter));
526
527 do {
528 ret = xmit_handler(adapter);
529 flush_signals_thread();
530 } while (_SUCCESS == ret);
531
532 RTW_INFO(FUNC_ADPT_FMT " Exit\n", FUNC_ADPT_ARG(adapter));
533
534 rtw_thread_wait_stop();
535
536 return 0;
537 }
538
539 /*
540 * Description:
541 * Transmit manage frame
542 *
543 * Return:
544 * _SUCCESS ok or enqueue
545 * _FAIL fail
546 */
rtl8822cs_mgnt_xmit(PADAPTER adapter,struct xmit_frame * pmgntframe)547 s32 rtl8822cs_mgnt_xmit(PADAPTER adapter, struct xmit_frame *pmgntframe)
548 {
549 s32 ret = _SUCCESS;
550 struct dvobj_priv *pdvobjpriv;
551 struct xmit_priv *pxmitpriv;
552 struct pkt_attrib *pattrib;
553 struct xmit_buf *pxmitbuf;
554 u32 page_size, desc_size;
555 u16 subtype;
556 u8 *pframe;
557
558
559 pdvobjpriv = adapter_to_dvobj(adapter);
560 pxmitpriv = &adapter->xmitpriv;
561 pattrib = &pmgntframe->attrib;
562 pxmitbuf = pmgntframe->pxmitbuf;
563 rtw_hal_get_def_var(adapter, HAL_DEF_TX_PAGE_SIZE, &page_size);
564 desc_size = rtl8822c_get_tx_desc_size(adapter);
565
566 rtl8822c_update_txdesc(pmgntframe, pmgntframe->buf_addr);
567
568 pxmitbuf->len = desc_size + pattrib->last_txcmdsz;
569 pxmitbuf->pg_num = PageNum(pxmitbuf->len, page_size);
570 pxmitbuf->ptail = pmgntframe->buf_addr + pxmitbuf->len;
571
572 pframe = pmgntframe->buf_addr + desc_size;
573 subtype = get_frame_sub_type(pframe);
574
575 rtw_count_tx_stats(adapter, pmgntframe, pattrib->last_txcmdsz);
576
577 rtw_free_xmitframe(pxmitpriv, pmgntframe);
578 pxmitbuf->priv_data = NULL;
579
580 if (subtype == WIFI_BEACON) {
581 /* dump beacon directly */
582 ret = rtw_write_port(adapter, 0, pxmitbuf->len, (u8 *)pxmitbuf);
583 if (ret != _SUCCESS)
584 rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_WRITE_PORT_ERR);
585
586 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
587 } else
588 enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
589
590 return ret;
591 }
592
593 /*
594 * Description:
595 * Enqueue management xmitframe
596 *
597 * Return:
598 * _TRUE enqueue ok
599 * _FALSE fail
600 */
601 #ifdef CONFIG_RTW_MGMT_QUEUE
rtl8822cs_hal_mgmt_xmit_enqueue(PADAPTER adapter,struct xmit_frame * pxmitframe)602 s32 rtl8822cs_hal_mgmt_xmit_enqueue(PADAPTER adapter, struct xmit_frame *pxmitframe)
603 {
604 struct xmit_priv *pxmitpriv;
605 s32 ret;
606
607 pxmitpriv = &adapter->xmitpriv;
608
609 ret = rtw_mgmt_xmitframe_enqueue(adapter, pxmitframe);
610 if (ret != _SUCCESS) {
611 rtw_free_xmitframe(pxmitpriv, pxmitframe);
612 pxmitpriv->tx_drop++;
613 return _FALSE;
614 }
615
616 #ifdef CONFIG_SDIO_TX_TASKLET
617 tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
618 #else
619 _rtw_up_sema(&pxmitpriv->SdioXmitSema);
620 #endif
621
622 return _TRUE;
623 }
624 #endif
625
626 /*
627 * Description:
628 * Enqueue xmitframe
629 *
630 * Return:
631 * _TRUE enqueue ok
632 * _FALSE fail
633 */
rtl8822cs_hal_xmit_enqueue(PADAPTER adapter,struct xmit_frame * pxmitframe)634 s32 rtl8822cs_hal_xmit_enqueue(PADAPTER adapter, struct xmit_frame *pxmitframe)
635 {
636 struct xmit_priv *pxmitpriv;
637 s32 ret;
638
639
640 pxmitpriv = &adapter->xmitpriv;
641
642 ret = rtw_xmitframe_enqueue(adapter, pxmitframe);
643 if (ret != _SUCCESS) {
644 rtw_free_xmitframe(pxmitpriv, pxmitframe);
645 pxmitpriv->tx_drop++;
646 return _FALSE;
647 }
648
649 #ifdef CONFIG_SDIO_TX_TASKLET
650 tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
651 #else /* !CONFIG_SDIO_TX_TASKLET */
652 _rtw_up_sema(&pxmitpriv->SdioXmitSema);
653 #endif /* !CONFIG_SDIO_TX_TASKLET */
654
655 return _TRUE;
656 }
657
658 /*
659 * Description:
660 * Handle xmitframe(packet) come from rtw_xmit()
661 *
662 * Return:
663 * _TRUE handle packet directly, maybe ok or drop
664 * _FALSE enqueue, temporary can't transmit packets to hardware
665 */
rtl8822cs_hal_xmit(PADAPTER adapter,struct xmit_frame * pxmitframe)666 s32 rtl8822cs_hal_xmit(PADAPTER adapter, struct xmit_frame *pxmitframe)
667 {
668 struct xmit_priv *pxmitpriv;
669 _irqL irql;
670 s32 ret;
671
672
673 pxmitframe->attrib.qsel = pxmitframe->attrib.priority;
674 pxmitpriv = &adapter->xmitpriv;
675
676 #ifdef CONFIG_80211N_HT
677 if ((pxmitframe->frame_tag == DATA_FRAMETAG)
678 && (pxmitframe->attrib.ether_type != 0x0806)
679 && (pxmitframe->attrib.ether_type != 0x888e)
680 && (pxmitframe->attrib.dhcp_pkt != 1)) {
681 rtw_issue_addbareq_cmd(adapter, pxmitframe, _TRUE);
682 }
683 #endif /* CONFIG_80211N_HT */
684
685 _enter_critical_bh(&pxmitpriv->lock, &irql);
686 ret = rtl8822cs_hal_xmit_enqueue(adapter, pxmitframe);
687 _exit_critical_bh(&pxmitpriv->lock, &irql);
688 if (ret != _TRUE) {
689 RTW_INFO("%s: enqueue xmitframe FAIL!\n", __FUNCTION__);
690 return _TRUE;
691 }
692
693 return _FALSE;
694 }
695 /*
696 * Return
697 * _SUCCESS start thread ok
698 * _FAIL start thread fail
699 *
700 */
rtl8822cs_init_xmit_priv(PADAPTER adapter)701 s32 rtl8822cs_init_xmit_priv(PADAPTER adapter)
702 {
703 struct xmit_priv *xmitpriv;
704
705
706 xmitpriv = &adapter->xmitpriv;
707
708 _rtw_init_sema(&xmitpriv->SdioXmitSema, 0);
709 #ifdef SDIO_FREE_XMIT_BUF_SEMA
710 _rtw_init_sema(&xmitpriv->sdio_free_xmitbuf_sema,
711 xmitpriv->free_xmitbuf_cnt);
712 #endif
713 rtl8822c_init_xmit_priv(adapter);
714 return _SUCCESS;
715 }
716
rtl8822cs_free_xmit_priv(PADAPTER adapter)717 void rtl8822cs_free_xmit_priv(PADAPTER adapter)
718 {
719 struct xmit_priv *pxmitpriv;
720 struct xmit_buf *pxmitbuf;
721 _queue *pqueue;
722 _list *plist, *phead;
723 _list tmplist;
724 _irqL irql;
725
726
727 pxmitpriv = &adapter->xmitpriv;
728 pqueue = &pxmitpriv->pending_xmitbuf_queue;
729 phead = get_list_head(pqueue);
730 _rtw_init_listhead(&tmplist);
731
732 _enter_critical_bh(&pqueue->lock, &irql);
733 if (_rtw_queue_empty(pqueue) == _FALSE) {
734 /*
735 * Insert tmplist to end of queue, and delete phead
736 * then tmplist become head of queue.
737 */
738 rtw_list_insert_tail(&tmplist, phead);
739 rtw_list_delete(phead);
740 }
741 _exit_critical_bh(&pqueue->lock, &irql);
742
743 phead = &tmplist;
744 while (rtw_is_list_empty(phead) == _FALSE) {
745 plist = get_next(phead);
746 rtw_list_delete(plist);
747
748 pxmitbuf = LIST_CONTAINOR(plist, struct xmit_buf, list);
749 rtw_free_xmitframe(pxmitpriv, (struct xmit_frame *)pxmitbuf->priv_data);
750 pxmitbuf->priv_data = NULL;
751 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
752 #ifdef SDIO_FREE_XMIT_BUF_SEMA
753 if (pxmitbuf->buf_tag == XMITBUF_DATA)
754 rtw_sdio_free_xmitbuf_sema_up(pxmitpriv);
755 #endif
756 }
757 }
758