xref: /OK3568_Linux_fs/external/rkwifibt/drivers/rtl8822cs/hal/rtl8822c/sdio/rtl8822cs_xmit.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
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, &param);
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