xref: /OK3568_Linux_fs/external/rkwifibt/drivers/rtl8189fs/hal/rtl8188f/sdio/rtl8189fs_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 _RTL8188FS_XMIT_C_
16 
17 #include <rtl8188f_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 		HalQueryTxOQTBufferStatus8188FSdio(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 			RTW_INFO("%s: bDriverStopped(%d) bSurpriseRemoved(%d)!\n"
94 				, __func__
95 				, rtw_is_drv_stopped(padapter)
96 				, rtw_is_surprise_removed(padapter));
97 			goto free_xmitbuf;
98 		}
99 #ifdef CONFIG_SDIO_TX_ENABLE_AVAL_INT
100 		if (!bUpdatePageNum) {
101 			rtw_hal_sdio_avail_page_threshold_en(padapter, PageIdx, pxmitbuf->pg_num);
102 
103 			/* Total number of page is NOT available, so update current FIFO status */
104 			HalQueryTxBufferStatus8188FSdio(padapter);
105 			bUpdatePageNum = _TRUE;
106 			goto query_free_page;
107 		} else {
108 			bUpdatePageNum = _FALSE;
109 			enqueue_pending_xmitbuf_to_head(pxmitpriv, pxmitbuf);
110 			#ifdef DBG_TX_FREE_PAGE
111 			RTW_INFO("DQWP page not enough, len:%d, agg:%d, req %s:%u, cur H:%u, M:%u, L:%u, P:%u\n"
112 				, pxmitbuf->len, pxmitbuf->agg_num
113 				, sdio_tx_queue_str(PageIdx), pxmitbuf->pg_num
114 				, hal_data->SdioTxFIFOFreePage[HI_QUEUE_IDX]
115 				, hal_data->SdioTxFIFOFreePage[MID_QUEUE_IDX]
116 				, hal_data->SdioTxFIFOFreePage[LOW_QUEUE_IDX]
117 				, hal_data->SdioTxFIFOFreePage[PUBLIC_QUEUE_IDX]
118 			);
119 			#endif
120 			return _TRUE;
121 		}
122 #else /* CONFIG_SDIO_TX_ENABLE_AVAL_INT */
123 		polling_num++;
124 		if ((polling_num % 10) == 0) {
125 			enqueue_pending_xmitbuf_to_head(pxmitpriv, pxmitbuf);
126 			#ifdef DBG_TX_FREE_PAGE
127 			RTW_INFO("DQWP FIFO starvation!(%d), len:%u, agg:%u, req %s:%u, cur H:%u, M:%u, L:%u, P:%u\n"
128 				, polling_num, pxmitbuf->len, pxmitbuf->agg_num
129 				, sdio_tx_queue_str(PageIdx), pxmitbuf->pg_num
130 				, hal_data->SdioTxFIFOFreePage[HI_QUEUE_IDX]
131 				, hal_data->SdioTxFIFOFreePage[MID_QUEUE_IDX]
132 				, hal_data->SdioTxFIFOFreePage[LOW_QUEUE_IDX]
133 				, hal_data->SdioTxFIFOFreePage[PUBLIC_QUEUE_IDX]
134 			);
135 			#endif
136 			rtw_usleep_os(50);
137 			return _FALSE;
138 		}
139 
140 		/* Total number of page is NOT available, so update current FIFO status */
141 		HalQueryTxBufferStatus8188FSdio(padapter);
142 		goto query_free_page;
143 #endif /* CONFIG_SDIO_TX_ENABLE_AVAL_INT */
144 	}
145 
146 	if (rtw_sdio_wait_enough_TxOQT_space(padapter, pxmitbuf->agg_num) == _FALSE)
147 		goto free_xmitbuf;
148 
149 #ifdef CONFIG_CHECK_LEAVE_LPS
150 	#ifdef CONFIG_LPS_CHK_BY_TP
151 	if (!adapter_to_pwrctl(padapter)->lps_chk_by_tp)
152 	#endif
153 		traffic_check_for_leave_lps(padapter, _TRUE, pxmitbuf->agg_num);
154 #endif
155 
156 	#ifdef DBG_TX_FREE_PAGE
157 	RTW_INFO("DQWP write, %s:%u\n", sdio_tx_queue_str(PageIdx), pxmitbuf->pg_num);
158 	#endif
159 
160 	rtw_write_port(padapter, deviceId, pxmitbuf->len, (u8 *)pxmitbuf);
161 
162 	rtw_hal_sdio_update_tx_freepage(padapter, PageIdx, pxmitbuf->pg_num);
163 	#ifdef DBG_TX_FREE_PAGE
164 	RTW_INFO("DQWP write done, cur H:%u, M:%u, L:%u, P:%u\n"
165 		, hal_data->SdioTxFIFOFreePage[HI_QUEUE_IDX]
166 		, hal_data->SdioTxFIFOFreePage[MID_QUEUE_IDX]
167 		, hal_data->SdioTxFIFOFreePage[LOW_QUEUE_IDX]
168 		, hal_data->SdioTxFIFOFreePage[PUBLIC_QUEUE_IDX]
169 	);
170 	#endif
171 
172 free_xmitbuf:
173 	/* rtw_free_xmitframe(pxmitpriv, pframe); */
174 	/* pxmitbuf->priv_data = NULL; */
175 	rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
176 	#ifdef SDIO_FREE_XMIT_BUF_SEMA
177 	if (pxmitbuf->buf_tag == XMITBUF_DATA)
178 		rtw_sdio_free_xmitbuf_sema_up(pxmitpriv);
179 	#endif
180 
181 #if 0 /* improve TX/RX throughput balance */
182 	{
183 		PSDIO_DATA psdio;
184 		struct sdio_func *func;
185 		static u8 i = 0;
186 		u32 sdio_hisr;
187 		u8 j;
188 
189 		psdio = &adapter_to_dvobj(padapter)->intf_data;
190 		func = psdio->func;
191 
192 		if (i == 2) {
193 			j = 0;
194 			while (j < 10) {
195 				sdio_hisr = SdioLocalCmd52Read1Byte(padapter, SDIO_REG_HISR);
196 				sdio_hisr &= GET_HAL_DATA(padapter)->sdio_himr;
197 				if (sdio_hisr & SDIO_HISR_RX_REQUEST) {
198 					sdio_claim_host(func);
199 					sd_int_hdl(GET_PRIMARY_ADAPTER(padapter));
200 					sdio_release_host(func);
201 				} else
202 					break;
203 				j++;
204 			}
205 			i = 0;
206 		} else
207 			i++;
208 	}
209 #endif
210 
211 #ifdef CONFIG_SDIO_TX_TASKLET
212 	tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
213 #endif
214 
215 	return _FALSE;
216 }
217 
218 /*
219  * Description
220  *	Transmit xmitbuf to hardware tx fifo
221  *
222  * Return
223  *	_SUCCESS	ok
224  *	_FAIL		something error
225  */
rtl8188fs_xmit_buf_handler(PADAPTER padapter)226 s32 rtl8188fs_xmit_buf_handler(PADAPTER padapter)
227 {
228 	struct xmit_priv *pxmitpriv;
229 	u8	queue_empty;
230 	s32	ret;
231 
232 	pxmitpriv = &padapter->xmitpriv;
233 
234 	ret = _rtw_down_sema(&pxmitpriv->xmit_sema);
235 	if (_FAIL == ret) {
236 		RTW_ERR("%s: down SdioXmitBufSema fail!\n", __FUNCTION__);
237 		return _FAIL;
238 	}
239 
240 	if (RTW_CANNOT_RUN(padapter)) {
241 		RTW_DBG(FUNC_ADPT_FMT "- bDriverStopped(%s) bSurpriseRemoved(%s)\n",
242 			FUNC_ADPT_ARG(padapter),
243 			rtw_is_drv_stopped(padapter) ? "True" : "False",
244 			rtw_is_surprise_removed(padapter) ? "True" : "False");
245 		return _FAIL;
246 	}
247 
248 	if (rtw_mi_check_pending_xmitbuf(padapter) == 0)
249 		return _SUCCESS;
250 
251 #ifdef CONFIG_LPS_LCLK
252 	ret = rtw_register_tx_alive(padapter);
253 	if (ret != _SUCCESS)
254 		return _SUCCESS;
255 #endif
256 
257 	do {
258 		queue_empty = rtw_mi_dequeue_writeport(padapter);
259 	} while (!queue_empty);
260 
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 
298 	err = 0;
299 	no_res = _FALSE;
300 	hwxmits = pxmitpriv->hwxmits;
301 	hwentry = pxmitpriv->hwxmit_entry;
302 	ptxservq = NULL;
303 	pxmitframe = NULL;
304 	pframe_queue = NULL;
305 	pxmitbuf = NULL;
306 
307 	rtw_hal_get_def_var(padapter, HAL_DEF_TX_PAGE_SIZE, &page_size);
308 
309 	if (padapter->registrypriv.wifi_spec == 1) {
310 		for (idx = 0; idx < 4; idx++)
311 			inx[idx] = pxmitpriv->wmm_para_seq[idx];
312 	} else {
313 		inx[0] = 0;
314 		inx[1] = 1;
315 		inx[2] = 2;
316 		inx[3] = 3;
317 	}
318 
319 	/* 0(VO), 1(VI), 2(BE), 3(BK) */
320 	for (idx = 0; idx < hwentry; idx++) {
321 		phwxmit = hwxmits + inx[idx];
322 		#ifdef SDIO_FREE_XMIT_BUF_SEMA
323 		consume = 0;
324 		#endif
325 
326 		if ((check_pending_xmitbuf(pxmitpriv) == _TRUE) && (padapter->mlmepriv.LinkDetectInfo.bHigherBusyTxTraffic == _TRUE)) {
327 			if ((phwxmit->accnt > 0) && (phwxmit->accnt < 5)) {
328 				err = RTW_TX_WAIT_MORE_FRAME;
329 				break;
330 			}
331 		}
332 
333 		max_xmit_len = rtw_hal_get_sdio_tx_max_length(padapter, inx[idx]);
334 
335 		_enter_critical_bh(&pxmitpriv->lock, &irql);
336 
337 		sta_phead = get_list_head(phwxmit->sta_queue);
338 		sta_plist = get_next(sta_phead);
339 		/* because stop_sta_xmit may delete sta_plist at any time */
340 		/* so we should add lock here, or while loop can not exit */
341 
342 		single_sta_in_queue = rtw_end_of_queue_search(sta_phead, get_next(sta_plist));
343 
344 		while (rtw_end_of_queue_search(sta_phead, sta_plist) == _FALSE) {
345 			ptxservq = LIST_CONTAINOR(sta_plist, struct tx_servq, tx_pending);
346 			sta_plist = get_next(sta_plist);
347 
348 #ifdef DBG_XMIT_BUF
349 			RTW_INFO("%s idx:%d hwxmit_pkt_num:%d ptxservq_pkt_num:%d\n", __func__, idx, phwxmit->accnt, ptxservq->qcnt);
350 			RTW_INFO("%s free_xmit_extbuf_cnt=%d free_xmitbuf_cnt=%d free_xmitframe_cnt=%d\n",
351 				__func__, pxmitpriv->free_xmit_extbuf_cnt, pxmitpriv->free_xmitbuf_cnt,
352 				 pxmitpriv->free_xmitframe_cnt);
353 #endif
354 			pframe_queue = &ptxservq->sta_pending;
355 
356 			frame_phead = get_list_head(pframe_queue);
357 
358 			while (rtw_is_list_empty(frame_phead) == _FALSE) {
359 				frame_plist = get_next(frame_phead);
360 				pxmitframe = LIST_CONTAINOR(frame_plist, struct xmit_frame, list);
361 
362 				/* check xmit_buf size enough or not */
363 				txlen = txdesc_size + rtw_wlan_pkt_size(pxmitframe);
364 				next_qsel = pxmitframe->attrib.qsel;
365 				if ((NULL == pxmitbuf)
366 					|| (pxmitbuf->pg_num + PageNum(txlen, page_size) > PageNum(max_xmit_len, page_size))
367 					|| (k >= (rtw_hal_sdio_max_txoqt_free_space(padapter) - 1))
368 					|| ((k != 0) && (_FAIL == rtw_hal_busagg_qsel_check(padapter, pre_qsel, next_qsel)))
369 				) {
370 					if (pxmitbuf) {
371 						/* pxmitbuf->priv_data will be NULL, and will crash here */
372 						if (pxmitbuf->len > 0 && pxmitbuf->priv_data) {
373 							struct xmit_frame *pframe;
374 							pframe = (struct xmit_frame *)pxmitbuf->priv_data;
375 							pframe->agg_num = k;
376 							pxmitbuf->agg_num = k;
377 							rtl8188f_update_txdesc(pframe, pframe->buf_addr);
378 							rtw_free_xmitframe(pxmitpriv, pframe);
379 							pxmitbuf->priv_data = NULL;
380 							enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
381 
382 							/* can not yield under lock */
383 							/* rtw_yield_os(); */
384 							if (single_sta_in_queue == _FALSE) {
385 								/* break the loop in case there is more than one sta in this ac queue */
386 								pxmitbuf = NULL;
387 								err = RTW_TX_BALANCE;
388 								break;
389 							}
390 
391 						} else {
392 							rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
393 							#ifdef SDIO_FREE_XMIT_BUF_SEMA
394 							consume--;
395 							#endif
396 						}
397 					}
398 
399 					pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv);
400 					if (pxmitbuf == NULL) {
401 #ifdef DBG_XMIT_BUF
402 						RTW_ERR("%s: xmit_buf is not enough!\n", __FUNCTION__);
403 #endif
404 						err = RTW_XBUF_UNAVAIL;
405 						break;
406 					}
407 					#ifdef SDIO_FREE_XMIT_BUF_SEMA
408 					consume++;
409 					#endif
410 					k = 0;
411 				}
412 
413 				/* ok to send, remove frame from queue */
414 #ifdef CONFIG_AP_MODE
415 				if (MLME_IS_AP(padapter) || MLME_IS_MESH(padapter)) {
416 					if ((pxmitframe->attrib.psta->state & WIFI_SLEEP_STATE) &&
417 					    (pxmitframe->attrib.triggered == 0)) {
418 						RTW_INFO("%s: one not triggered pkt in queue when this STA sleep,"
419 							" break and goto next sta\n", __func__);
420 						break;
421 					}
422 				}
423 #endif
424 				rtw_list_delete(&pxmitframe->list);
425 				ptxservq->qcnt--;
426 				phwxmit->accnt--;
427 
428 				if (k == 0) {
429 					pxmitbuf->ff_hwaddr = rtw_get_ff_hwaddr(pxmitframe);
430 					pxmitbuf->priv_data = (u8 *)pxmitframe;
431 				}
432 
433 				/* coalesce the xmitframe to xmitbuf */
434 				pxmitframe->pxmitbuf = pxmitbuf;
435 				pxmitframe->buf_addr = pxmitbuf->ptail;
436 
437 				ret = rtw_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe);
438 				if (ret == _FAIL) {
439 					RTW_ERR("%s: coalesce FAIL!", __FUNCTION__);
440 					/* Todo: error handler */
441 				} else {
442 					k++;
443 					if (k != 1)
444 						rtl8188f_update_txdesc(pxmitframe, pxmitframe->buf_addr);
445 					rtw_count_tx_stats(padapter, pxmitframe, pxmitframe->attrib.last_txcmdsz);
446 					pre_qsel = pxmitframe->attrib.qsel;
447 					txlen = txdesc_size + pxmitframe->attrib.last_txcmdsz;
448 					pxmitframe->pg_num = (txlen + 127) / 128;
449 					pxmitbuf->pg_num += (txlen + 127) / 128;
450 					/* if (k != 1) */
451 					/*	((struct xmit_frame*)pxmitbuf->priv_data)->pg_num += pxmitframe->pg_num; */
452 					pxmitbuf->ptail += _RND(txlen, 8); /* round to 8 bytes alignment */
453 					pxmitbuf->len = _RND(pxmitbuf->len, 8) + txlen;
454 				}
455 
456 				if (k != 1)
457 					rtw_free_xmitframe(pxmitpriv, pxmitframe);
458 				pxmitframe = NULL;
459 			}
460 
461 			if (_rtw_queue_empty(pframe_queue) == _TRUE)
462 				rtw_list_delete(&ptxservq->tx_pending);
463 			else if (err == RTW_TX_BALANCE) {
464 				/* Re-arrange the order of stations in this ac queue to balance the service for these stations */
465 				rtw_list_delete(&ptxservq->tx_pending);
466 				rtw_list_insert_tail(&ptxservq->tx_pending, get_list_head(phwxmit->sta_queue));
467 			}
468 
469 			if (err)
470 				break;
471 		}
472 		_exit_critical_bh(&pxmitpriv->lock, &irql);
473 
474 		#ifdef SDIO_FREE_XMIT_BUF_SEMA
475 		#ifdef DBG_SDIO_FREE_XMIT_BUF_SEMA
476 		if (consume)
477 			RTW_INFO(FUNC_ADPT_FMT" acq[%u], consume:%u\n", FUNC_ADPT_ARG(padapter), inx[idx], consume);
478 		#endif
479 		while (consume--)
480 			rtw_sdio_free_xmitbuf_sema_down(pxmitpriv);
481 		#endif
482 
483 		/* dump xmit_buf to hw tx fifo */
484 		if (pxmitbuf) {
485 
486 			if (pxmitbuf->len > 0) {
487 				struct xmit_frame *pframe;
488 				pframe = (struct xmit_frame *)pxmitbuf->priv_data;
489 				pframe->agg_num = k;
490 				pxmitbuf->agg_num = k;
491 				rtl8188f_update_txdesc(pframe, pframe->buf_addr);
492 				rtw_free_xmitframe(pxmitpriv, pframe);
493 				pxmitbuf->priv_data = NULL;
494 				enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
495 				rtw_yield_os();
496 			} else {
497 				rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
498 				#ifdef SDIO_FREE_XMIT_BUF_SEMA
499 				rtw_sdio_free_xmitbuf_sema_up(pxmitpriv);
500 				#endif
501 			}
502 			pxmitbuf = NULL;
503 		}
504 
505 		if (err == RTW_XBUF_UNAVAIL)
506 			break;
507 	}
508 
509 	return err;
510 }
511 
512 /*
513  * Description
514  *	Transmit xmitframe from queue
515  *
516  * Return
517  *	_SUCCESS	ok
518  *	_FAIL		something error
519  */
rtl8188fs_xmit_handler(PADAPTER padapter)520 s32 rtl8188fs_xmit_handler(PADAPTER padapter)
521 {
522 	struct xmit_priv *pxmitpriv;
523 	s32 ret;
524 	_irqL irql;
525 
526 
527 	pxmitpriv = &padapter->xmitpriv;
528 
529 	ret = _rtw_down_sema(&pxmitpriv->SdioXmitSema);
530 	if (_FAIL == ret) {
531 		RTW_ERR("%s: down sema fail!\n", __FUNCTION__);
532 		return _FAIL;
533 	}
534 
535 next:
536 	if (RTW_CANNOT_RUN(padapter)) {
537 		RTW_DBG(FUNC_ADPT_FMT "- bDriverStopped(%s) bSurpriseRemoved(%s)\n",
538 			FUNC_ADPT_ARG(padapter),
539 			rtw_is_drv_stopped(padapter) ? "True" : "False",
540 			rtw_is_surprise_removed(padapter) ? "True" : "False");
541 		return _FAIL;
542 	}
543 
544 	_enter_critical_bh(&pxmitpriv->lock, &irql);
545 	ret = rtw_txframes_pending(padapter);
546 	_exit_critical_bh(&pxmitpriv->lock, &irql);
547 	if (ret == 0)
548 		return _SUCCESS;
549 
550 	/* dequeue frame and write to hardware */
551 
552 	ret = xmit_xmitframes(padapter, pxmitpriv);
553 	if (ret == RTW_XBUF_UNAVAIL
554 		|| ret == RTW_TX_WAIT_MORE_FRAME
555 	) {
556 		#ifdef SDIO_FREE_XMIT_BUF_SEMA
557 		if (ret == RTW_XBUF_UNAVAIL) {
558 			rtw_sdio_free_xmitbuf_sema_down(pxmitpriv);
559 			rtw_sdio_free_xmitbuf_sema_up(pxmitpriv);
560 			goto next;
561 		}
562 		#endif
563 
564 		if (padapter->registrypriv.wifi_spec)
565 			rtw_msleep_os(1);
566 		else {
567 			#ifdef CONFIG_REDUCE_TX_CPU_LOADING
568 			rtw_msleep_os(1);
569 			#else
570 			rtw_yield_os();
571 			#endif
572 		}
573 		goto next;
574 	}
575 
576 	_enter_critical_bh(&pxmitpriv->lock, &irql);
577 	ret = rtw_txframes_pending(padapter);
578 	_exit_critical_bh(&pxmitpriv->lock, &irql);
579 	if (ret == 1) {
580 #ifdef CONFIG_REDUCE_TX_CPU_LOADING
581 		rtw_msleep_os(1);
582 #endif
583 		goto next;
584 	}
585 
586 	return _SUCCESS;
587 }
588 
rtl8188fs_xmit_thread(thread_context context)589 thread_return rtl8188fs_xmit_thread(thread_context context)
590 {
591 	s32 ret;
592 	PADAPTER padapter;
593 	struct xmit_priv *pxmitpriv;
594 	u8 thread_name[20] = {0};
595 
596 
597 	ret = _SUCCESS;
598 	padapter = (PADAPTER)context;
599 	pxmitpriv = &padapter->xmitpriv;
600 
601 	rtw_sprintf(thread_name, 20, "RTWHALXT-"ADPT_FMT, ADPT_ARG(padapter));
602 	thread_enter(thread_name);
603 
604 	RTW_INFO("start "FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
605 
606 	do {
607 		ret = rtl8188fs_xmit_handler(padapter);
608 		flush_signals_thread();
609 	} while (_SUCCESS == ret);
610 
611 	RTW_INFO(FUNC_ADPT_FMT " Exit\n", FUNC_ADPT_ARG(padapter));
612 
613 	rtw_thread_wait_stop();
614 	return 0;
615 
616 }
617 
rtl8188fs_mgnt_xmit(PADAPTER padapter,struct xmit_frame * pmgntframe)618 s32 rtl8188fs_mgnt_xmit(PADAPTER padapter, struct xmit_frame *pmgntframe)
619 {
620 	s32 ret = _SUCCESS;
621 	struct pkt_attrib *pattrib;
622 	struct xmit_buf *pxmitbuf;
623 	struct xmit_priv	*pxmitpriv = &padapter->xmitpriv;
624 	struct dvobj_priv	*pdvobjpriv = adapter_to_dvobj(padapter);
625 	u8 *pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
626 	u8 txdesc_size = TXDESC_SIZE;
627 
628 
629 	pattrib = &pmgntframe->attrib;
630 	pxmitbuf = pmgntframe->pxmitbuf;
631 
632 	rtl8188f_update_txdesc(pmgntframe, pmgntframe->buf_addr);
633 
634 	pxmitbuf->len = txdesc_size + pattrib->last_txcmdsz;
635 	/* pmgntframe->pg_num = (pxmitbuf->len + 127)/128; // 128 is tx page size */
636 	pxmitbuf->pg_num = (pxmitbuf->len + 127) / 128; /* 128 is tx page size */
637 	pxmitbuf->ptail = pmgntframe->buf_addr + pxmitbuf->len;
638 	pxmitbuf->ff_hwaddr = rtw_get_ff_hwaddr(pmgntframe);
639 
640 	rtw_count_tx_stats(padapter, pmgntframe, pattrib->last_txcmdsz);
641 
642 	rtw_free_xmitframe(pxmitpriv, pmgntframe);
643 
644 	pxmitbuf->priv_data = NULL;
645 
646 	if (get_frame_sub_type(pframe) == WIFI_BEACON) { /* dump beacon directly */
647 		ret = rtw_write_port(padapter, pdvobjpriv->Queue2Pipe[pxmitbuf->ff_hwaddr], pxmitbuf->len, (u8 *)pxmitbuf);
648 		if (ret != _SUCCESS)
649 			rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_WRITE_PORT_ERR);
650 
651 		rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
652 	} else
653 		enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
654 
655 	return ret;
656 }
657 
658 /*
659  * Description:
660  *	Handle xmitframe(packet) come from rtw_xmit()
661  *
662  * Return:
663  *	_TRUE	dump packet directly ok
664  *	_FALSE	enqueue, temporary can't transmit packets to hardware
665  */
rtl8188fs_hal_xmit(PADAPTER padapter,struct xmit_frame * pxmitframe)666 s32 rtl8188fs_hal_xmit(PADAPTER padapter, struct xmit_frame *pxmitframe)
667 {
668 	struct xmit_priv *pxmitpriv;
669 	_irqL irql;
670 	s32 err;
671 
672 
673 	pxmitframe->attrib.qsel = pxmitframe->attrib.priority;
674 	pxmitpriv = &padapter->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(padapter, pxmitframe, _TRUE);
682 	}
683 #endif
684 
685 	_enter_critical_bh(&pxmitpriv->lock, &irql);
686 	err = rtw_xmitframe_enqueue(padapter, pxmitframe);
687 	_exit_critical_bh(&pxmitpriv->lock, &irql);
688 	if (err != _SUCCESS) {
689 		rtw_free_xmitframe(pxmitpriv, pxmitframe);
690 
691 		pxmitpriv->tx_drop++;
692 		return _TRUE;
693 	}
694 
695 	_rtw_up_sema(&pxmitpriv->SdioXmitSema);
696 
697 	return _FALSE;
698 }
699 
rtl8188fs_hal_xmitframe_enqueue(_adapter * padapter,struct xmit_frame * pxmitframe)700 s32	rtl8188fs_hal_xmitframe_enqueue(_adapter *padapter, struct xmit_frame *pxmitframe)
701 {
702 	struct xmit_priv	*pxmitpriv = &padapter->xmitpriv;
703 	s32 err;
704 
705 	err = rtw_xmitframe_enqueue(padapter, pxmitframe);
706 	if (err != _SUCCESS) {
707 		rtw_free_xmitframe(pxmitpriv, pxmitframe);
708 
709 		pxmitpriv->tx_drop++;
710 	} else {
711 #ifdef CONFIG_SDIO_TX_TASKLET
712 		tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
713 #else
714 		_rtw_up_sema(&pxmitpriv->SdioXmitSema);
715 #endif
716 	}
717 
718 	return err;
719 
720 }
721 
722 /*
723  * Return
724  *	_SUCCESS	start thread ok
725  *	_FAIL		start thread fail
726  *
727  */
rtl8188fs_init_xmit_priv(PADAPTER padapter)728 s32 rtl8188fs_init_xmit_priv(PADAPTER padapter)
729 {
730 	struct xmit_priv *xmitpriv = &padapter->xmitpriv;
731 	PHAL_DATA_TYPE phal;
732 
733 
734 	phal = GET_HAL_DATA(padapter);
735 
736 	_rtw_spinlock_init(&phal->SdioTxFIFOFreePageLock);
737 	_rtw_init_sema(&xmitpriv->SdioXmitSema, 0);
738 	#ifdef SDIO_FREE_XMIT_BUF_SEMA
739 	_rtw_init_sema(&xmitpriv->sdio_free_xmitbuf_sema, xmitpriv->free_xmitbuf_cnt);
740 	#endif
741 
742 	return _SUCCESS;
743 }
744 
rtl8188fs_free_xmit_priv(PADAPTER padapter)745 void rtl8188fs_free_xmit_priv(PADAPTER padapter)
746 {
747 	PHAL_DATA_TYPE phal;
748 	struct xmit_priv *pxmitpriv;
749 	struct xmit_buf *pxmitbuf;
750 	_queue *pqueue;
751 	_list *plist, *phead;
752 	_list tmplist;
753 	_irqL irql;
754 
755 
756 	phal = GET_HAL_DATA(padapter);
757 	pxmitpriv = &padapter->xmitpriv;
758 	pqueue = &pxmitpriv->pending_xmitbuf_queue;
759 	phead = get_list_head(pqueue);
760 	_rtw_init_listhead(&tmplist);
761 
762 	_enter_critical_bh(&pqueue->lock, &irql);
763 	if (_rtw_queue_empty(pqueue) == _FALSE) {
764 		/* Insert tmplist to end of queue, and delete phead */
765 		/* then tmplist become head of queue. */
766 		rtw_list_insert_tail(&tmplist, phead);
767 		rtw_list_delete(phead);
768 	}
769 	_exit_critical_bh(&pqueue->lock, &irql);
770 
771 	phead = &tmplist;
772 	while (rtw_is_list_empty(phead) == _FALSE) {
773 		plist = get_next(phead);
774 		rtw_list_delete(plist);
775 
776 		pxmitbuf = LIST_CONTAINOR(plist, struct xmit_buf, list);
777 		rtw_free_xmitframe(pxmitpriv, (struct xmit_frame *)pxmitbuf->priv_data);
778 		pxmitbuf->priv_data = NULL;
779 		rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
780 		#ifdef SDIO_FREE_XMIT_BUF_SEMA
781 		if (pxmitbuf->buf_tag == XMITBUF_DATA)
782 			rtw_sdio_free_xmitbuf_sema_up(pxmitpriv);
783 		#endif
784 	}
785 
786 	_rtw_spinlock_free(&phal->SdioTxFIFOFreePageLock);
787 }
788