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