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