xref: /OK3568_Linux_fs/kernel/drivers/net/wireless/rockchip_wlan/rtl8822bs/hal/rtl8822b/sdio/rtl8822bs_xmit.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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, &param);
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