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