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