root/drivers/staging/rtl8723bs/hal/rtl8723bs_xmit.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. rtw_sdio_wait_enough_TxOQT_space
  2. rtl8723_dequeue_writeport
  3. rtl8723bs_xmit_buf_handler
  4. xmit_xmitframes
  5. rtl8723bs_xmit_handler
  6. rtl8723bs_xmit_thread
  7. rtl8723bs_mgnt_xmit
  8. rtl8723bs_hal_xmit
  9. rtl8723bs_hal_xmitframe_enqueue
  10. rtl8723bs_init_xmit_priv
  11. rtl8723bs_free_xmit_priv

   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) ||
  21                         (padapter->bDriverStopped)
  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 (ret)
  62                 pxmitbuf = dequeue_pending_xmitbuf_under_survey(pxmitpriv);
  63         else
  64                 pxmitbuf = dequeue_pending_xmitbuf(pxmitpriv);
  65 
  66         if (!pxmitbuf)
  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 (!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) ||
 103                 (padapter->bDriverStopped)
 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) || (padapter->bSurpriseRemoved);
 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)
 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 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         hwxmits = pxmitpriv->hwxmits;
 217         hwentry = pxmitpriv->hwxmit_entry;
 218         ptxservq = NULL;
 219         pxmitframe = NULL;
 220         pframe_queue = NULL;
 221         pxmitbuf = NULL;
 222 
 223         if (padapter->registrypriv.wifi_spec == 1) {
 224                 for (idx = 0; idx < 4; idx++)
 225                         inx[idx] = pxmitpriv->wmm_para_seq[idx];
 226         } else {
 227                 inx[0] = 0;
 228                 inx[1] = 1;
 229                 inx[2] = 2;
 230                 inx[3] = 3;
 231         }
 232 
 233         /*  0(VO), 1(VI), 2(BE), 3(BK) */
 234         for (idx = 0; idx < hwentry; idx++) {
 235                 phwxmit = hwxmits + inx[idx];
 236 
 237                 if (
 238                         (check_pending_xmitbuf(pxmitpriv)) &&
 239                         (padapter->mlmepriv.LinkDetectInfo.bHigherBusyTxTraffic)
 240                 ) {
 241                         if ((phwxmit->accnt > 0) && (phwxmit->accnt < 5)) {
 242                                 err = -2;
 243                                 break;
 244                         }
 245                 }
 246 
 247                 max_xmit_len = rtw_hal_get_sdio_tx_max_length(padapter, inx[idx]);
 248 
 249                 spin_lock_bh(&pxmitpriv->lock);
 250 
 251                 sta_phead = get_list_head(phwxmit->sta_queue);
 252                 sta_plist = get_next(sta_phead);
 253                 /* because stop_sta_xmit may delete sta_plist at any time */
 254                 /* so we should add lock here, or while loop can not exit */
 255                 while (sta_phead != sta_plist) {
 256                         ptxservq = LIST_CONTAINOR(sta_plist, struct tx_servq, tx_pending);
 257                         sta_plist = get_next(sta_plist);
 258 
 259 #ifdef DBG_XMIT_BUF
 260                         DBG_871X(
 261                                 "%s idx:%d hwxmit_pkt_num:%d ptxservq_pkt_num:%d\n",
 262                                 __func__,
 263                                 idx,
 264                                 phwxmit->accnt,
 265                                 ptxservq->qcnt
 266                         );
 267                         DBG_871X(
 268                                 "%s free_xmit_extbuf_cnt =%d free_xmitbuf_cnt =%d free_xmitframe_cnt =%d\n",
 269                                 __func__,
 270                                 pxmitpriv->free_xmit_extbuf_cnt,
 271                                 pxmitpriv->free_xmitbuf_cnt,
 272                                 pxmitpriv->free_xmitframe_cnt
 273                         );
 274 #endif
 275                         pframe_queue = &ptxservq->sta_pending;
 276 
 277                         frame_phead = get_list_head(pframe_queue);
 278 
 279                         while (list_empty(frame_phead) == false) {
 280                                 frame_plist = get_next(frame_phead);
 281                                 pxmitframe = LIST_CONTAINOR(frame_plist, struct xmit_frame, list);
 282 
 283                                 /*  check xmit_buf size enough or not */
 284                                 txlen = txdesc_size + rtw_wlan_pkt_size(pxmitframe);
 285                                 if(     !pxmitbuf ||
 286                                         ((_RND(pxmitbuf->len, 8) + txlen) > max_xmit_len) ||
 287                                         (k >= (rtw_hal_sdio_max_txoqt_free_space(padapter) - 1))
 288                                 ) {
 289                                         if (pxmitbuf) {
 290                                                 /* pxmitbuf->priv_data will be NULL, and will crash here */
 291                                                 if (pxmitbuf->len > 0 &&
 292                                                     pxmitbuf->priv_data) {
 293                                                         struct xmit_frame *pframe;
 294                                                         pframe = (struct xmit_frame *)pxmitbuf->priv_data;
 295                                                         pframe->agg_num = k;
 296                                                         pxmitbuf->agg_num = k;
 297                                                         rtl8723b_update_txdesc(pframe, pframe->buf_addr);
 298                                                         rtw_free_xmitframe(pxmitpriv, pframe);
 299                                                         pxmitbuf->priv_data = NULL;
 300                                                         enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
 301                                                         /* can not yield under lock */
 302                                                         /* yield(); */
 303                                                 } else
 304                                                         rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
 305                                         }
 306 
 307                                         pxmitbuf = rtw_alloc_xmitbuf(pxmitpriv);
 308                                         if (!pxmitbuf) {
 309 #ifdef DBG_XMIT_BUF
 310                                                 DBG_871X_LEVEL(_drv_err_, "%s: xmit_buf is not enough!\n", __func__);
 311 #endif
 312                                                 err = -2;
 313                                                 complete(&(pxmitpriv->xmit_comp));
 314                                                 break;
 315                                         }
 316                                         k = 0;
 317                                 }
 318 
 319                                 /*  ok to send, remove frame from queue */
 320                                 if (check_fwstate(&padapter->mlmepriv, WIFI_AP_STATE) == true) {
 321                                         if (
 322                                                 (pxmitframe->attrib.psta->state & WIFI_SLEEP_STATE) &&
 323                                                 (pxmitframe->attrib.triggered == 0)
 324                                         ) {
 325                                                 DBG_871X(
 326                                                         "%s: one not triggered pkt in queue when this STA sleep,"
 327                                                         " break and goto next sta\n",
 328                                                         __func__
 329                                                 );
 330                                                 break;
 331                                         }
 332                                 }
 333 
 334                                 list_del_init(&pxmitframe->list);
 335                                 ptxservq->qcnt--;
 336                                 phwxmit->accnt--;
 337 
 338                                 if (k == 0) {
 339                                         pxmitbuf->ff_hwaddr = rtw_get_ff_hwaddr(pxmitframe);
 340                                         pxmitbuf->priv_data = (u8 *)pxmitframe;
 341                                 }
 342 
 343                                 /*  coalesce the xmitframe to xmitbuf */
 344                                 pxmitframe->pxmitbuf = pxmitbuf;
 345                                 pxmitframe->buf_addr = pxmitbuf->ptail;
 346 
 347                                 ret = rtw_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe);
 348                                 if (ret == _FAIL) {
 349                                         DBG_871X_LEVEL(_drv_err_, "%s: coalesce FAIL!", __func__);
 350                                         /*  Todo: error handler */
 351                                 } else {
 352                                         k++;
 353                                         if (k != 1)
 354                                                 rtl8723b_update_txdesc(pxmitframe, pxmitframe->buf_addr);
 355                                         rtw_count_tx_stats(padapter, pxmitframe, pxmitframe->attrib.last_txcmdsz);
 356 
 357                                         txlen = txdesc_size + pxmitframe->attrib.last_txcmdsz;
 358                                         pxmitframe->pg_num = (txlen + 127) / 128;
 359                                         pxmitbuf->pg_num += (txlen + 127) / 128;
 360                                     /* if (k != 1) */
 361                                         /*      ((struct xmit_frame*)pxmitbuf->priv_data)->pg_num += pxmitframe->pg_num; */
 362                                         pxmitbuf->ptail += _RND(txlen, 8); /*  round to 8 bytes alignment */
 363                                         pxmitbuf->len = _RND(pxmitbuf->len, 8) + txlen;
 364                                 }
 365 
 366                                 if (k != 1)
 367                                         rtw_free_xmitframe(pxmitpriv, pxmitframe);
 368                                 pxmitframe = NULL;
 369                         }
 370 
 371                         if (list_empty(&pframe_queue->queue))
 372                                 list_del_init(&ptxservq->tx_pending);
 373 
 374                         if (err)
 375                                 break;
 376                 }
 377                 spin_unlock_bh(&pxmitpriv->lock);
 378 
 379                 /*  dump xmit_buf to hw tx fifo */
 380                 if (pxmitbuf) {
 381                         RT_TRACE(_module_hal_xmit_c_, _drv_info_, ("pxmitbuf->len =%d enqueue\n", pxmitbuf->len));
 382 
 383                         if (pxmitbuf->len > 0) {
 384                                 struct xmit_frame *pframe;
 385                                 pframe = (struct xmit_frame *)pxmitbuf->priv_data;
 386                                 pframe->agg_num = k;
 387                                 pxmitbuf->agg_num = k;
 388                                 rtl8723b_update_txdesc(pframe, pframe->buf_addr);
 389                                 rtw_free_xmitframe(pxmitpriv, pframe);
 390                                 pxmitbuf->priv_data = NULL;
 391                                 enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
 392                                 yield();
 393                         } else
 394                                 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
 395                         pxmitbuf = NULL;
 396                 }
 397 
 398                 if (err)
 399                         break;
 400         }
 401 
 402         return err;
 403 }
 404 
 405 /*
 406  * Description
 407  *Transmit xmitframe from queue
 408  *
 409  * Return
 410  *_SUCCESS      ok
 411  *_FAIL         something error
 412  */
 413 static s32 rtl8723bs_xmit_handler(struct adapter *padapter)
 414 {
 415         struct xmit_priv *pxmitpriv;
 416         s32 ret;
 417 
 418 
 419         pxmitpriv = &padapter->xmitpriv;
 420 
 421         if (wait_for_completion_interruptible(&pxmitpriv->SdioXmitStart)) {
 422                 DBG_871X_LEVEL(_drv_emerg_, "%s: SdioXmitStart fail!\n", __func__);
 423                 return _FAIL;
 424         }
 425 
 426 next:
 427         if (
 428                 (padapter->bDriverStopped) ||
 429                 (padapter->bSurpriseRemoved)
 430         ) {
 431                 RT_TRACE(
 432                         _module_hal_xmit_c_,
 433                         _drv_notice_,
 434                         (
 435                                 "%s: bDriverStopped(%d) bSurpriseRemoved(%d)\n",
 436                                 __func__,
 437                                 padapter->bDriverStopped,
 438                                 padapter->bSurpriseRemoved
 439                         )
 440                 );
 441                 return _FAIL;
 442         }
 443 
 444         spin_lock_bh(&pxmitpriv->lock);
 445         ret = rtw_txframes_pending(padapter);
 446         spin_unlock_bh(&pxmitpriv->lock);
 447         if (ret == 0) {
 448                 return _SUCCESS;
 449         }
 450 
 451         /*  dequeue frame and write to hardware */
 452 
 453         ret = xmit_xmitframes(padapter, pxmitpriv);
 454         if (ret == -2) {
 455                 /* here sleep 1ms will cause big TP loss of TX */
 456                 /* from 50+ to 40+ */
 457                 if (padapter->registrypriv.wifi_spec)
 458                         msleep(1);
 459                 else
 460                         yield();
 461                 goto next;
 462         }
 463 
 464         spin_lock_bh(&pxmitpriv->lock);
 465         ret = rtw_txframes_pending(padapter);
 466         spin_unlock_bh(&pxmitpriv->lock);
 467         if (ret == 1) {
 468                 goto next;
 469         }
 470 
 471         return _SUCCESS;
 472 }
 473 
 474 int rtl8723bs_xmit_thread(void *context)
 475 {
 476         s32 ret;
 477         struct adapter *padapter;
 478         struct xmit_priv *pxmitpriv;
 479         u8 thread_name[20];
 480 
 481         ret = _SUCCESS;
 482         padapter = context;
 483         pxmitpriv = &padapter->xmitpriv;
 484 
 485         rtw_sprintf(thread_name, 20, "RTWHALXT-" ADPT_FMT, ADPT_ARG(padapter));
 486         thread_enter(thread_name);
 487 
 488         DBG_871X("start "FUNC_ADPT_FMT"\n", FUNC_ADPT_ARG(padapter));
 489 
 490         do {
 491                 ret = rtl8723bs_xmit_handler(padapter);
 492                 if (signal_pending(current)) {
 493                         flush_signals(current);
 494                 }
 495         } while (_SUCCESS == ret);
 496 
 497         complete(&pxmitpriv->SdioXmitTerminate);
 498 
 499         RT_TRACE(_module_hal_xmit_c_, _drv_notice_, ("-%s\n", __func__));
 500 
 501         thread_exit();
 502 }
 503 
 504 s32 rtl8723bs_mgnt_xmit(
 505         struct adapter *padapter, struct xmit_frame *pmgntframe
 506 )
 507 {
 508         s32 ret = _SUCCESS;
 509         struct pkt_attrib *pattrib;
 510         struct xmit_buf *pxmitbuf;
 511         struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
 512         struct dvobj_priv *pdvobjpriv = adapter_to_dvobj(padapter);
 513         u8 *pframe = (u8 *)(pmgntframe->buf_addr) + TXDESC_OFFSET;
 514         u8 txdesc_size = TXDESC_SIZE;
 515 
 516         RT_TRACE(_module_hal_xmit_c_, _drv_info_, ("+%s\n", __func__));
 517 
 518         pattrib = &pmgntframe->attrib;
 519         pxmitbuf = pmgntframe->pxmitbuf;
 520 
 521         rtl8723b_update_txdesc(pmgntframe, pmgntframe->buf_addr);
 522 
 523         pxmitbuf->len = txdesc_size + pattrib->last_txcmdsz;
 524         pxmitbuf->pg_num = (pxmitbuf->len + 127) / 128; /*  128 is tx page size */
 525         pxmitbuf->ptail = pmgntframe->buf_addr + pxmitbuf->len;
 526         pxmitbuf->ff_hwaddr = rtw_get_ff_hwaddr(pmgntframe);
 527 
 528         rtw_count_tx_stats(padapter, pmgntframe, pattrib->last_txcmdsz);
 529 
 530         rtw_free_xmitframe(pxmitpriv, pmgntframe);
 531 
 532         pxmitbuf->priv_data = NULL;
 533 
 534         if (GetFrameSubType(pframe) == WIFI_BEACON) { /* dump beacon directly */
 535                 ret = rtw_write_port(padapter, pdvobjpriv->Queue2Pipe[pxmitbuf->ff_hwaddr], pxmitbuf->len, (u8 *)pxmitbuf);
 536                 if (ret != _SUCCESS)
 537                         rtw_sctx_done_err(&pxmitbuf->sctx, RTW_SCTX_DONE_WRITE_PORT_ERR);
 538 
 539                 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
 540         } else
 541                 enqueue_pending_xmitbuf(pxmitpriv, pxmitbuf);
 542 
 543         return ret;
 544 }
 545 
 546 /*
 547  * Description:
 548  *Handle xmitframe(packet) come from rtw_xmit()
 549  *
 550  * Return:
 551  *true  dump packet directly ok
 552  *false enqueue, temporary can't transmit packets to hardware
 553  */
 554 s32 rtl8723bs_hal_xmit(
 555         struct adapter *padapter, struct xmit_frame *pxmitframe
 556 )
 557 {
 558         struct xmit_priv *pxmitpriv;
 559         s32 err;
 560 
 561 
 562         pxmitframe->attrib.qsel = pxmitframe->attrib.priority;
 563         pxmitpriv = &padapter->xmitpriv;
 564 
 565         if (
 566                 (pxmitframe->frame_tag == DATA_FRAMETAG) &&
 567                 (pxmitframe->attrib.ether_type != 0x0806) &&
 568                 (pxmitframe->attrib.ether_type != 0x888e) &&
 569                 (pxmitframe->attrib.dhcp_pkt != 1)
 570         ) {
 571                 if (padapter->mlmepriv.LinkDetectInfo.bBusyTraffic)
 572                         rtw_issue_addbareq_cmd(padapter, pxmitframe);
 573         }
 574 
 575         spin_lock_bh(&pxmitpriv->lock);
 576         err = rtw_xmitframe_enqueue(padapter, pxmitframe);
 577         spin_unlock_bh(&pxmitpriv->lock);
 578         if (err != _SUCCESS) {
 579                 RT_TRACE(_module_hal_xmit_c_, _drv_err_, ("rtl8723bs_hal_xmit: enqueue xmitframe fail\n"));
 580                 rtw_free_xmitframe(pxmitpriv, pxmitframe);
 581 
 582                 pxmitpriv->tx_drop++;
 583                 return true;
 584         }
 585 
 586         complete(&pxmitpriv->SdioXmitStart);
 587 
 588         return false;
 589 }
 590 
 591 s32     rtl8723bs_hal_xmitframe_enqueue(
 592         struct adapter *padapter, struct xmit_frame *pxmitframe
 593 )
 594 {
 595         struct xmit_priv *pxmitpriv = &padapter->xmitpriv;
 596         s32 err;
 597 
 598         err = rtw_xmitframe_enqueue(padapter, pxmitframe);
 599         if (err != _SUCCESS) {
 600                 rtw_free_xmitframe(pxmitpriv, pxmitframe);
 601 
 602                 pxmitpriv->tx_drop++;
 603         } else {
 604 #ifdef CONFIG_SDIO_TX_TASKLET
 605                 tasklet_hi_schedule(&pxmitpriv->xmit_tasklet);
 606 #else
 607                 complete(&pxmitpriv->SdioXmitStart);
 608 #endif
 609         }
 610 
 611         return err;
 612 
 613 }
 614 
 615 /*
 616  * Return
 617  *_SUCCESS      start thread ok
 618  *_FAIL         start thread fail
 619  *
 620  */
 621 s32 rtl8723bs_init_xmit_priv(struct adapter *padapter)
 622 {
 623         struct xmit_priv *xmitpriv = &padapter->xmitpriv;
 624         struct hal_com_data *phal;
 625 
 626 
 627         phal = GET_HAL_DATA(padapter);
 628 
 629         spin_lock_init(&phal->SdioTxFIFOFreePageLock);
 630         init_completion(&xmitpriv->SdioXmitStart);
 631         init_completion(&xmitpriv->SdioXmitTerminate);
 632 
 633         return _SUCCESS;
 634 }
 635 
 636 void rtl8723bs_free_xmit_priv(struct adapter *padapter)
 637 {
 638         struct xmit_priv *pxmitpriv;
 639         struct xmit_buf *pxmitbuf;
 640         struct __queue *pqueue;
 641         struct list_head *plist, *phead;
 642         struct list_head tmplist;
 643 
 644 
 645         pxmitpriv = &padapter->xmitpriv;
 646         pqueue = &pxmitpriv->pending_xmitbuf_queue;
 647         phead = get_list_head(pqueue);
 648         INIT_LIST_HEAD(&tmplist);
 649 
 650         spin_lock_bh(&pqueue->lock);
 651         if (!list_empty(&pqueue->queue)) {
 652                 /*  Insert tmplist to end of queue, and delete phead */
 653                 /*  then tmplist become head of queue. */
 654                 list_add_tail(&tmplist, phead);
 655                 list_del_init(phead);
 656         }
 657         spin_unlock_bh(&pqueue->lock);
 658 
 659         phead = &tmplist;
 660         while (list_empty(phead) == false) {
 661                 plist = get_next(phead);
 662                 list_del_init(plist);
 663 
 664                 pxmitbuf = LIST_CONTAINOR(plist, struct xmit_buf, list);
 665                 rtw_free_xmitframe(pxmitpriv, (struct xmit_frame *)pxmitbuf->priv_data);
 666                 pxmitbuf->priv_data = NULL;
 667                 rtw_free_xmitbuf(pxmitpriv, pxmitbuf);
 668         }
 669 }

/* [<][>][^][v][top][bottom][index][help] */