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