1 /******************************************************************************
2 *
3 * Copyright(c) 2015 - 2019 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 _RTL8822BS_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 "../rtl8822b.h" /* rtl8822b_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 pxmitbuf = select_and_dequeue_pending_xmitbuf(adapter);
32
33 if (pxmitbuf == NULL)
34 return _TRUE;
35
36 /* check if hardware tx fifo page is enough */
37 while (rtw_halmac_sdio_tx_allowed(pdvobjpriv, pxmitbuf->pdata, pxmitbuf->len)) {
38 if (RTW_CANNOT_RUN(adapter)) {
39 RTW_INFO("%s: bSurpriseRemoved(write port)\n", __func__);
40 goto free_xmitbuf;
41 }
42
43 polling_num++;
44 /* Only polling (0x7F / 10) times here, since rtw_halmac_sdio_tx_allowed() has polled 10 times within */
45 if (((polling_num % (0x7F / 10))) == 0) {
46 enqueue_pending_xmitbuf_to_head(pxmitpriv, pxmitbuf);
47 rtw_msleep_os(1);
48 return _FALSE;
49 }
50 }
51
52 #ifdef CONFIG_CHECK_LEAVE_LPS
53 #ifdef CONFIG_LPS_CHK_BY_TP
54 if (!adapter_to_pwrctl(adapter)->lps_chk_by_tp)
55 #endif
56 traffic_check_for_leave_lps(adapter, _TRUE, pxmitbuf->agg_num);
57 #endif
58
59 rtw_write_port(adapter, 0, pxmitbuf->len, (u8 *)pxmitbuf);
60
61 free_xmitbuf:
62 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
63
64 #ifdef CONFIG_SDIO_TX_TASKLET
65 tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
66 #endif
67
68 return _FALSE;
69 }
70
71 /*
72 * Description
73 * For MI call.
74 */
rtl8822bs_dequeue_writeport(PADAPTER adapter)75 s32 rtl8822bs_dequeue_writeport(PADAPTER adapter)
76 {
77 return dequeue_writeport(adapter);
78 }
79
80 /*
81 * Description
82 * Transmit xmitbuf to hardware tx fifo
83 *
84 * Return
85 * _SUCCESS ok
86 * _FAIL something error
87 */
rtl8822bs_xmit_buf_handler(PADAPTER adapter)88 s32 rtl8822bs_xmit_buf_handler(PADAPTER adapter)
89 {
90 struct xmit_priv *pxmitpriv;
91 u8 queue_empty, queue_pending;
92 s32 ret;
93
94
95 pxmitpriv = &adapter->xmitpriv;
96
97 ret = _rtw_down_sema(&pxmitpriv->xmit_sema);
98 if (_FAIL == ret) {
99 RTW_ERR("%s: down SdioXmitBufSema fail!\n", __FUNCTION__);
100 return _FAIL;
101 }
102
103 if (RTW_CANNOT_RUN(adapter)) {
104 RTW_DBG(FUNC_ADPT_FMT "- bDriverStopped(%s) bSurpriseRemoved(%s)\n",
105 FUNC_ADPT_ARG(adapter),
106 rtw_is_drv_stopped(adapter) ? "True" : "False",
107 rtw_is_surprise_removed(adapter) ? "True" : "False");
108 return _FAIL;
109 }
110
111 if (rtw_mi_check_pending_xmitbuf(adapter) == 0)
112 return _SUCCESS;
113
114 #ifdef CONFIG_LPS_LCLK
115 ret = rtw_register_tx_alive(adapter);
116 if (ret != _SUCCESS)
117 return _SUCCESS;
118 #endif
119
120 do {
121 queue_empty = rtw_mi_dequeue_writeport(adapter);
122 } while (!queue_empty);
123
124 #ifdef CONFIG_LPS_LCLK
125 rtw_unregister_tx_alive(adapter);
126 #endif
127
128 return _SUCCESS;
129 }
130
131 /*
132 * Description:
133 * Aggregation packets and send to hardware
134 *
135 * Return:
136 * 0 Success
137 * -1 Hardware resource(TX FIFO) not ready
138 * -2 Software resource(xmitbuf) not ready
139 */
xmit_xmitframes(PADAPTER adapter,struct xmit_priv * pxmitpriv)140 static s32 xmit_xmitframes(PADAPTER adapter, struct xmit_priv *pxmitpriv)
141 {
142 s32 err, ret;
143 u32 k = 0;
144 u8 max_agg_num;
145 struct hw_xmit *hwxmits, *phwxmit;
146 u8 no_res, idx, hwentry;
147 _irqL irql;
148 struct tx_servq *ptxservq;
149 _list *sta_plist, *sta_phead, *frame_plist, *frame_phead;
150 struct xmit_frame *pxmitframe;
151 _queue *pframe_queue;
152 struct xmit_buf *pxmitbuf;
153 u32 txlen, max_txbuf_len, max_pg_num;
154 u32 page_size, desc_size;
155 int inx[4];
156 u8 pre_qsel = 0xFF, next_qsel = 0xFF;
157 u8 single_sta_in_queue = _FALSE;
158
159
160 err = 0;
161 no_res = _FALSE;
162 hwxmits = pxmitpriv->hwxmits;
163 hwentry = pxmitpriv->hwxmit_entry;
164 ptxservq = NULL;
165 pxmitframe = NULL;
166 pframe_queue = NULL;
167 pxmitbuf = NULL;
168 max_txbuf_len = MAX_XMITBUF_SZ;
169 max_agg_num = 0xFF;
170 rtw_halmac_get_oqt_size(adapter_to_dvobj(adapter), &max_agg_num);
171 rtw_hal_get_def_var(adapter, HAL_DEF_TX_PAGE_SIZE, &page_size);
172 desc_size = rtl8822b_get_tx_desc_size(adapter);
173
174 if (adapter->registrypriv.wifi_spec == 1) {
175 for (idx = 0; idx < 4; idx++)
176 inx[idx] = pxmitpriv->wmm_para_seq[idx];
177 } else {
178 inx[0] = 0;
179 inx[1] = 1;
180 inx[2] = 2;
181 inx[3] = 3;
182 }
183
184 /* 0(VO), 1(VI), 2(BE), 3(BK) */
185 for (idx = 0; idx < hwentry; idx++) {
186 phwxmit = hwxmits + inx[idx];
187
188 if ((check_pending_xmitbuf(pxmitpriv) == _TRUE)
189 && (adapter->mlmepriv.LinkDetectInfo.bHigherBusyTxTraffic == _TRUE)) {
190 if ((phwxmit->accnt > 0) && (phwxmit->accnt < 5)) {
191 err = -2;
192 break;
193 }
194 }
195
196 rtw_halmac_get_tx_queue_page_num(adapter_to_dvobj(adapter), inx[idx], &max_pg_num);
197
198 _enter_critical_bh(&pxmitpriv->lock, &irql);
199
200 sta_phead = get_list_head(phwxmit->sta_queue);
201 sta_plist = get_next(sta_phead);
202 /*
203 * Because stop_sta_xmit may delete sta_plist at any time,
204 * so we should add lock here, or while loop can not exit
205 */
206
207 single_sta_in_queue = rtw_end_of_queue_search(sta_phead, get_next(sta_plist));
208
209 while (rtw_end_of_queue_search(sta_phead, sta_plist) == _FALSE) {
210 ptxservq = LIST_CONTAINOR(sta_plist, struct tx_servq, tx_pending);
211 sta_plist = get_next(sta_plist);
212
213 #ifdef DBG_XMIT_BUF
214 RTW_INFO("%s idx:%d hwxmit_pkt_num:%d ptxservq_pkt_num:%d\n", __FUNCTION__, idx, phwxmit->accnt, ptxservq->qcnt);
215 RTW_INFO("%s free_xmit_extbuf_cnt=%d free_xmitbuf_cnt=%d free_xmitframe_cnt=%d\n",
216 __FUNCTION__, pxmitpriv->free_xmit_extbuf_cnt, pxmitpriv->free_xmitbuf_cnt,
217 pxmitpriv->free_xmitframe_cnt);
218 #endif
219 pframe_queue = &ptxservq->sta_pending;
220
221 frame_phead = get_list_head(pframe_queue);
222
223 while (rtw_is_list_empty(frame_phead) == _FALSE) {
224 frame_plist = get_next(frame_phead);
225 pxmitframe = LIST_CONTAINOR(frame_plist, struct xmit_frame, list);
226
227 /* check xmit_buf size enough or not */
228 txlen = desc_size + rtw_wlan_pkt_size(pxmitframe);
229 next_qsel = pxmitframe->attrib.qsel;
230 if ((NULL == pxmitbuf)
231 || ((_RND(pxmitbuf->len, 8) + txlen) > max_txbuf_len)
232 || ((pxmitbuf->pg_num + PageNum(txlen, page_size)) > max_pg_num)
233 || (k == max_agg_num)
234 || ((k != 0) && (_FAIL == rtw_hal_busagg_qsel_check(adapter, pre_qsel, next_qsel)))) {
235 if (pxmitbuf) {
236 if (pxmitbuf->len > 0 && pxmitbuf->priv_data) {
237 struct xmit_frame *pframe;
238
239 pframe = (struct xmit_frame *)pxmitbuf->priv_data;
240 pframe->agg_num = k;
241 pxmitbuf->agg_num = k;
242 rtl8822b_update_txdesc(pframe, pframe->buf_addr);
243 rtw_free_xmitframe(pxmitpriv, pframe);
244 pxmitbuf->priv_data = NULL;
245 enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
246
247 if (single_sta_in_queue == _FALSE) {
248 /* break the loop in case there is more than one sta in this ac queue */
249 pxmitbuf = NULL;
250 err = -3;
251 break;
252 }
253 } else
254 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
255 }
256
257 pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv);
258 if (pxmitbuf == NULL) {
259 #if 0
260 RTW_ERR("%s: xmit_buf is not enough!\n", __FUNCTION__);
261 #endif
262 err = -2;
263 #ifdef CONFIG_SDIO_TX_ENABLE_AVAL_INT
264 _rtw_up_sema(&GET_PRIMARY_ADAPTER(adapter)->xmitpriv.xmit_sema);
265 #endif /* CONFIG_SDIO_TX_ENABLE_AVAL_INT */
266 break;
267 }
268 k = 0;
269 }
270
271 /* ok to send, remove frame from queue */
272 #ifdef CONFIG_AP_MODE
273 if (MLME_IS_AP(adapter) || MLME_IS_MESH(adapter)) {
274 if ((pxmitframe->attrib.psta->state & WIFI_SLEEP_STATE)
275 && (pxmitframe->attrib.triggered == 0)) {
276 RTW_INFO("%s: one not triggered pkt in queue when this STA sleep, break and goto next sta\n", __FUNCTION__);
277 break;
278 }
279 }
280 #endif
281 rtw_list_delete(&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(adapter, pxmitframe->pkt, pxmitframe);
295 if (ret == _FAIL) {
296 RTW_ERR("%s: coalesce FAIL!", __FUNCTION__);
297 /* Todo: error handler */
298 } else {
299 k++;
300 if (k != 1)
301 rtl8822b_update_txdesc(pxmitframe, pxmitframe->buf_addr);
302 rtw_count_tx_stats(adapter, pxmitframe, pxmitframe->attrib.last_txcmdsz);
303 pre_qsel = pxmitframe->attrib.qsel;
304 txlen = desc_size + pxmitframe->attrib.last_txcmdsz;
305 pxmitframe->pg_num = PageNum(txlen, page_size);
306 pxmitbuf->pg_num += pxmitframe->pg_num;
307 pxmitbuf->ptail += _RND(txlen, 8); /* round to 8 bytes alignment */
308 pxmitbuf->len = _RND(pxmitbuf->len, 8) + txlen;
309 }
310
311 if (k != 1)
312 rtw_free_xmitframe(pxmitpriv, pxmitframe);
313 pxmitframe = NULL;
314 }
315 #if 0
316 /* dump xmit_buf to hw tx fifo */
317 if (pxmitbuf && (pxmitbuf->len > 0)) {
318 struct xmit_frame *pframe;
319
320 RTW_INFO("STA pxmitbuf->len=%d enqueue\n", pxmitbuf->len);
321
322 pframe = (struct xmit_frame *)pxmitbuf->priv_data;
323 pframe->agg_num = k;
324 pxmitbuf->agg_num = k;
325 rtl8822b_update_txdesc(pframe, pframe->buf_addr);
326 rtw_free_xmitframe(pxmitpriv, pframe);
327 pxmitbuf->priv_data = NULL;
328 enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
329
330 pxmitbuf = NULL;
331 }
332 #endif
333 if (_rtw_queue_empty(pframe_queue) == _TRUE)
334 rtw_list_delete(&ptxservq->tx_pending);
335 else if (err == -3) {
336 /* Re-arrange the order of stations in this ac queue to balance the service for these stations */
337 rtw_list_delete(&ptxservq->tx_pending);
338 rtw_list_insert_tail(&ptxservq->tx_pending, get_list_head(phwxmit->sta_queue));
339 err = 0;
340 }
341
342 if (err)
343 break;
344 }
345 _exit_critical_bh(&pxmitpriv->lock, &irql);
346
347 /* dump xmit_buf to hw tx fifo */
348 if (pxmitbuf) {
349 if (pxmitbuf->len > 0) {
350 struct xmit_frame *pframe;
351
352 pframe = (struct xmit_frame *)pxmitbuf->priv_data;
353 pframe->agg_num = k;
354 pxmitbuf->agg_num = k;
355 rtl8822b_update_txdesc(pframe, pframe->buf_addr);
356 rtw_free_xmitframe(pxmitpriv, pframe);
357 pxmitbuf->priv_data = NULL;
358 enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
359 rtw_yield_os();
360 } else
361 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
362 pxmitbuf = NULL;
363 }
364
365 if (err == -2)
366 break;
367 }
368
369 return err;
370 }
371
372 /*
373 * Description
374 * Transmit xmitframe from queue
375 *
376 * Return
377 * _SUCCESS ok
378 * _FAIL something error
379 */
xmit_handler(PADAPTER adapter)380 static s32 xmit_handler(PADAPTER adapter)
381 {
382 struct xmit_priv *pxmitpriv;
383 s32 ret;
384 _irqL irql;
385
386
387 pxmitpriv = &adapter->xmitpriv;
388
389 ret = _rtw_down_sema(&pxmitpriv->SdioXmitSema);
390 if (_FAIL == ret) {
391 RTW_ERR("%s: down sema fail!\n", __FUNCTION__);
392 return _FAIL;
393 }
394
395 next:
396 if (RTW_CANNOT_RUN(adapter)) {
397 RTW_DBG(FUNC_ADPT_FMT "- bDriverStopped(%s) bSurpriseRemoved(%s)\n",
398 FUNC_ADPT_ARG(adapter),
399 rtw_is_drv_stopped(adapter) ? "True" : "False",
400 rtw_is_surprise_removed(adapter) ? "True" : "False");
401 return _FAIL;
402 }
403
404 _enter_critical_bh(&pxmitpriv->lock, &irql);
405 ret = rtw_txframes_pending(adapter);
406 _exit_critical_bh(&pxmitpriv->lock, &irql);
407 /* All queues are empty! */
408 if (!ret)
409 return _SUCCESS;
410
411 /* Dequeue frame and write to hardware */
412 ret = xmit_xmitframes(adapter, pxmitpriv);
413 if (ret == -2) {
414 _rtw_up_sema(&pxmitpriv->SdioXmitSema);
415 /*
416 * here sleep 1ms will cause big TP loss of TX
417 * from 50+ to 40+
418 */
419 if (adapter->registrypriv.wifi_spec)
420 rtw_msleep_os(1);
421 else
422 #ifdef CONFIG_REDUCE_TX_CPU_LOADING
423 rtw_msleep_os(1);
424 #else
425 #ifdef RTW_XMIT_THREAD_HIGH_PRIORITY_AGG
426 rtw_usleep_os(10);
427 #else
428 rtw_yield_os();
429 #endif
430 #endif
431 goto next;
432 }
433
434 return _SUCCESS;
435 }
436
rtl8822bs_xmit_thread(thread_context context)437 thread_return rtl8822bs_xmit_thread(thread_context context)
438 {
439 s32 ret;
440 PADAPTER adapter;
441 struct xmit_priv *pxmitpriv;
442 u8 thread_name[20] = {0};
443 #ifdef RTW_XMIT_THREAD_HIGH_PRIORITY_AGG
444 #ifdef PLATFORM_LINUX
445 struct sched_param param = { .sched_priority = 1 };
446
447 sched_setscheduler(current, SCHED_FIFO, ¶m);
448 #endif /* PLATFORM_LINUX */
449 #endif /* RTW_XMIT_THREAD_HIGH_PRIORITY_AGG */
450
451
452 ret = _SUCCESS;
453 adapter = (PADAPTER)context;
454 pxmitpriv = &adapter->xmitpriv;
455
456 rtw_sprintf(thread_name, 20, "RTWHALXT-"ADPT_FMT, ADPT_ARG(adapter));
457 thread_enter(thread_name);
458
459 RTW_INFO("start "FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(adapter));
460
461 do {
462 ret = xmit_handler(adapter);
463 flush_signals_thread();
464 } while (_SUCCESS == ret);
465
466 RTW_INFO(FUNC_ADPT_FMT " Exit\n", FUNC_ADPT_ARG(adapter));
467
468 rtw_thread_wait_stop();
469
470 return 0;
471 }
472
473 /*
474 * Description:
475 * Transmit manage frame
476 *
477 * Return:
478 * _SUCCESS ok or enqueue
479 * _FAIL fail
480 */
rtl8822bs_mgnt_xmit(PADAPTER adapter,struct xmit_frame * pmgntframe)481 s32 rtl8822bs_mgnt_xmit(PADAPTER adapter, struct xmit_frame *pmgntframe)
482 {
483 s32 ret = _SUCCESS;
484 struct dvobj_priv *pdvobjpriv;
485 struct xmit_priv *pxmitpriv;
486 struct pkt_attrib *pattrib;
487 struct xmit_buf *pxmitbuf;
488 u32 page_size, desc_size;
489 u16 subtype;
490 u8 *pframe;
491
492
493 pdvobjpriv = adapter_to_dvobj(adapter);
494 pxmitpriv = &adapter->xmitpriv;
495 pattrib = &pmgntframe->attrib;
496 pxmitbuf = pmgntframe->pxmitbuf;
497 rtw_hal_get_def_var(adapter, HAL_DEF_TX_PAGE_SIZE, &page_size);
498 desc_size = rtl8822b_get_tx_desc_size(adapter);
499
500 rtl8822b_update_txdesc(pmgntframe, pmgntframe->buf_addr);
501
502 pxmitbuf->len = desc_size + pattrib->last_txcmdsz;
503 pxmitbuf->pg_num = PageNum(pxmitbuf->len, page_size);
504 pxmitbuf->ptail = pmgntframe->buf_addr + pxmitbuf->len;
505
506 pframe = pmgntframe->buf_addr + desc_size;
507 subtype = get_frame_sub_type(pframe);
508
509 rtw_count_tx_stats(adapter, pmgntframe, pattrib->last_txcmdsz);
510
511 rtw_free_xmitframe(pxmitpriv, pmgntframe);
512 pxmitbuf->priv_data = NULL;
513
514 if (subtype == WIFI_BEACON) {
515 /* dump beacon directly */
516 ret = rtw_write_port(adapter, 0, pxmitbuf->len, (u8 *)pxmitbuf);
517 if (ret != _SUCCESS)
518 rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_WRITE_PORT_ERR);
519
520 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
521 } else
522 enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
523
524 return ret;
525 }
526
527 /*
528 * Description:
529 * Enqueue xmitframe
530 *
531 * Return:
532 * _TRUE enqueue ok
533 * _FALSE fail
534 */
rtl8822bs_hal_xmit_enqueue(PADAPTER adapter,struct xmit_frame * pxmitframe)535 s32 rtl8822bs_hal_xmit_enqueue(PADAPTER adapter, struct xmit_frame *pxmitframe)
536 {
537 struct xmit_priv *pxmitpriv;
538 s32 ret;
539
540
541 pxmitpriv = &adapter->xmitpriv;
542
543 ret = rtw_xmitframe_enqueue(adapter, pxmitframe);
544 if (ret != _SUCCESS) {
545 rtw_free_xmitframe(pxmitpriv, pxmitframe);
546 pxmitpriv->tx_drop++;
547 return _FALSE;
548 }
549
550 #ifdef CONFIG_SDIO_TX_TASKLET
551 tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
552 #else /* !CONFIG_SDIO_TX_TASKLET */
553 _rtw_up_sema(&pxmitpriv->SdioXmitSema);
554 #endif /* !CONFIG_SDIO_TX_TASKLET */
555
556 return _TRUE;
557 }
558
559 /*
560 * Description:
561 * Handle xmitframe(packet) come from rtw_xmit()
562 *
563 * Return:
564 * _TRUE handle packet directly, maybe ok or drop
565 * _FALSE enqueue, temporary can't transmit packets to hardware
566 */
rtl8822bs_hal_xmit(PADAPTER adapter,struct xmit_frame * pxmitframe)567 s32 rtl8822bs_hal_xmit(PADAPTER adapter, struct xmit_frame *pxmitframe)
568 {
569 struct xmit_priv *pxmitpriv;
570 _irqL irql;
571 s32 ret;
572
573
574 pxmitpriv = &adapter->xmitpriv;
575
576 #ifdef CONFIG_80211N_HT
577 if ((pxmitframe->frame_tag == DATA_FRAMETAG)
578 && (pxmitframe->attrib.ether_type != 0x0806)
579 && (pxmitframe->attrib.ether_type != 0x888e)
580 && (pxmitframe->attrib.dhcp_pkt != 1)) {
581 if (adapter->mlmepriv.LinkDetectInfo.bBusyTraffic == _TRUE)
582 rtw_issue_addbareq_cmd(adapter, pxmitframe);
583 }
584 #endif /* CONFIG_80211N_HT */
585
586 _enter_critical_bh(&pxmitpriv->lock, &irql);
587 ret = rtl8822bs_hal_xmit_enqueue(adapter, pxmitframe);
588 _exit_critical_bh(&pxmitpriv->lock, &irql);
589 if (ret != _TRUE) {
590 RTW_INFO("%s: enqueue xmitframe FAIL!\n", __FUNCTION__);
591 return _TRUE;
592 }
593
594 return _FALSE;
595 }
596
597 /*
598 * Return
599 * _SUCCESS start thread ok
600 * _FAIL start thread fail
601 *
602 */
rtl8822bs_init_xmit_priv(PADAPTER adapter)603 s32 rtl8822bs_init_xmit_priv(PADAPTER adapter)
604 {
605 struct xmit_priv *xmitpriv;
606
607
608 xmitpriv = &adapter->xmitpriv;
609
610 _rtw_init_sema(&xmitpriv->SdioXmitSema, 0);
611 rtl8822b_init_xmit_priv(adapter);
612 return _SUCCESS;
613 }
614
rtl8822bs_free_xmit_priv(PADAPTER adapter)615 void rtl8822bs_free_xmit_priv(PADAPTER adapter)
616 {
617 struct xmit_priv *pxmitpriv;
618 struct xmit_buf *pxmitbuf;
619 _queue *pqueue;
620 _list *plist, *phead;
621 _list tmplist;
622 _irqL irql;
623
624
625 pxmitpriv = &adapter->xmitpriv;
626 pqueue = &pxmitpriv->pending_xmitbuf_queue;
627 phead = get_list_head(pqueue);
628 _rtw_init_listhead(&tmplist);
629
630 _enter_critical_bh(&pqueue->lock, &irql);
631 if (_rtw_queue_empty(pqueue) == _FALSE) {
632 /*
633 * Insert tmplist to end of queue, and delete phead
634 * then tmplist become head of queue.
635 */
636 rtw_list_insert_tail(&tmplist, phead);
637 rtw_list_delete(phead);
638 }
639 _exit_critical_bh(&pqueue->lock, &irql);
640
641 phead = &tmplist;
642 while (rtw_is_list_empty(phead) == _FALSE) {
643 plist = get_next(phead);
644 rtw_list_delete(plist);
645
646 pxmitbuf = LIST_CONTAINOR(plist, struct xmit_buf, list);
647 rtw_free_xmitframe(pxmitpriv, (struct xmit_frame *)pxmitbuf->priv_data);
648 pxmitbuf->priv_data = NULL;
649 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
650 }
651 }
652