1 // SPDX-License-Identifier: GPL-2.0
2 /******************************************************************************
3  *
4  * Copyright(c) 2007 - 2012 Realtek Corporation. All rights reserved.
5  *
6  ******************************************************************************/
7 #define _RTL8723BS_XMIT_C_
8 
9 #include <drv_types.h>
10 #include <rtw_debug.h>
11 #include <rtl8723b_hal.h>
12 
13 static u8 rtw_sdio_wait_enough_TxOQT_space(struct adapter *padapter, u8 agg_num)
14 {
15 	u32 n = 0;
16 	struct hal_com_data *pHalData = GET_HAL_DATA(padapter);
17 
18 	while (pHalData->SdioTxOQTFreeSpace < agg_num) {
19 		if (
20 			(padapter->bSurpriseRemoved == true) ||
21 			(padapter->bDriverStopped == true)
22 		) {
23 			DBG_871X("%s: bSurpriseRemoved or bDriverStopped (wait TxOQT)\n", __func__);
24 			return false;
25 		}
26 
27 		HalQueryTxOQTBufferStatus8723BSdio(padapter);
28 
29 		if ((++n % 60) == 0) {
30 			if ((n % 300) == 0) {
31 				DBG_871X("%s(%d): QOT free space(%d), agg_num: %d\n",
32 				__func__, n, pHalData->SdioTxOQTFreeSpace, agg_num);
33 			}
34 			msleep(1);
35 			/* yield(); */
36 		}
37 	}
38 
39 	pHalData->SdioTxOQTFreeSpace -= agg_num;
40 
41 	/* if (n > 1) */
42 	/* 	++priv->pshare->nr_out_of_txoqt_space; */
43 
44 	return true;
45 }
46 
47 static s32 rtl8723_dequeue_writeport(struct adapter *padapter)
48 {
49 	struct mlme_priv *pmlmepriv = &padapter->mlmepriv;
50 	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
51 	struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
52 	struct xmit_buf *pxmitbuf;
53 	struct adapter *pri_padapter = padapter;
54 	s32 ret = 0;
55 	u8 PageIdx = 0;
56 	u32 deviceId;
57 	u8 bUpdatePageNum = false;
58 
59 	ret = ret || check_fwstate(pmlmepriv, _FW_UNDER_SURVEY);
60 
61 	if (true == ret)
62 		pxmitbuf = dequeue_pending_xmitbuf_under_survey(pxmitpriv);
63 	else
64 		pxmitbuf = dequeue_pending_xmitbuf(pxmitpriv);
65 
66 	if (pxmitbuf == NULL)
67 		return true;
68 
69 	deviceId = ffaddr2deviceId(pdvobjpriv, pxmitbuf->ff_hwaddr);
70 
71 	/*  translate fifo addr to queue index */
72 	switch (deviceId) {
73 	case WLAN_TX_HIQ_DEVICE_ID:
74 		PageIdx = HI_QUEUE_IDX;
75 		break;
76 
77 	case WLAN_TX_MIQ_DEVICE_ID:
78 		PageIdx = MID_QUEUE_IDX;
79 		break;
80 
81 	case WLAN_TX_LOQ_DEVICE_ID:
82 		PageIdx = LOW_QUEUE_IDX;
83 		break;
84 	}
85 
86 query_free_page:
87 	/*  check if hardware tx fifo page is enough */
88 	if (false == rtw_hal_sdio_query_tx_freepage(pri_padapter, PageIdx, pxmitbuf->pg_num)) {
89 		if (!bUpdatePageNum) {
90 			/*  Total number of page is NOT available, so update current FIFO status */
91 			HalQueryTxBufferStatus8723BSdio(padapter);
92 			bUpdatePageNum = true;
93 			goto query_free_page;
94 		} else {
95 			bUpdatePageNum = false;
96 			enqueue_pending_xmitbuf_to_head(pxmitpriv, pxmitbuf);
97 			return true;
98 		}
99 	}
100 
101 	if (
102 		(padapter->bSurpriseRemoved == true) ||
103 		(padapter->bDriverStopped == true)
104 	) {
105 		RT_TRACE(
106 			_module_hal_xmit_c_,
107 			_drv_notice_,
108 			("%s: bSurpriseRemoved(write port)\n", __func__)
109 		);
110 		goto free_xmitbuf;
111 	}
112 
113 	if (rtw_sdio_wait_enough_TxOQT_space(padapter, pxmitbuf->agg_num) == false)
114 		goto free_xmitbuf;
115 
116 	traffic_check_for_leave_lps(padapter, true, pxmitbuf->agg_num);
117 
118 	rtw_write_port(padapter, deviceId, pxmitbuf->len, (u8 *)pxmitbuf);
119 
120 	rtw_hal_sdio_update_tx_freepage(pri_padapter, PageIdx, pxmitbuf->pg_num);
121 
122 free_xmitbuf:
123 	/* rtw_free_xmitframe(pxmitpriv, pframe); */
124 	/* pxmitbuf->priv_data = NULL; */
125 	rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
126 
127 #ifdef CONFIG_SDIO_TX_TASKLET
128 	tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
129 #endif
130 
131 	return _FAIL;
132 }
133 
134 /*
135  * Description
136  *Transmit xmitbuf to hardware tx fifo
137  *
138  * Return
139  *_SUCCESS	ok
140  *_FAIL		something error
141  */
142 s32 rtl8723bs_xmit_buf_handler(struct adapter *padapter)
143 {
144 	struct xmit_priv *pxmitpriv;
145 	u8 queue_empty, queue_pending;
146 	s32 ret;
147 
148 
149 	pxmitpriv = &padapter->xmitpriv;
150 
151 	if (wait_for_completion_interruptible(&pxmitpriv->xmit_comp)) {
152 		DBG_871X_LEVEL(_drv_emerg_, "%s: down SdioXmitBufSema fail!\n", __func__);
153 		return _FAIL;
154 	}
155 
156 	ret = (padapter->bDriverStopped == true) || (padapter->bSurpriseRemoved == true);
157 	if (ret) {
158 		RT_TRACE(
159 			_module_hal_xmit_c_,
160 			_drv_err_,
161 			(
162 				"%s: bDriverStopped(%d) bSurpriseRemoved(%d)!\n",
163 				__func__,
164 				padapter->bDriverStopped,
165 				padapter->bSurpriseRemoved
166 			)
167 		);
168 		return _FAIL;
169 	}
170 
171 	queue_pending = check_pending_xmitbuf(pxmitpriv);
172 
173 	if (queue_pending == false)
174 		return _SUCCESS;
175 
176 	ret = rtw_register_tx_alive(padapter);
177 	if (ret != _SUCCESS) {
178 		return _SUCCESS;
179 	}
180 
181 	do {
182 		queue_empty = rtl8723_dequeue_writeport(padapter);
183 /* 	dump secondary adapter xmitbuf */
184 	} while (!queue_empty);
185 
186 	rtw_unregister_tx_alive(padapter);
187 
188 	return _SUCCESS;
189 }
190 
191 /*
192  * Description:
193  *Aggregation packets and send to hardware
194  *
195  * Return:
196  *0	Success
197  *-1	Hardware resource(TX FIFO) not ready
198  *-2	Software resource(xmitbuf) not ready
199  */
200 static s32 xmit_xmitframes(struct adapter *padapter, struct xmit_priv *pxmitpriv)
201 {
202 	s32 err, ret;
203 	u32 k = 0;
204 	struct hw_xmit *hwxmits, *phwxmit;
205 	u8 no_res, idx, hwentry;
206 	struct tx_servq *ptxservq;
207 	struct list_head *sta_plist, *sta_phead, *frame_plist, *frame_phead;
208 	struct xmit_frame *pxmitframe;
209 	struct __queue *pframe_queue;
210 	struct xmit_buf *pxmitbuf;
211 	u32 txlen, max_xmit_len;
212 	u8 txdesc_size = TXDESC_SIZE;
213 	int inx[4];
214 
215 	err = 0;
216 	no_res = false;
217 	hwxmits = pxmitpriv->hwxmits;
218 	hwentry = pxmitpriv->hwxmit_entry;
219 	ptxservq = NULL;
220 	pxmitframe = NULL;
221 	pframe_queue = NULL;
222 	pxmitbuf = NULL;
223 
224 	if (padapter->registrypriv.wifi_spec == 1) {
225 		for (idx = 0; idx < 4; idx++)
226 			inx[idx] = pxmitpriv->wmm_para_seq[idx];
227 	} else {
228 		inx[0] = 0;
229 		inx[1] = 1;
230 		inx[2] = 2;
231 		inx[3] = 3;
232 	}
233 
234 	/*  0(VO), 1(VI), 2(BE), 3(BK) */
235 	for (idx = 0; idx < hwentry; idx++) {
236 		phwxmit = hwxmits + inx[idx];
237 
238 		if (
239 			(check_pending_xmitbuf(pxmitpriv) == true) &&
240 			(padapter->mlmepriv.LinkDetectInfo.bHigherBusyTxTraffic == true)
241 		) {
242 			if ((phwxmit->accnt > 0) && (phwxmit->accnt < 5)) {
243 				err = -2;
244 				break;
245 			}
246 		}
247 
248 		max_xmit_len = rtw_hal_get_sdio_tx_max_length(padapter, inx[idx]);
249 
250 		spin_lock_bh(&pxmitpriv->lock);
251 
252 		sta_phead = get_list_head(phwxmit->sta_queue);
253 		sta_plist = get_next(sta_phead);
254 		/* because stop_sta_xmit may delete sta_plist at any time */
255 		/* so we should add lock here, or while loop can not exit */
256 		while (sta_phead != sta_plist) {
257 			ptxservq = LIST_CONTAINOR(sta_plist, struct tx_servq, tx_pending);
258 			sta_plist = get_next(sta_plist);
259 
260 #ifdef DBG_XMIT_BUF
261 			DBG_871X(
262 				"%s idx:%d hwxmit_pkt_num:%d ptxservq_pkt_num:%d\n",
263 				__func__,
264 				idx,
265 				phwxmit->accnt,
266 				ptxservq->qcnt
267 			);
268 			DBG_871X(
269 				"%s free_xmit_extbuf_cnt =%d free_xmitbuf_cnt =%d free_xmitframe_cnt =%d\n",
270 				__func__,
271 				pxmitpriv->free_xmit_extbuf_cnt,
272 				pxmitpriv->free_xmitbuf_cnt,
273 				pxmitpriv->free_xmitframe_cnt
274 			);
275 #endif
276 			pframe_queue = &ptxservq->sta_pending;
277 
278 			frame_phead = get_list_head(pframe_queue);
279 
280 			while (list_empty(frame_phead) == false) {
281 				frame_plist = get_next(frame_phead);
282 				pxmitframe = LIST_CONTAINOR(frame_plist, struct xmit_frame, list);
283 
284 				/*  check xmit_buf size enough or not */
285 				txlen = txdesc_size + rtw_wlan_pkt_size(pxmitframe);
286 				if (
287 					(NULL == pxmitbuf) ||
288 					((_RND(pxmitbuf->len, 8) + txlen) > max_xmit_len) ||
289 					(k >= (rtw_hal_sdio_max_txoqt_free_space(padapter)-1))
290 				) {
291 					if (pxmitbuf) {
292 						/* pxmitbuf->priv_data will be NULL, and will crash here */
293 						if (pxmitbuf->len > 0 &&
294 						    pxmitbuf->priv_data) {
295 							struct xmit_frame *pframe;
296 							pframe = (struct xmit_frame *)pxmitbuf->priv_data;
297 							pframe->agg_num = k;
298 							pxmitbuf->agg_num = k;
299 							rtl8723b_update_txdesc(pframe, pframe->buf_addr);
300 							rtw_free_xmitframe(pxmitpriv, pframe);
301 							pxmitbuf->priv_data = NULL;
302 							enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
303 							/* can not yield under lock */
304 							/* yield(); */
305 						} else
306 							rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
307 					}
308 
309 					pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv);
310 					if (pxmitbuf == NULL) {
311 #ifdef DBG_XMIT_BUF
312 						DBG_871X_LEVEL(_drv_err_, "%s: xmit_buf is not enough!\n", __func__);
313 #endif
314 						err = -2;
315 						complete(&(pxmitpriv->xmit_comp));
316 						break;
317 					}
318 					k = 0;
319 				}
320 
321 				/*  ok to send, remove frame from queue */
322 				if (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == true) {
323 					if (
324 						(pxmitframe->attrib.psta->state & WIFI_SLEEP_STATE) &&
325 						(pxmitframe->attrib.triggered == 0)
326 					) {
327 						DBG_871X(
328 							"%s: one not triggered pkt in queue when this STA sleep,"
329 							" break and goto next sta\n",
330 							__func__
331 						);
332 						break;
333 					}
334 				}
335 
336 				list_del_init(&pxmitframe->list);
337 				ptxservq->qcnt--;
338 				phwxmit->accnt--;
339 
340 				if (k == 0) {
341 					pxmitbuf->ff_hwaddr = rtw_get_ff_hwaddr(pxmitframe);
342 					pxmitbuf->priv_data = (u8 *)pxmitframe;
343 				}
344 
345 				/*  coalesce the xmitframe to xmitbuf */
346 				pxmitframe->pxmitbuf = pxmitbuf;
347 				pxmitframe->buf_addr = pxmitbuf->ptail;
348 
349 				ret = rtw_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe);
350 				if (ret == _FAIL) {
351 					DBG_871X_LEVEL(_drv_err_, "%s: coalesce FAIL!", __func__);
352 					/*  Todo: error handler */
353 				} else {
354 					k++;
355 					if (k != 1)
356 						rtl8723b_update_txdesc(pxmitframe, pxmitframe->buf_addr);
357 					rtw_count_tx_stats(padapter, pxmitframe, pxmitframe->attrib.last_txcmdsz);
358 
359 					txlen = txdesc_size + pxmitframe->attrib.last_txcmdsz;
360 					pxmitframe->pg_num = (txlen + 127)/128;
361 					pxmitbuf->pg_num += (txlen + 127)/128;
362 				    /* if (k != 1) */
363 					/* 	((struct xmit_frame*)pxmitbuf->priv_data)->pg_num += pxmitframe->pg_num; */
364 					pxmitbuf->ptail += _RND(txlen, 8); /*  round to 8 bytes alignment */
365 					pxmitbuf->len = _RND(pxmitbuf->len, 8) + txlen;
366 				}
367 
368 				if (k != 1)
369 					rtw_free_xmitframe(pxmitpriv, pxmitframe);
370 				pxmitframe = NULL;
371 			}
372 
373 			if (list_empty(&pframe_queue->queue))
374 				list_del_init(&ptxservq->tx_pending);
375 
376 			if (err)
377 				break;
378 		}
379 		spin_unlock_bh(&pxmitpriv->lock);
380 
381 		/*  dump xmit_buf to hw tx fifo */
382 		if (pxmitbuf) {
383 			RT_TRACE(_module_hal_xmit_c_, _drv_info_, ("pxmitbuf->len =%d enqueue\n", pxmitbuf->len));
384 
385 			if (pxmitbuf->len > 0) {
386 				struct xmit_frame *pframe;
387 				pframe = (struct xmit_frame *)pxmitbuf->priv_data;
388 				pframe->agg_num = k;
389 				pxmitbuf->agg_num = k;
390 				rtl8723b_update_txdesc(pframe, pframe->buf_addr);
391 				rtw_free_xmitframe(pxmitpriv, pframe);
392 				pxmitbuf->priv_data = NULL;
393 				enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
394 				yield();
395 			} else
396 				rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
397 			pxmitbuf = NULL;
398 		}
399 
400 		if (err)
401 			break;
402 	}
403 
404 	return err;
405 }
406 
407 /*
408  * Description
409  *Transmit xmitframe from queue
410  *
411  * Return
412  *_SUCCESS	ok
413  *_FAIL		something error
414  */
415 static s32 rtl8723bs_xmit_handler(struct adapter *padapter)
416 {
417 	struct xmit_priv *pxmitpriv;
418 	s32 ret;
419 
420 
421 	pxmitpriv = &padapter->xmitpriv;
422 
423 	if (wait_for_completion_interruptible(&pxmitpriv->SdioXmitStart)) {
424 		DBG_871X_LEVEL(_drv_emerg_, "%s: SdioXmitStart fail!\n", __func__);
425 		return _FAIL;
426 	}
427 
428 next:
429 	if (
430 		(padapter->bDriverStopped == true) ||
431 		(padapter->bSurpriseRemoved == true)
432 	) {
433 		RT_TRACE(
434 			_module_hal_xmit_c_,
435 			_drv_notice_,
436 			(
437 				"%s: bDriverStopped(%d) bSurpriseRemoved(%d)\n",
438 				__func__,
439 				padapter->bDriverStopped,
440 				padapter->bSurpriseRemoved
441 			)
442 		);
443 		return _FAIL;
444 	}
445 
446 	spin_lock_bh(&pxmitpriv->lock);
447 	ret = rtw_txframes_pending(padapter);
448 	spin_unlock_bh(&pxmitpriv->lock);
449 	if (ret == 0) {
450 		return _SUCCESS;
451 	}
452 
453 	/*  dequeue frame and write to hardware */
454 
455 	ret = xmit_xmitframes(padapter, pxmitpriv);
456 	if (ret == -2) {
457 		/* here sleep 1ms will cause big TP loss of TX */
458 		/* from 50+ to 40+ */
459 		if (padapter->registrypriv.wifi_spec)
460 			msleep(1);
461 		else
462 			yield();
463 		goto next;
464 	}
465 
466 	spin_lock_bh(&pxmitpriv->lock);
467 	ret = rtw_txframes_pending(padapter);
468 	spin_unlock_bh(&pxmitpriv->lock);
469 	if (ret == 1) {
470 		goto next;
471 	}
472 
473 	return _SUCCESS;
474 }
475 
476 int rtl8723bs_xmit_thread(void *context)
477 {
478 	s32 ret;
479 	struct adapter *padapter;
480 	struct xmit_priv *pxmitpriv;
481 	u8 thread_name[20] = "RTWHALXT";
482 
483 
484 	ret = _SUCCESS;
485 	padapter = context;
486 	pxmitpriv = &padapter->xmitpriv;
487 
488 	rtw_sprintf(thread_name, 20, "%s-"ADPT_FMT, thread_name, ADPT_ARG(padapter));
489 	thread_enter(thread_name);
490 
491 	DBG_871X("start "FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
492 
493 	do {
494 		ret = rtl8723bs_xmit_handler(padapter);
495 		if (signal_pending(current)) {
496 			flush_signals(current);
497 		}
498 	} while (_SUCCESS == ret);
499 
500 	complete(&pxmitpriv->SdioXmitTerminate);
501 
502 	RT_TRACE(_module_hal_xmit_c_, _drv_notice_, ("-%s\n", __func__));
503 
504 	thread_exit();
505 }
506 
507 s32 rtl8723bs_mgnt_xmit(
508 	struct adapter *padapter, struct xmit_frame *pmgntframe
509 )
510 {
511 	s32 ret = _SUCCESS;
512 	struct pkt_attrib *pattrib;
513 	struct xmit_buf *pxmitbuf;
514 	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
515 	struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
516 	u8 *pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
517 	u8 txdesc_size = TXDESC_SIZE;
518 
519 	RT_TRACE(_module_hal_xmit_c_, _drv_info_, ("+%s\n", __func__));
520 
521 	pattrib = &pmgntframe->attrib;
522 	pxmitbuf = pmgntframe->pxmitbuf;
523 
524 	rtl8723b_update_txdesc(pmgntframe, pmgntframe->buf_addr);
525 
526 	pxmitbuf->len = txdesc_size + pattrib->last_txcmdsz;
527 	pxmitbuf->pg_num = (pxmitbuf->len + 127)/128; /*  128 is tx page size */
528 	pxmitbuf->ptail = pmgntframe->buf_addr + pxmitbuf->len;
529 	pxmitbuf->ff_hwaddr = rtw_get_ff_hwaddr(pmgntframe);
530 
531 	rtw_count_tx_stats(padapter, pmgntframe, pattrib->last_txcmdsz);
532 
533 	rtw_free_xmitframe(pxmitpriv, pmgntframe);
534 
535 	pxmitbuf->priv_data = NULL;
536 
537 	if (GetFrameSubType(pframe) == WIFI_BEACON) { /* dump beacon directly */
538 		ret = rtw_write_port(padapter, pdvobjpriv->Queue2Pipe[pxmitbuf->ff_hwaddr], pxmitbuf->len, (u8 *)pxmitbuf);
539 		if (ret != _SUCCESS)
540 			rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_WRITE_PORT_ERR);
541 
542 		rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
543 	} else
544 		enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
545 
546 	return ret;
547 }
548 
549 /*
550  * Description:
551  *Handle xmitframe(packet) come from rtw_xmit()
552  *
553  * Return:
554  *true	dump packet directly ok
555  *false	enqueue, temporary can't transmit packets to hardware
556  */
557 s32 rtl8723bs_hal_xmit(
558 	struct adapter *padapter, struct xmit_frame *pxmitframe
559 )
560 {
561 	struct xmit_priv *pxmitpriv;
562 	s32 err;
563 
564 
565 	pxmitframe->attrib.qsel = pxmitframe->attrib.priority;
566 	pxmitpriv = &padapter->xmitpriv;
567 
568 	if (
569 		(pxmitframe->frame_tag == DATA_FRAMETAG) &&
570 		(pxmitframe->attrib.ether_type != 0x0806) &&
571 		(pxmitframe->attrib.ether_type != 0x888e) &&
572 		(pxmitframe->attrib.dhcp_pkt != 1)
573 	) {
574 		if (padapter->mlmepriv.LinkDetectInfo.bBusyTraffic == true)
575 			rtw_issue_addbareq_cmd(padapter, pxmitframe);
576 	}
577 
578 	spin_lock_bh(&pxmitpriv->lock);
579 	err = rtw_xmitframe_enqueue(padapter, pxmitframe);
580 	spin_unlock_bh(&pxmitpriv->lock);
581 	if (err != _SUCCESS) {
582 		RT_TRACE(_module_hal_xmit_c_, _drv_err_, ("rtl8723bs_hal_xmit: enqueue xmitframe fail\n"));
583 		rtw_free_xmitframe(pxmitpriv, pxmitframe);
584 
585 		pxmitpriv->tx_drop++;
586 		return true;
587 	}
588 
589 	complete(&pxmitpriv->SdioXmitStart);
590 
591 	return false;
592 }
593 
594 s32	rtl8723bs_hal_xmitframe_enqueue(
595 	struct adapter *padapter, struct xmit_frame *pxmitframe
596 )
597 {
598 	struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
599 	s32 err;
600 
601 	err = rtw_xmitframe_enqueue(padapter, pxmitframe);
602 	if (err != _SUCCESS) {
603 		rtw_free_xmitframe(pxmitpriv, pxmitframe);
604 
605 		pxmitpriv->tx_drop++;
606 	} else {
607 #ifdef CONFIG_SDIO_TX_TASKLET
608 		tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
609 #else
610 		complete(&pxmitpriv->SdioXmitStart);
611 #endif
612 	}
613 
614 	return err;
615 
616 }
617 
618 /*
619  * Return
620  *_SUCCESS	start thread ok
621  *_FAIL		start thread fail
622  *
623  */
624 s32 rtl8723bs_init_xmit_priv(struct adapter *padapter)
625 {
626 	struct xmit_priv *xmitpriv = &padapter->xmitpriv;
627 	struct hal_com_data *phal;
628 
629 
630 	phal = GET_HAL_DATA(padapter);
631 
632 	spin_lock_init(&phal->SdioTxFIFOFreePageLock);
633 	init_completion(&xmitpriv->SdioXmitStart);
634 	init_completion(&xmitpriv->SdioXmitTerminate);
635 
636 	return _SUCCESS;
637 }
638 
639 void rtl8723bs_free_xmit_priv(struct adapter *padapter)
640 {
641 	struct hal_com_data *phal;
642 	struct xmit_priv *pxmitpriv;
643 	struct xmit_buf *pxmitbuf;
644 	struct __queue *pqueue;
645 	struct list_head *plist, *phead;
646 	struct list_head tmplist;
647 
648 
649 	phal = GET_HAL_DATA(padapter);
650 	pxmitpriv = &padapter->xmitpriv;
651 	pqueue = &pxmitpriv->pending_xmitbuf_queue;
652 	phead = get_list_head(pqueue);
653 	INIT_LIST_HEAD(&tmplist);
654 
655 	spin_lock_bh(&pqueue->lock);
656 	if (!list_empty(&pqueue->queue)) {
657 		/*  Insert tmplist to end of queue, and delete phead */
658 		/*  then tmplist become head of queue. */
659 		list_add_tail(&tmplist, phead);
660 		list_del_init(phead);
661 	}
662 	spin_unlock_bh(&pqueue->lock);
663 
664 	phead = &tmplist;
665 	while (list_empty(phead) == false) {
666 		plist = get_next(phead);
667 		list_del_init(plist);
668 
669 		pxmitbuf = LIST_CONTAINOR(plist, struct xmit_buf, list);
670 		rtw_free_xmitframe(pxmitpriv, (struct xmit_frame *)pxmitbuf->priv_data);
671 		pxmitbuf->priv_data = NULL;
672 		rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
673 	}
674 }
675