diff options
author | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
---|---|---|
committer | Andrea Bastoni <bastoni@cs.unc.edu> | 2010-05-30 19:16:45 -0400 |
commit | ada47b5fe13d89735805b566185f4885f5a3f750 (patch) | |
tree | 644b88f8a71896307d71438e9b3af49126ffb22b /drivers/net/wireless/b43/pio.c | |
parent | 43e98717ad40a4ae64545b5ba047c7b86aa44f4f (diff) | |
parent | 3280f21d43ee541f97f8cda5792150d2dbec20d5 (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.c | 103 |
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 | ||
36 | static u16 generate_cookie(struct b43_pio_txqueue *q, | 37 | static 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 | ||
602 | void 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. */ |
619 | static bool pio_rx_frame(struct b43_pio_rxqueue *q) | 609 | static 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 | ||
747 | rx_error: | 746 | rx_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 | ||