Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

staging: r8712u: Merging Realtek's latest (v2.6.6). Tx aggregation.

Tx Aggregation (CONFIG_R8712_TX_AGGR, known as CONFIG_USB_TX_AGGR in the
Realtek tarball) is now added.

However, its tests have not been successful! The default in the Realtek
tarball is to not build it -- and the Release Notes does not seem to list this
as a feature. I have tested the driver with and without this feature; the
former does not successfully associate when WPA2 is used.

Signed-off-by: Ali Bahar <ali@internetDog.org>
Signed-off-by: Larry Finger <Larry.Finger@lwfinger.net>
Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>

authored by

Ali Bahar and committed by
Greg Kroah-Hartman
93c55dda ee5b1aad

+266 -2
+7
drivers/staging/rtl8712/Kconfig
··· 16 16 ---help--- 17 17 This option allows the Realtek RTL8712 USB device to be an Access Point. 18 18 19 + config R8712_TX_AGGR 20 + bool "Realtek RTL8712U Transmit Aggregation code" 21 + depends on R8712U && BROKEN 22 + default N 23 + ---help--- 24 + This option provides transmit aggregation for the Realtek RTL8712 USB device. 25 + 19 26
+239
drivers/staging/rtl8712/rtl8712_xmit.c
··· 260 260 pattrib->qsel = qsel; 261 261 } 262 262 263 + #ifdef CONFIG_R8712_TX_AGGR 264 + u8 r8712_construct_txaggr_cmd_desc(struct xmit_buf *pxmitbuf) 265 + { 266 + struct tx_desc *ptx_desc = (struct tx_desc *)pxmitbuf->pbuf; 267 + 268 + /* Fill up TxCmd Descriptor according as USB FW Tx Aaggregation info.*/ 269 + /* dw0 */ 270 + ptx_desc->txdw0 = cpu_to_le32(CMD_HDR_SZ&0xffff); 271 + ptx_desc->txdw0 |= 272 + cpu_to_le32(((TXDESC_SIZE+OFFSET_SZ)<<OFFSET_SHT)&0x00ff0000); 273 + ptx_desc->txdw0 |= cpu_to_le32(OWN | FSG | LSG); 274 + 275 + /* dw1 */ 276 + ptx_desc->txdw1 |= cpu_to_le32((0x13<<QSEL_SHT)&0x00001f00); 277 + 278 + return _SUCCESS; 279 + } 280 + 281 + u8 r8712_construct_txaggr_cmd_hdr(struct xmit_buf *pxmitbuf) 282 + { 283 + struct xmit_frame *pxmitframe = (struct xmit_frame *) 284 + pxmitbuf->priv_data; 285 + struct _adapter *padapter = pxmitframe->padapter; 286 + struct cmd_priv *pcmdpriv = &(padapter->cmdpriv); 287 + struct cmd_hdr *pcmd_hdr = (struct cmd_hdr *) 288 + (pxmitbuf->pbuf + TXDESC_SIZE); 289 + 290 + /* Fill up Cmd Header for USB FW Tx Aggregation.*/ 291 + /* dw0 */ 292 + pcmd_hdr->cmd_dw0 = cpu_to_le32((GEN_CMD_CODE(_AMSDU_TO_AMPDU) << 16) | 293 + (pcmdpriv->cmd_seq << 24)); 294 + pcmdpriv->cmd_seq++; 295 + 296 + return _SUCCESS; 297 + } 298 + 299 + u8 r8712_append_mpdu_unit(struct xmit_buf *pxmitbuf, 300 + struct xmit_frame *pxmitframe) 301 + { 302 + struct _adapter *padapter = pxmitframe->padapter; 303 + struct tx_desc *ptx_desc = (struct tx_desc *)pxmitbuf->pbuf; 304 + int last_txcmdsz = 0; 305 + int padding_sz = 0; 306 + 307 + /* 802.3->802.11 convertor */ 308 + r8712_xmitframe_coalesce(padapter, pxmitframe->pkt, pxmitframe); 309 + /* free skb struct */ 310 + r8712_xmit_complete(padapter, pxmitframe); 311 + if (pxmitframe->attrib.ether_type != 0x0806) { 312 + if ((pxmitframe->attrib.ether_type != 0x888e) && 313 + (pxmitframe->attrib.dhcp_pkt != 1)) { 314 + r8712_issue_addbareq_cmd(padapter, 315 + pxmitframe->attrib.priority); 316 + } 317 + } 318 + pxmitframe->last[0] = 1; 319 + update_txdesc(pxmitframe, (uint *)(pxmitframe->buf_addr), 320 + pxmitframe->attrib.last_txcmdsz); 321 + /*padding zero */ 322 + last_txcmdsz = pxmitframe->attrib.last_txcmdsz; 323 + padding_sz = (8 - (last_txcmdsz % 8)); 324 + if ((last_txcmdsz % 8) != 0) { 325 + int i; 326 + for (i = 0; i < padding_sz; i++) 327 + *(pxmitframe->buf_addr+TXDESC_SIZE+last_txcmdsz+i) = 0; 328 + } 329 + /* Add the new mpdu's length */ 330 + ptx_desc->txdw0 = cpu_to_le32((ptx_desc->txdw0&0xffff0000) | 331 + ((ptx_desc->txdw0&0x0000ffff)+ 332 + ((TXDESC_SIZE+last_txcmdsz+padding_sz)&0x0000ffff))); 333 + 334 + return _SUCCESS; 335 + } 336 + 337 + 338 + u8 r8712_xmitframe_aggr_1st(struct xmit_buf *pxmitbuf, 339 + struct xmit_frame *pxmitframe) 340 + { 341 + /* linux complete context doesnt need to protect */ 342 + pxmitframe->pxmitbuf = pxmitbuf; 343 + pxmitbuf->priv_data = pxmitframe; 344 + pxmitframe->pxmit_urb[0] = pxmitbuf->pxmit_urb[0]; 345 + /* buffer addr assoc */ 346 + pxmitframe->buf_addr = pxmitbuf->pbuf+TXDESC_SIZE+CMD_HDR_SZ; 347 + /*RTL8712_DMA_H2CCMD */ 348 + r8712_construct_txaggr_cmd_desc(pxmitbuf); 349 + r8712_construct_txaggr_cmd_hdr(pxmitbuf); 350 + if (r8712_append_mpdu_unit(pxmitbuf, pxmitframe) == _SUCCESS) 351 + pxmitbuf->aggr_nr = 1; 352 + 353 + return _SUCCESS; 354 + } 355 + 356 + u16 r8712_xmitframe_aggr_next(struct xmit_buf *pxmitbuf, 357 + struct xmit_frame *pxmitframe) 358 + { 359 + pxmitframe->pxmitbuf = pxmitbuf; 360 + pxmitbuf->priv_data = pxmitframe; 361 + pxmitframe->pxmit_urb[0] = pxmitbuf->pxmit_urb[0]; 362 + /* buffer addr assoc */ 363 + pxmitframe->buf_addr = pxmitbuf->pbuf + TXDESC_SIZE + 364 + (((struct tx_desc *)pxmitbuf->pbuf)->txdw0 & 0x0000ffff); 365 + if (r8712_append_mpdu_unit(pxmitbuf, pxmitframe) == _SUCCESS) { 366 + r8712_free_xmitframe_ex(&pxmitframe->padapter->xmitpriv, 367 + pxmitframe); 368 + pxmitbuf->aggr_nr++; 369 + } 370 + 371 + return TXDESC_SIZE + 372 + (((struct tx_desc *)pxmitbuf->pbuf)->txdw0 & 0x0000ffff); 373 + } 374 + 375 + u8 r8712_dump_aggr_xframe(struct xmit_buf *pxmitbuf, 376 + struct xmit_frame *pxmitframe) 377 + { 378 + struct _adapter *padapter = pxmitframe->padapter; 379 + struct dvobj_priv *pdvobj = (struct dvobj_priv *) &padapter->dvobjpriv; 380 + struct tx_desc * ptxdesc = (struct tx_desc *)pxmitbuf->pbuf; 381 + struct cmd_hdr *pcmd_hdr = (struct cmd_hdr *) 382 + (pxmitbuf->pbuf + TXDESC_SIZE); 383 + u16 total_length = (u16) (ptxdesc->txdw0 & 0xffff); 384 + 385 + /* use 1st xmitframe as media */ 386 + xmitframe_xmitbuf_attach(pxmitframe, pxmitbuf); 387 + pcmd_hdr->cmd_dw0 = cpu_to_le32(((total_length-CMD_HDR_SZ)&0x0000ffff)| 388 + (pcmd_hdr->cmd_dw0&0xffff0000)); 389 + 390 + /* urb length in cmd_dw1 */ 391 + pcmd_hdr->cmd_dw1 = cpu_to_le32((pxmitbuf->aggr_nr & 0xff)| 392 + ((total_length+TXDESC_SIZE) << 16)); 393 + pxmitframe->last[0] = 1; 394 + pxmitframe->bpending[0] = false; 395 + pxmitframe->mem_addr = pxmitbuf->pbuf; 396 + 397 + if ((pdvobj->ishighspeed && ((total_length+TXDESC_SIZE)%0x200) == 0) || 398 + ((!pdvobj->ishighspeed && 399 + ((total_length+TXDESC_SIZE)%0x40) == 0))) { 400 + ptxdesc->txdw0 |= cpu_to_le32 401 + (((TXDESC_SIZE+OFFSET_SZ+8)<<OFFSET_SHT)&0x00ff0000); 402 + /*32 bytes for TX Desc + 8 bytes pending*/ 403 + } else { 404 + ptxdesc->txdw0 |= cpu_to_le32 405 + (((TXDESC_SIZE+OFFSET_SZ)<<OFFSET_SHT)&0x00ff0000); 406 + /*default = 32 bytes for TX Desc*/ 407 + } 408 + r8712_write_port(pxmitframe->padapter, RTL8712_DMA_H2CCMD, 409 + total_length+TXDESC_SIZE, (u8 *)pxmitframe); 410 + 411 + return _SUCCESS; 412 + } 413 + 414 + #endif 415 + 263 416 static void update_txdesc(struct xmit_frame *pxmitframe, uint *pmem, int sz) 264 417 { 265 418 uint qsel; ··· 423 270 struct pkt_attrib *pattrib = &pxmitframe->attrib; 424 271 struct tx_desc *ptxdesc = (struct tx_desc *)pmem; 425 272 struct dvobj_priv *pdvobj = (struct dvobj_priv *)&padapter->dvobjpriv; 273 + #ifdef CONFIG_R8712_TX_AGGR 274 + struct cmd_priv *pcmdpriv = (struct cmd_priv *)&padapter->cmdpriv; 275 + #endif 426 276 u8 blnSetTxDescOffset; 427 277 sint bmcst = IS_MCAST(pattrib->ra); 428 278 struct ht_priv *phtpriv = &pmlmepriv->htpriv; ··· 459 303 if (pxmitframe->frame_tag == DATA_FRAMETAG) { 460 304 /* offset 4 */ 461 305 ptxdesc->txdw1 |= cpu_to_le32((pattrib->mac_id)&0x1f); 306 + 307 + #ifdef CONFIG_R8712_TX_AGGR 308 + /* dirty workaround, need to check if it is aggr cmd. */ 309 + if ((u8 *)pmem != (u8 *)pxmitframe->pxmitbuf->pbuf) { 310 + ptxdesc->txdw0 |= cpu_to_le32 311 + ((0x3 << TYPE_SHT)&TYPE_MSK); 312 + qsel = (uint)(pattrib->qsel & 0x0000001f); 313 + if (qsel == 2) 314 + qsel = 0; 315 + ptxdesc->txdw1 |= cpu_to_le32 316 + ((qsel << QSEL_SHT) & 0x00001f00); 317 + ptxdesc->txdw2 = cpu_to_le32 318 + ((qsel << RTS_RC_SHT)&0x001f0000); 319 + ptxdesc->txdw6 |= cpu_to_le32 320 + ((0x5 << RSVD6_SHT)&RSVD6_MSK); 321 + } else { 322 + ptxdesc->txdw0 |= cpu_to_le32 323 + ((0x3 << TYPE_SHT)&TYPE_MSK); 324 + ptxdesc->txdw1 |= cpu_to_le32 325 + ((0x13 << QSEL_SHT) & 0x00001f00); 326 + qsel = (uint)(pattrib->qsel & 0x0000001f); 327 + if (qsel == 2) 328 + qsel = 0; 329 + ptxdesc->txdw2 = cpu_to_le32 330 + ((qsel << RTS_RC_SHT)&0x0001f000); 331 + ptxdesc->txdw7 |= cpu_to_le32 332 + (pcmdpriv->cmd_seq << 24); 333 + pcmdpriv->cmd_seq++; 334 + } 335 + pattrib->qsel = 0x13; 336 + #else 462 337 qsel = (uint)(pattrib->qsel & 0x0000001f); 463 338 ptxdesc->txdw1 |= cpu_to_le32((qsel << QSEL_SHT) & 0x00001f00); 339 + #endif 464 340 if (!pqospriv->qos_option) 465 341 ptxdesc->txdw1 |= cpu_to_le32(BIT(16));/*Non-QoS*/ 466 342 if ((pattrib->encrypt > 0) && !pattrib->bswenc) { ··· 614 426 struct hw_xmit *phwxmits; 615 427 sint hwentry; 616 428 struct xmit_frame *pxmitframe = NULL; 429 + #ifdef CONFIG_R8712_TX_AGGR 430 + struct xmit_frame *p2ndxmitframe = NULL; 431 + #else 617 432 int res = _SUCCESS, xcnt = 0; 433 + #endif 618 434 619 435 phwxmits = pxmitpriv->hwxmits; 620 436 hwentry = pxmitpriv->hwxmit_entry; ··· 626 434 pxmitbuf = r8712_alloc_xmitbuf(pxmitpriv); 627 435 if (!pxmitbuf) 628 436 return false; 437 + #ifdef CONFIG_R8712_TX_AGGR 438 + pxmitbuf->aggr_nr = 0; 439 + #endif 629 440 } 630 441 /* 1st frame dequeued */ 631 442 pxmitframe = dequeue_xframe_ex(pxmitpriv, phwxmits, hwentry); 632 443 /* need to remember the 1st frame */ 633 444 if (pxmitframe != NULL) { 634 445 446 + #ifdef CONFIG_R8712_TX_AGGR 447 + /* 1. dequeue 2nd frame 448 + * 2. aggr if 2nd xframe is dequeued, else dump directly 449 + */ 450 + if (AGGR_NR_HIGH_BOUND > 1) 451 + p2ndxmitframe = dequeue_xframe_ex(pxmitpriv, phwxmits, 452 + hwentry); 453 + if (pxmitframe->frame_tag != DATA_FRAMETAG) { 454 + r8712_free_xmitbuf(pxmitpriv, pxmitbuf); 455 + return false; 456 + } 457 + if (p2ndxmitframe != NULL) 458 + if (p2ndxmitframe->frame_tag != DATA_FRAMETAG) { 459 + r8712_free_xmitbuf(pxmitpriv, pxmitbuf); 460 + return false; 461 + } 462 + r8712_xmitframe_aggr_1st(pxmitbuf, pxmitframe); 463 + if (p2ndxmitframe != NULL) { 464 + u16 total_length; 465 + total_length = r8712_xmitframe_aggr_next( 466 + pxmitbuf, p2ndxmitframe); 467 + do { 468 + p2ndxmitframe = dequeue_xframe_ex( 469 + pxmitpriv, phwxmits, hwentry); 470 + if (p2ndxmitframe != NULL) 471 + total_length = 472 + r8712_xmitframe_aggr_next( 473 + pxmitbuf, 474 + p2ndxmitframe); 475 + else 476 + break; 477 + } while (total_length <= 0x1800 && 478 + pxmitbuf->aggr_nr <= AGGR_NR_HIGH_BOUND); 479 + } 480 + if (pxmitbuf->aggr_nr > 0) 481 + r8712_dump_aggr_xframe(pxmitbuf, pxmitframe); 482 + 483 + #else 635 484 636 485 xmitframe_xmitbuf_attach(pxmitframe, pxmitbuf); 637 486 if (pxmitframe->frame_tag == DATA_FRAMETAG) { ··· 688 455 else 689 456 r8712_free_xmitframe_ex(pxmitpriv, pxmitframe); 690 457 xcnt++; 458 + #endif 691 459 692 460 } else { /* pxmitframe == NULL && p2ndxmitframe == NULL */ 693 461 r8712_free_xmitbuf(pxmitpriv, pxmitbuf); ··· 727 493 pxmitframe->mem_addr = mem_addr; 728 494 pxmitframe->bpending[t] = false; 729 495 ff_hwaddr = get_ff_hwaddr(pxmitframe); 496 + #ifdef CONFIG_R8712_TX_AGGR 497 + r8712_write_port(padapter, RTL8712_DMA_H2CCMD, w_sz, 498 + (unsigned char *)pxmitframe); 499 + #else 730 500 r8712_write_port(padapter, ff_hwaddr, w_sz, 731 501 (unsigned char *)pxmitframe); 502 + #endif 732 503 mem_addr += w_sz; 733 504 mem_addr = (u8 *)RND4(((addr_t)(mem_addr))); 734 505 }
+7
drivers/staging/rtl8712/rtl8712_xmit.h
··· 113 113 void r8712_do_queue_select(struct _adapter *padapter, 114 114 struct pkt_attrib *pattrib); 115 115 116 + #ifdef CONFIG_R8712_TX_AGGR 117 + u8 r8712_xmitframe_aggr_1st(struct xmit_buf *pxmitbuf, 118 + struct xmit_frame *pxmitframe); 119 + u8 r8712_dump_aggr_xframe(struct xmit_buf *pxmitbuf, 120 + struct xmit_frame *pxmitframe); 121 + #endif 122 + 116 123 #endif
+13 -2
drivers/staging/rtl8712/rtl871x_xmit.h
··· 30 30 #include "drv_types.h" 31 31 #include "xmit_osdep.h" 32 32 33 - #define MAX_XMITBUF_SZ (2048) 34 - #define NR_XMITBUFF (4) 33 + #ifdef CONFIG_R8712_TX_AGGR 34 + #define MAX_XMITBUF_SZ (16384) 35 + #else 36 + #define MAX_XMITBUF_SZ (2048) 37 + #endif 38 + 39 + #define NR_XMITBUFF (4) 40 + 41 + #ifdef CONFIG_R8712_TX_AGGR 42 + #define AGGR_NR_HIGH_BOUND (4) /*(8) */ 43 + #define AGGR_NR_LOW_BOUND (2) 44 + #endif 45 + 35 46 #define XMITBUF_ALIGN_SZ 512 36 47 #define TX_GUARD_BAND 5 37 48 #define MAX_NUMBLKS (1)