aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/b43/pio.c
diff options
context:
space:
mode:
authorAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
committerAndrea Bastoni <bastoni@cs.unc.edu>2010-05-30 19:16:45 -0400
commitada47b5fe13d89735805b566185f4885f5a3f750 (patch)
tree644b88f8a71896307d71438e9b3af49126ffb22b /drivers/net/wireless/b43/pio.c
parent43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff)
parent3280f21d43ee541f97f8cda5792150d2dbec20d5 (diff)
Merge branch 'wip-2.6.34' into old-private-masterarchived-private-master
Diffstat (limited to 'drivers/net/wireless/b43/pio.c')
-rw-r--r--drivers/net/wireless/b43/pio.c103
1 files changed, 53 insertions, 50 deletions
diff --git a/drivers/net/wireless/b43/pio.c b/drivers/net/wireless/b43/pio.c
index 9b9044400218..aa12273ae716 100644
--- a/drivers/net/wireless/b43/pio.c
+++ b/drivers/net/wireless/b43/pio.c
@@ -31,6 +31,7 @@
31 31
32#include <linux/delay.h> 32#include <linux/delay.h>
33#include <linux/sched.h> 33#include <linux/sched.h>
34#include <linux/slab.h>
34 35
35 36
36static u16 generate_cookie(struct b43_pio_txqueue *q, 37static u16 generate_cookie(struct b43_pio_txqueue *q,
@@ -342,12 +343,15 @@ static u16 tx_write_2byte_queue(struct b43_pio_txqueue *q,
342 q->mmio_base + B43_PIO_TXDATA, 343 q->mmio_base + B43_PIO_TXDATA,
343 sizeof(u16)); 344 sizeof(u16));
344 if (data_len & 1) { 345 if (data_len & 1) {
346 u8 *tail = wl->pio_tailspace;
347 BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 2);
348
345 /* Write the last byte. */ 349 /* Write the last byte. */
346 ctl &= ~B43_PIO_TXCTL_WRITEHI; 350 ctl &= ~B43_PIO_TXCTL_WRITEHI;
347 b43_piotx_write16(q, B43_PIO_TXCTL, ctl); 351 b43_piotx_write16(q, B43_PIO_TXCTL, ctl);
348 wl->tx_tail[0] = data[data_len - 1]; 352 tail[0] = data[data_len - 1];
349 wl->tx_tail[1] = 0; 353 tail[1] = 0;
350 ssb_block_write(dev->dev, wl->tx_tail, 2, 354 ssb_block_write(dev->dev, tail, 2,
351 q->mmio_base + B43_PIO_TXDATA, 355 q->mmio_base + B43_PIO_TXDATA,
352 sizeof(u16)); 356 sizeof(u16));
353 } 357 }
@@ -393,31 +397,31 @@ static u32 tx_write_4byte_queue(struct b43_pio_txqueue *q,
393 q->mmio_base + B43_PIO8_TXDATA, 397 q->mmio_base + B43_PIO8_TXDATA,
394 sizeof(u32)); 398 sizeof(u32));
395 if (data_len & 3) { 399 if (data_len & 3) {
396 wl->tx_tail[3] = 0; 400 u8 *tail = wl->pio_tailspace;
401 BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 4);
402
403 memset(tail, 0, 4);
397 /* Write the last few bytes. */ 404 /* Write the last few bytes. */
398 ctl &= ~(B43_PIO8_TXCTL_8_15 | B43_PIO8_TXCTL_16_23 | 405 ctl &= ~(B43_PIO8_TXCTL_8_15 | B43_PIO8_TXCTL_16_23 |
399 B43_PIO8_TXCTL_24_31); 406 B43_PIO8_TXCTL_24_31);
400 switch (data_len & 3) { 407 switch (data_len & 3) {
401 case 3: 408 case 3:
402 ctl |= B43_PIO8_TXCTL_16_23 | B43_PIO8_TXCTL_8_15; 409 ctl |= B43_PIO8_TXCTL_16_23 | B43_PIO8_TXCTL_8_15;
403 wl->tx_tail[0] = data[data_len - 3]; 410 tail[0] = data[data_len - 3];
404 wl->tx_tail[1] = data[data_len - 2]; 411 tail[1] = data[data_len - 2];
405 wl->tx_tail[2] = data[data_len - 1]; 412 tail[2] = data[data_len - 1];
406 break; 413 break;
407 case 2: 414 case 2:
408 ctl |= B43_PIO8_TXCTL_8_15; 415 ctl |= B43_PIO8_TXCTL_8_15;
409 wl->tx_tail[0] = data[data_len - 2]; 416 tail[0] = data[data_len - 2];
410 wl->tx_tail[1] = data[data_len - 1]; 417 tail[1] = data[data_len - 1];
411 wl->tx_tail[2] = 0;
412 break; 418 break;
413 case 1: 419 case 1:
414 wl->tx_tail[0] = data[data_len - 1]; 420 tail[0] = data[data_len - 1];
415 wl->tx_tail[1] = 0;
416 wl->tx_tail[2] = 0;
417 break; 421 break;
418 } 422 }
419 b43_piotx_write32(q, B43_PIO8_TXCTL, ctl); 423 b43_piotx_write32(q, B43_PIO8_TXCTL, ctl);
420 ssb_block_write(dev->dev, wl->tx_tail, 4, 424 ssb_block_write(dev->dev, tail, 4,
421 q->mmio_base + B43_PIO8_TXDATA, 425 q->mmio_base + B43_PIO8_TXDATA,
422 sizeof(u32)); 426 sizeof(u32));
423 } 427 }
@@ -456,6 +460,7 @@ static int pio_tx_frame(struct b43_pio_txqueue *q,
456 int err; 460 int err;
457 unsigned int hdrlen; 461 unsigned int hdrlen;
458 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb); 462 struct ieee80211_tx_info *info = IEEE80211_SKB_CB(skb);
463 struct b43_txhdr *txhdr = (struct b43_txhdr *)wl->pio_scratchspace;
459 464
460 B43_WARN_ON(list_empty(&q->packets_list)); 465 B43_WARN_ON(list_empty(&q->packets_list));
461 pack = list_entry(q->packets_list.next, 466 pack = list_entry(q->packets_list.next,
@@ -463,7 +468,9 @@ static int pio_tx_frame(struct b43_pio_txqueue *q,
463 468
464 cookie = generate_cookie(q, pack); 469 cookie = generate_cookie(q, pack);
465 hdrlen = b43_txhdr_size(dev); 470 hdrlen = b43_txhdr_size(dev);
466 err = b43_generate_txhdr(dev, (u8 *)&wl->txhdr, skb, 471 BUILD_BUG_ON(sizeof(wl->pio_scratchspace) < sizeof(struct b43_txhdr));
472 B43_WARN_ON(sizeof(wl->pio_scratchspace) < hdrlen);
473 err = b43_generate_txhdr(dev, (u8 *)txhdr, skb,
467 info, cookie); 474 info, cookie);
468 if (err) 475 if (err)
469 return err; 476 return err;
@@ -477,9 +484,9 @@ static int pio_tx_frame(struct b43_pio_txqueue *q,
477 484
478 pack->skb = skb; 485 pack->skb = skb;
479 if (q->rev >= 8) 486 if (q->rev >= 8)
480 pio_tx_frame_4byte_queue(pack, (const u8 *)&wl->txhdr, hdrlen); 487 pio_tx_frame_4byte_queue(pack, (const u8 *)txhdr, hdrlen);
481 else 488 else
482 pio_tx_frame_2byte_queue(pack, (const u8 *)&wl->txhdr, hdrlen); 489 pio_tx_frame_2byte_queue(pack, (const u8 *)txhdr, hdrlen);
483 490
484 /* Remove it from the list of available packet slots. 491 /* Remove it from the list of available packet slots.
485 * It will be put back when we receive the status report. */ 492 * It will be put back when we receive the status report. */
@@ -553,7 +560,6 @@ int b43_pio_tx(struct b43_wldev *dev, struct sk_buff *skb)
553 b43err(dev->wl, "PIO transmission failure\n"); 560 b43err(dev->wl, "PIO transmission failure\n");
554 goto out; 561 goto out;
555 } 562 }
556 q->nr_tx_packets++;
557 563
558 B43_WARN_ON(q->buffer_used > q->buffer_size); 564 B43_WARN_ON(q->buffer_used > q->buffer_size);
559 if (((q->buffer_size - q->buffer_used) < roundup(2 + 2 + 6, 4)) || 565 if (((q->buffer_size - q->buffer_used) < roundup(2 + 2 + 6, 4)) ||
@@ -599,22 +605,6 @@ void b43_pio_handle_txstatus(struct b43_wldev *dev,
599 } 605 }
600} 606}
601 607
602void b43_pio_get_tx_stats(struct b43_wldev *dev,
603 struct ieee80211_tx_queue_stats *stats)
604{
605 const int nr_queues = dev->wl->hw->queues;
606 struct b43_pio_txqueue *q;
607 int i;
608
609 for (i = 0; i < nr_queues; i++) {
610 q = select_queue_by_priority(dev, i);
611
612 stats[i].len = B43_PIO_MAX_NR_TXPACKETS - q->free_packet_slots;
613 stats[i].limit = B43_PIO_MAX_NR_TXPACKETS;
614 stats[i].count = q->nr_tx_packets;
615 }
616}
617
618/* Returns whether we should fetch another frame. */ 608/* Returns whether we should fetch another frame. */
619static bool pio_rx_frame(struct b43_pio_rxqueue *q) 609static bool pio_rx_frame(struct b43_pio_rxqueue *q)
620{ 610{
@@ -625,8 +615,11 @@ static bool pio_rx_frame(struct b43_pio_rxqueue *q)
625 unsigned int i, padding; 615 unsigned int i, padding;
626 struct sk_buff *skb; 616 struct sk_buff *skb;
627 const char *err_msg = NULL; 617 const char *err_msg = NULL;
618 struct b43_rxhdr_fw4 *rxhdr =
619 (struct b43_rxhdr_fw4 *)wl->pio_scratchspace;
628 620
629 memset(&wl->rxhdr, 0, sizeof(wl->rxhdr)); 621 BUILD_BUG_ON(sizeof(wl->pio_scratchspace) < sizeof(*rxhdr));
622 memset(rxhdr, 0, sizeof(*rxhdr));
630 623
631 /* Check if we have data and wait for it to get ready. */ 624 /* Check if we have data and wait for it to get ready. */
632 if (q->rev >= 8) { 625 if (q->rev >= 8) {
@@ -664,16 +657,16 @@ data_ready:
664 657
665 /* Get the preamble (RX header) */ 658 /* Get the preamble (RX header) */
666 if (q->rev >= 8) { 659 if (q->rev >= 8) {
667 ssb_block_read(dev->dev, &wl->rxhdr, sizeof(wl->rxhdr), 660 ssb_block_read(dev->dev, rxhdr, sizeof(*rxhdr),
668 q->mmio_base + B43_PIO8_RXDATA, 661 q->mmio_base + B43_PIO8_RXDATA,
669 sizeof(u32)); 662 sizeof(u32));
670 } else { 663 } else {
671 ssb_block_read(dev->dev, &wl->rxhdr, sizeof(wl->rxhdr), 664 ssb_block_read(dev->dev, rxhdr, sizeof(*rxhdr),
672 q->mmio_base + B43_PIO_RXDATA, 665 q->mmio_base + B43_PIO_RXDATA,
673 sizeof(u16)); 666 sizeof(u16));
674 } 667 }
675 /* Sanity checks. */ 668 /* Sanity checks. */
676 len = le16_to_cpu(wl->rxhdr.frame_len); 669 len = le16_to_cpu(rxhdr->frame_len);
677 if (unlikely(len > 0x700)) { 670 if (unlikely(len > 0x700)) {
678 err_msg = "len > 0x700"; 671 err_msg = "len > 0x700";
679 goto rx_error; 672 goto rx_error;
@@ -683,7 +676,7 @@ data_ready:
683 goto rx_error; 676 goto rx_error;
684 } 677 }
685 678
686 macstat = le32_to_cpu(wl->rxhdr.mac_status); 679 macstat = le32_to_cpu(rxhdr->mac_status);
687 if (macstat & B43_RX_MAC_FCSERR) { 680 if (macstat & B43_RX_MAC_FCSERR) {
688 if (!(q->dev->wl->filter_flags & FIF_FCSFAIL)) { 681 if (!(q->dev->wl->filter_flags & FIF_FCSFAIL)) {
689 /* Drop frames with failed FCS. */ 682 /* Drop frames with failed FCS. */
@@ -708,22 +701,25 @@ data_ready:
708 q->mmio_base + B43_PIO8_RXDATA, 701 q->mmio_base + B43_PIO8_RXDATA,
709 sizeof(u32)); 702 sizeof(u32));
710 if (len & 3) { 703 if (len & 3) {
704 u8 *tail = wl->pio_tailspace;
705 BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 4);
706
711 /* Read the last few bytes. */ 707 /* Read the last few bytes. */
712 ssb_block_read(dev->dev, wl->rx_tail, 4, 708 ssb_block_read(dev->dev, tail, 4,
713 q->mmio_base + B43_PIO8_RXDATA, 709 q->mmio_base + B43_PIO8_RXDATA,
714 sizeof(u32)); 710 sizeof(u32));
715 switch (len & 3) { 711 switch (len & 3) {
716 case 3: 712 case 3:
717 skb->data[len + padding - 3] = wl->rx_tail[0]; 713 skb->data[len + padding - 3] = tail[0];
718 skb->data[len + padding - 2] = wl->rx_tail[1]; 714 skb->data[len + padding - 2] = tail[1];
719 skb->data[len + padding - 1] = wl->rx_tail[2]; 715 skb->data[len + padding - 1] = tail[2];
720 break; 716 break;
721 case 2: 717 case 2:
722 skb->data[len + padding - 2] = wl->rx_tail[0]; 718 skb->data[len + padding - 2] = tail[0];
723 skb->data[len + padding - 1] = wl->rx_tail[1]; 719 skb->data[len + padding - 1] = tail[1];
724 break; 720 break;
725 case 1: 721 case 1:
726 skb->data[len + padding - 1] = wl->rx_tail[0]; 722 skb->data[len + padding - 1] = tail[0];
727 break; 723 break;
728 } 724 }
729 } 725 }
@@ -732,22 +728,29 @@ data_ready:
732 q->mmio_base + B43_PIO_RXDATA, 728 q->mmio_base + B43_PIO_RXDATA,
733 sizeof(u16)); 729 sizeof(u16));
734 if (len & 1) { 730 if (len & 1) {
731 u8 *tail = wl->pio_tailspace;
732 BUILD_BUG_ON(sizeof(wl->pio_tailspace) < 2);
733
735 /* Read the last byte. */ 734 /* Read the last byte. */
736 ssb_block_read(dev->dev, wl->rx_tail, 2, 735 ssb_block_read(dev->dev, tail, 2,
737 q->mmio_base + B43_PIO_RXDATA, 736 q->mmio_base + B43_PIO_RXDATA,
738 sizeof(u16)); 737 sizeof(u16));
739 skb->data[len + padding - 1] = wl->rx_tail[0]; 738 skb->data[len + padding - 1] = tail[0];
740 } 739 }
741 } 740 }
742 741
743 b43_rx(q->dev, skb, &wl->rxhdr); 742 b43_rx(q->dev, skb, rxhdr);
744 743
745 return 1; 744 return 1;
746 745
747rx_error: 746rx_error:
748 if (err_msg) 747 if (err_msg)
749 b43dbg(q->dev->wl, "PIO RX error: %s\n", err_msg); 748 b43dbg(q->dev->wl, "PIO RX error: %s\n", err_msg);
750 b43_piorx_write16(q, B43_PIO_RXCTL, B43_PIO_RXCTL_DATARDY); 749 if (q->rev >= 8)
750 b43_piorx_write32(q, B43_PIO8_RXCTL, B43_PIO8_RXCTL_DATARDY);
751 else
752 b43_piorx_write16(q, B43_PIO_RXCTL, B43_PIO_RXCTL_DATARDY);
753
751 return 1; 754 return 1;
752} 755}
753 756