aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/b43/pio.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/b43/pio.c')
-rw-r--r--drivers/net/wireless/b43/pio.c79
1 files changed, 40 insertions, 39 deletions
diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c
index 9c1397996e0a..9b9044400218 100644
--- a/drivers/net/wireless/b43/pio.c
+++ b/drivers/net/wireless/b43/pio.c
@@ -30,6 +30,7 @@
30#include "xmit.h" 30#include "xmit.h"
31 31
32#include <linux/delay.h> 32#include <linux/delay.h>
33#include <linux/sched.h>
33 34
34 35
35static u16 generate_cookie(struct b43_pio_txqueue *q, 36static u16 generate_cookie(struct b43_pio_txqueue *q,
@@ -331,6 +332,7 @@ static u16 tx_write_2byte_queue(struct b43_pio_txqueue *q,
331 unsigned int data_len) 332 unsigned int data_len)
332{ 333{
333 struct b43_wldev *dev = q->dev; 334 struct b43_wldev *dev = q->dev;
335 struct b43_wl *wl = dev->wl;
334 const u8 *data = _data; 336 const u8 *data = _data;
335 337
336 ctl |= B43_PIO_TXCTL_WRITELO | B43_PIO_TXCTL_WRITEHI; 338 ctl |= B43_PIO_TXCTL_WRITELO | B43_PIO_TXCTL_WRITEHI;
@@ -340,13 +342,12 @@ static u16 tx_write_2byte_queue(struct b43_pio_txqueue *q,
340 q->mmio_base + B43_PIO_TXDATA, 342 q->mmio_base + B43_PIO_TXDATA,
341 sizeof(u16)); 343 sizeof(u16));
342 if (data_len & 1) { 344 if (data_len & 1) {
343 u8 tail[2] = { 0, };
344
345 /* Write the last byte. */ 345 /* Write the last byte. */
346 ctl &= ~B43_PIO_TXCTL_WRITEHI; 346 ctl &= ~B43_PIO_TXCTL_WRITEHI;
347 b43_piotx_write16(q, B43_PIO_TXCTL, ctl); 347 b43_piotx_write16(q, B43_PIO_TXCTL, ctl);
348 tail[0] = data[data_len - 1]; 348 wl->tx_tail[0] = data[data_len - 1];
349 ssb_block_write(dev->dev, tail, 2, 349 wl->tx_tail[1] = 0;
350 ssb_block_write(dev->dev, wl->tx_tail, 2,
350 q->mmio_base + B43_PIO_TXDATA, 351 q->mmio_base + B43_PIO_TXDATA,
351 sizeof(u16)); 352 sizeof(u16));
352 } 353 }
@@ -381,6 +382,7 @@ static u32 tx_write_4byte_queue(struct b43_pio_txqueue *q,
381 unsigned int data_len) 382 unsigned int data_len)
382{ 383{
383 struct b43_wldev *dev = q->dev; 384 struct b43_wldev *dev = q->dev;
385 struct b43_wl *wl = dev->wl;
384 const u8 *data = _data; 386 const u8 *data = _data;
385 387
386 ctl |= B43_PIO8_TXCTL_0_7 | B43_PIO8_TXCTL_8_15 | 388 ctl |= B43_PIO8_TXCTL_0_7 | B43_PIO8_TXCTL_8_15 |
@@ -391,29 +393,31 @@ static u32 tx_write_4byte_queue(struct b43_pio_txqueue *q,
391 q->mmio_base + B43_PIO8_TXDATA, 393 q->mmio_base + B43_PIO8_TXDATA,
392 sizeof(u32)); 394 sizeof(u32));
393 if (data_len & 3) { 395 if (data_len & 3) {
394 u8 tail[4] = { 0, }; 396 wl->tx_tail[3] = 0;
395
396 /* Write the last few bytes. */ 397 /* Write the last few bytes. */
397 ctl &= ~(B43_PIO8_TXCTL_8_15 | B43_PIO8_TXCTL_16_23 | 398 ctl &= ~(B43_PIO8_TXCTL_8_15 | B43_PIO8_TXCTL_16_23 |
398 B43_PIO8_TXCTL_24_31); 399 B43_PIO8_TXCTL_24_31);
399 switch (data_len & 3) { 400 switch (data_len & 3) {
400 case 3: 401 case 3:
401 ctl |= B43_PIO8_TXCTL_16_23 | B43_PIO8_TXCTL_8_15; 402 ctl |= B43_PIO8_TXCTL_16_23 | B43_PIO8_TXCTL_8_15;
402 tail[0] = data[data_len - 3]; 403 wl->tx_tail[0] = data[data_len - 3];
403 tail[1] = data[data_len - 2]; 404 wl->tx_tail[1] = data[data_len - 2];
404 tail[2] = data[data_len - 1]; 405 wl->tx_tail[2] = data[data_len - 1];
405 break; 406 break;
406 case 2: 407 case 2:
407 ctl |= B43_PIO8_TXCTL_8_15; 408 ctl |= B43_PIO8_TXCTL_8_15;
408 tail[0] = data[data_len - 2]; 409 wl->tx_tail[0] = data[data_len - 2];
409 tail[1] = data[data_len - 1]; 410 wl->tx_tail[1] = data[data_len - 1];
411 wl->tx_tail[2] = 0;
410 break; 412 break;
411 case 1: 413 case 1:
412 tail[0] = data[data_len - 1]; 414 wl->tx_tail[0] = data[data_len - 1];
415 wl->tx_tail[1] = 0;
416 wl->tx_tail[2] = 0;
413 break; 417 break;
414 } 418 }
415 b43_piotx_write32(q, B43_PIO8_TXCTL, ctl); 419 b43_piotx_write32(q, B43_PIO8_TXCTL, ctl);
416 ssb_block_write(dev->dev, tail, 4, 420 ssb_block_write(dev->dev, wl->tx_tail, 4,
417 q->mmio_base + B43_PIO8_TXDATA, 421 q->mmio_base + B43_PIO8_TXDATA,
418 sizeof(u32)); 422 sizeof(u32));
419 } 423 }
@@ -445,8 +449,9 @@ static void pio_tx_frame_4byte_queue(struct b43_pio_txpacket *pack,
445static int pio_tx_frame(struct b43_pio_txqueue *q, 449static int pio_tx_frame(struct b43_pio_txqueue *q,
446 struct sk_buff *skb) 450 struct sk_buff *skb)
447{ 451{
452 struct b43_wldev *dev = q->dev;
453 struct b43_wl *wl = dev->wl;
448 struct b43_pio_txpacket *pack; 454 struct b43_pio_txpacket *pack;
449 struct b43_txhdr txhdr;
450 u16 cookie; 455 u16 cookie;
451 int err; 456 int err;
452 unsigned int hdrlen; 457 unsigned int hdrlen;
@@ -457,8 +462,8 @@ static int pio_tx_frame(struct b43_pio_txqueue *q,
457 struct b43_pio_txpacket, list); 462 struct b43_pio_txpacket, list);
458 463
459 cookie = generate_cookie(q, pack); 464 cookie = generate_cookie(q, pack);
460 hdrlen = b43_txhdr_size(q->dev); 465 hdrlen = b43_txhdr_size(dev);
461 err = b43_generate_txhdr(q->dev, (u8 *)&txhdr, skb, 466 err = b43_generate_txhdr(dev, (u8 *)&wl->txhdr, skb,
462 info, cookie); 467 info, cookie);
463 if (err) 468 if (err)
464 return err; 469 return err;
@@ -466,15 +471,15 @@ static int pio_tx_frame(struct b43_pio_txqueue *q,
466 if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) { 471 if (info->flags & IEEE80211_TX_CTL_SEND_AFTER_DTIM) {
467 /* Tell the firmware about the cookie of the last 472 /* Tell the firmware about the cookie of the last
468 * mcast frame, so it can clear the more-data bit in it. */ 473 * mcast frame, so it can clear the more-data bit in it. */
469 b43_shm_write16(q->dev, B43_SHM_SHARED, 474 b43_shm_write16(dev, B43_SHM_SHARED,
470 B43_SHM_SH_MCASTCOOKIE, cookie); 475 B43_SHM_SH_MCASTCOOKIE, cookie);
471 } 476 }
472 477
473 pack->skb = skb; 478 pack->skb = skb;
474 if (q->rev >= 8) 479 if (q->rev >= 8)
475 pio_tx_frame_4byte_queue(pack, (const u8 *)&txhdr, hdrlen); 480 pio_tx_frame_4byte_queue(pack, (const u8 *)&wl->txhdr, hdrlen);
476 else 481 else
477 pio_tx_frame_2byte_queue(pack, (const u8 *)&txhdr, hdrlen); 482 pio_tx_frame_2byte_queue(pack, (const u8 *)&wl->txhdr, hdrlen);
478 483
479 /* Remove it from the list of available packet slots. 484 /* Remove it from the list of available packet slots.
480 * It will be put back when we receive the status report. */ 485 * It will be put back when we receive the status report. */
@@ -614,14 +619,14 @@ void b43_pio_get_tx_stats(struct b43_wldev *dev,
614static bool pio_rx_frame(struct b43_pio_rxqueue *q) 619static bool pio_rx_frame(struct b43_pio_rxqueue *q)
615{ 620{
616 struct b43_wldev *dev = q->dev; 621 struct b43_wldev *dev = q->dev;
617 struct b43_rxhdr_fw4 rxhdr; 622 struct b43_wl *wl = dev->wl;
618 u16 len; 623 u16 len;
619 u32 macstat; 624 u32 macstat;
620 unsigned int i, padding; 625 unsigned int i, padding;
621 struct sk_buff *skb; 626 struct sk_buff *skb;
622 const char *err_msg = NULL; 627 const char *err_msg = NULL;
623 628
624 memset(&rxhdr, 0, sizeof(rxhdr)); 629 memset(&wl->rxhdr, 0, sizeof(wl->rxhdr));
625 630
626 /* Check if we have data and wait for it to get ready. */ 631 /* Check if we have data and wait for it to get ready. */
627 if (q->rev >= 8) { 632 if (q->rev >= 8) {
@@ -659,16 +664,16 @@ data_ready:
659 664
660 /* Get the preamble (RX header) */ 665 /* Get the preamble (RX header) */
661 if (q->rev >= 8) { 666 if (q->rev >= 8) {
662 ssb_block_read(dev->dev, &rxhdr, sizeof(rxhdr), 667 ssb_block_read(dev->dev, &wl->rxhdr, sizeof(wl->rxhdr),
663 q->mmio_base + B43_PIO8_RXDATA, 668 q->mmio_base + B43_PIO8_RXDATA,
664 sizeof(u32)); 669 sizeof(u32));
665 } else { 670 } else {
666 ssb_block_read(dev->dev, &rxhdr, sizeof(rxhdr), 671 ssb_block_read(dev->dev, &wl->rxhdr, sizeof(wl->rxhdr),
667 q->mmio_base + B43_PIO_RXDATA, 672 q->mmio_base + B43_PIO_RXDATA,
668 sizeof(u16)); 673 sizeof(u16));
669 } 674 }
670 /* Sanity checks. */ 675 /* Sanity checks. */
671 len = le16_to_cpu(rxhdr.frame_len); 676 len = le16_to_cpu(wl->rxhdr.frame_len);
672 if (unlikely(len > 0x700)) { 677 if (unlikely(len > 0x700)) {
673 err_msg = "len > 0x700"; 678 err_msg = "len > 0x700";
674 goto rx_error; 679 goto rx_error;
@@ -678,7 +683,7 @@ data_ready:
678 goto rx_error; 683 goto rx_error;
679 } 684 }
680 685
681 macstat = le32_to_cpu(rxhdr.mac_status); 686 macstat = le32_to_cpu(wl->rxhdr.mac_status);
682 if (macstat & B43_RX_MAC_FCSERR) { 687 if (macstat & B43_RX_MAC_FCSERR) {
683 if (!(q->dev->wl->filter_flags & FIF_FCSFAIL)) { 688 if (!(q->dev->wl->filter_flags & FIF_FCSFAIL)) {
684 /* Drop frames with failed FCS. */ 689 /* Drop frames with failed FCS. */
@@ -703,24 +708,22 @@ data_ready:
703 q->mmio_base + B43_PIO8_RXDATA, 708 q->mmio_base + B43_PIO8_RXDATA,
704 sizeof(u32)); 709 sizeof(u32));
705 if (len & 3) { 710 if (len & 3) {
706 u8 tail[4] = { 0, };
707
708 /* Read the last few bytes. */ 711 /* Read the last few bytes. */
709 ssb_block_read(dev->dev, tail, 4, 712 ssb_block_read(dev->dev, wl->rx_tail, 4,
710 q->mmio_base + B43_PIO8_RXDATA, 713 q->mmio_base + B43_PIO8_RXDATA,
711 sizeof(u32)); 714 sizeof(u32));
712 switch (len & 3) { 715 switch (len & 3) {
713 case 3: 716 case 3:
714 skb->data[len + padding - 3] = tail[0]; 717 skb->data[len + padding - 3] = wl->rx_tail[0];
715 skb->data[len + padding - 2] = tail[1]; 718 skb->data[len + padding - 2] = wl->rx_tail[1];
716 skb->data[len + padding - 1] = tail[2]; 719 skb->data[len + padding - 1] = wl->rx_tail[2];
717 break; 720 break;
718 case 2: 721 case 2:
719 skb->data[len + padding - 2] = tail[0]; 722 skb->data[len + padding - 2] = wl->rx_tail[0];
720 skb->data[len + padding - 1] = tail[1]; 723 skb->data[len + padding - 1] = wl->rx_tail[1];
721 break; 724 break;
722 case 1: 725 case 1:
723 skb->data[len + padding - 1] = tail[0]; 726 skb->data[len + padding - 1] = wl->rx_tail[0];
724 break; 727 break;
725 } 728 }
726 } 729 }
@@ -729,17 +732,15 @@ data_ready:
729 q->mmio_base + B43_PIO_RXDATA, 732 q->mmio_base + B43_PIO_RXDATA,
730 sizeof(u16)); 733 sizeof(u16));
731 if (len & 1) { 734 if (len & 1) {
732 u8 tail[2] = { 0, };
733
734 /* Read the last byte. */ 735 /* Read the last byte. */
735 ssb_block_read(dev->dev, tail, 2, 736 ssb_block_read(dev->dev, wl->rx_tail, 2,
736 q->mmio_base + B43_PIO_RXDATA, 737 q->mmio_base + B43_PIO_RXDATA,
737 sizeof(u16)); 738 sizeof(u16));
738 skb->data[len + padding - 1] = tail[0]; 739 skb->data[len + padding - 1] = wl->rx_tail[0];
739 } 740 }
740 } 741 }
741 742
742 b43_rx(q->dev, skb, &rxhdr); 743 b43_rx(q->dev, skb, &wl->rxhdr);
743 744
744 return 1; 745 return 1;
745 746