1 // SPDX-License-Identifier: GPL-2.0 2 /****************************************************************************** 3 * rtl8712_xmit.c 4 * 5 * Copyright(c) 2007 - 2010 Realtek Corporation. All rights reserved. 6 * Linux device driver for RTL8192SU 7 * 8 * Modifications for inclusion into the Linux staging tree are 9 * Copyright(c) 2010 Larry Finger. All rights reserved. 10 * 11 * Contact information: 12 * WLAN FAE <wlanfae@realtek.com> 13 * Larry Finger <Larry.Finger@lwfinger.net> 14 * 15 ******************************************************************************/ 16 17 #define _RTL8712_XMIT_C_ 18 19 #include "osdep_service.h" 20 #include "drv_types.h" 21 #include "wifi.h" 22 #include "osdep_intf.h" 23 #include "usb_ops.h" 24 25 static void dump_xframe(struct _adapter *padapter, 26 struct xmit_frame *pxmitframe); 27 static void update_txdesc(struct xmit_frame *pxmitframe, uint *pmem, int sz); 28 29 sint _r8712_init_hw_txqueue(struct hw_txqueue *phw_txqueue, u8 ac_tag) 30 { 31 phw_txqueue->ac_tag = ac_tag; 32 switch (ac_tag) { 33 case BE_QUEUE_INX: 34 phw_txqueue->ff_hwaddr = RTL8712_DMA_BEQ; 35 break; 36 case BK_QUEUE_INX: 37 phw_txqueue->ff_hwaddr = RTL8712_DMA_BKQ; 38 break; 39 case VI_QUEUE_INX: 40 phw_txqueue->ff_hwaddr = RTL8712_DMA_VIQ; 41 break; 42 case VO_QUEUE_INX: 43 phw_txqueue->ff_hwaddr = RTL8712_DMA_VOQ; 44 break; 45 case BMC_QUEUE_INX: 46 phw_txqueue->ff_hwaddr = RTL8712_DMA_BEQ; 47 break; 48 } 49 return _SUCCESS; 50 } 51 52 int r8712_txframes_sta_ac_pending(struct _adapter *padapter, 53 struct pkt_attrib *pattrib) 54 { 55 struct sta_info *psta; 56 struct tx_servq *ptxservq; 57 int priority = pattrib->priority; 58 59 psta = pattrib->psta; 60 switch (priority) { 61 case 1: 62 case 2: 63 ptxservq = &psta->sta_xmitpriv.bk_q; 64 break; 65 case 4: 66 case 5: 67 ptxservq = &psta->sta_xmitpriv.vi_q; 68 break; 69 case 6: 70 case 7: 71 ptxservq = &psta->sta_xmitpriv.vo_q; 72 break; 73 case 0: 74 case 3: 75 default: 76 ptxservq = &psta->sta_xmitpriv.be_q; 77 break; 78 } 79 return ptxservq->qcnt; 80 } 81 82 static u32 get_ff_hwaddr(struct xmit_frame *pxmitframe) 83 { 84 u32 addr = 0; 85 struct pkt_attrib *pattrib = &pxmitframe->attrib; 86 struct _adapter *padapter = pxmitframe->padapter; 87 struct dvobj_priv *pdvobj = &padapter->dvobjpriv; 88 89 if (pxmitframe->frame_tag == TXAGG_FRAMETAG) { 90 addr = RTL8712_DMA_H2CCMD; 91 } else if (pxmitframe->frame_tag == MGNT_FRAMETAG) { 92 addr = RTL8712_DMA_MGTQ; 93 } else if (pdvobj->nr_endpoint == 6) { 94 switch (pattrib->priority) { 95 case 0: 96 case 3: 97 addr = RTL8712_DMA_BEQ; 98 break; 99 case 1: 100 case 2: 101 addr = RTL8712_DMA_BKQ; 102 break; 103 case 4: 104 case 5: 105 addr = RTL8712_DMA_VIQ; 106 break; 107 case 6: 108 case 7: 109 addr = RTL8712_DMA_VOQ; 110 break; 111 case 0x10: 112 case 0x11: 113 case 0x12: 114 case 0x13: 115 addr = RTL8712_DMA_H2CCMD; 116 break; 117 default: 118 addr = RTL8712_DMA_BEQ; 119 break; 120 } 121 } else if (pdvobj->nr_endpoint == 4) { 122 switch (pattrib->qsel) { 123 case 0: 124 case 3: 125 case 1: 126 case 2: 127 addr = RTL8712_DMA_BEQ;/*RTL8712_EP_LO;*/ 128 break; 129 case 4: 130 case 5: 131 case 6: 132 case 7: 133 addr = RTL8712_DMA_VOQ;/*RTL8712_EP_HI;*/ 134 break; 135 case 0x10: 136 case 0x11: 137 case 0x12: 138 case 0x13: 139 addr = RTL8712_DMA_H2CCMD; 140 break; 141 default: 142 addr = RTL8712_DMA_BEQ;/*RTL8712_EP_LO;*/ 143 break; 144 } 145 } 146 return addr; 147 } 148 149 static struct xmit_frame *dequeue_one_xmitframe(struct xmit_priv *pxmitpriv, 150 struct hw_xmit *phwxmit, 151 struct tx_servq *ptxservq, 152 struct __queue *pframe_queue) 153 { 154 struct list_head *xmitframe_plist, *xmitframe_phead; 155 struct xmit_frame *pxmitframe = NULL; 156 157 xmitframe_phead = &pframe_queue->queue; 158 xmitframe_plist = xmitframe_phead->next; 159 if (!end_of_queue_search(xmitframe_phead, xmitframe_plist)) { 160 pxmitframe = container_of(xmitframe_plist, 161 struct xmit_frame, list); 162 list_del_init(&pxmitframe->list); 163 ptxservq->qcnt--; 164 phwxmit->txcmdcnt++; 165 } 166 return pxmitframe; 167 } 168 169 static struct xmit_frame *dequeue_xframe_ex(struct xmit_priv *pxmitpriv, 170 struct hw_xmit *phwxmit_i, sint entry) 171 { 172 unsigned long irqL0; 173 struct list_head *sta_plist, *sta_phead; 174 struct hw_xmit *phwxmit; 175 struct tx_servq *ptxservq = NULL; 176 struct __queue *pframe_queue = NULL; 177 struct xmit_frame *pxmitframe = NULL; 178 int i, inx[4]; 179 int j, acirp_cnt[4]; 180 181 /*entry indx: 0->vo, 1->vi, 2->be, 3->bk.*/ 182 inx[0] = 0; acirp_cnt[0] = pxmitpriv->voq_cnt; 183 inx[1] = 1; acirp_cnt[1] = pxmitpriv->viq_cnt; 184 inx[2] = 2; acirp_cnt[2] = pxmitpriv->beq_cnt; 185 inx[3] = 3; acirp_cnt[3] = pxmitpriv->bkq_cnt; 186 for (i = 0; i < 4; i++) { 187 for (j = i + 1; j < 4; j++) { 188 if (acirp_cnt[j] < acirp_cnt[i]) { 189 swap(acirp_cnt[i], acirp_cnt[j]); 190 swap(inx[i], inx[j]); 191 } 192 } 193 } 194 spin_lock_irqsave(&pxmitpriv->lock, irqL0); 195 for (i = 0; i < entry; i++) { 196 phwxmit = phwxmit_i + inx[i]; 197 sta_phead = &phwxmit->sta_queue->queue; 198 sta_plist = sta_phead->next; 199 while (!end_of_queue_search(sta_phead, sta_plist)) { 200 ptxservq = container_of(sta_plist, struct tx_servq, 201 tx_pending); 202 pframe_queue = &ptxservq->sta_pending; 203 pxmitframe = dequeue_one_xmitframe(pxmitpriv, phwxmit, 204 ptxservq, pframe_queue); 205 if (pxmitframe) { 206 phwxmit->accnt--; 207 goto exit_dequeue_xframe_ex; 208 } 209 sta_plist = sta_plist->next; 210 /*Remove sta node when there are no pending packets.*/ 211 if (list_empty(&pframe_queue->queue)) { 212 /* must be done after sta_plist->next 213 * and before break 214 */ 215 list_del_init(&ptxservq->tx_pending); 216 } 217 } 218 } 219 exit_dequeue_xframe_ex: 220 spin_unlock_irqrestore(&pxmitpriv->lock, irqL0); 221 return pxmitframe; 222 } 223 224 void r8712_do_queue_select(struct _adapter *padapter, 225 struct pkt_attrib *pattrib) 226 { 227 unsigned int qsel = 0; 228 struct dvobj_priv *pdvobj = &padapter->dvobjpriv; 229 230 if (pdvobj->nr_endpoint == 6) { 231 qsel = (unsigned int) pattrib->priority; 232 } else if (pdvobj->nr_endpoint == 4) { 233 qsel = (unsigned int) pattrib->priority; 234 if (qsel == 0 || qsel == 3) 235 qsel = 3; 236 else if (qsel == 1 || qsel == 2) 237 qsel = 1; 238 else if (qsel == 4 || qsel == 5) 239 qsel = 5; 240 else if (qsel == 6 || qsel == 7) 241 qsel = 7; 242 else 243 qsel = 3; 244 } 245 pattrib->qsel = qsel; 246 } 247 248 #ifdef CONFIG_R8712_TX_AGGR 249 void r8712_construct_txaggr_cmd_desc(struct xmit_buf *pxmitbuf) 250 { 251 struct tx_desc *ptx_desc = (struct tx_desc *)pxmitbuf->pbuf; 252 253 /* Fill up TxCmd Descriptor according as USB FW Tx Aaggregation info.*/ 254 /* dw0 */ 255 ptx_desc->txdw0 = cpu_to_le32(CMD_HDR_SZ & 0xffff); 256 ptx_desc->txdw0 |= 257 cpu_to_le32(((TXDESC_SIZE + OFFSET_SZ) << OFFSET_SHT) & 258 0x00ff0000); 259 ptx_desc->txdw0 |= cpu_to_le32(OWN | FSG | LSG); 260 261 /* dw1 */ 262 ptx_desc->txdw1 |= cpu_to_le32((0x13 << QSEL_SHT) & 0x00001f00); 263 } 264 265 void r8712_construct_txaggr_cmd_hdr(struct xmit_buf *pxmitbuf) 266 { 267 struct xmit_frame *pxmitframe = (struct xmit_frame *) 268 pxmitbuf->priv_data; 269 struct _adapter *padapter = pxmitframe->padapter; 270 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 271 struct cmd_hdr *pcmd_hdr = (struct cmd_hdr *) 272 (pxmitbuf->pbuf + TXDESC_SIZE); 273 274 /* Fill up Cmd Header for USB FW Tx Aggregation.*/ 275 /* dw0 */ 276 pcmd_hdr->cmd_dw0 = cpu_to_le32((GEN_CMD_CODE(_AMSDU_TO_AMPDU) << 16) | 277 (pcmdpriv->cmd_seq << 24)); 278 pcmdpriv->cmd_seq++; 279 } 280 281 void r8712_append_mpdu_unit(struct xmit_buf *pxmitbuf, 282 struct xmit_frame *pxmitframe) 283 { 284 struct _adapter *padapter = pxmitframe->padapter; 285 struct tx_desc *ptx_desc = (struct tx_desc *)pxmitbuf->pbuf; 286 int last_txcmdsz = 0; 287 int padding_sz = 0; 288 289 /* 802.3->802.11 converter */ 290 r8712_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe); 291 /* free skb struct */ 292 r8712_xmit_complete(padapter, pxmitframe); 293 if (pxmitframe->attrib.ether_type != 0x0806) { 294 if ((pxmitframe->attrib.ether_type != 0x888e) && 295 (pxmitframe->attrib.dhcp_pkt != 1)) { 296 r8712_issue_addbareq_cmd(padapter, 297 pxmitframe->attrib.priority); 298 } 299 } 300 pxmitframe->last[0] = 1; 301 update_txdesc(pxmitframe, (uint *)(pxmitframe->buf_addr), 302 pxmitframe->attrib.last_txcmdsz); 303 /*padding zero */ 304 last_txcmdsz = pxmitframe->attrib.last_txcmdsz; 305 padding_sz = (8 - (last_txcmdsz % 8)); 306 if ((last_txcmdsz % 8) != 0) { 307 int i; 308 309 for (i = 0; i < padding_sz; i++) 310 *(pxmitframe->buf_addr + TXDESC_SIZE + last_txcmdsz + 311 i) = 0; 312 } 313 /* Add the new mpdu's length */ 314 ptx_desc->txdw0 = cpu_to_le32((ptx_desc->txdw0 & 0xffff0000) | 315 ((ptx_desc->txdw0 & 0x0000ffff) + 316 ((TXDESC_SIZE + last_txcmdsz + padding_sz) & 317 0x0000ffff))); 318 } 319 320 321 void r8712_xmitframe_aggr_1st(struct xmit_buf *pxmitbuf, 322 struct xmit_frame *pxmitframe) 323 { 324 /* linux complete context doesn't need to protect */ 325 pxmitframe->pxmitbuf = pxmitbuf; 326 pxmitbuf->priv_data = pxmitframe; 327 pxmitframe->pxmit_urb[0] = pxmitbuf->pxmit_urb[0]; 328 /* buffer addr assoc */ 329 pxmitframe->buf_addr = pxmitbuf->pbuf + TXDESC_SIZE + CMD_HDR_SZ; 330 /*RTL8712_DMA_H2CCMD */ 331 r8712_construct_txaggr_cmd_desc(pxmitbuf); 332 r8712_construct_txaggr_cmd_hdr(pxmitbuf); 333 r8712_append_mpdu_unit(pxmitbuf, pxmitframe); 334 pxmitbuf->aggr_nr = 1; 335 } 336 337 u16 r8712_xmitframe_aggr_next(struct xmit_buf *pxmitbuf, 338 struct xmit_frame *pxmitframe) 339 { 340 pxmitframe->pxmitbuf = pxmitbuf; 341 pxmitbuf->priv_data = pxmitframe; 342 pxmitframe->pxmit_urb[0] = pxmitbuf->pxmit_urb[0]; 343 /* buffer addr assoc */ 344 pxmitframe->buf_addr = pxmitbuf->pbuf + TXDESC_SIZE + 345 (((struct tx_desc *)pxmitbuf->pbuf)->txdw0 & 0x0000ffff); 346 r8712_append_mpdu_unit(pxmitbuf, pxmitframe); 347 r8712_free_xmitframe_ex(&pxmitframe->padapter->xmitpriv, 348 pxmitframe); 349 pxmitbuf->aggr_nr++; 350 351 return TXDESC_SIZE + 352 (((struct tx_desc *)pxmitbuf->pbuf)->txdw0 & 0x0000ffff); 353 } 354 355 void r8712_dump_aggr_xframe(struct xmit_buf *pxmitbuf, 356 struct xmit_frame *pxmitframe) 357 { 358 struct _adapter *padapter = pxmitframe->padapter; 359 struct dvobj_priv *pdvobj = &padapter->dvobjpriv; 360 struct tx_desc *ptxdesc = pxmitbuf->pbuf; 361 struct cmd_hdr *pcmd_hdr = (struct cmd_hdr *) 362 (pxmitbuf->pbuf + TXDESC_SIZE); 363 u16 total_length = (u16) (ptxdesc->txdw0 & 0xffff); 364 365 /* use 1st xmitframe as media */ 366 xmitframe_xmitbuf_attach(pxmitframe, pxmitbuf); 367 pcmd_hdr->cmd_dw0 = cpu_to_le32(((total_length - CMD_HDR_SZ) & 368 0x0000ffff) | (pcmd_hdr->cmd_dw0 & 369 0xffff0000)); 370 371 /* urb length in cmd_dw1 */ 372 pcmd_hdr->cmd_dw1 = cpu_to_le32((pxmitbuf->aggr_nr & 0xff)| 373 ((total_length + TXDESC_SIZE) << 16)); 374 pxmitframe->last[0] = 1; 375 pxmitframe->bpending[0] = false; 376 pxmitframe->mem_addr = pxmitbuf->pbuf; 377 378 if ((pdvobj->ishighspeed && ((total_length + TXDESC_SIZE) % 0x200) == 379 0) || ((!pdvobj->ishighspeed && ((total_length + TXDESC_SIZE) % 380 0x40) == 0))) { 381 ptxdesc->txdw0 |= cpu_to_le32 382 (((TXDESC_SIZE + OFFSET_SZ + 8) << OFFSET_SHT) & 383 0x00ff0000); 384 /*32 bytes for TX Desc + 8 bytes pending*/ 385 } else { 386 ptxdesc->txdw0 |= cpu_to_le32 387 (((TXDESC_SIZE + OFFSET_SZ) << OFFSET_SHT) & 388 0x00ff0000); 389 /*default = 32 bytes for TX Desc*/ 390 } 391 r8712_write_port(pxmitframe->padapter, RTL8712_DMA_H2CCMD, 392 total_length + TXDESC_SIZE, (u8 *)pxmitframe); 393 } 394 395 #endif 396 397 static void update_txdesc(struct xmit_frame *pxmitframe, uint *pmem, int sz) 398 { 399 uint qsel; 400 struct _adapter *padapter = pxmitframe->padapter; 401 struct mlme_priv *pmlmepriv = &padapter->mlmepriv; 402 struct qos_priv *pqospriv = &pmlmepriv->qospriv; 403 struct security_priv *psecuritypriv = &padapter->securitypriv; 404 struct pkt_attrib *pattrib = &pxmitframe->attrib; 405 struct tx_desc *ptxdesc = (struct tx_desc *)pmem; 406 struct dvobj_priv *pdvobj = &padapter->dvobjpriv; 407 #ifdef CONFIG_R8712_TX_AGGR 408 struct cmd_priv *pcmdpriv = &padapter->cmdpriv; 409 #endif 410 u8 blnSetTxDescOffset; 411 bool bmcst = is_multicast_ether_addr(pattrib->ra); 412 struct ht_priv *phtpriv = &pmlmepriv->htpriv; 413 struct tx_desc txdesc_mp; 414 415 memcpy(&txdesc_mp, ptxdesc, sizeof(struct tx_desc)); 416 memset(ptxdesc, 0, sizeof(struct tx_desc)); 417 /* offset 0 */ 418 ptxdesc->txdw0 |= cpu_to_le32(sz & 0x0000ffff); 419 if (pdvobj->ishighspeed) { 420 if (((sz + TXDESC_SIZE) % 512) == 0) 421 blnSetTxDescOffset = 1; 422 else 423 blnSetTxDescOffset = 0; 424 } else { 425 if (((sz + TXDESC_SIZE) % 64) == 0) 426 blnSetTxDescOffset = 1; 427 else 428 blnSetTxDescOffset = 0; 429 } 430 if (blnSetTxDescOffset) { 431 /* 32 bytes for TX Desc + 8 bytes pending */ 432 ptxdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE + OFFSET_SZ + 8) << 433 OFFSET_SHT) & 0x00ff0000); 434 } else { 435 /* default = 32 bytes for TX Desc */ 436 ptxdesc->txdw0 |= cpu_to_le32(((TXDESC_SIZE + OFFSET_SZ) << 437 OFFSET_SHT) & 0x00ff0000); 438 } 439 ptxdesc->txdw0 |= cpu_to_le32(OWN | FSG | LSG); 440 if (pxmitframe->frame_tag == DATA_FRAMETAG) { 441 /* offset 4 */ 442 ptxdesc->txdw1 |= cpu_to_le32((pattrib->mac_id) & 0x1f); 443 444 #ifdef CONFIG_R8712_TX_AGGR 445 /* dirty workaround, need to check if it is aggr cmd. */ 446 if ((u8 *)pmem != (u8 *)pxmitframe->pxmitbuf->pbuf) { 447 ptxdesc->txdw0 |= cpu_to_le32 448 ((0x3 << TYPE_SHT) & TYPE_MSK); 449 qsel = (uint)(pattrib->qsel & 0x0000001f); 450 if (qsel == 2) 451 qsel = 0; 452 ptxdesc->txdw1 |= cpu_to_le32 453 ((qsel << QSEL_SHT) & 0x00001f00); 454 ptxdesc->txdw2 = cpu_to_le32 455 ((qsel << RTS_RC_SHT) & 0x001f0000); 456 ptxdesc->txdw6 |= cpu_to_le32 457 ((0x5 << RSVD6_SHT) & RSVD6_MSK); 458 } else { 459 ptxdesc->txdw0 |= cpu_to_le32 460 ((0x3 << TYPE_SHT) & TYPE_MSK); 461 ptxdesc->txdw1 |= cpu_to_le32 462 ((0x13 << QSEL_SHT) & 0x00001f00); 463 qsel = (uint)(pattrib->qsel & 0x0000001f); 464 if (qsel == 2) 465 qsel = 0; 466 ptxdesc->txdw2 = cpu_to_le32 467 ((qsel << RTS_RC_SHT) & 0x0001f000); 468 ptxdesc->txdw7 |= cpu_to_le32 469 (pcmdpriv->cmd_seq << 24); 470 pcmdpriv->cmd_seq++; 471 } 472 pattrib->qsel = 0x13; 473 #else 474 qsel = (uint)(pattrib->qsel & 0x0000001f); 475 ptxdesc->txdw1 |= cpu_to_le32((qsel << QSEL_SHT) & 0x00001f00); 476 #endif 477 if (!pqospriv->qos_option) 478 ptxdesc->txdw1 |= cpu_to_le32(BIT(16));/*Non-QoS*/ 479 if ((pattrib->encrypt > 0) && !pattrib->bswenc) { 480 switch (pattrib->encrypt) { /*SEC_TYPE*/ 481 case _WEP40_: 482 case _WEP104_: 483 ptxdesc->txdw1 |= cpu_to_le32((0x01 << 22) & 484 0x00c00000); 485 /*KEY_ID when WEP is used;*/ 486 ptxdesc->txdw1 |= cpu_to_le32((psecuritypriv-> 487 PrivacyKeyIndex << 17) & 488 0x00060000); 489 break; 490 case _TKIP_: 491 case _TKIP_WTMIC_: 492 ptxdesc->txdw1 |= cpu_to_le32((0x02 << 22) & 493 0x00c00000); 494 break; 495 case _AES_: 496 ptxdesc->txdw1 |= cpu_to_le32((0x03 << 22) & 497 0x00c00000); 498 break; 499 case _NO_PRIVACY_: 500 default: 501 break; 502 } 503 } 504 /*offset 8*/ 505 if (bmcst) 506 ptxdesc->txdw2 |= cpu_to_le32(BMC); 507 508 /*offset 12*/ 509 /* f/w will increase the seqnum by itself, driver pass the 510 * correct priority to fw 511 * fw will check the correct priority for increasing the 512 * seqnum per tid. about usb using 4-endpoint, qsel points out 513 * the correct mapping between AC&Endpoint, 514 * the purpose is that correct mapping lets the MAC release 515 * the AC Queue list correctly. 516 */ 517 ptxdesc->txdw3 = cpu_to_le32((pattrib->priority << SEQ_SHT) & 518 0x0fff0000); 519 if ((pattrib->ether_type != 0x888e) && 520 (pattrib->ether_type != 0x0806) && 521 (pattrib->dhcp_pkt != 1)) { 522 /*Not EAP & ARP type data packet*/ 523 if (phtpriv->ht_option == 1) { /*B/G/N Mode*/ 524 if (!phtpriv->ampdu_enable) 525 ptxdesc->txdw2 |= cpu_to_le32(BK); 526 } 527 } else { 528 /* EAP data packet and ARP packet. 529 * Use the 1M data rate to send the EAP/ARP packet. 530 * This will maybe make the handshake smooth. 531 */ 532 /*driver uses data rate*/ 533 ptxdesc->txdw4 = cpu_to_le32(0x80000000); 534 ptxdesc->txdw5 = cpu_to_le32(0x001f8000);/*1M*/ 535 } 536 if (pattrib->pctrl == 1) { /* mp tx packets */ 537 struct tx_desc *ptxdesc_mp; 538 539 ptxdesc_mp = &txdesc_mp; 540 /* offset 8 */ 541 ptxdesc->txdw2 = ptxdesc_mp->txdw2; 542 if (bmcst) 543 ptxdesc->txdw2 |= cpu_to_le32(BMC); 544 ptxdesc->txdw2 |= cpu_to_le32(BK); 545 /* offset 16 */ 546 ptxdesc->txdw4 = ptxdesc_mp->txdw4; 547 /* offset 20 */ 548 ptxdesc->txdw5 = ptxdesc_mp->txdw5; 549 pattrib->pctrl = 0;/* reset to zero; */ 550 } 551 } else if (pxmitframe->frame_tag == MGNT_FRAMETAG) { 552 /* offset 4 */ 553 /* CAM_ID(MAC_ID), default=5; */ 554 ptxdesc->txdw1 |= cpu_to_le32((0x05) & 0x1f); 555 qsel = (uint)(pattrib->qsel & 0x0000001f); 556 ptxdesc->txdw1 |= cpu_to_le32((qsel << QSEL_SHT) & 0x00001f00); 557 ptxdesc->txdw1 |= cpu_to_le32(BIT(16));/* Non-QoS */ 558 /* offset 8 */ 559 if (bmcst) 560 ptxdesc->txdw2 |= cpu_to_le32(BMC); 561 /* offset 12 */ 562 /* f/w will increase the seqnum by itself, driver pass the 563 * correct priority to fw 564 * fw will check the correct priority for increasing the seqnum 565 * per tid. about usb using 4-endpoint, qsel points out the 566 * correct mapping between AC&Endpoint, 567 * the purpose is that correct mapping let the MAC releases 568 * the AC Queue list correctly. 569 */ 570 ptxdesc->txdw3 = cpu_to_le32((pattrib->priority << SEQ_SHT) & 571 0x0fff0000); 572 /* offset 16 */ 573 ptxdesc->txdw4 = cpu_to_le32(0x80002040);/*gtest*/ 574 /* offset 20 */ 575 ptxdesc->txdw5 = cpu_to_le32(0x001f8000);/* gtest 1M */ 576 } else if (pxmitframe->frame_tag == TXAGG_FRAMETAG) { 577 /* offset 4 */ 578 qsel = 0x13; 579 ptxdesc->txdw1 |= cpu_to_le32((qsel << QSEL_SHT) & 0x00001f00); 580 } else { 581 /* offset 4 */ 582 qsel = (uint)(pattrib->priority & 0x0000001f); 583 ptxdesc->txdw1 |= cpu_to_le32((qsel << QSEL_SHT) & 0x00001f00); 584 /*offset 8*/ 585 /*offset 12*/ 586 ptxdesc->txdw3 = cpu_to_le32((pattrib->seqnum << SEQ_SHT) & 587 0x0fff0000); 588 /*offset 16*/ 589 ptxdesc->txdw4 = cpu_to_le32(0x80002040);/*gtest*/ 590 /*offset 20*/ 591 ptxdesc->txdw5 = cpu_to_le32(0x001f9600);/*gtest*/ 592 } 593 } 594 595 int r8712_xmitframe_complete(struct _adapter *padapter, 596 struct xmit_priv *pxmitpriv, 597 struct xmit_buf *pxmitbuf) 598 { 599 struct hw_xmit *phwxmits; 600 sint hwentry; 601 struct xmit_frame *pxmitframe = NULL; 602 #ifdef CONFIG_R8712_TX_AGGR 603 struct xmit_frame *p2ndxmitframe = NULL; 604 #else 605 int res = _SUCCESS, xcnt = 0; 606 #endif 607 608 phwxmits = pxmitpriv->hwxmits; 609 hwentry = pxmitpriv->hwxmit_entry; 610 if (!pxmitbuf) { 611 pxmitbuf = r8712_alloc_xmitbuf(pxmitpriv); 612 if (!pxmitbuf) 613 return false; 614 #ifdef CONFIG_R8712_TX_AGGR 615 pxmitbuf->aggr_nr = 0; 616 #endif 617 } 618 /* 1st frame dequeued */ 619 pxmitframe = dequeue_xframe_ex(pxmitpriv, phwxmits, hwentry); 620 /* need to remember the 1st frame */ 621 if (pxmitframe) { 622 623 #ifdef CONFIG_R8712_TX_AGGR 624 /* 1. dequeue 2nd frame 625 * 2. aggr if 2nd xframe is dequeued, else dump directly 626 */ 627 if (AGGR_NR_HIGH_BOUND > 1) 628 p2ndxmitframe = dequeue_xframe_ex(pxmitpriv, phwxmits, 629 hwentry); 630 if (pxmitframe->frame_tag != DATA_FRAMETAG) { 631 r8712_free_xmitbuf(pxmitpriv, pxmitbuf); 632 return false; 633 } 634 if (p2ndxmitframe) 635 if (p2ndxmitframe->frame_tag != DATA_FRAMETAG) { 636 r8712_free_xmitbuf(pxmitpriv, pxmitbuf); 637 return false; 638 } 639 r8712_xmitframe_aggr_1st(pxmitbuf, pxmitframe); 640 if (p2ndxmitframe) { 641 u16 total_length; 642 643 total_length = r8712_xmitframe_aggr_next( 644 pxmitbuf, p2ndxmitframe); 645 do { 646 p2ndxmitframe = dequeue_xframe_ex( 647 pxmitpriv, phwxmits, hwentry); 648 if (p2ndxmitframe) 649 total_length = 650 r8712_xmitframe_aggr_next( 651 pxmitbuf, 652 p2ndxmitframe); 653 else 654 break; 655 } while (total_length <= 0x1800 && 656 pxmitbuf->aggr_nr <= AGGR_NR_HIGH_BOUND); 657 } 658 if (pxmitbuf->aggr_nr > 0) 659 r8712_dump_aggr_xframe(pxmitbuf, pxmitframe); 660 661 #else 662 663 xmitframe_xmitbuf_attach(pxmitframe, pxmitbuf); 664 if (pxmitframe->frame_tag == DATA_FRAMETAG) { 665 if (pxmitframe->attrib.priority <= 15) 666 res = r8712_xmitframe_coalesce(padapter, 667 pxmitframe->pkt, pxmitframe); 668 /* always return ndis_packet after 669 * r8712_xmitframe_coalesce 670 */ 671 r8712_xmit_complete(padapter, pxmitframe); 672 } 673 if (res == _SUCCESS) 674 dump_xframe(padapter, pxmitframe); 675 else 676 r8712_free_xmitframe_ex(pxmitpriv, pxmitframe); 677 xcnt++; 678 #endif 679 680 } else { /* pxmitframe == NULL && p2ndxmitframe == NULL */ 681 r8712_free_xmitbuf(pxmitpriv, pxmitbuf); 682 return false; 683 } 684 return true; 685 } 686 687 static void dump_xframe(struct _adapter *padapter, 688 struct xmit_frame *pxmitframe) 689 { 690 int t, sz, w_sz; 691 u8 *mem_addr; 692 u32 ff_hwaddr; 693 struct pkt_attrib *pattrib = &pxmitframe->attrib; 694 struct xmit_priv *pxmitpriv = &padapter->xmitpriv; 695 struct security_priv *psecuritypriv = &padapter->securitypriv; 696 697 if (pxmitframe->attrib.ether_type != 0x0806) { 698 if (pxmitframe->attrib.ether_type != 0x888e) 699 r8712_issue_addbareq_cmd(padapter, pattrib->priority); 700 } 701 mem_addr = pxmitframe->buf_addr; 702 for (t = 0; t < pattrib->nr_frags; t++) { 703 if (t != (pattrib->nr_frags - 1)) { 704 sz = pxmitpriv->frag_len; 705 sz = sz - 4 - (psecuritypriv->sw_encrypt ? 0 : 706 pattrib->icv_len); 707 pxmitframe->last[t] = 0; 708 } else { 709 sz = pattrib->last_txcmdsz; 710 pxmitframe->last[t] = 1; 711 } 712 update_txdesc(pxmitframe, (uint *)mem_addr, sz); 713 w_sz = sz + TXDESC_SIZE; 714 pxmitframe->mem_addr = mem_addr; 715 pxmitframe->bpending[t] = false; 716 ff_hwaddr = get_ff_hwaddr(pxmitframe); 717 #ifdef CONFIG_R8712_TX_AGGR 718 r8712_write_port(padapter, RTL8712_DMA_H2CCMD, w_sz, 719 (unsigned char *)pxmitframe); 720 #else 721 r8712_write_port(padapter, ff_hwaddr, w_sz, 722 (unsigned char *)pxmitframe); 723 #endif 724 mem_addr += w_sz; 725 mem_addr = (u8 *)RND4(((addr_t)(mem_addr))); 726 } 727 } 728 729 void r8712_xmit_direct(struct _adapter *padapter, struct xmit_frame *pxmitframe) 730 { 731 int res; 732 733 res = r8712_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe); 734 pxmitframe->pkt = NULL; 735 if (res == _SUCCESS) 736 dump_xframe(padapter, pxmitframe); 737 } 738 739 int r8712_xmit_enqueue(struct _adapter *padapter, struct xmit_frame *pxmitframe) 740 { 741 if (r8712_xmit_classifier(padapter, pxmitframe)) { 742 pxmitframe->pkt = NULL; 743 return _FAIL; 744 } 745 return _SUCCESS; 746 } 747