diff options
author | David S. Miller <davem@davemloft.net> | 2008-12-21 22:57:10 -0500 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2008-12-21 22:57:10 -0500 |
commit | c2da953a46b18b7515ad476c1c1686640a12e93a (patch) | |
tree | b384f097718119e715cdebd74710ddceeb80fdc8 | |
parent | c94cb314503a69492bf4455dce4f6d300cff0851 (diff) | |
parent | 9cf7f247bd0cd21e475c71a4e018bb612ef02aab (diff) |
Merge branch 'master' of git://git.kernel.org/pub/scm/linux/kernel/git/linville/wireless-next-2.6
50 files changed, 1166 insertions, 651 deletions
diff --git a/drivers/net/wireless/ath5k/ath5k.h b/drivers/net/wireless/ath5k/ath5k.h index 13df1191b070..183ffc8e62ca 100644 --- a/drivers/net/wireless/ath5k/ath5k.h +++ b/drivers/net/wireless/ath5k/ath5k.h | |||
@@ -1350,4 +1350,9 @@ static inline u32 ath5k_hw_bitswap(u32 val, unsigned int bits) | |||
1350 | return retval; | 1350 | return retval; |
1351 | } | 1351 | } |
1352 | 1352 | ||
1353 | static inline int ath5k_pad_size(int hdrlen) | ||
1354 | { | ||
1355 | return (hdrlen < 24) ? 0 : hdrlen & 3; | ||
1356 | } | ||
1357 | |||
1353 | #endif | 1358 | #endif |
diff --git a/drivers/net/wireless/ath5k/base.c b/drivers/net/wireless/ath5k/base.c index 0e4317010ed0..4af2607deec0 100644 --- a/drivers/net/wireless/ath5k/base.c +++ b/drivers/net/wireless/ath5k/base.c | |||
@@ -1668,7 +1668,7 @@ ath5k_tasklet_rx(unsigned long data) | |||
1668 | struct ath5k_desc *ds; | 1668 | struct ath5k_desc *ds; |
1669 | int ret; | 1669 | int ret; |
1670 | int hdrlen; | 1670 | int hdrlen; |
1671 | int pad; | 1671 | int padsize; |
1672 | 1672 | ||
1673 | spin_lock(&sc->rxbuflock); | 1673 | spin_lock(&sc->rxbuflock); |
1674 | if (list_empty(&sc->rxbuf)) { | 1674 | if (list_empty(&sc->rxbuf)) { |
@@ -1753,16 +1753,19 @@ accept: | |||
1753 | 1753 | ||
1754 | skb_put(skb, rs.rs_datalen); | 1754 | skb_put(skb, rs.rs_datalen); |
1755 | 1755 | ||
1756 | /* | 1756 | /* The MAC header is padded to have 32-bit boundary if the |
1757 | * the hardware adds a padding to 4 byte boundaries between | 1757 | * packet payload is non-zero. The general calculation for |
1758 | * the header and the payload data if the header length is | 1758 | * padsize would take into account odd header lengths: |
1759 | * not multiples of 4 - remove it | 1759 | * padsize = (4 - hdrlen % 4) % 4; However, since only |
1760 | */ | 1760 | * even-length headers are used, padding can only be 0 or 2 |
1761 | * bytes and we can optimize this a bit. In addition, we must | ||
1762 | * not try to remove padding from short control frames that do | ||
1763 | * not have payload. */ | ||
1761 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); | 1764 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); |
1762 | if (hdrlen & 3) { | 1765 | padsize = ath5k_pad_size(hdrlen); |
1763 | pad = hdrlen % 4; | 1766 | if (padsize) { |
1764 | memmove(skb->data + pad, skb->data, hdrlen); | 1767 | memmove(skb->data + padsize, skb->data, hdrlen); |
1765 | skb_pull(skb, pad); | 1768 | skb_pull(skb, padsize); |
1766 | } | 1769 | } |
1767 | 1770 | ||
1768 | /* | 1771 | /* |
@@ -2623,7 +2626,7 @@ ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
2623 | struct ath5k_buf *bf; | 2626 | struct ath5k_buf *bf; |
2624 | unsigned long flags; | 2627 | unsigned long flags; |
2625 | int hdrlen; | 2628 | int hdrlen; |
2626 | int pad; | 2629 | int padsize; |
2627 | 2630 | ||
2628 | ath5k_debug_dump_skb(sc, skb, "TX ", 1); | 2631 | ath5k_debug_dump_skb(sc, skb, "TX ", 1); |
2629 | 2632 | ||
@@ -2635,15 +2638,16 @@ ath5k_tx(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
2635 | * if this is not the case we add the padding after the header | 2638 | * if this is not the case we add the padding after the header |
2636 | */ | 2639 | */ |
2637 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); | 2640 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); |
2638 | if (hdrlen & 3) { | 2641 | padsize = ath5k_pad_size(hdrlen); |
2639 | pad = hdrlen % 4; | 2642 | if (padsize) { |
2640 | if (skb_headroom(skb) < pad) { | 2643 | |
2644 | if (skb_headroom(skb) < padsize) { | ||
2641 | ATH5K_ERR(sc, "tx hdrlen not %%4: %d not enough" | 2645 | ATH5K_ERR(sc, "tx hdrlen not %%4: %d not enough" |
2642 | " headroom to pad %d\n", hdrlen, pad); | 2646 | " headroom to pad %d\n", hdrlen, padsize); |
2643 | return -1; | 2647 | return -1; |
2644 | } | 2648 | } |
2645 | skb_push(skb, pad); | 2649 | skb_push(skb, padsize); |
2646 | memmove(skb->data, skb->data+pad, hdrlen); | 2650 | memmove(skb->data, skb->data+padsize, hdrlen); |
2647 | } | 2651 | } |
2648 | 2652 | ||
2649 | spin_lock_irqsave(&sc->txbuflock, flags); | 2653 | spin_lock_irqsave(&sc->txbuflock, flags); |
diff --git a/drivers/net/wireless/ath5k/desc.c b/drivers/net/wireless/ath5k/desc.c index 5e362a7a3620..b40a9287a39a 100644 --- a/drivers/net/wireless/ath5k/desc.c +++ b/drivers/net/wireless/ath5k/desc.c | |||
@@ -71,7 +71,7 @@ ath5k_hw_setup_2word_tx_desc(struct ath5k_hw *ah, struct ath5k_desc *desc, | |||
71 | /* Verify and set frame length */ | 71 | /* Verify and set frame length */ |
72 | 72 | ||
73 | /* remove padding we might have added before */ | 73 | /* remove padding we might have added before */ |
74 | frame_len = pkt_len - (hdr_len & 3) + FCS_LEN; | 74 | frame_len = pkt_len - ath5k_pad_size(hdr_len) + FCS_LEN; |
75 | 75 | ||
76 | if (frame_len & ~AR5K_2W_TX_DESC_CTL0_FRAME_LEN) | 76 | if (frame_len & ~AR5K_2W_TX_DESC_CTL0_FRAME_LEN) |
77 | return -EINVAL; | 77 | return -EINVAL; |
@@ -202,7 +202,7 @@ static int ath5k_hw_setup_4word_tx_desc(struct ath5k_hw *ah, | |||
202 | /* Verify and set frame length */ | 202 | /* Verify and set frame length */ |
203 | 203 | ||
204 | /* remove padding we might have added before */ | 204 | /* remove padding we might have added before */ |
205 | frame_len = pkt_len - (hdr_len & 3) + FCS_LEN; | 205 | frame_len = pkt_len - ath5k_pad_size(hdr_len) + FCS_LEN; |
206 | 206 | ||
207 | if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN) | 207 | if (frame_len & ~AR5K_4W_TX_DESC_CTL0_FRAME_LEN) |
208 | return -EINVAL; | 208 | return -EINVAL; |
diff --git a/drivers/net/wireless/ath9k/core.h b/drivers/net/wireless/ath9k/core.h index e38f0331cfd5..4ca2aed236e0 100644 --- a/drivers/net/wireless/ath9k/core.h +++ b/drivers/net/wireless/ath9k/core.h | |||
@@ -701,6 +701,7 @@ struct ath_softc { | |||
701 | struct ath_hal *sc_ah; | 701 | struct ath_hal *sc_ah; |
702 | void __iomem *mem; | 702 | void __iomem *mem; |
703 | spinlock_t sc_resetlock; | 703 | spinlock_t sc_resetlock; |
704 | struct mutex mutex; | ||
704 | 705 | ||
705 | u8 sc_curbssid[ETH_ALEN]; | 706 | u8 sc_curbssid[ETH_ALEN]; |
706 | u8 sc_myaddr[ETH_ALEN]; | 707 | u8 sc_myaddr[ETH_ALEN]; |
diff --git a/drivers/net/wireless/ath9k/main.c b/drivers/net/wireless/ath9k/main.c index 02e1771bb274..191eec50dc75 100644 --- a/drivers/net/wireless/ath9k/main.c +++ b/drivers/net/wireless/ath9k/main.c | |||
@@ -61,8 +61,7 @@ static void bus_read_cachesize(struct ath_softc *sc, int *csz) | |||
61 | 61 | ||
62 | static void ath_setcurmode(struct ath_softc *sc, enum wireless_mode mode) | 62 | static void ath_setcurmode(struct ath_softc *sc, enum wireless_mode mode) |
63 | { | 63 | { |
64 | if (!sc->sc_curaid) | 64 | sc->cur_rate_table = sc->hw_rate_table[mode]; |
65 | sc->cur_rate_table = sc->hw_rate_table[mode]; | ||
66 | /* | 65 | /* |
67 | * All protection frames are transmited at 2Mb/s for | 66 | * All protection frames are transmited at 2Mb/s for |
68 | * 11g, otherwise at 1Mb/s. | 67 | * 11g, otherwise at 1Mb/s. |
@@ -623,37 +622,40 @@ static int ath_get_channel(struct ath_softc *sc, | |||
623 | return -1; | 622 | return -1; |
624 | } | 623 | } |
625 | 624 | ||
626 | /* ext_chan_offset: (-1, 0, 1) (below, none, above) */ | ||
627 | |||
628 | static u32 ath_get_extchanmode(struct ath_softc *sc, | 625 | static u32 ath_get_extchanmode(struct ath_softc *sc, |
629 | struct ieee80211_channel *chan, | 626 | struct ieee80211_channel *chan, |
630 | int ext_chan_offset, | 627 | enum nl80211_channel_type channel_type) |
631 | enum ath9k_ht_macmode tx_chan_width) | ||
632 | { | 628 | { |
633 | u32 chanmode = 0; | 629 | u32 chanmode = 0; |
634 | 630 | ||
635 | switch (chan->band) { | 631 | switch (chan->band) { |
636 | case IEEE80211_BAND_2GHZ: | 632 | case IEEE80211_BAND_2GHZ: |
637 | if ((ext_chan_offset == 0) && | 633 | switch(channel_type) { |
638 | (tx_chan_width == ATH9K_HT_MACMODE_20)) | 634 | case NL80211_CHAN_NO_HT: |
635 | case NL80211_CHAN_HT20: | ||
639 | chanmode = CHANNEL_G_HT20; | 636 | chanmode = CHANNEL_G_HT20; |
640 | if ((ext_chan_offset == 1) && | 637 | break; |
641 | (tx_chan_width == ATH9K_HT_MACMODE_2040)) | 638 | case NL80211_CHAN_HT40PLUS: |
642 | chanmode = CHANNEL_G_HT40PLUS; | 639 | chanmode = CHANNEL_G_HT40PLUS; |
643 | if ((ext_chan_offset == -1) && | 640 | break; |
644 | (tx_chan_width == ATH9K_HT_MACMODE_2040)) | 641 | case NL80211_CHAN_HT40MINUS: |
645 | chanmode = CHANNEL_G_HT40MINUS; | 642 | chanmode = CHANNEL_G_HT40MINUS; |
643 | break; | ||
644 | } | ||
646 | break; | 645 | break; |
647 | case IEEE80211_BAND_5GHZ: | 646 | case IEEE80211_BAND_5GHZ: |
648 | if ((ext_chan_offset == 0) && | 647 | switch(channel_type) { |
649 | (tx_chan_width == ATH9K_HT_MACMODE_20)) | 648 | case NL80211_CHAN_NO_HT: |
649 | case NL80211_CHAN_HT20: | ||
650 | chanmode = CHANNEL_A_HT20; | 650 | chanmode = CHANNEL_A_HT20; |
651 | if ((ext_chan_offset == 1) && | 651 | break; |
652 | (tx_chan_width == ATH9K_HT_MACMODE_2040)) | 652 | case NL80211_CHAN_HT40PLUS: |
653 | chanmode = CHANNEL_A_HT40PLUS; | 653 | chanmode = CHANNEL_A_HT40PLUS; |
654 | if ((ext_chan_offset == -1) && | 654 | break; |
655 | (tx_chan_width == ATH9K_HT_MACMODE_2040)) | 655 | case NL80211_CHAN_HT40MINUS: |
656 | chanmode = CHANNEL_A_HT40MINUS; | 656 | chanmode = CHANNEL_A_HT40MINUS; |
657 | break; | ||
658 | } | ||
657 | break; | 659 | break; |
658 | default: | 660 | default: |
659 | break; | 661 | break; |
@@ -662,13 +664,6 @@ static u32 ath_get_extchanmode(struct ath_softc *sc, | |||
662 | return chanmode; | 664 | return chanmode; |
663 | } | 665 | } |
664 | 666 | ||
665 | static void ath_key_reset(struct ath_softc *sc, u16 keyix, int freeslot) | ||
666 | { | ||
667 | ath9k_hw_keyreset(sc->sc_ah, keyix); | ||
668 | if (freeslot) | ||
669 | clear_bit(keyix, sc->sc_keymap); | ||
670 | } | ||
671 | |||
672 | static int ath_keyset(struct ath_softc *sc, u16 keyix, | 667 | static int ath_keyset(struct ath_softc *sc, u16 keyix, |
673 | struct ath9k_keyval *hk, const u8 mac[ETH_ALEN]) | 668 | struct ath9k_keyval *hk, const u8 mac[ETH_ALEN]) |
674 | { | 669 | { |
@@ -680,21 +675,20 @@ static int ath_keyset(struct ath_softc *sc, u16 keyix, | |||
680 | return status != false; | 675 | return status != false; |
681 | } | 676 | } |
682 | 677 | ||
683 | static int ath_setkey_tkip(struct ath_softc *sc, | 678 | static int ath_setkey_tkip(struct ath_softc *sc, u16 keyix, const u8 *key, |
684 | struct ieee80211_key_conf *key, | ||
685 | struct ath9k_keyval *hk, | 679 | struct ath9k_keyval *hk, |
686 | const u8 *addr) | 680 | const u8 *addr) |
687 | { | 681 | { |
688 | u8 *key_rxmic = NULL; | 682 | const u8 *key_rxmic; |
689 | u8 *key_txmic = NULL; | 683 | const u8 *key_txmic; |
690 | 684 | ||
691 | key_txmic = key->key + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY; | 685 | key_txmic = key + NL80211_TKIP_DATA_OFFSET_TX_MIC_KEY; |
692 | key_rxmic = key->key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY; | 686 | key_rxmic = key + NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY; |
693 | 687 | ||
694 | if (addr == NULL) { | 688 | if (addr == NULL) { |
695 | /* Group key installation */ | 689 | /* Group key installation */ |
696 | memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); | 690 | memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); |
697 | return ath_keyset(sc, key->keyidx, hk, addr); | 691 | return ath_keyset(sc, keyix, hk, addr); |
698 | } | 692 | } |
699 | if (!sc->sc_splitmic) { | 693 | if (!sc->sc_splitmic) { |
700 | /* | 694 | /* |
@@ -703,14 +697,14 @@ static int ath_setkey_tkip(struct ath_softc *sc, | |||
703 | */ | 697 | */ |
704 | memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); | 698 | memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); |
705 | memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_txmic)); | 699 | memcpy(hk->kv_txmic, key_txmic, sizeof(hk->kv_txmic)); |
706 | return ath_keyset(sc, key->keyidx, hk, addr); | 700 | return ath_keyset(sc, keyix, hk, addr); |
707 | } | 701 | } |
708 | /* | 702 | /* |
709 | * TX key goes at first index, RX key at +32. | 703 | * TX key goes at first index, RX key at +32. |
710 | * The hal handles the MIC keys at index+64. | 704 | * The hal handles the MIC keys at index+64. |
711 | */ | 705 | */ |
712 | memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic)); | 706 | memcpy(hk->kv_mic, key_txmic, sizeof(hk->kv_mic)); |
713 | if (!ath_keyset(sc, key->keyidx, hk, NULL)) { | 707 | if (!ath_keyset(sc, keyix, hk, NULL)) { |
714 | /* Txmic entry failed. No need to proceed further */ | 708 | /* Txmic entry failed. No need to proceed further */ |
715 | DPRINTF(sc, ATH_DBG_KEYCACHE, | 709 | DPRINTF(sc, ATH_DBG_KEYCACHE, |
716 | "Setting TX MIC Key Failed\n"); | 710 | "Setting TX MIC Key Failed\n"); |
@@ -719,18 +713,97 @@ static int ath_setkey_tkip(struct ath_softc *sc, | |||
719 | 713 | ||
720 | memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); | 714 | memcpy(hk->kv_mic, key_rxmic, sizeof(hk->kv_mic)); |
721 | /* XXX delete tx key on failure? */ | 715 | /* XXX delete tx key on failure? */ |
722 | return ath_keyset(sc, key->keyidx+32, hk, addr); | 716 | return ath_keyset(sc, keyix + 32, hk, addr); |
717 | } | ||
718 | |||
719 | static int ath_reserve_key_cache_slot_tkip(struct ath_softc *sc) | ||
720 | { | ||
721 | int i; | ||
722 | |||
723 | for (i = IEEE80211_WEP_NKID; i < sc->sc_keymax / 2; i++) { | ||
724 | if (test_bit(i, sc->sc_keymap) || | ||
725 | test_bit(i + 64, sc->sc_keymap)) | ||
726 | continue; /* At least one part of TKIP key allocated */ | ||
727 | if (sc->sc_splitmic && | ||
728 | (test_bit(i + 32, sc->sc_keymap) || | ||
729 | test_bit(i + 64 + 32, sc->sc_keymap))) | ||
730 | continue; /* At least one part of TKIP key allocated */ | ||
731 | |||
732 | /* Found a free slot for a TKIP key */ | ||
733 | return i; | ||
734 | } | ||
735 | return -1; | ||
736 | } | ||
737 | |||
738 | static int ath_reserve_key_cache_slot(struct ath_softc *sc) | ||
739 | { | ||
740 | int i; | ||
741 | |||
742 | /* First, try to find slots that would not be available for TKIP. */ | ||
743 | if (sc->sc_splitmic) { | ||
744 | for (i = IEEE80211_WEP_NKID; i < sc->sc_keymax / 4; i++) { | ||
745 | if (!test_bit(i, sc->sc_keymap) && | ||
746 | (test_bit(i + 32, sc->sc_keymap) || | ||
747 | test_bit(i + 64, sc->sc_keymap) || | ||
748 | test_bit(i + 64 + 32, sc->sc_keymap))) | ||
749 | return i; | ||
750 | if (!test_bit(i + 32, sc->sc_keymap) && | ||
751 | (test_bit(i, sc->sc_keymap) || | ||
752 | test_bit(i + 64, sc->sc_keymap) || | ||
753 | test_bit(i + 64 + 32, sc->sc_keymap))) | ||
754 | return i + 32; | ||
755 | if (!test_bit(i + 64, sc->sc_keymap) && | ||
756 | (test_bit(i , sc->sc_keymap) || | ||
757 | test_bit(i + 32, sc->sc_keymap) || | ||
758 | test_bit(i + 64 + 32, sc->sc_keymap))) | ||
759 | return i + 64; | ||
760 | if (!test_bit(i + 64 + 32, sc->sc_keymap) && | ||
761 | (test_bit(i, sc->sc_keymap) || | ||
762 | test_bit(i + 32, sc->sc_keymap) || | ||
763 | test_bit(i + 64, sc->sc_keymap))) | ||
764 | return i + 64 + 32; | ||
765 | } | ||
766 | } else { | ||
767 | for (i = IEEE80211_WEP_NKID; i < sc->sc_keymax / 2; i++) { | ||
768 | if (!test_bit(i, sc->sc_keymap) && | ||
769 | test_bit(i + 64, sc->sc_keymap)) | ||
770 | return i; | ||
771 | if (test_bit(i, sc->sc_keymap) && | ||
772 | !test_bit(i + 64, sc->sc_keymap)) | ||
773 | return i + 64; | ||
774 | } | ||
775 | } | ||
776 | |||
777 | /* No partially used TKIP slots, pick any available slot */ | ||
778 | for (i = IEEE80211_WEP_NKID; i < sc->sc_keymax; i++) { | ||
779 | /* Do not allow slots that could be needed for TKIP group keys | ||
780 | * to be used. This limitation could be removed if we know that | ||
781 | * TKIP will not be used. */ | ||
782 | if (i >= 64 && i < 64 + IEEE80211_WEP_NKID) | ||
783 | continue; | ||
784 | if (sc->sc_splitmic) { | ||
785 | if (i >= 32 && i < 32 + IEEE80211_WEP_NKID) | ||
786 | continue; | ||
787 | if (i >= 64 + 32 && i < 64 + 32 + IEEE80211_WEP_NKID) | ||
788 | continue; | ||
789 | } | ||
790 | |||
791 | if (!test_bit(i, sc->sc_keymap)) | ||
792 | return i; /* Found a free slot for a key */ | ||
793 | } | ||
794 | |||
795 | /* No free slot found */ | ||
796 | return -1; | ||
723 | } | 797 | } |
724 | 798 | ||
725 | static int ath_key_config(struct ath_softc *sc, | 799 | static int ath_key_config(struct ath_softc *sc, |
726 | const u8 *addr, | 800 | const u8 *addr, |
727 | struct ieee80211_key_conf *key) | 801 | struct ieee80211_key_conf *key) |
728 | { | 802 | { |
729 | struct ieee80211_vif *vif; | ||
730 | struct ath9k_keyval hk; | 803 | struct ath9k_keyval hk; |
731 | const u8 *mac = NULL; | 804 | const u8 *mac = NULL; |
732 | int ret = 0; | 805 | int ret = 0; |
733 | enum nl80211_iftype opmode; | 806 | int idx; |
734 | 807 | ||
735 | memset(&hk, 0, sizeof(hk)); | 808 | memset(&hk, 0, sizeof(hk)); |
736 | 809 | ||
@@ -748,65 +821,69 @@ static int ath_key_config(struct ath_softc *sc, | |||
748 | return -EINVAL; | 821 | return -EINVAL; |
749 | } | 822 | } |
750 | 823 | ||
751 | hk.kv_len = key->keylen; | 824 | hk.kv_len = key->keylen; |
752 | memcpy(hk.kv_val, key->key, key->keylen); | 825 | memcpy(hk.kv_val, key->key, key->keylen); |
753 | 826 | ||
754 | if (!sc->sc_vaps[0]) | 827 | if (!(key->flags & IEEE80211_KEY_FLAG_PAIRWISE)) { |
755 | return -EIO; | 828 | /* For now, use the default keys for broadcast keys. This may |
756 | 829 | * need to change with virtual interfaces. */ | |
757 | vif = sc->sc_vaps[0]; | 830 | idx = key->keyidx; |
758 | opmode = vif->type; | 831 | } else if (key->keyidx) { |
832 | struct ieee80211_vif *vif; | ||
759 | 833 | ||
760 | /* | 834 | mac = addr; |
761 | * Strategy: | 835 | vif = sc->sc_vaps[0]; |
762 | * For STA mc tx, we will not setup a key at | 836 | if (vif->type != NL80211_IFTYPE_AP) { |
763 | * all since we never tx mc. | 837 | /* Only keyidx 0 should be used with unicast key, but |
764 | * | 838 | * allow this for client mode for now. */ |
765 | * For STA mc rx, we will use the keyID. | 839 | idx = key->keyidx; |
766 | * | 840 | } else |
767 | * For ADHOC mc tx, we will use the keyID, and no macaddr. | 841 | return -EIO; |
768 | * | ||
769 | * For ADHOC mc rx, we will alloc a slot and plumb the mac of | ||
770 | * the peer node. | ||
771 | * BUT we will plumb a cleartext key so that we can do | ||
772 | * per-Sta default key table lookup in software. | ||
773 | */ | ||
774 | if (is_broadcast_ether_addr(addr)) { | ||
775 | switch (opmode) { | ||
776 | case NL80211_IFTYPE_STATION: | ||
777 | /* default key: could be group WPA key | ||
778 | * or could be static WEP key */ | ||
779 | mac = NULL; | ||
780 | break; | ||
781 | case NL80211_IFTYPE_ADHOC: | ||
782 | break; | ||
783 | case NL80211_IFTYPE_AP: | ||
784 | break; | ||
785 | default: | ||
786 | ASSERT(0); | ||
787 | break; | ||
788 | } | ||
789 | } else { | 842 | } else { |
790 | mac = addr; | 843 | mac = addr; |
844 | if (key->alg == ALG_TKIP) | ||
845 | idx = ath_reserve_key_cache_slot_tkip(sc); | ||
846 | else | ||
847 | idx = ath_reserve_key_cache_slot(sc); | ||
848 | if (idx < 0) | ||
849 | return -EIO; /* no free key cache entries */ | ||
791 | } | 850 | } |
792 | 851 | ||
793 | if (key->alg == ALG_TKIP) | 852 | if (key->alg == ALG_TKIP) |
794 | ret = ath_setkey_tkip(sc, key, &hk, mac); | 853 | ret = ath_setkey_tkip(sc, idx, key->key, &hk, mac); |
795 | else | 854 | else |
796 | ret = ath_keyset(sc, key->keyidx, &hk, mac); | 855 | ret = ath_keyset(sc, idx, &hk, mac); |
797 | 856 | ||
798 | if (!ret) | 857 | if (!ret) |
799 | return -EIO; | 858 | return -EIO; |
800 | 859 | ||
801 | return 0; | 860 | set_bit(idx, sc->sc_keymap); |
861 | if (key->alg == ALG_TKIP) { | ||
862 | set_bit(idx + 64, sc->sc_keymap); | ||
863 | if (sc->sc_splitmic) { | ||
864 | set_bit(idx + 32, sc->sc_keymap); | ||
865 | set_bit(idx + 64 + 32, sc->sc_keymap); | ||
866 | } | ||
867 | } | ||
868 | |||
869 | return idx; | ||
802 | } | 870 | } |
803 | 871 | ||
804 | static void ath_key_delete(struct ath_softc *sc, struct ieee80211_key_conf *key) | 872 | static void ath_key_delete(struct ath_softc *sc, struct ieee80211_key_conf *key) |
805 | { | 873 | { |
806 | int freeslot; | 874 | ath9k_hw_keyreset(sc->sc_ah, key->hw_key_idx); |
875 | if (key->hw_key_idx < IEEE80211_WEP_NKID) | ||
876 | return; | ||
877 | |||
878 | clear_bit(key->hw_key_idx, sc->sc_keymap); | ||
879 | if (key->alg != ALG_TKIP) | ||
880 | return; | ||
807 | 881 | ||
808 | freeslot = (key->keyidx >= 4) ? 1 : 0; | 882 | clear_bit(key->hw_key_idx + 64, sc->sc_keymap); |
809 | ath_key_reset(sc, key->keyidx, freeslot); | 883 | if (sc->sc_splitmic) { |
884 | clear_bit(key->hw_key_idx + 32, sc->sc_keymap); | ||
885 | clear_bit(key->hw_key_idx + 64 + 32, sc->sc_keymap); | ||
886 | } | ||
810 | } | 887 | } |
811 | 888 | ||
812 | static void setup_ht_cap(struct ieee80211_sta_ht_cap *ht_info) | 889 | static void setup_ht_cap(struct ieee80211_sta_ht_cap *ht_info) |
@@ -829,45 +906,15 @@ static void setup_ht_cap(struct ieee80211_sta_ht_cap *ht_info) | |||
829 | ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; | 906 | ht_info->mcs.tx_params = IEEE80211_HT_MCS_TX_DEFINED; |
830 | } | 907 | } |
831 | 908 | ||
832 | static void ath9k_ht_conf(struct ath_softc *sc, | ||
833 | struct ieee80211_bss_conf *bss_conf) | ||
834 | { | ||
835 | if (sc->hw->conf.ht.enabled) { | ||
836 | if (bss_conf->ht.width_40_ok) | ||
837 | sc->tx_chan_width = ATH9K_HT_MACMODE_2040; | ||
838 | else | ||
839 | sc->tx_chan_width = ATH9K_HT_MACMODE_20; | ||
840 | |||
841 | ath9k_hw_set11nmac2040(sc->sc_ah, sc->tx_chan_width); | ||
842 | |||
843 | DPRINTF(sc, ATH_DBG_CONFIG, | ||
844 | "BSS Changed HT, chanwidth: %d\n", sc->tx_chan_width); | ||
845 | } | ||
846 | } | ||
847 | |||
848 | static inline int ath_sec_offset(u8 ext_offset) | ||
849 | { | ||
850 | if (ext_offset == IEEE80211_HT_PARAM_CHA_SEC_NONE) | ||
851 | return 0; | ||
852 | else if (ext_offset == IEEE80211_HT_PARAM_CHA_SEC_ABOVE) | ||
853 | return 1; | ||
854 | else if (ext_offset == IEEE80211_HT_PARAM_CHA_SEC_BELOW) | ||
855 | return -1; | ||
856 | |||
857 | return 0; | ||
858 | } | ||
859 | |||
860 | static void ath9k_bss_assoc_info(struct ath_softc *sc, | 909 | static void ath9k_bss_assoc_info(struct ath_softc *sc, |
861 | struct ieee80211_vif *vif, | 910 | struct ieee80211_vif *vif, |
862 | struct ieee80211_bss_conf *bss_conf) | 911 | struct ieee80211_bss_conf *bss_conf) |
863 | { | 912 | { |
864 | struct ieee80211_hw *hw = sc->hw; | ||
865 | struct ieee80211_channel *curchan = hw->conf.channel; | ||
866 | struct ath_vap *avp = (void *)vif->drv_priv; | 913 | struct ath_vap *avp = (void *)vif->drv_priv; |
867 | int pos; | ||
868 | 914 | ||
869 | if (bss_conf->assoc) { | 915 | if (bss_conf->assoc) { |
870 | DPRINTF(sc, ATH_DBG_CONFIG, "Bss Info ASSOC %d\n", bss_conf->aid); | 916 | DPRINTF(sc, ATH_DBG_CONFIG, "Bss Info ASSOC %d, bssid: %pM\n", |
917 | bss_conf->aid, sc->sc_curbssid); | ||
871 | 918 | ||
872 | /* New association, store aid */ | 919 | /* New association, store aid */ |
873 | if (avp->av_opmode == NL80211_IFTYPE_STATION) { | 920 | if (avp->av_opmode == NL80211_IFTYPE_STATION) { |
@@ -886,40 +933,6 @@ static void ath9k_bss_assoc_info(struct ath_softc *sc, | |||
886 | sc->sc_halstats.ns_avgtxrssi = ATH_RSSI_DUMMY_MARKER; | 933 | sc->sc_halstats.ns_avgtxrssi = ATH_RSSI_DUMMY_MARKER; |
887 | sc->sc_halstats.ns_avgtxrate = ATH_RATE_DUMMY_MARKER; | 934 | sc->sc_halstats.ns_avgtxrate = ATH_RATE_DUMMY_MARKER; |
888 | 935 | ||
889 | /* Update chainmask */ | ||
890 | ath_update_chainmask(sc, hw->conf.ht.enabled); | ||
891 | |||
892 | DPRINTF(sc, ATH_DBG_CONFIG, | ||
893 | "bssid %pM aid 0x%x\n", | ||
894 | sc->sc_curbssid, sc->sc_curaid); | ||
895 | |||
896 | pos = ath_get_channel(sc, curchan); | ||
897 | if (pos == -1) { | ||
898 | DPRINTF(sc, ATH_DBG_FATAL, | ||
899 | "Invalid channel: %d\n", curchan->center_freq); | ||
900 | return; | ||
901 | } | ||
902 | |||
903 | if (hw->conf.ht.enabled) { | ||
904 | int offset = | ||
905 | ath_sec_offset(bss_conf->ht.secondary_channel_offset); | ||
906 | sc->tx_chan_width = (bss_conf->ht.width_40_ok) ? | ||
907 | ATH9K_HT_MACMODE_2040 : ATH9K_HT_MACMODE_20; | ||
908 | |||
909 | sc->sc_ah->ah_channels[pos].chanmode = | ||
910 | ath_get_extchanmode(sc, curchan, | ||
911 | offset, sc->tx_chan_width); | ||
912 | } else { | ||
913 | sc->sc_ah->ah_channels[pos].chanmode = | ||
914 | (curchan->band == IEEE80211_BAND_2GHZ) ? | ||
915 | CHANNEL_G : CHANNEL_A; | ||
916 | } | ||
917 | |||
918 | /* set h/w channel */ | ||
919 | if (ath_set_channel(sc, &sc->sc_ah->ah_channels[pos]) < 0) | ||
920 | DPRINTF(sc, ATH_DBG_FATAL, "Unable to set channel: %d\n", | ||
921 | curchan->center_freq); | ||
922 | |||
923 | /* Start ANI */ | 936 | /* Start ANI */ |
924 | mod_timer(&sc->sc_ani.timer, | 937 | mod_timer(&sc->sc_ani.timer, |
925 | jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL)); | 938 | jiffies + msecs_to_jiffies(ATH_ANI_POLLINTERVAL)); |
@@ -1291,9 +1304,6 @@ static void ath_detach(struct ath_softc *sc) | |||
1291 | ath_deinit_leds(sc); | 1304 | ath_deinit_leds(sc); |
1292 | 1305 | ||
1293 | ieee80211_unregister_hw(hw); | 1306 | ieee80211_unregister_hw(hw); |
1294 | |||
1295 | ath_rate_control_unregister(); | ||
1296 | |||
1297 | ath_rx_cleanup(sc); | 1307 | ath_rx_cleanup(sc); |
1298 | ath_tx_cleanup(sc); | 1308 | ath_tx_cleanup(sc); |
1299 | 1309 | ||
@@ -1326,6 +1336,7 @@ static int ath_init(u16 devid, struct ath_softc *sc) | |||
1326 | printk(KERN_ERR "Unable to create debugfs files\n"); | 1336 | printk(KERN_ERR "Unable to create debugfs files\n"); |
1327 | 1337 | ||
1328 | spin_lock_init(&sc->sc_resetlock); | 1338 | spin_lock_init(&sc->sc_resetlock); |
1339 | mutex_init(&sc->mutex); | ||
1329 | tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc); | 1340 | tasklet_init(&sc->intr_tq, ath9k_tasklet, (unsigned long)sc); |
1330 | tasklet_init(&sc->bcon_tasklet, ath9k_beacon_tasklet, | 1341 | tasklet_init(&sc->bcon_tasklet, ath9k_beacon_tasklet, |
1331 | (unsigned long)sc); | 1342 | (unsigned long)sc); |
@@ -1362,18 +1373,6 @@ static int ath_init(u16 devid, struct ath_softc *sc) | |||
1362 | */ | 1373 | */ |
1363 | for (i = 0; i < sc->sc_keymax; i++) | 1374 | for (i = 0; i < sc->sc_keymax; i++) |
1364 | ath9k_hw_keyreset(ah, (u16) i); | 1375 | ath9k_hw_keyreset(ah, (u16) i); |
1365 | /* | ||
1366 | * Mark key cache slots associated with global keys | ||
1367 | * as in use. If we knew TKIP was not to be used we | ||
1368 | * could leave the +32, +64, and +32+64 slots free. | ||
1369 | * XXX only for splitmic. | ||
1370 | */ | ||
1371 | for (i = 0; i < IEEE80211_WEP_NKID; i++) { | ||
1372 | set_bit(i, sc->sc_keymap); | ||
1373 | set_bit(i + 32, sc->sc_keymap); | ||
1374 | set_bit(i + 64, sc->sc_keymap); | ||
1375 | set_bit(i + 32 + 64, sc->sc_keymap); | ||
1376 | } | ||
1377 | 1376 | ||
1378 | /* Collect the channel list using the default country code */ | 1377 | /* Collect the channel list using the default country code */ |
1379 | 1378 | ||
@@ -1574,15 +1573,7 @@ static int ath_attach(u16 devid, struct ath_softc *sc) | |||
1574 | hw->sta_data_size = sizeof(struct ath_node); | 1573 | hw->sta_data_size = sizeof(struct ath_node); |
1575 | hw->vif_data_size = sizeof(struct ath_vap); | 1574 | hw->vif_data_size = sizeof(struct ath_vap); |
1576 | 1575 | ||
1577 | /* Register rate control */ | ||
1578 | hw->rate_control_algorithm = "ath9k_rate_control"; | 1576 | hw->rate_control_algorithm = "ath9k_rate_control"; |
1579 | error = ath_rate_control_register(); | ||
1580 | if (error != 0) { | ||
1581 | DPRINTF(sc, ATH_DBG_FATAL, | ||
1582 | "Unable to register rate control algorithm: %d\n", error); | ||
1583 | ath_rate_control_unregister(); | ||
1584 | goto bad; | ||
1585 | } | ||
1586 | 1577 | ||
1587 | if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) { | 1578 | if (sc->sc_ah->ah_caps.hw_caps & ATH9K_HW_CAP_HT) { |
1588 | setup_ht_cap(&sc->sbands[IEEE80211_BAND_2GHZ].ht_cap); | 1579 | setup_ht_cap(&sc->sbands[IEEE80211_BAND_2GHZ].ht_cap); |
@@ -1615,10 +1606,6 @@ static int ath_attach(u16 devid, struct ath_softc *sc) | |||
1615 | #endif | 1606 | #endif |
1616 | 1607 | ||
1617 | error = ieee80211_register_hw(hw); | 1608 | error = ieee80211_register_hw(hw); |
1618 | if (error != 0) { | ||
1619 | ath_rate_control_unregister(); | ||
1620 | goto bad; | ||
1621 | } | ||
1622 | 1609 | ||
1623 | /* Initialize LED control */ | 1610 | /* Initialize LED control */ |
1624 | ath_init_leds(sc); | 1611 | ath_init_leds(sc); |
@@ -1626,7 +1613,6 @@ static int ath_attach(u16 devid, struct ath_softc *sc) | |||
1626 | return 0; | 1613 | return 0; |
1627 | detach: | 1614 | detach: |
1628 | ath_detach(sc); | 1615 | ath_detach(sc); |
1629 | bad: | ||
1630 | return error; | 1616 | return error; |
1631 | } | 1617 | } |
1632 | 1618 | ||
@@ -2146,7 +2132,9 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
2146 | struct ath_softc *sc = hw->priv; | 2132 | struct ath_softc *sc = hw->priv; |
2147 | struct ieee80211_conf *conf = &hw->conf; | 2133 | struct ieee80211_conf *conf = &hw->conf; |
2148 | 2134 | ||
2149 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { | 2135 | mutex_lock(&sc->mutex); |
2136 | if (changed & (IEEE80211_CONF_CHANGE_CHANNEL | | ||
2137 | IEEE80211_CONF_CHANGE_HT)) { | ||
2150 | struct ieee80211_channel *curchan = hw->conf.channel; | 2138 | struct ieee80211_channel *curchan = hw->conf.channel; |
2151 | int pos; | 2139 | int pos; |
2152 | 2140 | ||
@@ -2157,6 +2145,7 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
2157 | if (pos == -1) { | 2145 | if (pos == -1) { |
2158 | DPRINTF(sc, ATH_DBG_FATAL, "Invalid channel: %d\n", | 2146 | DPRINTF(sc, ATH_DBG_FATAL, "Invalid channel: %d\n", |
2159 | curchan->center_freq); | 2147 | curchan->center_freq); |
2148 | mutex_unlock(&sc->mutex); | ||
2160 | return -EINVAL; | 2149 | return -EINVAL; |
2161 | } | 2150 | } |
2162 | 2151 | ||
@@ -2165,29 +2154,29 @@ static int ath9k_config(struct ieee80211_hw *hw, u32 changed) | |||
2165 | (curchan->band == IEEE80211_BAND_2GHZ) ? | 2154 | (curchan->band == IEEE80211_BAND_2GHZ) ? |
2166 | CHANNEL_G : CHANNEL_A; | 2155 | CHANNEL_G : CHANNEL_A; |
2167 | 2156 | ||
2168 | if ((sc->sc_ah->ah_opmode == NL80211_IFTYPE_AP) && | 2157 | if (conf->ht.enabled) { |
2169 | (conf->ht.enabled)) { | 2158 | if (conf->ht.channel_type == NL80211_CHAN_HT40PLUS || |
2170 | sc->tx_chan_width = (!!conf->ht.sec_chan_offset) ? | 2159 | conf->ht.channel_type == NL80211_CHAN_HT40MINUS) |
2171 | ATH9K_HT_MACMODE_2040 : ATH9K_HT_MACMODE_20; | 2160 | sc->tx_chan_width = ATH9K_HT_MACMODE_2040; |
2172 | 2161 | ||
2173 | sc->sc_ah->ah_channels[pos].chanmode = | 2162 | sc->sc_ah->ah_channels[pos].chanmode = |
2174 | ath_get_extchanmode(sc, curchan, | 2163 | ath_get_extchanmode(sc, curchan, |
2175 | conf->ht.sec_chan_offset, | 2164 | conf->ht.channel_type); |
2176 | sc->tx_chan_width); | ||
2177 | } | 2165 | } |
2178 | 2166 | ||
2179 | if (ath_set_channel(sc, &sc->sc_ah->ah_channels[pos]) < 0) { | 2167 | if (ath_set_channel(sc, &sc->sc_ah->ah_channels[pos]) < 0) { |
2180 | DPRINTF(sc, ATH_DBG_FATAL, "Unable to set channel\n"); | 2168 | DPRINTF(sc, ATH_DBG_FATAL, "Unable to set channel\n"); |
2169 | mutex_unlock(&sc->mutex); | ||
2181 | return -EINVAL; | 2170 | return -EINVAL; |
2182 | } | 2171 | } |
2183 | } | ||
2184 | 2172 | ||
2185 | if (changed & IEEE80211_CONF_CHANGE_HT) | ||
2186 | ath_update_chainmask(sc, conf->ht.enabled); | 2173 | ath_update_chainmask(sc, conf->ht.enabled); |
2174 | } | ||
2187 | 2175 | ||
2188 | if (changed & IEEE80211_CONF_CHANGE_POWER) | 2176 | if (changed & IEEE80211_CONF_CHANGE_POWER) |
2189 | sc->sc_config.txpowlimit = 2 * conf->power_level; | 2177 | sc->sc_config.txpowlimit = 2 * conf->power_level; |
2190 | 2178 | ||
2179 | mutex_unlock(&sc->mutex); | ||
2191 | return 0; | 2180 | return 0; |
2192 | } | 2181 | } |
2193 | 2182 | ||
@@ -2371,18 +2360,17 @@ static int ath9k_set_key(struct ieee80211_hw *hw, | |||
2371 | switch (cmd) { | 2360 | switch (cmd) { |
2372 | case SET_KEY: | 2361 | case SET_KEY: |
2373 | ret = ath_key_config(sc, addr, key); | 2362 | ret = ath_key_config(sc, addr, key); |
2374 | if (!ret) { | 2363 | if (ret >= 0) { |
2375 | set_bit(key->keyidx, sc->sc_keymap); | 2364 | key->hw_key_idx = ret; |
2376 | key->hw_key_idx = key->keyidx; | ||
2377 | /* push IV and Michael MIC generation to stack */ | 2365 | /* push IV and Michael MIC generation to stack */ |
2378 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; | 2366 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_IV; |
2379 | if (key->alg == ALG_TKIP) | 2367 | if (key->alg == ALG_TKIP) |
2380 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; | 2368 | key->flags |= IEEE80211_KEY_FLAG_GENERATE_MMIC; |
2369 | ret = 0; | ||
2381 | } | 2370 | } |
2382 | break; | 2371 | break; |
2383 | case DISABLE_KEY: | 2372 | case DISABLE_KEY: |
2384 | ath_key_delete(sc, key); | 2373 | ath_key_delete(sc, key); |
2385 | clear_bit(key->keyidx, sc->sc_keymap); | ||
2386 | break; | 2374 | break; |
2387 | default: | 2375 | default: |
2388 | ret = -EINVAL; | 2376 | ret = -EINVAL; |
@@ -2417,9 +2405,6 @@ static void ath9k_bss_info_changed(struct ieee80211_hw *hw, | |||
2417 | sc->sc_flags &= ~SC_OP_PROTECT_ENABLE; | 2405 | sc->sc_flags &= ~SC_OP_PROTECT_ENABLE; |
2418 | } | 2406 | } |
2419 | 2407 | ||
2420 | if (changed & BSS_CHANGED_HT) | ||
2421 | ath9k_ht_conf(sc, bss_conf); | ||
2422 | |||
2423 | if (changed & BSS_CHANGED_ASSOC) { | 2408 | if (changed & BSS_CHANGED_ASSOC) { |
2424 | DPRINTF(sc, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n", | 2409 | DPRINTF(sc, ATH_DBG_CONFIG, "BSS Changed ASSOC %d\n", |
2425 | bss_conf->assoc); | 2410 | bss_conf->assoc); |
@@ -2780,11 +2765,24 @@ static struct pci_driver ath_pci_driver = { | |||
2780 | 2765 | ||
2781 | static int __init init_ath_pci(void) | 2766 | static int __init init_ath_pci(void) |
2782 | { | 2767 | { |
2768 | int error; | ||
2769 | |||
2783 | printk(KERN_INFO "%s: %s\n", dev_info, ATH_PCI_VERSION); | 2770 | printk(KERN_INFO "%s: %s\n", dev_info, ATH_PCI_VERSION); |
2784 | 2771 | ||
2772 | /* Register rate control algorithm */ | ||
2773 | error = ath_rate_control_register(); | ||
2774 | if (error != 0) { | ||
2775 | printk(KERN_ERR | ||
2776 | "Unable to register rate control algorithm: %d\n", | ||
2777 | error); | ||
2778 | ath_rate_control_unregister(); | ||
2779 | return error; | ||
2780 | } | ||
2781 | |||
2785 | if (pci_register_driver(&ath_pci_driver) < 0) { | 2782 | if (pci_register_driver(&ath_pci_driver) < 0) { |
2786 | printk(KERN_ERR | 2783 | printk(KERN_ERR |
2787 | "ath_pci: No devices found, driver not installed.\n"); | 2784 | "ath_pci: No devices found, driver not installed.\n"); |
2785 | ath_rate_control_unregister(); | ||
2788 | pci_unregister_driver(&ath_pci_driver); | 2786 | pci_unregister_driver(&ath_pci_driver); |
2789 | return -ENODEV; | 2787 | return -ENODEV; |
2790 | } | 2788 | } |
@@ -2795,6 +2793,7 @@ module_init(init_ath_pci); | |||
2795 | 2793 | ||
2796 | static void __exit exit_ath_pci(void) | 2794 | static void __exit exit_ath_pci(void) |
2797 | { | 2795 | { |
2796 | ath_rate_control_unregister(); | ||
2798 | pci_unregister_driver(&ath_pci_driver); | 2797 | pci_unregister_driver(&ath_pci_driver); |
2799 | printk(KERN_INFO "%s: Driver unloaded\n", dev_info); | 2798 | printk(KERN_INFO "%s: Driver unloaded\n", dev_info); |
2800 | } | 2799 | } |
diff --git a/drivers/net/wireless/ath9k/rc.c b/drivers/net/wireless/ath9k/rc.c index 0ae5988e0b65..04ab457a8faa 100644 --- a/drivers/net/wireless/ath9k/rc.c +++ b/drivers/net/wireless/ath9k/rc.c | |||
@@ -1498,7 +1498,8 @@ static void ath_get_rate(void *priv, struct ieee80211_sta *sta, void *priv_sta, | |||
1498 | __le16 fc = hdr->frame_control; | 1498 | __le16 fc = hdr->frame_control; |
1499 | 1499 | ||
1500 | /* lowest rate for management and multicast/broadcast frames */ | 1500 | /* lowest rate for management and multicast/broadcast frames */ |
1501 | if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1)) { | 1501 | if (!ieee80211_is_data(fc) || is_multicast_ether_addr(hdr->addr1) || |
1502 | !sta) { | ||
1502 | tx_info->control.rates[0].idx = rate_lowest_index(sband, sta); | 1503 | tx_info->control.rates[0].idx = rate_lowest_index(sband, sta); |
1503 | tx_info->control.rates[0].count = | 1504 | tx_info->control.rates[0].count = |
1504 | is_multicast_ether_addr(hdr->addr1) ? 1 : ATH_MGT_TXMAXTRY; | 1505 | is_multicast_ether_addr(hdr->addr1) ? 1 : ATH_MGT_TXMAXTRY; |
diff --git a/drivers/net/wireless/ath9k/recv.c b/drivers/net/wireless/ath9k/recv.c index f2327d8e9c28..462e08c3d09d 100644 --- a/drivers/net/wireless/ath9k/recv.c +++ b/drivers/net/wireless/ath9k/recv.c | |||
@@ -111,33 +111,6 @@ static struct sk_buff *ath_rxbuf_alloc(struct ath_softc *sc, u32 len) | |||
111 | return skb; | 111 | return skb; |
112 | } | 112 | } |
113 | 113 | ||
114 | static int ath_rate2idx(struct ath_softc *sc, int rate) | ||
115 | { | ||
116 | int i = 0, cur_band, n_rates; | ||
117 | struct ieee80211_hw *hw = sc->hw; | ||
118 | |||
119 | cur_band = hw->conf.channel->band; | ||
120 | n_rates = sc->sbands[cur_band].n_bitrates; | ||
121 | |||
122 | for (i = 0; i < n_rates; i++) { | ||
123 | if (sc->sbands[cur_band].bitrates[i].bitrate == rate) | ||
124 | break; | ||
125 | } | ||
126 | |||
127 | /* | ||
128 | * NB:mac80211 validates rx rate index against the supported legacy rate | ||
129 | * index only (should be done against ht rates also), return the highest | ||
130 | * legacy rate index for rx rate which does not match any one of the | ||
131 | * supported basic and extended rates to make mac80211 happy. | ||
132 | * The following hack will be cleaned up once the issue with | ||
133 | * the rx rate index validation in mac80211 is fixed. | ||
134 | */ | ||
135 | if (i == n_rates) | ||
136 | return n_rates - 1; | ||
137 | |||
138 | return i; | ||
139 | } | ||
140 | |||
141 | /* | 114 | /* |
142 | * For Decrypt or Demic errors, we only mark packet status here and always push | 115 | * For Decrypt or Demic errors, we only mark packet status here and always push |
143 | * up the frame up to let mac80211 handle the actual error case, be it no | 116 | * up the frame up to let mac80211 handle the actual error case, be it no |
@@ -147,9 +120,7 @@ static int ath_rx_prepare(struct sk_buff *skb, struct ath_desc *ds, | |||
147 | struct ieee80211_rx_status *rx_status, bool *decrypt_error, | 120 | struct ieee80211_rx_status *rx_status, bool *decrypt_error, |
148 | struct ath_softc *sc) | 121 | struct ath_softc *sc) |
149 | { | 122 | { |
150 | struct ath_rate_table *rate_table = sc->cur_rate_table; | ||
151 | struct ieee80211_hdr *hdr; | 123 | struct ieee80211_hdr *hdr; |
152 | int ratekbps, rix; | ||
153 | u8 ratecode; | 124 | u8 ratecode; |
154 | __le16 fc; | 125 | __le16 fc; |
155 | 126 | ||
@@ -204,15 +175,36 @@ static int ath_rx_prepare(struct sk_buff *skb, struct ath_desc *ds, | |||
204 | } | 175 | } |
205 | 176 | ||
206 | ratecode = ds->ds_rxstat.rs_rate; | 177 | ratecode = ds->ds_rxstat.rs_rate; |
207 | rix = rate_table->rateCodeToIndex[ratecode]; | ||
208 | ratekbps = rate_table->info[rix].ratekbps; | ||
209 | 178 | ||
210 | /* HT rate */ | ||
211 | if (ratecode & 0x80) { | 179 | if (ratecode & 0x80) { |
180 | /* HT rate */ | ||
181 | rx_status->flag |= RX_FLAG_HT; | ||
212 | if (ds->ds_rxstat.rs_flags & ATH9K_RX_2040) | 182 | if (ds->ds_rxstat.rs_flags & ATH9K_RX_2040) |
213 | ratekbps = (ratekbps * 27) / 13; | 183 | rx_status->flag |= RX_FLAG_40MHZ; |
214 | if (ds->ds_rxstat.rs_flags & ATH9K_RX_GI) | 184 | if (ds->ds_rxstat.rs_flags & ATH9K_RX_GI) |
215 | ratekbps = (ratekbps * 10) / 9; | 185 | rx_status->flag |= RX_FLAG_SHORT_GI; |
186 | rx_status->rate_idx = ratecode & 0x7f; | ||
187 | } else { | ||
188 | int i = 0, cur_band, n_rates; | ||
189 | struct ieee80211_hw *hw = sc->hw; | ||
190 | |||
191 | cur_band = hw->conf.channel->band; | ||
192 | n_rates = sc->sbands[cur_band].n_bitrates; | ||
193 | |||
194 | for (i = 0; i < n_rates; i++) { | ||
195 | if (sc->sbands[cur_band].bitrates[i].hw_value == | ||
196 | ratecode) { | ||
197 | rx_status->rate_idx = i; | ||
198 | break; | ||
199 | } | ||
200 | |||
201 | if (sc->sbands[cur_band].bitrates[i].hw_value_short == | ||
202 | ratecode) { | ||
203 | rx_status->rate_idx = i; | ||
204 | rx_status->flag |= RX_FLAG_SHORTPRE; | ||
205 | break; | ||
206 | } | ||
207 | } | ||
216 | } | 208 | } |
217 | 209 | ||
218 | rx_status->mactime = ath_extend_tsf(sc, ds->ds_rxstat.rs_tstamp); | 210 | rx_status->mactime = ath_extend_tsf(sc, ds->ds_rxstat.rs_tstamp); |
@@ -220,7 +212,6 @@ static int ath_rx_prepare(struct sk_buff *skb, struct ath_desc *ds, | |||
220 | rx_status->freq = sc->hw->conf.channel->center_freq; | 212 | rx_status->freq = sc->hw->conf.channel->center_freq; |
221 | rx_status->noise = sc->sc_ani.sc_noise_floor; | 213 | rx_status->noise = sc->sc_ani.sc_noise_floor; |
222 | rx_status->signal = rx_status->noise + ds->ds_rxstat.rs_rssi; | 214 | rx_status->signal = rx_status->noise + ds->ds_rxstat.rs_rssi; |
223 | rx_status->rate_idx = ath_rate2idx(sc, (ratekbps / 100)); | ||
224 | rx_status->antenna = ds->ds_rxstat.rs_antenna; | 215 | rx_status->antenna = ds->ds_rxstat.rs_antenna; |
225 | 216 | ||
226 | /* at 45 you will be able to use MCS 15 reliably. A more elaborate | 217 | /* at 45 you will be able to use MCS 15 reliably. A more elaborate |
@@ -529,6 +520,15 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) | |||
529 | continue; | 520 | continue; |
530 | 521 | ||
531 | /* | 522 | /* |
523 | * Synchronize the DMA transfer with CPU before | ||
524 | * 1. accessing the frame | ||
525 | * 2. requeueing the same buffer to h/w | ||
526 | */ | ||
527 | pci_dma_sync_single_for_cpu(sc->pdev, bf->bf_buf_addr, | ||
528 | sc->rx.bufsize, | ||
529 | PCI_DMA_FROMDEVICE); | ||
530 | |||
531 | /* | ||
532 | * If we're asked to flush receive queue, directly | 532 | * If we're asked to flush receive queue, directly |
533 | * chain it back at the queue without processing it. | 533 | * chain it back at the queue without processing it. |
534 | */ | 534 | */ |
@@ -556,10 +556,7 @@ int ath_rx_tasklet(struct ath_softc *sc, int flush) | |||
556 | if (!requeue_skb) | 556 | if (!requeue_skb) |
557 | goto requeue; | 557 | goto requeue; |
558 | 558 | ||
559 | /* Sync and unmap the frame */ | 559 | /* Unmap the frame */ |
560 | pci_dma_sync_single_for_cpu(sc->pdev, bf->bf_buf_addr, | ||
561 | sc->rx.bufsize, | ||
562 | PCI_DMA_FROMDEVICE); | ||
563 | pci_unmap_single(sc->pdev, bf->bf_buf_addr, | 560 | pci_unmap_single(sc->pdev, bf->bf_buf_addr, |
564 | sc->rx.bufsize, | 561 | sc->rx.bufsize, |
565 | PCI_DMA_FROMDEVICE); | 562 | PCI_DMA_FROMDEVICE); |
diff --git a/drivers/net/wireless/ath9k/xmit.c b/drivers/net/wireless/ath9k/xmit.c index f9c309ed3a2d..3bfc3b90f256 100644 --- a/drivers/net/wireless/ath9k/xmit.c +++ b/drivers/net/wireless/ath9k/xmit.c | |||
@@ -106,6 +106,7 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | |||
106 | struct ieee80211_hw *hw = sc->hw; | 106 | struct ieee80211_hw *hw = sc->hw; |
107 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); | 107 | struct ieee80211_tx_info *tx_info = IEEE80211_SKB_CB(skb); |
108 | struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info); | 108 | struct ath_tx_info_priv *tx_info_priv = ATH_TX_INFO_PRIV(tx_info); |
109 | int hdrlen, padsize; | ||
109 | 110 | ||
110 | DPRINTF(sc, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb); | 111 | DPRINTF(sc, ATH_DBG_XMIT, "TX complete: skb: %p\n", skb); |
111 | 112 | ||
@@ -125,7 +126,26 @@ static void ath_tx_complete(struct ath_softc *sc, struct sk_buff *skb, | |||
125 | tx_info->flags |= IEEE80211_TX_STAT_ACK; | 126 | tx_info->flags |= IEEE80211_TX_STAT_ACK; |
126 | } | 127 | } |
127 | 128 | ||
128 | tx_info->status.rates[0].count = tx_status->retries + 1; | 129 | tx_info->status.rates[0].count = tx_status->retries; |
130 | if (tx_info->status.rates[0].flags & IEEE80211_TX_RC_MCS) { | ||
131 | /* Change idx from internal table index to MCS index */ | ||
132 | int idx = tx_info->status.rates[0].idx; | ||
133 | struct ath_rate_table *rate_table = sc->cur_rate_table; | ||
134 | if (idx >= 0 && idx < rate_table->rate_cnt) | ||
135 | tx_info->status.rates[0].idx = | ||
136 | rate_table->info[idx].ratecode & 0x7f; | ||
137 | } | ||
138 | |||
139 | hdrlen = ieee80211_get_hdrlen_from_skb(skb); | ||
140 | padsize = hdrlen & 3; | ||
141 | if (padsize && hdrlen >= 24) { | ||
142 | /* | ||
143 | * Remove MAC header padding before giving the frame back to | ||
144 | * mac80211. | ||
145 | */ | ||
146 | memmove(skb->data + padsize, skb->data, hdrlen); | ||
147 | skb_pull(skb, padsize); | ||
148 | } | ||
129 | 149 | ||
130 | ieee80211_tx_status(hw, skb); | 150 | ieee80211_tx_status(hw, skb); |
131 | } | 151 | } |
diff --git a/drivers/net/wireless/b43/debugfs.c b/drivers/net/wireless/b43/debugfs.c index 06a01da80160..e04fc91f569e 100644 --- a/drivers/net/wireless/b43/debugfs.c +++ b/drivers/net/wireless/b43/debugfs.c | |||
@@ -731,6 +731,7 @@ static void b43_add_dynamic_debug(struct b43_wldev *dev) | |||
731 | add_dyn_dbg("debug_pwork_stop", B43_DBG_PWORK_STOP, 0); | 731 | add_dyn_dbg("debug_pwork_stop", B43_DBG_PWORK_STOP, 0); |
732 | add_dyn_dbg("debug_lo", B43_DBG_LO, 0); | 732 | add_dyn_dbg("debug_lo", B43_DBG_LO, 0); |
733 | add_dyn_dbg("debug_firmware", B43_DBG_FIRMWARE, 0); | 733 | add_dyn_dbg("debug_firmware", B43_DBG_FIRMWARE, 0); |
734 | add_dyn_dbg("debug_keys", B43_DBG_KEYS, 0); | ||
734 | 735 | ||
735 | #undef add_dyn_dbg | 736 | #undef add_dyn_dbg |
736 | } | 737 | } |
diff --git a/drivers/net/wireless/b43/debugfs.h b/drivers/net/wireless/b43/debugfs.h index 22ffd02ba554..7886cbe2d1d1 100644 --- a/drivers/net/wireless/b43/debugfs.h +++ b/drivers/net/wireless/b43/debugfs.h | |||
@@ -12,6 +12,7 @@ enum b43_dyndbg { /* Dynamic debugging features */ | |||
12 | B43_DBG_PWORK_STOP, | 12 | B43_DBG_PWORK_STOP, |
13 | B43_DBG_LO, | 13 | B43_DBG_LO, |
14 | B43_DBG_FIRMWARE, | 14 | B43_DBG_FIRMWARE, |
15 | B43_DBG_KEYS, | ||
15 | __B43_NR_DYNDBG, | 16 | __B43_NR_DYNDBG, |
16 | }; | 17 | }; |
17 | 18 | ||
diff --git a/drivers/net/wireless/b43/main.c b/drivers/net/wireless/b43/main.c index ba7a5ab7fe1d..7b31a327b24a 100644 --- a/drivers/net/wireless/b43/main.c +++ b/drivers/net/wireless/b43/main.c | |||
@@ -992,6 +992,52 @@ static void b43_clear_keys(struct b43_wldev *dev) | |||
992 | b43_key_clear(dev, i); | 992 | b43_key_clear(dev, i); |
993 | } | 993 | } |
994 | 994 | ||
995 | static void b43_dump_keymemory(struct b43_wldev *dev) | ||
996 | { | ||
997 | unsigned int i, index, offset; | ||
998 | DECLARE_MAC_BUF(macbuf); | ||
999 | u8 mac[ETH_ALEN]; | ||
1000 | u16 algo; | ||
1001 | u32 rcmta0; | ||
1002 | u16 rcmta1; | ||
1003 | u64 hf; | ||
1004 | struct b43_key *key; | ||
1005 | |||
1006 | if (!b43_debug(dev, B43_DBG_KEYS)) | ||
1007 | return; | ||
1008 | |||
1009 | hf = b43_hf_read(dev); | ||
1010 | b43dbg(dev->wl, "Hardware key memory dump: USEDEFKEYS=%u\n", | ||
1011 | !!(hf & B43_HF_USEDEFKEYS)); | ||
1012 | for (index = 0; index < dev->max_nr_keys; index++) { | ||
1013 | key = &(dev->key[index]); | ||
1014 | printk(KERN_DEBUG "Key slot %02u: %s", | ||
1015 | index, (key->keyconf == NULL) ? " " : "*"); | ||
1016 | offset = dev->ktp + (index * B43_SEC_KEYSIZE); | ||
1017 | for (i = 0; i < B43_SEC_KEYSIZE; i += 2) { | ||
1018 | u16 tmp = b43_shm_read16(dev, B43_SHM_SHARED, offset + i); | ||
1019 | printk("%02X%02X", (tmp & 0xFF), ((tmp >> 8) & 0xFF)); | ||
1020 | } | ||
1021 | |||
1022 | algo = b43_shm_read16(dev, B43_SHM_SHARED, | ||
1023 | B43_SHM_SH_KEYIDXBLOCK + (index * 2)); | ||
1024 | printk(" Algo: %04X/%02X", algo, key->algorithm); | ||
1025 | |||
1026 | if (index >= 4) { | ||
1027 | rcmta0 = b43_shm_read32(dev, B43_SHM_RCMTA, | ||
1028 | ((index - 4) * 2) + 0); | ||
1029 | rcmta1 = b43_shm_read16(dev, B43_SHM_RCMTA, | ||
1030 | ((index - 4) * 2) + 1); | ||
1031 | *((__le32 *)(&mac[0])) = cpu_to_le32(rcmta0); | ||
1032 | *((__le16 *)(&mac[4])) = cpu_to_le16(rcmta1); | ||
1033 | printk(" MAC: %s", | ||
1034 | print_mac(macbuf, mac)); | ||
1035 | } else | ||
1036 | printk(" DEFAULT KEY"); | ||
1037 | printk("\n"); | ||
1038 | } | ||
1039 | } | ||
1040 | |||
995 | void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags) | 1041 | void b43_power_saving_ctl_bits(struct b43_wldev *dev, unsigned int ps_flags) |
996 | { | 1042 | { |
997 | u32 macctl; | 1043 | u32 macctl; |
@@ -3324,7 +3370,6 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed) | |||
3324 | unsigned long flags; | 3370 | unsigned long flags; |
3325 | int antenna; | 3371 | int antenna; |
3326 | int err = 0; | 3372 | int err = 0; |
3327 | u32 savedirqs; | ||
3328 | 3373 | ||
3329 | mutex_lock(&wl->mutex); | 3374 | mutex_lock(&wl->mutex); |
3330 | 3375 | ||
@@ -3335,24 +3380,14 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed) | |||
3335 | dev = wl->current_dev; | 3380 | dev = wl->current_dev; |
3336 | phy = &dev->phy; | 3381 | phy = &dev->phy; |
3337 | 3382 | ||
3383 | b43_mac_suspend(dev); | ||
3384 | |||
3338 | if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) | 3385 | if (changed & IEEE80211_CONF_CHANGE_RETRY_LIMITS) |
3339 | b43_set_retry_limits(dev, conf->short_frame_max_tx_count, | 3386 | b43_set_retry_limits(dev, conf->short_frame_max_tx_count, |
3340 | conf->long_frame_max_tx_count); | 3387 | conf->long_frame_max_tx_count); |
3341 | changed &= ~IEEE80211_CONF_CHANGE_RETRY_LIMITS; | 3388 | changed &= ~IEEE80211_CONF_CHANGE_RETRY_LIMITS; |
3342 | if (!changed) | 3389 | if (!changed) |
3343 | goto out_unlock_mutex; | 3390 | goto out_mac_enable; |
3344 | |||
3345 | /* Disable IRQs while reconfiguring the device. | ||
3346 | * This makes it possible to drop the spinlock throughout | ||
3347 | * the reconfiguration process. */ | ||
3348 | spin_lock_irqsave(&wl->irq_lock, flags); | ||
3349 | if (b43_status(dev) < B43_STAT_STARTED) { | ||
3350 | spin_unlock_irqrestore(&wl->irq_lock, flags); | ||
3351 | goto out_unlock_mutex; | ||
3352 | } | ||
3353 | savedirqs = b43_interrupt_disable(dev, B43_IRQ_ALL); | ||
3354 | spin_unlock_irqrestore(&wl->irq_lock, flags); | ||
3355 | b43_synchronize_irq(dev); | ||
3356 | 3391 | ||
3357 | /* Switch to the requested channel. | 3392 | /* Switch to the requested channel. |
3358 | * The firmware takes care of races with the TX handler. */ | 3393 | * The firmware takes care of races with the TX handler. */ |
@@ -3399,11 +3434,9 @@ static int b43_op_config(struct ieee80211_hw *hw, u32 changed) | |||
3399 | } | 3434 | } |
3400 | } | 3435 | } |
3401 | 3436 | ||
3402 | spin_lock_irqsave(&wl->irq_lock, flags); | 3437 | out_mac_enable: |
3403 | b43_interrupt_enable(dev, savedirqs); | 3438 | b43_mac_enable(dev); |
3404 | mmiowb(); | 3439 | out_unlock_mutex: |
3405 | spin_unlock_irqrestore(&wl->irq_lock, flags); | ||
3406 | out_unlock_mutex: | ||
3407 | mutex_unlock(&wl->mutex); | 3440 | mutex_unlock(&wl->mutex); |
3408 | 3441 | ||
3409 | return err; | 3442 | return err; |
@@ -3461,27 +3494,12 @@ static void b43_op_bss_info_changed(struct ieee80211_hw *hw, | |||
3461 | { | 3494 | { |
3462 | struct b43_wl *wl = hw_to_b43_wl(hw); | 3495 | struct b43_wl *wl = hw_to_b43_wl(hw); |
3463 | struct b43_wldev *dev; | 3496 | struct b43_wldev *dev; |
3464 | struct b43_phy *phy; | ||
3465 | unsigned long flags; | ||
3466 | u32 savedirqs; | ||
3467 | 3497 | ||
3468 | mutex_lock(&wl->mutex); | 3498 | mutex_lock(&wl->mutex); |
3469 | 3499 | ||
3470 | dev = wl->current_dev; | 3500 | dev = wl->current_dev; |
3471 | phy = &dev->phy; | 3501 | if (!dev || b43_status(dev) < B43_STAT_STARTED) |
3472 | |||
3473 | /* Disable IRQs while reconfiguring the device. | ||
3474 | * This makes it possible to drop the spinlock throughout | ||
3475 | * the reconfiguration process. */ | ||
3476 | spin_lock_irqsave(&wl->irq_lock, flags); | ||
3477 | if (b43_status(dev) < B43_STAT_STARTED) { | ||
3478 | spin_unlock_irqrestore(&wl->irq_lock, flags); | ||
3479 | goto out_unlock_mutex; | 3502 | goto out_unlock_mutex; |
3480 | } | ||
3481 | savedirqs = b43_interrupt_disable(dev, B43_IRQ_ALL); | ||
3482 | spin_unlock_irqrestore(&wl->irq_lock, flags); | ||
3483 | b43_synchronize_irq(dev); | ||
3484 | |||
3485 | b43_mac_suspend(dev); | 3503 | b43_mac_suspend(dev); |
3486 | 3504 | ||
3487 | if (changed & BSS_CHANGED_BASIC_RATES) | 3505 | if (changed & BSS_CHANGED_BASIC_RATES) |
@@ -3495,13 +3513,7 @@ static void b43_op_bss_info_changed(struct ieee80211_hw *hw, | |||
3495 | } | 3513 | } |
3496 | 3514 | ||
3497 | b43_mac_enable(dev); | 3515 | b43_mac_enable(dev); |
3498 | 3516 | out_unlock_mutex: | |
3499 | spin_lock_irqsave(&wl->irq_lock, flags); | ||
3500 | b43_interrupt_enable(dev, savedirqs); | ||
3501 | /* XXX: why? */ | ||
3502 | mmiowb(); | ||
3503 | spin_unlock_irqrestore(&wl->irq_lock, flags); | ||
3504 | out_unlock_mutex: | ||
3505 | mutex_unlock(&wl->mutex); | 3517 | mutex_unlock(&wl->mutex); |
3506 | 3518 | ||
3507 | return; | 3519 | return; |
@@ -3599,15 +3611,18 @@ static int b43_op_set_key(struct ieee80211_hw *hw, enum set_key_cmd cmd, | |||
3599 | default: | 3611 | default: |
3600 | B43_WARN_ON(1); | 3612 | B43_WARN_ON(1); |
3601 | } | 3613 | } |
3614 | |||
3602 | out_unlock: | 3615 | out_unlock: |
3603 | spin_unlock_irqrestore(&wl->irq_lock, flags); | ||
3604 | mutex_unlock(&wl->mutex); | ||
3605 | if (!err) { | 3616 | if (!err) { |
3606 | b43dbg(wl, "%s hardware based encryption for keyidx: %d, " | 3617 | b43dbg(wl, "%s hardware based encryption for keyidx: %d, " |
3607 | "mac: %pM\n", | 3618 | "mac: %pM\n", |
3608 | cmd == SET_KEY ? "Using" : "Disabling", key->keyidx, | 3619 | cmd == SET_KEY ? "Using" : "Disabling", key->keyidx, |
3609 | addr); | 3620 | addr); |
3621 | b43_dump_keymemory(dev); | ||
3610 | } | 3622 | } |
3623 | spin_unlock_irqrestore(&wl->irq_lock, flags); | ||
3624 | mutex_unlock(&wl->mutex); | ||
3625 | |||
3611 | return err; | 3626 | return err; |
3612 | } | 3627 | } |
3613 | 3628 | ||
diff --git a/drivers/net/wireless/b43/phy_common.c b/drivers/net/wireless/b43/phy_common.c index af37abccccb3..026b61c03fb9 100644 --- a/drivers/net/wireless/b43/phy_common.c +++ b/drivers/net/wireless/b43/phy_common.c | |||
@@ -178,13 +178,27 @@ void b43_phy_unlock(struct b43_wldev *dev) | |||
178 | b43_power_saving_ctl_bits(dev, 0); | 178 | b43_power_saving_ctl_bits(dev, 0); |
179 | } | 179 | } |
180 | 180 | ||
181 | static inline void assert_mac_suspended(struct b43_wldev *dev) | ||
182 | { | ||
183 | if (!B43_DEBUG) | ||
184 | return; | ||
185 | if ((b43_status(dev) >= B43_STAT_INITIALIZED) && | ||
186 | (dev->mac_suspended <= 0)) { | ||
187 | b43dbg(dev->wl, "PHY/RADIO register access with " | ||
188 | "enabled MAC.\n"); | ||
189 | dump_stack(); | ||
190 | } | ||
191 | } | ||
192 | |||
181 | u16 b43_radio_read(struct b43_wldev *dev, u16 reg) | 193 | u16 b43_radio_read(struct b43_wldev *dev, u16 reg) |
182 | { | 194 | { |
195 | assert_mac_suspended(dev); | ||
183 | return dev->phy.ops->radio_read(dev, reg); | 196 | return dev->phy.ops->radio_read(dev, reg); |
184 | } | 197 | } |
185 | 198 | ||
186 | void b43_radio_write(struct b43_wldev *dev, u16 reg, u16 value) | 199 | void b43_radio_write(struct b43_wldev *dev, u16 reg, u16 value) |
187 | { | 200 | { |
201 | assert_mac_suspended(dev); | ||
188 | dev->phy.ops->radio_write(dev, reg, value); | 202 | dev->phy.ops->radio_write(dev, reg, value); |
189 | } | 203 | } |
190 | 204 | ||
@@ -208,11 +222,13 @@ void b43_radio_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set) | |||
208 | 222 | ||
209 | u16 b43_phy_read(struct b43_wldev *dev, u16 reg) | 223 | u16 b43_phy_read(struct b43_wldev *dev, u16 reg) |
210 | { | 224 | { |
225 | assert_mac_suspended(dev); | ||
211 | return dev->phy.ops->phy_read(dev, reg); | 226 | return dev->phy.ops->phy_read(dev, reg); |
212 | } | 227 | } |
213 | 228 | ||
214 | void b43_phy_write(struct b43_wldev *dev, u16 reg, u16 value) | 229 | void b43_phy_write(struct b43_wldev *dev, u16 reg, u16 value) |
215 | { | 230 | { |
231 | assert_mac_suspended(dev); | ||
216 | dev->phy.ops->phy_write(dev, reg, value); | 232 | dev->phy.ops->phy_write(dev, reg, value); |
217 | } | 233 | } |
218 | 234 | ||
@@ -280,8 +296,10 @@ void b43_software_rfkill(struct b43_wldev *dev, enum rfkill_state state) | |||
280 | state = RFKILL_STATE_SOFT_BLOCKED; | 296 | state = RFKILL_STATE_SOFT_BLOCKED; |
281 | } | 297 | } |
282 | 298 | ||
299 | b43_mac_suspend(dev); | ||
283 | phy->ops->software_rfkill(dev, state); | 300 | phy->ops->software_rfkill(dev, state); |
284 | phy->radio_on = (state == RFKILL_STATE_UNBLOCKED); | 301 | phy->radio_on = (state == RFKILL_STATE_UNBLOCKED); |
302 | b43_mac_enable(dev); | ||
285 | } | 303 | } |
286 | 304 | ||
287 | /** | 305 | /** |
diff --git a/drivers/net/wireless/b43/phy_g.c b/drivers/net/wireless/b43/phy_g.c index 232181f6333c..3b1d673796cc 100644 --- a/drivers/net/wireless/b43/phy_g.c +++ b/drivers/net/wireless/b43/phy_g.c | |||
@@ -3047,6 +3047,8 @@ static void b43_gphy_op_adjust_txpower(struct b43_wldev *dev) | |||
3047 | int rfatt, bbatt; | 3047 | int rfatt, bbatt; |
3048 | u8 tx_control; | 3048 | u8 tx_control; |
3049 | 3049 | ||
3050 | b43_mac_suspend(dev); | ||
3051 | |||
3050 | spin_lock_irq(&dev->wl->irq_lock); | 3052 | spin_lock_irq(&dev->wl->irq_lock); |
3051 | 3053 | ||
3052 | /* Calculate the new attenuation values. */ | 3054 | /* Calculate the new attenuation values. */ |
@@ -3103,6 +3105,8 @@ static void b43_gphy_op_adjust_txpower(struct b43_wldev *dev) | |||
3103 | gphy->tx_control); | 3105 | gphy->tx_control); |
3104 | b43_radio_unlock(dev); | 3106 | b43_radio_unlock(dev); |
3105 | b43_phy_unlock(dev); | 3107 | b43_phy_unlock(dev); |
3108 | |||
3109 | b43_mac_enable(dev); | ||
3106 | } | 3110 | } |
3107 | 3111 | ||
3108 | static enum b43_txpwr_result b43_gphy_op_recalc_txpower(struct b43_wldev *dev, | 3112 | static enum b43_txpwr_result b43_gphy_op_recalc_txpower(struct b43_wldev *dev, |
@@ -3215,9 +3219,9 @@ static void b43_gphy_op_pwork_15sec(struct b43_wldev *dev) | |||
3215 | struct b43_phy *phy = &dev->phy; | 3219 | struct b43_phy *phy = &dev->phy; |
3216 | struct b43_phy_g *gphy = phy->g; | 3220 | struct b43_phy_g *gphy = phy->g; |
3217 | 3221 | ||
3222 | b43_mac_suspend(dev); | ||
3218 | //TODO: update_aci_moving_average | 3223 | //TODO: update_aci_moving_average |
3219 | if (gphy->aci_enable && gphy->aci_wlan_automatic) { | 3224 | if (gphy->aci_enable && gphy->aci_wlan_automatic) { |
3220 | b43_mac_suspend(dev); | ||
3221 | if (!gphy->aci_enable && 1 /*TODO: not scanning? */ ) { | 3225 | if (!gphy->aci_enable && 1 /*TODO: not scanning? */ ) { |
3222 | if (0 /*TODO: bunch of conditions */ ) { | 3226 | if (0 /*TODO: bunch of conditions */ ) { |
3223 | phy->ops->interf_mitigation(dev, | 3227 | phy->ops->interf_mitigation(dev, |
@@ -3227,12 +3231,12 @@ static void b43_gphy_op_pwork_15sec(struct b43_wldev *dev) | |||
3227 | if (/*(aci_average > 1000) &&*/ !b43_gphy_aci_scan(dev)) | 3231 | if (/*(aci_average > 1000) &&*/ !b43_gphy_aci_scan(dev)) |
3228 | phy->ops->interf_mitigation(dev, B43_INTERFMODE_NONE); | 3232 | phy->ops->interf_mitigation(dev, B43_INTERFMODE_NONE); |
3229 | } | 3233 | } |
3230 | b43_mac_enable(dev); | ||
3231 | } else if (gphy->interfmode == B43_INTERFMODE_NONWLAN && | 3234 | } else if (gphy->interfmode == B43_INTERFMODE_NONWLAN && |
3232 | phy->rev == 1) { | 3235 | phy->rev == 1) { |
3233 | //TODO: implement rev1 workaround | 3236 | //TODO: implement rev1 workaround |
3234 | } | 3237 | } |
3235 | b43_lo_g_maintanance_work(dev); | 3238 | b43_lo_g_maintanance_work(dev); |
3239 | b43_mac_enable(dev); | ||
3236 | } | 3240 | } |
3237 | 3241 | ||
3238 | static void b43_gphy_op_pwork_60sec(struct b43_wldev *dev) | 3242 | static void b43_gphy_op_pwork_60sec(struct b43_wldev *dev) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.c b/drivers/net/wireless/iwlwifi/iwl-3945.c index d0c9bdcf393a..8fdb34222c0a 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.c +++ b/drivers/net/wireless/iwlwifi/iwl-3945.c | |||
@@ -2482,7 +2482,6 @@ unsigned int iwl3945_hw_get_beacon_cmd(struct iwl3945_priv *priv, | |||
2482 | 2482 | ||
2483 | frame_size = iwl3945_fill_beacon_frame(priv, | 2483 | frame_size = iwl3945_fill_beacon_frame(priv, |
2484 | tx_beacon_cmd->frame, | 2484 | tx_beacon_cmd->frame, |
2485 | iwl3945_broadcast_addr, | ||
2486 | sizeof(frame->u) - sizeof(*tx_beacon_cmd)); | 2485 | sizeof(frame->u) - sizeof(*tx_beacon_cmd)); |
2487 | 2486 | ||
2488 | BUG_ON(frame_size > MAX_MPDU_SIZE); | 2487 | BUG_ON(frame_size > MAX_MPDU_SIZE); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-3945.h b/drivers/net/wireless/iwlwifi/iwl-3945.h index ec6084c8fd13..2c0ddc5110c6 100644 --- a/drivers/net/wireless/iwlwifi/iwl-3945.h +++ b/drivers/net/wireless/iwlwifi/iwl-3945.h | |||
@@ -405,12 +405,6 @@ struct iwl3945_rx_queue { | |||
405 | 405 | ||
406 | #define SCAN_INTERVAL 100 | 406 | #define SCAN_INTERVAL 100 |
407 | 407 | ||
408 | #define MAX_A_CHANNELS 252 | ||
409 | #define MIN_A_CHANNELS 7 | ||
410 | |||
411 | #define MAX_B_CHANNELS 14 | ||
412 | #define MIN_B_CHANNELS 1 | ||
413 | |||
414 | #define STATUS_HCMD_ACTIVE 0 /* host command in progress */ | 408 | #define STATUS_HCMD_ACTIVE 0 /* host command in progress */ |
415 | #define STATUS_HCMD_SYNC_ACTIVE 1 /* sync host command in progress */ | 409 | #define STATUS_HCMD_SYNC_ACTIVE 1 /* sync host command in progress */ |
416 | #define STATUS_INT_ENABLED 2 | 410 | #define STATUS_INT_ENABLED 2 |
@@ -590,8 +584,7 @@ extern int iwl3945_send_cmd_pdu(struct iwl3945_priv *priv, u8 id, u16 len, | |||
590 | extern int __must_check iwl3945_send_cmd(struct iwl3945_priv *priv, | 584 | extern int __must_check iwl3945_send_cmd(struct iwl3945_priv *priv, |
591 | struct iwl3945_host_cmd *cmd); | 585 | struct iwl3945_host_cmd *cmd); |
592 | extern unsigned int iwl3945_fill_beacon_frame(struct iwl3945_priv *priv, | 586 | extern unsigned int iwl3945_fill_beacon_frame(struct iwl3945_priv *priv, |
593 | struct ieee80211_hdr *hdr, | 587 | struct ieee80211_hdr *hdr,int left); |
594 | const u8 *dest, int left); | ||
595 | extern int iwl3945_rx_queue_update_write_ptr(struct iwl3945_priv *priv, | 588 | extern int iwl3945_rx_queue_update_write_ptr(struct iwl3945_priv *priv, |
596 | struct iwl3945_rx_queue *q); | 589 | struct iwl3945_rx_queue *q); |
597 | extern int iwl3945_send_statistics_request(struct iwl3945_priv *priv); | 590 | extern int iwl3945_send_statistics_request(struct iwl3945_priv *priv); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-4965.c b/drivers/net/wireless/iwlwifi/iwl-4965.c index a7e6e32bd489..5a72bc0377de 100644 --- a/drivers/net/wireless/iwlwifi/iwl-4965.c +++ b/drivers/net/wireless/iwlwifi/iwl-4965.c | |||
@@ -426,7 +426,6 @@ static void iwl4965_nic_config(struct iwl_priv *priv) | |||
426 | 426 | ||
427 | static int iwl4965_apm_stop_master(struct iwl_priv *priv) | 427 | static int iwl4965_apm_stop_master(struct iwl_priv *priv) |
428 | { | 428 | { |
429 | int ret = 0; | ||
430 | unsigned long flags; | 429 | unsigned long flags; |
431 | 430 | ||
432 | spin_lock_irqsave(&priv->lock, flags); | 431 | spin_lock_irqsave(&priv->lock, flags); |
@@ -434,16 +433,13 @@ static int iwl4965_apm_stop_master(struct iwl_priv *priv) | |||
434 | /* set stop master bit */ | 433 | /* set stop master bit */ |
435 | iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER); | 434 | iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER); |
436 | 435 | ||
437 | ret = iwl_poll_direct_bit(priv, CSR_RESET, | 436 | iwl_poll_direct_bit(priv, CSR_RESET, |
438 | CSR_RESET_REG_FLAG_MASTER_DISABLED, 100); | 437 | CSR_RESET_REG_FLAG_MASTER_DISABLED, 100); |
439 | if (ret < 0) | ||
440 | goto out; | ||
441 | 438 | ||
442 | out: | ||
443 | spin_unlock_irqrestore(&priv->lock, flags); | 439 | spin_unlock_irqrestore(&priv->lock, flags); |
444 | IWL_DEBUG_INFO("stop master\n"); | 440 | IWL_DEBUG_INFO("stop master\n"); |
445 | 441 | ||
446 | return ret; | 442 | return 0; |
447 | } | 443 | } |
448 | 444 | ||
449 | static void iwl4965_apm_stop(struct iwl_priv *priv) | 445 | static void iwl4965_apm_stop(struct iwl_priv *priv) |
@@ -2354,7 +2350,7 @@ module_param_named(disable, iwl4965_mod_params.disable, int, 0444); | |||
2354 | MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])"); | 2350 | MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])"); |
2355 | module_param_named(swcrypto, iwl4965_mod_params.sw_crypto, int, 0444); | 2351 | module_param_named(swcrypto, iwl4965_mod_params.sw_crypto, int, 0444); |
2356 | MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])"); | 2352 | MODULE_PARM_DESC(swcrypto, "using crypto in software (default 0 [hardware])"); |
2357 | module_param_named(debug, iwl4965_mod_params.debug, int, 0444); | 2353 | module_param_named(debug, iwl4965_mod_params.debug, uint, 0444); |
2358 | MODULE_PARM_DESC(debug, "debug output mask"); | 2354 | MODULE_PARM_DESC(debug, "debug output mask"); |
2359 | module_param_named( | 2355 | module_param_named( |
2360 | disable_hw_scan, iwl4965_mod_params.disable_hw_scan, int, 0444); | 2356 | disable_hw_scan, iwl4965_mod_params.disable_hw_scan, int, 0444); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-5000.c b/drivers/net/wireless/iwlwifi/iwl-5000.c index 2344de945974..66d053d28a74 100644 --- a/drivers/net/wireless/iwlwifi/iwl-5000.c +++ b/drivers/net/wireless/iwlwifi/iwl-5000.c | |||
@@ -73,7 +73,6 @@ static const u16 iwl5000_default_queue_to_tx_fifo[] = { | |||
73 | /* FIXME: same implementation as 4965 */ | 73 | /* FIXME: same implementation as 4965 */ |
74 | static int iwl5000_apm_stop_master(struct iwl_priv *priv) | 74 | static int iwl5000_apm_stop_master(struct iwl_priv *priv) |
75 | { | 75 | { |
76 | int ret = 0; | ||
77 | unsigned long flags; | 76 | unsigned long flags; |
78 | 77 | ||
79 | spin_lock_irqsave(&priv->lock, flags); | 78 | spin_lock_irqsave(&priv->lock, flags); |
@@ -81,16 +80,13 @@ static int iwl5000_apm_stop_master(struct iwl_priv *priv) | |||
81 | /* set stop master bit */ | 80 | /* set stop master bit */ |
82 | iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER); | 81 | iwl_set_bit(priv, CSR_RESET, CSR_RESET_REG_FLAG_STOP_MASTER); |
83 | 82 | ||
84 | ret = iwl_poll_direct_bit(priv, CSR_RESET, | 83 | iwl_poll_direct_bit(priv, CSR_RESET, |
85 | CSR_RESET_REG_FLAG_MASTER_DISABLED, 100); | 84 | CSR_RESET_REG_FLAG_MASTER_DISABLED, 100); |
86 | if (ret < 0) | ||
87 | goto out; | ||
88 | 85 | ||
89 | out: | ||
90 | spin_unlock_irqrestore(&priv->lock, flags); | 86 | spin_unlock_irqrestore(&priv->lock, flags); |
91 | IWL_DEBUG_INFO("stop master\n"); | 87 | IWL_DEBUG_INFO("stop master\n"); |
92 | 88 | ||
93 | return ret; | 89 | return 0; |
94 | } | 90 | } |
95 | 91 | ||
96 | 92 | ||
@@ -1623,7 +1619,7 @@ MODULE_PARM_DESC(disable50, | |||
1623 | module_param_named(swcrypto50, iwl50_mod_params.sw_crypto, bool, 0444); | 1619 | module_param_named(swcrypto50, iwl50_mod_params.sw_crypto, bool, 0444); |
1624 | MODULE_PARM_DESC(swcrypto50, | 1620 | MODULE_PARM_DESC(swcrypto50, |
1625 | "using software crypto engine (default 0 [hardware])\n"); | 1621 | "using software crypto engine (default 0 [hardware])\n"); |
1626 | module_param_named(debug50, iwl50_mod_params.debug, int, 0444); | 1622 | module_param_named(debug50, iwl50_mod_params.debug, uint, 0444); |
1627 | MODULE_PARM_DESC(debug50, "50XX debug output mask"); | 1623 | MODULE_PARM_DESC(debug50, "50XX debug output mask"); |
1628 | module_param_named(queues_num50, iwl50_mod_params.num_of_queues, int, 0444); | 1624 | module_param_named(queues_num50, iwl50_mod_params.num_of_queues, int, 0444); |
1629 | MODULE_PARM_DESC(queues_num50, "number of hw queues in 50xx series"); | 1625 | MODULE_PARM_DESC(queues_num50, "number of hw queues in 50xx series"); |
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c index 37b892044a18..f3f17929ca0b 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn-rs.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn-rs.c | |||
@@ -836,6 +836,10 @@ static void rs_tx_status(void *priv_r, struct ieee80211_supported_band *sband, | |||
836 | (hw->wiphy->bands[priv->band]->bitrates[rs_index].bitrate != | 836 | (hw->wiphy->bands[priv->band]->bitrates[rs_index].bitrate != |
837 | hw->wiphy->bands[info->band]->bitrates[info->status.rates[0].idx].bitrate)) { | 837 | hw->wiphy->bands[info->band]->bitrates[info->status.rates[0].idx].bitrate)) { |
838 | IWL_DEBUG_RATE("initial rate does not match 0x%x\n", tx_rate); | 838 | IWL_DEBUG_RATE("initial rate does not match 0x%x\n", tx_rate); |
839 | /* the last LQ command could failed so the LQ in ucode not | ||
840 | * the same in driver sync up | ||
841 | */ | ||
842 | iwl_send_lq_cmd(priv, &lq_sta->lq, CMD_ASYNC); | ||
839 | goto out; | 843 | goto out; |
840 | } | 844 | } |
841 | 845 | ||
@@ -2167,6 +2171,7 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, | |||
2167 | struct iwl_priv *priv = (struct iwl_priv *)priv_r; | 2171 | struct iwl_priv *priv = (struct iwl_priv *)priv_r; |
2168 | struct ieee80211_conf *conf = &priv->hw->conf; | 2172 | struct ieee80211_conf *conf = &priv->hw->conf; |
2169 | struct iwl_lq_sta *lq_sta = priv_sta; | 2173 | struct iwl_lq_sta *lq_sta = priv_sta; |
2174 | u16 mask_bit = 0; | ||
2170 | 2175 | ||
2171 | lq_sta->flush_timer = 0; | 2176 | lq_sta->flush_timer = 0; |
2172 | lq_sta->supp_rates = sta->supp_rates[sband->band]; | 2177 | lq_sta->supp_rates = sta->supp_rates[sband->band]; |
@@ -2200,16 +2205,6 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, | |||
2200 | priv->assoc_station_added = 1; | 2205 | priv->assoc_station_added = 1; |
2201 | } | 2206 | } |
2202 | 2207 | ||
2203 | /* Find highest tx rate supported by hardware and destination station */ | ||
2204 | lq_sta->last_txrate_idx = 3; | ||
2205 | for (i = 0; i < sband->n_bitrates; i++) | ||
2206 | if (sta->supp_rates[sband->band] & BIT(i)) | ||
2207 | lq_sta->last_txrate_idx = i; | ||
2208 | |||
2209 | /* For MODE_IEEE80211A, skip over cck rates in global rate table */ | ||
2210 | if (sband->band == IEEE80211_BAND_5GHZ) | ||
2211 | lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; | ||
2212 | |||
2213 | lq_sta->is_dup = 0; | 2208 | lq_sta->is_dup = 0; |
2214 | lq_sta->is_green = rs_use_green(priv, conf); | 2209 | lq_sta->is_green = rs_use_green(priv, conf); |
2215 | lq_sta->active_legacy_rate = priv->active_rate & ~(0x1000); | 2210 | lq_sta->active_legacy_rate = priv->active_rate & ~(0x1000); |
@@ -2248,6 +2243,17 @@ static void rs_rate_init(void *priv_r, struct ieee80211_supported_band *sband, | |||
2248 | lq_sta->tx_agg_tid_en = IWL_AGG_ALL_TID; | 2243 | lq_sta->tx_agg_tid_en = IWL_AGG_ALL_TID; |
2249 | lq_sta->drv = priv; | 2244 | lq_sta->drv = priv; |
2250 | 2245 | ||
2246 | /* Find highest tx rate supported by hardware and destination station */ | ||
2247 | mask_bit = sta->supp_rates[sband->band] & lq_sta->active_legacy_rate; | ||
2248 | lq_sta->last_txrate_idx = 3; | ||
2249 | for (i = 0; i < sband->n_bitrates; i++) | ||
2250 | if (mask_bit & BIT(i)) | ||
2251 | lq_sta->last_txrate_idx = i; | ||
2252 | |||
2253 | /* For MODE_IEEE80211A, skip over cck rates in global rate table */ | ||
2254 | if (sband->band == IEEE80211_BAND_5GHZ) | ||
2255 | lq_sta->last_txrate_idx += IWL_FIRST_OFDM_RATE; | ||
2256 | |||
2251 | rs_initialize_lq(priv, conf, sta, lq_sta); | 2257 | rs_initialize_lq(priv, conf, sta, lq_sta); |
2252 | } | 2258 | } |
2253 | 2259 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-agn.c b/drivers/net/wireless/iwlwifi/iwl-agn.c index 2f5e86e12916..5da6b35cd26d 100644 --- a/drivers/net/wireless/iwlwifi/iwl-agn.c +++ b/drivers/net/wireless/iwlwifi/iwl-agn.c | |||
@@ -371,7 +371,7 @@ static void iwl_free_frame(struct iwl_priv *priv, struct iwl_frame *frame) | |||
371 | 371 | ||
372 | static unsigned int iwl_fill_beacon_frame(struct iwl_priv *priv, | 372 | static unsigned int iwl_fill_beacon_frame(struct iwl_priv *priv, |
373 | struct ieee80211_hdr *hdr, | 373 | struct ieee80211_hdr *hdr, |
374 | const u8 *dest, int left) | 374 | int left) |
375 | { | 375 | { |
376 | if (!iwl_is_associated(priv) || !priv->ibss_beacon || | 376 | if (!iwl_is_associated(priv) || !priv->ibss_beacon || |
377 | ((priv->iw_mode != NL80211_IFTYPE_ADHOC) && | 377 | ((priv->iw_mode != NL80211_IFTYPE_ADHOC) && |
@@ -424,7 +424,6 @@ static unsigned int iwl_hw_get_beacon_cmd(struct iwl_priv *priv, | |||
424 | tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; | 424 | tx_beacon_cmd->tx.stop_time.life_time = TX_CMD_LIFE_TIME_INFINITE; |
425 | 425 | ||
426 | frame_size = iwl_fill_beacon_frame(priv, tx_beacon_cmd->frame, | 426 | frame_size = iwl_fill_beacon_frame(priv, tx_beacon_cmd->frame, |
427 | iwl_bcast_addr, | ||
428 | sizeof(frame->u) - sizeof(*tx_beacon_cmd)); | 427 | sizeof(frame->u) - sizeof(*tx_beacon_cmd)); |
429 | 428 | ||
430 | BUG_ON(frame_size > MAX_MPDU_SIZE); | 429 | BUG_ON(frame_size > MAX_MPDU_SIZE); |
@@ -515,19 +514,27 @@ static void iwl_ht_conf(struct iwl_priv *priv, | |||
515 | iwl_conf->supported_chan_width = | 514 | iwl_conf->supported_chan_width = |
516 | !!(ht_conf->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40); | 515 | !!(ht_conf->cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40); |
517 | 516 | ||
518 | iwl_conf->extension_chan_offset = bss_conf->ht.secondary_channel_offset; | 517 | /* |
518 | * XXX: The HT configuration needs to be moved into iwl_mac_config() | ||
519 | * to be done there correctly. | ||
520 | */ | ||
521 | |||
522 | iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE; | ||
523 | if (priv->hw->conf.ht.channel_type == NL80211_CHAN_HT40MINUS) | ||
524 | iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_BELOW; | ||
525 | else if(priv->hw->conf.ht.channel_type == NL80211_CHAN_HT40PLUS) | ||
526 | iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_ABOVE; | ||
527 | |||
519 | /* If no above or below channel supplied disable FAT channel */ | 528 | /* If no above or below channel supplied disable FAT channel */ |
520 | if (iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_ABOVE && | 529 | if (iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_ABOVE && |
521 | iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_BELOW) { | 530 | iwl_conf->extension_chan_offset != IEEE80211_HT_PARAM_CHA_SEC_BELOW) |
522 | iwl_conf->extension_chan_offset = IEEE80211_HT_PARAM_CHA_SEC_NONE; | ||
523 | iwl_conf->supported_chan_width = 0; | 531 | iwl_conf->supported_chan_width = 0; |
524 | } | ||
525 | 532 | ||
526 | iwl_conf->sm_ps = (u8)((ht_conf->cap & IEEE80211_HT_CAP_SM_PS) >> 2); | 533 | iwl_conf->sm_ps = (u8)((ht_conf->cap & IEEE80211_HT_CAP_SM_PS) >> 2); |
527 | 534 | ||
528 | memcpy(&iwl_conf->mcs, &ht_conf->mcs, 16); | 535 | memcpy(&iwl_conf->mcs, &ht_conf->mcs, 16); |
529 | 536 | ||
530 | iwl_conf->tx_chan_width = bss_conf->ht.width_40_ok; | 537 | iwl_conf->tx_chan_width = iwl_conf->supported_chan_width != 0; |
531 | iwl_conf->ht_protection = | 538 | iwl_conf->ht_protection = |
532 | bss_conf->ht.operation_mode & IEEE80211_HT_OP_MODE_PROTECTION; | 539 | bss_conf->ht.operation_mode & IEEE80211_HT_OP_MODE_PROTECTION; |
533 | iwl_conf->non_GF_STA_present = | 540 | iwl_conf->non_GF_STA_present = |
@@ -1103,16 +1110,6 @@ static void iwl_setup_rx_handlers(struct iwl_priv *priv) | |||
1103 | priv->cfg->ops->lib->rx_handler_setup(priv); | 1110 | priv->cfg->ops->lib->rx_handler_setup(priv); |
1104 | } | 1111 | } |
1105 | 1112 | ||
1106 | /* | ||
1107 | * this should be called while priv->lock is locked | ||
1108 | */ | ||
1109 | static void __iwl_rx_replenish(struct iwl_priv *priv) | ||
1110 | { | ||
1111 | iwl_rx_allocate(priv); | ||
1112 | iwl_rx_queue_restock(priv); | ||
1113 | } | ||
1114 | |||
1115 | |||
1116 | /** | 1113 | /** |
1117 | * iwl_rx_handle - Main entry function for receiving responses from uCode | 1114 | * iwl_rx_handle - Main entry function for receiving responses from uCode |
1118 | * | 1115 | * |
@@ -1221,7 +1218,7 @@ void iwl_rx_handle(struct iwl_priv *priv) | |||
1221 | count++; | 1218 | count++; |
1222 | if (count >= 8) { | 1219 | if (count >= 8) { |
1223 | priv->rxq.read = i; | 1220 | priv->rxq.read = i; |
1224 | __iwl_rx_replenish(priv); | 1221 | iwl_rx_queue_restock(priv); |
1225 | count = 0; | 1222 | count = 0; |
1226 | } | 1223 | } |
1227 | } | 1224 | } |
@@ -3335,7 +3332,7 @@ static int iwl_mac_beacon_update(struct ieee80211_hw *hw, struct sk_buff *skb) | |||
3335 | 3332 | ||
3336 | /* | 3333 | /* |
3337 | * The following adds a new attribute to the sysfs representation | 3334 | * The following adds a new attribute to the sysfs representation |
3338 | * of this device driver (i.e. a new file in /sys/bus/pci/drivers/iwl/) | 3335 | * of this device driver (i.e. a new file in /sys/class/net/wlan0/device/) |
3339 | * used for controlling the debug level. | 3336 | * used for controlling the debug level. |
3340 | * | 3337 | * |
3341 | * See the level definitions in iwl for details. | 3338 | * See the level definitions in iwl for details. |
@@ -3421,7 +3418,11 @@ static ssize_t show_tx_power(struct device *d, | |||
3421 | struct device_attribute *attr, char *buf) | 3418 | struct device_attribute *attr, char *buf) |
3422 | { | 3419 | { |
3423 | struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; | 3420 | struct iwl_priv *priv = (struct iwl_priv *)d->driver_data; |
3424 | return sprintf(buf, "%d\n", priv->tx_power_user_lmt); | 3421 | |
3422 | if (!iwl_is_ready_rf(priv)) | ||
3423 | return sprintf(buf, "off\n"); | ||
3424 | else | ||
3425 | return sprintf(buf, "%d\n", priv->tx_power_user_lmt); | ||
3425 | } | 3426 | } |
3426 | 3427 | ||
3427 | static ssize_t store_tx_power(struct device *d, | 3428 | static ssize_t store_tx_power(struct device *d, |
diff --git a/drivers/net/wireless/iwlwifi/iwl-calib.c b/drivers/net/wireless/iwlwifi/iwl-calib.c index 7956e0873614..f836ecc55758 100644 --- a/drivers/net/wireless/iwlwifi/iwl-calib.c +++ b/drivers/net/wireless/iwlwifi/iwl-calib.c | |||
@@ -70,6 +70,15 @@ | |||
70 | * INIT calibrations framework | 70 | * INIT calibrations framework |
71 | *****************************************************************************/ | 71 | *****************************************************************************/ |
72 | 72 | ||
73 | struct statistics_general_data { | ||
74 | u32 beacon_silence_rssi_a; | ||
75 | u32 beacon_silence_rssi_b; | ||
76 | u32 beacon_silence_rssi_c; | ||
77 | u32 beacon_energy_a; | ||
78 | u32 beacon_energy_b; | ||
79 | u32 beacon_energy_c; | ||
80 | }; | ||
81 | |||
73 | int iwl_send_calib_results(struct iwl_priv *priv) | 82 | int iwl_send_calib_results(struct iwl_priv *priv) |
74 | { | 83 | { |
75 | int ret = 0; | 84 | int ret = 0; |
diff --git a/drivers/net/wireless/iwlwifi/iwl-commands.h b/drivers/net/wireless/iwlwifi/iwl-commands.h index 60e79d9bd725..52966ffbef6e 100644 --- a/drivers/net/wireless/iwlwifi/iwl-commands.h +++ b/drivers/net/wireless/iwlwifi/iwl-commands.h | |||
@@ -2418,6 +2418,8 @@ struct statistics_rx_ht_phy { | |||
2418 | __le32 reserved2; | 2418 | __le32 reserved2; |
2419 | } __attribute__ ((packed)); | 2419 | } __attribute__ ((packed)); |
2420 | 2420 | ||
2421 | #define INTERFERENCE_DATA_AVAILABLE __constant_cpu_to_le32(1) | ||
2422 | |||
2421 | struct statistics_rx_non_phy { | 2423 | struct statistics_rx_non_phy { |
2422 | __le32 bogus_cts; /* CTS received when not expecting CTS */ | 2424 | __le32 bogus_cts; /* CTS received when not expecting CTS */ |
2423 | __le32 bogus_ack; /* ACK received when not expecting ACK */ | 2425 | __le32 bogus_ack; /* ACK received when not expecting ACK */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-core.h b/drivers/net/wireless/iwlwifi/iwl-core.h index 08b842f85768..7c3a20a986bb 100644 --- a/drivers/net/wireless/iwlwifi/iwl-core.h +++ b/drivers/net/wireless/iwlwifi/iwl-core.h | |||
@@ -154,7 +154,7 @@ struct iwl_ops { | |||
154 | struct iwl_mod_params { | 154 | struct iwl_mod_params { |
155 | int disable; /* def: 0 = enable radio */ | 155 | int disable; /* def: 0 = enable radio */ |
156 | int sw_crypto; /* def: 0 = using hardware encryption */ | 156 | int sw_crypto; /* def: 0 = using hardware encryption */ |
157 | int debug; /* def: 0 = minimal debug log messages */ | 157 | u32 debug; /* def: 0 = minimal debug log messages */ |
158 | int disable_hw_scan; /* def: 0 = use h/w scan */ | 158 | int disable_hw_scan; /* def: 0 = use h/w scan */ |
159 | int num_of_queues; /* def: HW dependent */ | 159 | int num_of_queues; /* def: HW dependent */ |
160 | int num_of_ampdu_queues;/* def: HW dependent */ | 160 | int num_of_ampdu_queues;/* def: HW dependent */ |
diff --git a/drivers/net/wireless/iwlwifi/iwl-debug.h b/drivers/net/wireless/iwlwifi/iwl-debug.h index e4c264b4f7b0..56c13b458de7 100644 --- a/drivers/net/wireless/iwlwifi/iwl-debug.h +++ b/drivers/net/wireless/iwlwifi/iwl-debug.h | |||
@@ -96,28 +96,25 @@ static inline void iwl_dbgfs_unregister(struct iwl_priv *priv) | |||
96 | #endif /* CONFIG_IWLWIFI_DEBUGFS */ | 96 | #endif /* CONFIG_IWLWIFI_DEBUGFS */ |
97 | 97 | ||
98 | /* | 98 | /* |
99 | * To use the debug system; | 99 | * To use the debug system: |
100 | * | 100 | * |
101 | * If you are defining a new debug classification, simply add it to the #define | 101 | * If you are defining a new debug classification, simply add it to the #define |
102 | * list here in the form of: | 102 | * list here in the form of |
103 | * | 103 | * |
104 | * #define IWL_DL_xxxx VALUE | 104 | * #define IWL_DL_xxxx VALUE |
105 | * | 105 | * |
106 | * shifting value to the left one bit from the previous entry. xxxx should be | 106 | * where xxxx should be the name of the classification (for example, WEP). |
107 | * the name of the classification (for example, WEP) | ||
108 | * | 107 | * |
109 | * You then need to either add a IWL_xxxx_DEBUG() macro definition for your | 108 | * You then need to either add a IWL_xxxx_DEBUG() macro definition for your |
110 | * classification, or use IWL_DEBUG(IWL_DL_xxxx, ...) whenever you want | 109 | * classification, or use IWL_DEBUG(IWL_DL_xxxx, ...) whenever you want |
111 | * to send output to that classification. | 110 | * to send output to that classification. |
112 | * | 111 | * |
113 | * To add your debug level to the list of levels seen when you perform | 112 | * The active debug levels can be accessed via files |
114 | * | 113 | * |
115 | * % cat /sys/class/net/wlanX/device/debug_level | 114 | * /sys/module/iwlagn/parameters/debug{50} |
115 | * /sys/class/net/wlan0/device/debug_level | ||
116 | * | 116 | * |
117 | * you simply need to add your entry to the iwl_debug_levels array. | 117 | * when CONFIG_IWLWIFI_DEBUG=y. |
118 | * | ||
119 | * If you do not see debug_level in /sys/class/net/wlanX/device/debug_level | ||
120 | * then you do not have CONFIG_IWLWIFI_DEBUG defined in your kernel config file | ||
121 | */ | 118 | */ |
122 | 119 | ||
123 | #define IWL_DL_INFO (1 << 0) | 120 | #define IWL_DL_INFO (1 << 0) |
diff --git a/drivers/net/wireless/iwlwifi/iwl-dev.h b/drivers/net/wireless/iwlwifi/iwl-dev.h index eaf0c9cc33a5..0468fcc1ea98 100644 --- a/drivers/net/wireless/iwlwifi/iwl-dev.h +++ b/drivers/net/wireless/iwlwifi/iwl-dev.h | |||
@@ -323,14 +323,6 @@ struct iwl_rx_queue { | |||
323 | 323 | ||
324 | #define IWL_SUPPORTED_RATES_IE_LEN 8 | 324 | #define IWL_SUPPORTED_RATES_IE_LEN 8 |
325 | 325 | ||
326 | #define SCAN_INTERVAL 100 | ||
327 | |||
328 | #define MAX_A_CHANNELS 252 | ||
329 | #define MIN_A_CHANNELS 7 | ||
330 | |||
331 | #define MAX_B_CHANNELS 14 | ||
332 | #define MIN_B_CHANNELS 1 | ||
333 | |||
334 | #define MAX_TID_COUNT 9 | 326 | #define MAX_TID_COUNT 9 |
335 | 327 | ||
336 | #define IWL_INVALID_RATE 0xFF | 328 | #define IWL_INVALID_RATE 0xFF |
@@ -496,8 +488,6 @@ struct iwl_sensitivity_ranges { | |||
496 | }; | 488 | }; |
497 | 489 | ||
498 | 490 | ||
499 | #define IWL_FAT_CHANNEL_52 BIT(IEEE80211_BAND_5GHZ) | ||
500 | |||
501 | #define KELVIN_TO_CELSIUS(x) ((x)-273) | 491 | #define KELVIN_TO_CELSIUS(x) ((x)-273) |
502 | #define CELSIUS_TO_KELVIN(x) ((x)+273) | 492 | #define CELSIUS_TO_KELVIN(x) ((x)+273) |
503 | 493 | ||
@@ -546,9 +536,6 @@ struct iwl_hw_params { | |||
546 | const struct iwl_sensitivity_ranges *sens; | 536 | const struct iwl_sensitivity_ranges *sens; |
547 | }; | 537 | }; |
548 | 538 | ||
549 | #define HT_SHORT_GI_20MHZ (1 << 0) | ||
550 | #define HT_SHORT_GI_40MHZ (1 << 1) | ||
551 | |||
552 | 539 | ||
553 | /****************************************************************************** | 540 | /****************************************************************************** |
554 | * | 541 | * |
@@ -590,15 +577,15 @@ static inline u8 get_cmd_index(struct iwl_queue *q, u32 index, int is_huge) | |||
590 | } | 577 | } |
591 | 578 | ||
592 | 579 | ||
593 | struct iwl_priv; | ||
594 | |||
595 | |||
596 | struct iwl_dma_ptr { | 580 | struct iwl_dma_ptr { |
597 | dma_addr_t dma; | 581 | dma_addr_t dma; |
598 | void *addr; | 582 | void *addr; |
599 | size_t size; | 583 | size_t size; |
600 | }; | 584 | }; |
601 | 585 | ||
586 | #define HT_SHORT_GI_20MHZ (1 << 0) | ||
587 | #define HT_SHORT_GI_40MHZ (1 << 1) | ||
588 | |||
602 | #define IWL_CHANNEL_WIDTH_20MHZ 0 | 589 | #define IWL_CHANNEL_WIDTH_20MHZ 0 |
603 | #define IWL_CHANNEL_WIDTH_40MHZ 1 | 590 | #define IWL_CHANNEL_WIDTH_40MHZ 1 |
604 | 591 | ||
@@ -613,7 +600,6 @@ struct iwl_dma_ptr { | |||
613 | #define TX_POWER_IWL_ILLEGAL_VOLTAGE -10000 | 600 | #define TX_POWER_IWL_ILLEGAL_VOLTAGE -10000 |
614 | 601 | ||
615 | /* Sensitivity and chain noise calibration */ | 602 | /* Sensitivity and chain noise calibration */ |
616 | #define INTERFERENCE_DATA_AVAILABLE __constant_cpu_to_le32(1) | ||
617 | #define INITIALIZATION_VALUE 0xFFFF | 603 | #define INITIALIZATION_VALUE 0xFFFF |
618 | #define CAL_NUM_OF_BEACONS 20 | 604 | #define CAL_NUM_OF_BEACONS 20 |
619 | #define MAXIMUM_ALLOWED_PATHLOSS 15 | 605 | #define MAXIMUM_ALLOWED_PATHLOSS 15 |
@@ -666,15 +652,6 @@ enum iwl4965_calib_enabled_state { | |||
666 | IWL_CALIB_ENABLED = 1, | 652 | IWL_CALIB_ENABLED = 1, |
667 | }; | 653 | }; |
668 | 654 | ||
669 | struct statistics_general_data { | ||
670 | u32 beacon_silence_rssi_a; | ||
671 | u32 beacon_silence_rssi_b; | ||
672 | u32 beacon_silence_rssi_c; | ||
673 | u32 beacon_energy_a; | ||
674 | u32 beacon_energy_b; | ||
675 | u32 beacon_energy_c; | ||
676 | }; | ||
677 | |||
678 | 655 | ||
679 | /* | 656 | /* |
680 | * enum iwl_calib | 657 | * enum iwl_calib |
diff --git a/drivers/net/wireless/iwlwifi/iwl-io.h b/drivers/net/wireless/iwlwifi/iwl-io.h index 998ac1971696..0a92e7431ada 100644 --- a/drivers/net/wireless/iwlwifi/iwl-io.h +++ b/drivers/net/wireless/iwlwifi/iwl-io.h | |||
@@ -87,17 +87,18 @@ static inline u32 __iwl_read32(char *f, u32 l, struct iwl_priv *priv, u32 ofs) | |||
87 | #define iwl_read32(p, o) _iwl_read32(p, o) | 87 | #define iwl_read32(p, o) _iwl_read32(p, o) |
88 | #endif | 88 | #endif |
89 | 89 | ||
90 | #define IWL_POLL_INTERVAL 10 /* microseconds */ | ||
90 | static inline int _iwl_poll_bit(struct iwl_priv *priv, u32 addr, | 91 | static inline int _iwl_poll_bit(struct iwl_priv *priv, u32 addr, |
91 | u32 bits, u32 mask, int timeout) | 92 | u32 bits, u32 mask, int timeout) |
92 | { | 93 | { |
93 | int i = 0; | 94 | int t = 0; |
94 | 95 | ||
95 | do { | 96 | do { |
96 | if ((_iwl_read32(priv, addr) & mask) == (bits & mask)) | 97 | if ((_iwl_read32(priv, addr) & mask) == (bits & mask)) |
97 | return i; | 98 | return t; |
98 | udelay(10); | 99 | udelay(IWL_POLL_INTERVAL); |
99 | i += 10; | 100 | t += IWL_POLL_INTERVAL; |
100 | } while (i < timeout); | 101 | } while (t < timeout); |
101 | 102 | ||
102 | return -ETIMEDOUT; | 103 | return -ETIMEDOUT; |
103 | } | 104 | } |
diff --git a/drivers/net/wireless/iwlwifi/iwl-led.c b/drivers/net/wireless/iwlwifi/iwl-led.c index dce32ff8dec1..11eccd7d268c 100644 --- a/drivers/net/wireless/iwlwifi/iwl-led.c +++ b/drivers/net/wireless/iwlwifi/iwl-led.c | |||
@@ -292,7 +292,7 @@ static int iwl_get_blink_rate(struct iwl_priv *priv) | |||
292 | if (tpt > (blink_tbl[i].tpt * IWL_1MB_RATE)) | 292 | if (tpt > (blink_tbl[i].tpt * IWL_1MB_RATE)) |
293 | break; | 293 | break; |
294 | 294 | ||
295 | IWL_DEBUG_LED("LED BLINK IDX=%d", i); | 295 | IWL_DEBUG_LED("LED BLINK IDX=%d\n", i); |
296 | return i; | 296 | return i; |
297 | } | 297 | } |
298 | 298 | ||
diff --git a/drivers/net/wireless/iwlwifi/iwl-rx.c b/drivers/net/wireless/iwlwifi/iwl-rx.c index 919a775121e4..c5f1aa0feac8 100644 --- a/drivers/net/wireless/iwlwifi/iwl-rx.c +++ b/drivers/net/wireless/iwlwifi/iwl-rx.c | |||
@@ -244,25 +244,31 @@ void iwl_rx_allocate(struct iwl_priv *priv) | |||
244 | struct list_head *element; | 244 | struct list_head *element; |
245 | struct iwl_rx_mem_buffer *rxb; | 245 | struct iwl_rx_mem_buffer *rxb; |
246 | unsigned long flags; | 246 | unsigned long flags; |
247 | spin_lock_irqsave(&rxq->lock, flags); | 247 | |
248 | while (!list_empty(&rxq->rx_used)) { | 248 | while (1) { |
249 | spin_lock_irqsave(&rxq->lock, flags); | ||
250 | |||
251 | if (list_empty(&rxq->rx_used)) { | ||
252 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
253 | return; | ||
254 | } | ||
249 | element = rxq->rx_used.next; | 255 | element = rxq->rx_used.next; |
250 | rxb = list_entry(element, struct iwl_rx_mem_buffer, list); | 256 | rxb = list_entry(element, struct iwl_rx_mem_buffer, list); |
257 | list_del(element); | ||
258 | |||
259 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
251 | 260 | ||
252 | /* Alloc a new receive buffer */ | 261 | /* Alloc a new receive buffer */ |
253 | rxb->skb = alloc_skb(priv->hw_params.rx_buf_size + 256, | 262 | rxb->skb = alloc_skb(priv->hw_params.rx_buf_size + 256, |
254 | __GFP_NOWARN | GFP_ATOMIC); | 263 | GFP_KERNEL); |
255 | if (!rxb->skb) { | 264 | if (!rxb->skb) { |
256 | if (net_ratelimit()) | 265 | printk(KERN_CRIT DRV_NAME |
257 | printk(KERN_CRIT DRV_NAME | 266 | "Can not allocate SKB buffers\n"); |
258 | ": Can not allocate SKB buffers\n"); | ||
259 | /* We don't reschedule replenish work here -- we will | 267 | /* We don't reschedule replenish work here -- we will |
260 | * call the restock method and if it still needs | 268 | * call the restock method and if it still needs |
261 | * more buffers it will schedule replenish */ | 269 | * more buffers it will schedule replenish */ |
262 | break; | 270 | break; |
263 | } | 271 | } |
264 | priv->alloc_rxb_skb++; | ||
265 | list_del(element); | ||
266 | 272 | ||
267 | /* Get physical address of RB/SKB */ | 273 | /* Get physical address of RB/SKB */ |
268 | rxb->real_dma_addr = pci_map_single( | 274 | rxb->real_dma_addr = pci_map_single( |
@@ -276,12 +282,15 @@ void iwl_rx_allocate(struct iwl_priv *priv) | |||
276 | rxb->aligned_dma_addr = ALIGN(rxb->real_dma_addr, 256); | 282 | rxb->aligned_dma_addr = ALIGN(rxb->real_dma_addr, 256); |
277 | skb_reserve(rxb->skb, rxb->aligned_dma_addr - rxb->real_dma_addr); | 283 | skb_reserve(rxb->skb, rxb->aligned_dma_addr - rxb->real_dma_addr); |
278 | 284 | ||
285 | spin_lock_irqsave(&rxq->lock, flags); | ||
286 | |||
279 | list_add_tail(&rxb->list, &rxq->rx_free); | 287 | list_add_tail(&rxb->list, &rxq->rx_free); |
280 | rxq->free_count++; | 288 | rxq->free_count++; |
289 | priv->alloc_rxb_skb++; | ||
290 | |||
291 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
281 | } | 292 | } |
282 | spin_unlock_irqrestore(&rxq->lock, flags); | ||
283 | } | 293 | } |
284 | EXPORT_SYMBOL(iwl_rx_allocate); | ||
285 | 294 | ||
286 | void iwl_rx_replenish(struct iwl_priv *priv) | 295 | void iwl_rx_replenish(struct iwl_priv *priv) |
287 | { | 296 | { |
diff --git a/drivers/net/wireless/iwlwifi/iwl-tx.c b/drivers/net/wireless/iwlwifi/iwl-tx.c index 1e7cd8d9039e..b0ee86c62685 100644 --- a/drivers/net/wireless/iwlwifi/iwl-tx.c +++ b/drivers/net/wireless/iwlwifi/iwl-tx.c | |||
@@ -645,7 +645,7 @@ static void iwl_tx_cmd_build_basic(struct iwl_priv *priv, | |||
645 | struct iwl_tx_cmd *tx_cmd, | 645 | struct iwl_tx_cmd *tx_cmd, |
646 | struct ieee80211_tx_info *info, | 646 | struct ieee80211_tx_info *info, |
647 | struct ieee80211_hdr *hdr, | 647 | struct ieee80211_hdr *hdr, |
648 | int is_unicast, u8 std_id) | 648 | u8 std_id) |
649 | { | 649 | { |
650 | __le16 fc = hdr->frame_control; | 650 | __le16 fc = hdr->frame_control; |
651 | __le32 tx_flags = tx_cmd->tx_flags; | 651 | __le32 tx_flags = tx_cmd->tx_flags; |
@@ -834,7 +834,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
834 | u16 len, len_org; | 834 | u16 len, len_org; |
835 | u16 seq_number = 0; | 835 | u16 seq_number = 0; |
836 | __le16 fc; | 836 | __le16 fc; |
837 | u8 hdr_len, unicast; | 837 | u8 hdr_len; |
838 | u8 sta_id; | 838 | u8 sta_id; |
839 | u8 wait_write_ptr = 0; | 839 | u8 wait_write_ptr = 0; |
840 | u8 tid = 0; | 840 | u8 tid = 0; |
@@ -854,8 +854,6 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
854 | goto drop_unlock; | 854 | goto drop_unlock; |
855 | } | 855 | } |
856 | 856 | ||
857 | unicast = !is_multicast_ether_addr(hdr->addr1); | ||
858 | |||
859 | fc = hdr->frame_control; | 857 | fc = hdr->frame_control; |
860 | 858 | ||
861 | #ifdef CONFIG_IWLWIFI_DEBUG | 859 | #ifdef CONFIG_IWLWIFI_DEBUG |
@@ -994,7 +992,7 @@ int iwl_tx_skb(struct iwl_priv *priv, struct sk_buff *skb) | |||
994 | len = (u16)skb->len; | 992 | len = (u16)skb->len; |
995 | tx_cmd->len = cpu_to_le16(len); | 993 | tx_cmd->len = cpu_to_le16(len); |
996 | /* TODO need this for burst mode later on */ | 994 | /* TODO need this for burst mode later on */ |
997 | iwl_tx_cmd_build_basic(priv, tx_cmd, info, hdr, unicast, sta_id); | 995 | iwl_tx_cmd_build_basic(priv, tx_cmd, info, hdr, sta_id); |
998 | 996 | ||
999 | /* set is_hcca to 0; it probably will never be implemented */ | 997 | /* set is_hcca to 0; it probably will never be implemented */ |
1000 | iwl_tx_cmd_build_rate(priv, tx_cmd, info, fc, sta_id, 0); | 998 | iwl_tx_cmd_build_rate(priv, tx_cmd, info, fc, sta_id, 0); |
diff --git a/drivers/net/wireless/iwlwifi/iwl3945-base.c b/drivers/net/wireless/iwlwifi/iwl3945-base.c index 352ccac7187b..d64580805d6e 100644 --- a/drivers/net/wireless/iwlwifi/iwl3945-base.c +++ b/drivers/net/wireless/iwlwifi/iwl3945-base.c | |||
@@ -65,7 +65,7 @@ static int iwl3945_tx_queue_update_write_ptr(struct iwl3945_priv *priv, | |||
65 | 65 | ||
66 | /* module parameters */ | 66 | /* module parameters */ |
67 | static int iwl3945_param_disable_hw_scan; /* def: 0 = use 3945's h/w scan */ | 67 | static int iwl3945_param_disable_hw_scan; /* def: 0 = use 3945's h/w scan */ |
68 | static int iwl3945_param_debug; /* def: 0 = minimal debug log messages */ | 68 | static u32 iwl3945_param_debug; /* def: 0 = minimal debug log messages */ |
69 | static int iwl3945_param_disable; /* def: 0 = enable radio */ | 69 | static int iwl3945_param_disable; /* def: 0 = enable radio */ |
70 | static int iwl3945_param_antenna; /* def: 0 = both antennas (use diversity) */ | 70 | static int iwl3945_param_antenna; /* def: 0 = both antennas (use diversity) */ |
71 | int iwl3945_param_hwcrypto; /* def: 0 = use software encryption */ | 71 | int iwl3945_param_hwcrypto; /* def: 0 = use software encryption */ |
@@ -1402,7 +1402,7 @@ static void iwl3945_free_frame(struct iwl3945_priv *priv, struct iwl3945_frame * | |||
1402 | 1402 | ||
1403 | unsigned int iwl3945_fill_beacon_frame(struct iwl3945_priv *priv, | 1403 | unsigned int iwl3945_fill_beacon_frame(struct iwl3945_priv *priv, |
1404 | struct ieee80211_hdr *hdr, | 1404 | struct ieee80211_hdr *hdr, |
1405 | const u8 *dest, int left) | 1405 | int left) |
1406 | { | 1406 | { |
1407 | 1407 | ||
1408 | if (!iwl3945_is_associated(priv) || !priv->ibss_beacon || | 1408 | if (!iwl3945_is_associated(priv) || !priv->ibss_beacon || |
@@ -8343,7 +8343,7 @@ MODULE_PARM_DESC(disable, "manually disable the radio (default 0 [radio on])"); | |||
8343 | module_param_named(hwcrypto, iwl3945_param_hwcrypto, int, 0444); | 8343 | module_param_named(hwcrypto, iwl3945_param_hwcrypto, int, 0444); |
8344 | MODULE_PARM_DESC(hwcrypto, | 8344 | MODULE_PARM_DESC(hwcrypto, |
8345 | "using hardware crypto engine (default 0 [software])\n"); | 8345 | "using hardware crypto engine (default 0 [software])\n"); |
8346 | module_param_named(debug, iwl3945_param_debug, int, 0444); | 8346 | module_param_named(debug, iwl3945_param_debug, uint, 0444); |
8347 | MODULE_PARM_DESC(debug, "debug output mask"); | 8347 | MODULE_PARM_DESC(debug, "debug output mask"); |
8348 | module_param_named(disable_hw_scan, iwl3945_param_disable_hw_scan, int, 0444); | 8348 | module_param_named(disable_hw_scan, iwl3945_param_disable_hw_scan, int, 0444); |
8349 | MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)"); | 8349 | MODULE_PARM_DESC(disable_hw_scan, "disable hardware scanning (default 0)"); |
diff --git a/drivers/net/wireless/libertas/if_sdio.c b/drivers/net/wireless/libertas/if_sdio.c index b54e2ea8346b..4519d7314f47 100644 --- a/drivers/net/wireless/libertas/if_sdio.c +++ b/drivers/net/wireless/libertas/if_sdio.c | |||
@@ -26,6 +26,7 @@ | |||
26 | * if_sdio_card_to_host() to pad the data. | 26 | * if_sdio_card_to_host() to pad the data. |
27 | */ | 27 | */ |
28 | 28 | ||
29 | #include <linux/kernel.h> | ||
29 | #include <linux/moduleparam.h> | 30 | #include <linux/moduleparam.h> |
30 | #include <linux/firmware.h> | 31 | #include <linux/firmware.h> |
31 | #include <linux/netdevice.h> | 32 | #include <linux/netdevice.h> |
@@ -581,7 +582,7 @@ static int if_sdio_prog_real(struct if_sdio_card *card) | |||
581 | chunk_size, (chunk_size + 31) / 32 * 32); | 582 | chunk_size, (chunk_size + 31) / 32 * 32); |
582 | */ | 583 | */ |
583 | ret = sdio_writesb(card->func, card->ioport, | 584 | ret = sdio_writesb(card->func, card->ioport, |
584 | chunk_buffer, (chunk_size + 31) / 32 * 32); | 585 | chunk_buffer, roundup(chunk_size, 32)); |
585 | if (ret) | 586 | if (ret) |
586 | goto release; | 587 | goto release; |
587 | 588 | ||
diff --git a/drivers/net/wireless/mac80211_hwsim.c b/drivers/net/wireless/mac80211_hwsim.c index fd5a537ac51d..f83d69e813d3 100644 --- a/drivers/net/wireless/mac80211_hwsim.c +++ b/drivers/net/wireless/mac80211_hwsim.c | |||
@@ -495,11 +495,9 @@ static void mac80211_hwsim_bss_info_changed(struct ieee80211_hw *hw, | |||
495 | } | 495 | } |
496 | 496 | ||
497 | if (changed & BSS_CHANGED_HT) { | 497 | if (changed & BSS_CHANGED_HT) { |
498 | printk(KERN_DEBUG " %s: HT: sec_ch_offs=%d width_40_ok=%d " | 498 | printk(KERN_DEBUG " %s: HT: op_mode=0x%x\n", |
499 | "op_mode=%d\n", | ||
500 | wiphy_name(hw->wiphy), | 499 | wiphy_name(hw->wiphy), |
501 | info->ht.secondary_channel_offset, | 500 | info->ht.operation_mode); |
502 | info->ht.width_40_ok, info->ht.operation_mode); | ||
503 | } | 501 | } |
504 | 502 | ||
505 | if (changed & BSS_CHANGED_BASIC_RATES) { | 503 | if (changed & BSS_CHANGED_BASIC_RATES) { |
diff --git a/drivers/net/wireless/p54/p54.h b/drivers/net/wireless/p54/p54.h index d2dbb9e15d97..ab79e32f0b27 100644 --- a/drivers/net/wireless/p54/p54.h +++ b/drivers/net/wireless/p54/p54.h | |||
@@ -44,6 +44,9 @@ enum p54_control_frame_types { | |||
44 | P54_CONTROL_TYPE_BT_OPTIONS = 35 | 44 | P54_CONTROL_TYPE_BT_OPTIONS = 35 |
45 | }; | 45 | }; |
46 | 46 | ||
47 | #define P54_HDR_FLAG_CONTROL BIT(15) | ||
48 | #define P54_HDR_FLAG_CONTROL_OPSET (BIT(15) + BIT(0)) | ||
49 | |||
47 | struct p54_hdr { | 50 | struct p54_hdr { |
48 | __le16 flags; | 51 | __le16 flags; |
49 | __le16 len; | 52 | __le16 len; |
@@ -54,6 +57,10 @@ struct p54_hdr { | |||
54 | u8 data[0]; | 57 | u8 data[0]; |
55 | } __attribute__ ((packed)); | 58 | } __attribute__ ((packed)); |
56 | 59 | ||
60 | #define FREE_AFTER_TX(skb) \ | ||
61 | ((((struct p54_hdr *) ((struct sk_buff *) skb)->data)-> \ | ||
62 | flags) == cpu_to_le16(P54_HDR_FLAG_CONTROL_OPSET)) | ||
63 | |||
57 | struct p54_edcf_queue_param { | 64 | struct p54_edcf_queue_param { |
58 | __le16 aifs; | 65 | __le16 aifs; |
59 | __le16 cwmin; | 66 | __le16 cwmin; |
@@ -61,6 +68,13 @@ struct p54_edcf_queue_param { | |||
61 | __le16 txop; | 68 | __le16 txop; |
62 | } __attribute__ ((packed)); | 69 | } __attribute__ ((packed)); |
63 | 70 | ||
71 | struct p54_rssi_linear_approximation { | ||
72 | s16 mul; | ||
73 | s16 add; | ||
74 | s16 longbow_unkn; | ||
75 | s16 longbow_unk2; | ||
76 | }; | ||
77 | |||
64 | #define EEPROM_READBACK_LEN 0x3fc | 78 | #define EEPROM_READBACK_LEN 0x3fc |
65 | 79 | ||
66 | #define ISL38XX_DEV_FIRMWARE_ADDR 0x20000 | 80 | #define ISL38XX_DEV_FIRMWARE_ADDR 0x20000 |
@@ -71,11 +85,11 @@ struct p54_edcf_queue_param { | |||
71 | #define FW_LM20 0x4c4d3230 | 85 | #define FW_LM20 0x4c4d3230 |
72 | 86 | ||
73 | struct p54_common { | 87 | struct p54_common { |
88 | struct ieee80211_hw *hw; | ||
74 | u32 rx_start; | 89 | u32 rx_start; |
75 | u32 rx_end; | 90 | u32 rx_end; |
76 | struct sk_buff_head tx_queue; | 91 | struct sk_buff_head tx_queue; |
77 | void (*tx)(struct ieee80211_hw *dev, struct sk_buff *skb, | 92 | void (*tx)(struct ieee80211_hw *dev, struct sk_buff *skb); |
78 | int free_on_tx); | ||
79 | int (*open)(struct ieee80211_hw *dev); | 93 | int (*open)(struct ieee80211_hw *dev); |
80 | void (*stop)(struct ieee80211_hw *dev); | 94 | void (*stop)(struct ieee80211_hw *dev); |
81 | int mode; | 95 | int mode; |
@@ -90,6 +104,7 @@ struct p54_common { | |||
90 | struct pda_channel_output_limit *output_limit; | 104 | struct pda_channel_output_limit *output_limit; |
91 | unsigned int output_limit_len; | 105 | unsigned int output_limit_len; |
92 | struct pda_pa_curve_data *curve_data; | 106 | struct pda_pa_curve_data *curve_data; |
107 | struct p54_rssi_linear_approximation rssical_db[IEEE80211_NUM_BANDS]; | ||
93 | unsigned int filter_flags; | 108 | unsigned int filter_flags; |
94 | bool use_short_slot; | 109 | bool use_short_slot; |
95 | u16 rxhw; | 110 | u16 rxhw; |
@@ -106,9 +121,7 @@ struct p54_common { | |||
106 | struct ieee80211_tx_queue_stats tx_stats[8]; | 121 | struct ieee80211_tx_queue_stats tx_stats[8]; |
107 | struct p54_edcf_queue_param qos_params[8]; | 122 | struct p54_edcf_queue_param qos_params[8]; |
108 | struct ieee80211_low_level_stats stats; | 123 | struct ieee80211_low_level_stats stats; |
109 | struct timer_list stats_timer; | 124 | struct delayed_work work; |
110 | struct completion stats_comp; | ||
111 | struct sk_buff *cached_stats; | ||
112 | struct sk_buff *cached_beacon; | 125 | struct sk_buff *cached_beacon; |
113 | int noise; | 126 | int noise; |
114 | void *eeprom; | 127 | void *eeprom; |
diff --git a/drivers/net/wireless/p54/p54common.c b/drivers/net/wireless/p54/p54common.c index a4e99b02af02..82354b974a04 100644 --- a/drivers/net/wireless/p54/p54common.c +++ b/drivers/net/wireless/p54/p54common.c | |||
@@ -335,6 +335,36 @@ static const char *p54_rf_chips[] = { "NULL", "Duette3", "Duette2", | |||
335 | "Frisbee", "Xbow", "Longbow", "NULL", "NULL" }; | 335 | "Frisbee", "Xbow", "Longbow", "NULL", "NULL" }; |
336 | static int p54_init_xbow_synth(struct ieee80211_hw *dev); | 336 | static int p54_init_xbow_synth(struct ieee80211_hw *dev); |
337 | 337 | ||
338 | static void p54_parse_rssical(struct ieee80211_hw *dev, void *data, int len, | ||
339 | u16 type) | ||
340 | { | ||
341 | struct p54_common *priv = dev->priv; | ||
342 | int offset = (type == PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED) ? 2 : 0; | ||
343 | int entry_size = sizeof(struct pda_rssi_cal_entry) + offset; | ||
344 | int num_entries = (type == PDR_RSSI_LINEAR_APPROXIMATION) ? 1 : 2; | ||
345 | int i; | ||
346 | |||
347 | if (len != (entry_size * num_entries)) { | ||
348 | printk(KERN_ERR "%s: unknown rssi calibration data packing " | ||
349 | " type:(%x) len:%d.\n", | ||
350 | wiphy_name(dev->wiphy), type, len); | ||
351 | |||
352 | print_hex_dump_bytes("rssical:", DUMP_PREFIX_NONE, | ||
353 | data, len); | ||
354 | |||
355 | printk(KERN_ERR "%s: please report this issue.\n", | ||
356 | wiphy_name(dev->wiphy)); | ||
357 | return; | ||
358 | } | ||
359 | |||
360 | for (i = 0; i < num_entries; i++) { | ||
361 | struct pda_rssi_cal_entry *cal = data + | ||
362 | (offset + i * entry_size); | ||
363 | priv->rssical_db[i].mul = (s16) le16_to_cpu(cal->mul); | ||
364 | priv->rssical_db[i].add = (s16) le16_to_cpu(cal->add); | ||
365 | } | ||
366 | } | ||
367 | |||
338 | static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) | 368 | static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) |
339 | { | 369 | { |
340 | struct p54_common *priv = dev->priv; | 370 | struct p54_common *priv = dev->priv; |
@@ -434,6 +464,12 @@ static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) | |||
434 | case PDR_HARDWARE_PLATFORM_COMPONENT_ID: | 464 | case PDR_HARDWARE_PLATFORM_COMPONENT_ID: |
435 | priv->version = *(u8 *)(entry->data + 1); | 465 | priv->version = *(u8 *)(entry->data + 1); |
436 | break; | 466 | break; |
467 | case PDR_RSSI_LINEAR_APPROXIMATION: | ||
468 | case PDR_RSSI_LINEAR_APPROXIMATION_DUAL_BAND: | ||
469 | case PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED: | ||
470 | p54_parse_rssical(dev, entry->data, data_len, | ||
471 | le16_to_cpu(entry->code)); | ||
472 | break; | ||
437 | case PDR_END: | 473 | case PDR_END: |
438 | /* make it overrun */ | 474 | /* make it overrun */ |
439 | entry_len = len; | 475 | entry_len = len; |
@@ -453,10 +489,7 @@ static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) | |||
453 | case PDR_DEFAULT_COUNTRY: | 489 | case PDR_DEFAULT_COUNTRY: |
454 | case PDR_ANTENNA_GAIN: | 490 | case PDR_ANTENNA_GAIN: |
455 | case PDR_PRISM_INDIGO_PA_CALIBRATION_DATA: | 491 | case PDR_PRISM_INDIGO_PA_CALIBRATION_DATA: |
456 | case PDR_RSSI_LINEAR_APPROXIMATION: | ||
457 | case PDR_RSSI_LINEAR_APPROXIMATION_DUAL_BAND: | ||
458 | case PDR_REGULATORY_POWER_LIMITS: | 492 | case PDR_REGULATORY_POWER_LIMITS: |
459 | case PDR_RSSI_LINEAR_APPROXIMATION_EXTENDED: | ||
460 | case PDR_RADIATED_TRANSMISSION_CORRECTION: | 493 | case PDR_RADIATED_TRANSMISSION_CORRECTION: |
461 | case PDR_PRISM_TX_IQ_CALIBRATION: | 494 | case PDR_PRISM_TX_IQ_CALIBRATION: |
462 | case PDR_BASEBAND_REGISTERS: | 495 | case PDR_BASEBAND_REGISTERS: |
@@ -527,8 +560,11 @@ static int p54_parse_eeprom(struct ieee80211_hw *dev, void *eeprom, int len) | |||
527 | 560 | ||
528 | static int p54_rssi_to_dbm(struct ieee80211_hw *dev, int rssi) | 561 | static int p54_rssi_to_dbm(struct ieee80211_hw *dev, int rssi) |
529 | { | 562 | { |
530 | /* TODO: get the rssi_add & rssi_mul data from the eeprom */ | 563 | struct p54_common *priv = dev->priv; |
531 | return ((rssi * 0x83) / 64 - 400) / 4; | 564 | int band = dev->conf.channel->band; |
565 | |||
566 | return ((rssi * priv->rssical_db[band].mul) / 64 + | ||
567 | priv->rssical_db[band].add) / 4; | ||
532 | } | 568 | } |
533 | 569 | ||
534 | static int p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb) | 570 | static int p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb) |
@@ -589,6 +625,9 @@ static int p54_rx_data(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
589 | 625 | ||
590 | ieee80211_rx_irqsafe(dev, skb, &rx_status); | 626 | ieee80211_rx_irqsafe(dev, skb, &rx_status); |
591 | 627 | ||
628 | queue_delayed_work(dev->workqueue, &priv->work, | ||
629 | msecs_to_jiffies(P54_STATISTICS_UPDATE)); | ||
630 | |||
592 | return -1; | 631 | return -1; |
593 | } | 632 | } |
594 | 633 | ||
@@ -644,7 +683,7 @@ void p54_free_skb(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
644 | freed = priv->rx_end - last_addr; | 683 | freed = priv->rx_end - last_addr; |
645 | __skb_unlink(skb, &priv->tx_queue); | 684 | __skb_unlink(skb, &priv->tx_queue); |
646 | spin_unlock_irqrestore(&priv->tx_queue.lock, flags); | 685 | spin_unlock_irqrestore(&priv->tx_queue.lock, flags); |
647 | kfree_skb(skb); | 686 | dev_kfree_skb_any(skb); |
648 | 687 | ||
649 | if (freed >= priv->headroom + sizeof(struct p54_hdr) + 48 + | 688 | if (freed >= priv->headroom + sizeof(struct p54_hdr) + 48 + |
650 | IEEE80211_MAX_RTS_THRESHOLD + priv->tailroom) | 689 | IEEE80211_MAX_RTS_THRESHOLD + priv->tailroom) |
@@ -652,6 +691,27 @@ void p54_free_skb(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
652 | } | 691 | } |
653 | EXPORT_SYMBOL_GPL(p54_free_skb); | 692 | EXPORT_SYMBOL_GPL(p54_free_skb); |
654 | 693 | ||
694 | static struct sk_buff *p54_find_tx_entry(struct ieee80211_hw *dev, | ||
695 | __le32 req_id) | ||
696 | { | ||
697 | struct p54_common *priv = dev->priv; | ||
698 | struct sk_buff *entry = priv->tx_queue.next; | ||
699 | unsigned long flags; | ||
700 | |||
701 | spin_lock_irqsave(&priv->tx_queue.lock, flags); | ||
702 | while (entry != (struct sk_buff *)&priv->tx_queue) { | ||
703 | struct p54_hdr *hdr = (struct p54_hdr *) entry->data; | ||
704 | |||
705 | if (hdr->req_id == req_id) { | ||
706 | spin_unlock_irqrestore(&priv->tx_queue.lock, flags); | ||
707 | return entry; | ||
708 | } | ||
709 | entry = entry->next; | ||
710 | } | ||
711 | spin_unlock_irqrestore(&priv->tx_queue.lock, flags); | ||
712 | return NULL; | ||
713 | } | ||
714 | |||
655 | static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) | 715 | static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) |
656 | { | 716 | { |
657 | struct p54_common *priv = dev->priv; | 717 | struct p54_common *priv = dev->priv; |
@@ -696,6 +756,7 @@ static void p54_rx_frame_sent(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
696 | entry_hdr = (struct p54_hdr *) entry->data; | 756 | entry_hdr = (struct p54_hdr *) entry->data; |
697 | entry_data = (struct p54_tx_data *) entry_hdr->data; | 757 | entry_data = (struct p54_tx_data *) entry_hdr->data; |
698 | priv->tx_stats[entry_data->hw_queue].len--; | 758 | priv->tx_stats[entry_data->hw_queue].len--; |
759 | priv->stats.dot11ACKFailureCount += payload->tries - 1; | ||
699 | 760 | ||
700 | if (unlikely(entry == priv->cached_beacon)) { | 761 | if (unlikely(entry == priv->cached_beacon)) { |
701 | kfree_skb(entry); | 762 | kfree_skb(entry); |
@@ -775,8 +836,12 @@ static void p54_rx_stats(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
775 | struct p54_common *priv = dev->priv; | 836 | struct p54_common *priv = dev->priv; |
776 | struct p54_hdr *hdr = (struct p54_hdr *) skb->data; | 837 | struct p54_hdr *hdr = (struct p54_hdr *) skb->data; |
777 | struct p54_statistics *stats = (struct p54_statistics *) hdr->data; | 838 | struct p54_statistics *stats = (struct p54_statistics *) hdr->data; |
778 | u32 tsf32 = le32_to_cpu(stats->tsf32); | 839 | u32 tsf32; |
779 | 840 | ||
841 | if (unlikely(priv->mode == NL80211_IFTYPE_UNSPECIFIED)) | ||
842 | return ; | ||
843 | |||
844 | tsf32 = le32_to_cpu(stats->tsf32); | ||
780 | if (tsf32 < priv->tsf_low32) | 845 | if (tsf32 < priv->tsf_low32) |
781 | priv->tsf_high32++; | 846 | priv->tsf_high32++; |
782 | priv->tsf_low32 = tsf32; | 847 | priv->tsf_low32 = tsf32; |
@@ -786,9 +851,8 @@ static void p54_rx_stats(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
786 | priv->stats.dot11FCSErrorCount = le32_to_cpu(stats->rx_bad_fcs); | 851 | priv->stats.dot11FCSErrorCount = le32_to_cpu(stats->rx_bad_fcs); |
787 | 852 | ||
788 | priv->noise = p54_rssi_to_dbm(dev, le32_to_cpu(stats->noise)); | 853 | priv->noise = p54_rssi_to_dbm(dev, le32_to_cpu(stats->noise)); |
789 | complete(&priv->stats_comp); | ||
790 | 854 | ||
791 | mod_timer(&priv->stats_timer, jiffies + 5 * HZ); | 855 | p54_free_skb(dev, p54_find_tx_entry(dev, hdr->req_id)); |
792 | } | 856 | } |
793 | 857 | ||
794 | static void p54_rx_trap(struct ieee80211_hw *dev, struct sk_buff *skb) | 858 | static void p54_rx_trap(struct ieee80211_hw *dev, struct sk_buff *skb) |
@@ -897,6 +961,8 @@ static int p54_assign_address(struct ieee80211_hw *dev, struct sk_buff *skb, | |||
897 | * have a few spare slots for control frames left. | 961 | * have a few spare slots for control frames left. |
898 | */ | 962 | */ |
899 | ieee80211_stop_queues(dev); | 963 | ieee80211_stop_queues(dev); |
964 | queue_delayed_work(dev->workqueue, &priv->work, | ||
965 | msecs_to_jiffies(P54_TX_TIMEOUT)); | ||
900 | 966 | ||
901 | if (unlikely(left == 32)) { | 967 | if (unlikely(left == 32)) { |
902 | /* | 968 | /* |
@@ -1022,7 +1088,7 @@ int p54_read_eeprom(struct ieee80211_hw *dev) | |||
1022 | eeprom_hdr->v2.magic2 = 0xf; | 1088 | eeprom_hdr->v2.magic2 = 0xf; |
1023 | memcpy(eeprom_hdr->v2.magic, (const char *)"LOCK", 4); | 1089 | memcpy(eeprom_hdr->v2.magic, (const char *)"LOCK", 4); |
1024 | } | 1090 | } |
1025 | priv->tx(dev, skb, 0); | 1091 | priv->tx(dev, skb); |
1026 | 1092 | ||
1027 | if (!wait_for_completion_interruptible_timeout(&priv->eeprom_comp, HZ)) { | 1093 | if (!wait_for_completion_interruptible_timeout(&priv->eeprom_comp, HZ)) { |
1028 | printk(KERN_ERR "%s: device does not respond!\n", | 1094 | printk(KERN_ERR "%s: device does not respond!\n", |
@@ -1063,7 +1129,7 @@ static int p54_set_tim(struct ieee80211_hw *dev, struct ieee80211_sta *sta, | |||
1063 | tim = (struct p54_tim *) skb_put(skb, sizeof(*tim)); | 1129 | tim = (struct p54_tim *) skb_put(skb, sizeof(*tim)); |
1064 | tim->count = 1; | 1130 | tim->count = 1; |
1065 | tim->entry[0] = cpu_to_le16(set ? (sta->aid | 0x8000) : sta->aid); | 1131 | tim->entry[0] = cpu_to_le16(set ? (sta->aid | 0x8000) : sta->aid); |
1066 | priv->tx(dev, skb, 1); | 1132 | priv->tx(dev, skb); |
1067 | return 0; | 1133 | return 0; |
1068 | } | 1134 | } |
1069 | 1135 | ||
@@ -1081,7 +1147,7 @@ static int p54_sta_unlock(struct ieee80211_hw *dev, u8 *addr) | |||
1081 | 1147 | ||
1082 | sta = (struct p54_sta_unlock *)skb_put(skb, sizeof(*sta)); | 1148 | sta = (struct p54_sta_unlock *)skb_put(skb, sizeof(*sta)); |
1083 | memcpy(sta->addr, addr, ETH_ALEN); | 1149 | memcpy(sta->addr, addr, ETH_ALEN); |
1084 | priv->tx(dev, skb, 1); | 1150 | priv->tx(dev, skb); |
1085 | return 0; | 1151 | return 0; |
1086 | } | 1152 | } |
1087 | 1153 | ||
@@ -1124,7 +1190,7 @@ static int p54_tx_cancel(struct ieee80211_hw *dev, struct sk_buff *entry) | |||
1124 | hdr = (void *)entry->data; | 1190 | hdr = (void *)entry->data; |
1125 | cancel = (struct p54_txcancel *)skb_put(skb, sizeof(*cancel)); | 1191 | cancel = (struct p54_txcancel *)skb_put(skb, sizeof(*cancel)); |
1126 | cancel->req_id = hdr->req_id; | 1192 | cancel->req_id = hdr->req_id; |
1127 | priv->tx(dev, skb, 1); | 1193 | priv->tx(dev, skb); |
1128 | return 0; | 1194 | return 0; |
1129 | } | 1195 | } |
1130 | 1196 | ||
@@ -1353,7 +1419,11 @@ static int p54_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
1353 | /* modifies skb->cb and with it info, so must be last! */ | 1419 | /* modifies skb->cb and with it info, so must be last! */ |
1354 | if (unlikely(p54_assign_address(dev, skb, hdr, skb->len + tim_len))) | 1420 | if (unlikely(p54_assign_address(dev, skb, hdr, skb->len + tim_len))) |
1355 | goto err; | 1421 | goto err; |
1356 | priv->tx(dev, skb, 0); | 1422 | priv->tx(dev, skb); |
1423 | |||
1424 | queue_delayed_work(dev->workqueue, &priv->work, | ||
1425 | msecs_to_jiffies(P54_TX_FRAME_LIFETIME)); | ||
1426 | |||
1357 | return 0; | 1427 | return 0; |
1358 | 1428 | ||
1359 | err: | 1429 | err: |
@@ -1428,19 +1498,19 @@ static int p54_setup_mac(struct ieee80211_hw *dev) | |||
1428 | setup->v2.lpf_bandwidth = cpu_to_le16(65535); | 1498 | setup->v2.lpf_bandwidth = cpu_to_le16(65535); |
1429 | setup->v2.osc_start_delay = cpu_to_le16(65535); | 1499 | setup->v2.osc_start_delay = cpu_to_le16(65535); |
1430 | } | 1500 | } |
1431 | priv->tx(dev, skb, 1); | 1501 | priv->tx(dev, skb); |
1432 | return 0; | 1502 | return 0; |
1433 | } | 1503 | } |
1434 | 1504 | ||
1435 | static int p54_scan(struct ieee80211_hw *dev, u16 mode, u16 dwell, | 1505 | static int p54_scan(struct ieee80211_hw *dev, u16 mode, u16 dwell) |
1436 | u16 frequency) | ||
1437 | { | 1506 | { |
1438 | struct p54_common *priv = dev->priv; | 1507 | struct p54_common *priv = dev->priv; |
1439 | struct sk_buff *skb; | 1508 | struct sk_buff *skb; |
1440 | struct p54_scan *chan; | 1509 | struct p54_scan *chan; |
1441 | unsigned int i; | 1510 | unsigned int i; |
1442 | void *entry; | 1511 | void *entry; |
1443 | __le16 freq = cpu_to_le16(frequency); | 1512 | __le16 freq = cpu_to_le16(dev->conf.channel->center_freq); |
1513 | int band = dev->conf.channel->band; | ||
1444 | 1514 | ||
1445 | skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*chan) + | 1515 | skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL_OPSET, sizeof(*chan) + |
1446 | sizeof(struct p54_hdr), P54_CONTROL_TYPE_SCAN, | 1516 | sizeof(struct p54_hdr), P54_CONTROL_TYPE_SCAN, |
@@ -1501,15 +1571,15 @@ static int p54_scan(struct ieee80211_hw *dev, u16 mode, u16 dwell, | |||
1501 | } | 1571 | } |
1502 | 1572 | ||
1503 | if (priv->fw_var < 0x500) { | 1573 | if (priv->fw_var < 0x500) { |
1504 | chan->v1.rssical_mul = cpu_to_le16(130); | 1574 | chan->v1_rssi.mul = cpu_to_le16(priv->rssical_db[band].mul); |
1505 | chan->v1.rssical_add = cpu_to_le16(0xfe70); | 1575 | chan->v1_rssi.add = cpu_to_le16(priv->rssical_db[band].add); |
1506 | } else { | 1576 | } else { |
1507 | chan->v2.rssical_mul = cpu_to_le16(130); | 1577 | chan->v2.rssi.mul = cpu_to_le16(priv->rssical_db[band].mul); |
1508 | chan->v2.rssical_add = cpu_to_le16(0xfe70); | 1578 | chan->v2.rssi.add = cpu_to_le16(priv->rssical_db[band].add); |
1509 | chan->v2.basic_rate_mask = cpu_to_le32(priv->basic_rate_mask); | 1579 | chan->v2.basic_rate_mask = cpu_to_le32(priv->basic_rate_mask); |
1510 | memset(chan->v2.rts_rates, 0, 8); | 1580 | memset(chan->v2.rts_rates, 0, 8); |
1511 | } | 1581 | } |
1512 | priv->tx(dev, skb, 1); | 1582 | priv->tx(dev, skb); |
1513 | return 0; | 1583 | return 0; |
1514 | 1584 | ||
1515 | err: | 1585 | err: |
@@ -1535,7 +1605,7 @@ static int p54_set_leds(struct ieee80211_hw *dev, int mode, int link, int act) | |||
1535 | led->led_permanent = cpu_to_le16(link); | 1605 | led->led_permanent = cpu_to_le16(link); |
1536 | led->led_temporary = cpu_to_le16(act); | 1606 | led->led_temporary = cpu_to_le16(act); |
1537 | led->duration = cpu_to_le16(1000); | 1607 | led->duration = cpu_to_le16(1000); |
1538 | priv->tx(dev, skb, 1); | 1608 | priv->tx(dev, skb); |
1539 | return 0; | 1609 | return 0; |
1540 | } | 1610 | } |
1541 | 1611 | ||
@@ -1575,21 +1645,7 @@ static int p54_set_edcf(struct ieee80211_hw *dev) | |||
1575 | edcf->flags = 0; | 1645 | edcf->flags = 0; |
1576 | memset(edcf->mapping, 0, sizeof(edcf->mapping)); | 1646 | memset(edcf->mapping, 0, sizeof(edcf->mapping)); |
1577 | memcpy(edcf->queue, priv->qos_params, sizeof(edcf->queue)); | 1647 | memcpy(edcf->queue, priv->qos_params, sizeof(edcf->queue)); |
1578 | priv->tx(dev, skb, 1); | 1648 | priv->tx(dev, skb); |
1579 | return 0; | ||
1580 | } | ||
1581 | |||
1582 | static int p54_init_stats(struct ieee80211_hw *dev) | ||
1583 | { | ||
1584 | struct p54_common *priv = dev->priv; | ||
1585 | |||
1586 | priv->cached_stats = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL, | ||
1587 | sizeof(struct p54_hdr) + sizeof(struct p54_statistics), | ||
1588 | P54_CONTROL_TYPE_STAT_READBACK, GFP_KERNEL); | ||
1589 | if (!priv->cached_stats) | ||
1590 | return -ENOMEM; | ||
1591 | |||
1592 | mod_timer(&priv->stats_timer, jiffies + HZ); | ||
1593 | return 0; | 1649 | return 0; |
1594 | } | 1650 | } |
1595 | 1651 | ||
@@ -1686,9 +1742,6 @@ static int p54_start(struct ieee80211_hw *dev) | |||
1686 | err = p54_set_edcf(dev); | 1742 | err = p54_set_edcf(dev); |
1687 | if (err) | 1743 | if (err) |
1688 | goto out; | 1744 | goto out; |
1689 | err = p54_init_stats(dev); | ||
1690 | if (err) | ||
1691 | goto out; | ||
1692 | 1745 | ||
1693 | memset(priv->bssid, ~0, ETH_ALEN); | 1746 | memset(priv->bssid, ~0, ETH_ALEN); |
1694 | priv->mode = NL80211_IFTYPE_MONITOR; | 1747 | priv->mode = NL80211_IFTYPE_MONITOR; |
@@ -1698,6 +1751,8 @@ static int p54_start(struct ieee80211_hw *dev) | |||
1698 | goto out; | 1751 | goto out; |
1699 | } | 1752 | } |
1700 | 1753 | ||
1754 | queue_delayed_work(dev->workqueue, &priv->work, 0); | ||
1755 | |||
1701 | out: | 1756 | out: |
1702 | mutex_unlock(&priv->conf_mutex); | 1757 | mutex_unlock(&priv->conf_mutex); |
1703 | return err; | 1758 | return err; |
@@ -1710,9 +1765,7 @@ static void p54_stop(struct ieee80211_hw *dev) | |||
1710 | 1765 | ||
1711 | mutex_lock(&priv->conf_mutex); | 1766 | mutex_lock(&priv->conf_mutex); |
1712 | priv->mode = NL80211_IFTYPE_UNSPECIFIED; | 1767 | priv->mode = NL80211_IFTYPE_UNSPECIFIED; |
1713 | del_timer(&priv->stats_timer); | 1768 | cancel_delayed_work_sync(&priv->work); |
1714 | p54_free_skb(dev, priv->cached_stats); | ||
1715 | priv->cached_stats = NULL; | ||
1716 | if (priv->cached_beacon) | 1769 | if (priv->cached_beacon) |
1717 | p54_tx_cancel(dev, priv->cached_beacon); | 1770 | p54_tx_cancel(dev, priv->cached_beacon); |
1718 | 1771 | ||
@@ -1784,8 +1837,7 @@ static int p54_config(struct ieee80211_hw *dev, u32 changed) | |||
1784 | goto out; | 1837 | goto out; |
1785 | } | 1838 | } |
1786 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { | 1839 | if (changed & IEEE80211_CONF_CHANGE_CHANNEL) { |
1787 | ret = p54_scan(dev, P54_SCAN_EXIT, 0, | 1840 | ret = p54_scan(dev, P54_SCAN_EXIT, 0); |
1788 | conf->channel->center_freq); | ||
1789 | if (ret) | 1841 | if (ret) |
1790 | goto out; | 1842 | goto out; |
1791 | } | 1843 | } |
@@ -1811,8 +1863,7 @@ static int p54_config_interface(struct ieee80211_hw *dev, | |||
1811 | } | 1863 | } |
1812 | 1864 | ||
1813 | if (conf->changed & IEEE80211_IFCC_BEACON) { | 1865 | if (conf->changed & IEEE80211_IFCC_BEACON) { |
1814 | ret = p54_scan(dev, P54_SCAN_EXIT, 0, | 1866 | ret = p54_scan(dev, P54_SCAN_EXIT, 0); |
1815 | dev->conf.channel->center_freq); | ||
1816 | if (ret) | 1867 | if (ret) |
1817 | goto out; | 1868 | goto out; |
1818 | ret = p54_setup_mac(dev); | 1869 | ret = p54_setup_mac(dev); |
@@ -1885,18 +1936,33 @@ static int p54_init_xbow_synth(struct ieee80211_hw *dev) | |||
1885 | xbow->magic2 = cpu_to_le16(0x2); | 1936 | xbow->magic2 = cpu_to_le16(0x2); |
1886 | xbow->freq = cpu_to_le16(5390); | 1937 | xbow->freq = cpu_to_le16(5390); |
1887 | memset(xbow->padding, 0, sizeof(xbow->padding)); | 1938 | memset(xbow->padding, 0, sizeof(xbow->padding)); |
1888 | priv->tx(dev, skb, 1); | 1939 | priv->tx(dev, skb); |
1889 | return 0; | 1940 | return 0; |
1890 | } | 1941 | } |
1891 | 1942 | ||
1892 | static void p54_statistics_timer(unsigned long data) | 1943 | static void p54_work(struct work_struct *work) |
1893 | { | 1944 | { |
1894 | struct ieee80211_hw *dev = (struct ieee80211_hw *) data; | 1945 | struct p54_common *priv = container_of(work, struct p54_common, |
1895 | struct p54_common *priv = dev->priv; | 1946 | work.work); |
1947 | struct ieee80211_hw *dev = priv->hw; | ||
1948 | struct sk_buff *skb; | ||
1896 | 1949 | ||
1897 | BUG_ON(!priv->cached_stats); | 1950 | if (unlikely(priv->mode == NL80211_IFTYPE_UNSPECIFIED)) |
1951 | return ; | ||
1952 | |||
1953 | /* | ||
1954 | * TODO: walk through tx_queue and do the following tasks | ||
1955 | * 1. initiate bursts. | ||
1956 | * 2. cancel stuck frames / reset the device if necessary. | ||
1957 | */ | ||
1898 | 1958 | ||
1899 | priv->tx(dev, priv->cached_stats, 0); | 1959 | skb = p54_alloc_skb(dev, P54_HDR_FLAG_CONTROL, sizeof(struct p54_hdr) + |
1960 | sizeof(struct p54_statistics), | ||
1961 | P54_CONTROL_TYPE_STAT_READBACK, GFP_KERNEL); | ||
1962 | if (!skb) | ||
1963 | return ; | ||
1964 | |||
1965 | priv->tx(dev, skb); | ||
1900 | } | 1966 | } |
1901 | 1967 | ||
1902 | static int p54_get_stats(struct ieee80211_hw *dev, | 1968 | static int p54_get_stats(struct ieee80211_hw *dev, |
@@ -1904,17 +1970,7 @@ static int p54_get_stats(struct ieee80211_hw *dev, | |||
1904 | { | 1970 | { |
1905 | struct p54_common *priv = dev->priv; | 1971 | struct p54_common *priv = dev->priv; |
1906 | 1972 | ||
1907 | del_timer(&priv->stats_timer); | ||
1908 | p54_statistics_timer((unsigned long)dev); | ||
1909 | |||
1910 | if (!wait_for_completion_interruptible_timeout(&priv->stats_comp, HZ)) { | ||
1911 | printk(KERN_ERR "%s: device does not respond!\n", | ||
1912 | wiphy_name(dev->wiphy)); | ||
1913 | return -EBUSY; | ||
1914 | } | ||
1915 | |||
1916 | memcpy(stats, &priv->stats, sizeof(*stats)); | 1973 | memcpy(stats, &priv->stats, sizeof(*stats)); |
1917 | |||
1918 | return 0; | 1974 | return 0; |
1919 | } | 1975 | } |
1920 | 1976 | ||
@@ -1946,8 +2002,7 @@ static void p54_bss_info_changed(struct ieee80211_hw *dev, | |||
1946 | priv->basic_rate_mask = info->basic_rates; | 2002 | priv->basic_rate_mask = info->basic_rates; |
1947 | p54_setup_mac(dev); | 2003 | p54_setup_mac(dev); |
1948 | if (priv->fw_var >= 0x500) | 2004 | if (priv->fw_var >= 0x500) |
1949 | p54_scan(dev, P54_SCAN_EXIT, 0, | 2005 | p54_scan(dev, P54_SCAN_EXIT, 0); |
1950 | dev->conf.channel->center_freq); | ||
1951 | } | 2006 | } |
1952 | if (changed & BSS_CHANGED_ASSOC) { | 2007 | if (changed & BSS_CHANGED_ASSOC) { |
1953 | if (info->assoc) { | 2008 | if (info->assoc) { |
@@ -2039,7 +2094,7 @@ static int p54_set_key(struct ieee80211_hw *dev, enum set_key_cmd cmd, | |||
2039 | [NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY]), 8); | 2094 | [NL80211_TKIP_DATA_OFFSET_RX_MIC_KEY]), 8); |
2040 | } | 2095 | } |
2041 | 2096 | ||
2042 | priv->tx(dev, skb, 1); | 2097 | priv->tx(dev, skb); |
2043 | mutex_unlock(&priv->conf_mutex); | 2098 | mutex_unlock(&priv->conf_mutex); |
2044 | return 0; | 2099 | return 0; |
2045 | } | 2100 | } |
@@ -2072,6 +2127,7 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len) | |||
2072 | return NULL; | 2127 | return NULL; |
2073 | 2128 | ||
2074 | priv = dev->priv; | 2129 | priv = dev->priv; |
2130 | priv->hw = dev; | ||
2075 | priv->mode = NL80211_IFTYPE_UNSPECIFIED; | 2131 | priv->mode = NL80211_IFTYPE_UNSPECIFIED; |
2076 | priv->basic_rate_mask = 0x15f; | 2132 | priv->basic_rate_mask = 0x15f; |
2077 | skb_queue_head_init(&priv->tx_queue); | 2133 | skb_queue_head_init(&priv->tx_queue); |
@@ -2107,9 +2163,7 @@ struct ieee80211_hw *p54_init_common(size_t priv_data_len) | |||
2107 | 2163 | ||
2108 | mutex_init(&priv->conf_mutex); | 2164 | mutex_init(&priv->conf_mutex); |
2109 | init_completion(&priv->eeprom_comp); | 2165 | init_completion(&priv->eeprom_comp); |
2110 | init_completion(&priv->stats_comp); | 2166 | INIT_DELAYED_WORK(&priv->work, p54_work); |
2111 | setup_timer(&priv->stats_timer, p54_statistics_timer, | ||
2112 | (unsigned long)dev); | ||
2113 | 2167 | ||
2114 | return dev; | 2168 | return dev; |
2115 | } | 2169 | } |
@@ -2118,8 +2172,6 @@ EXPORT_SYMBOL_GPL(p54_init_common); | |||
2118 | void p54_free_common(struct ieee80211_hw *dev) | 2172 | void p54_free_common(struct ieee80211_hw *dev) |
2119 | { | 2173 | { |
2120 | struct p54_common *priv = dev->priv; | 2174 | struct p54_common *priv = dev->priv; |
2121 | del_timer(&priv->stats_timer); | ||
2122 | kfree_skb(priv->cached_stats); | ||
2123 | kfree(priv->iq_autocal); | 2175 | kfree(priv->iq_autocal); |
2124 | kfree(priv->output_limit); | 2176 | kfree(priv->output_limit); |
2125 | kfree(priv->curve_data); | 2177 | kfree(priv->curve_data); |
diff --git a/drivers/net/wireless/p54/p54common.h b/drivers/net/wireless/p54/p54common.h index 5a68fdae7730..f5729de83fe1 100644 --- a/drivers/net/wireless/p54/p54common.h +++ b/drivers/net/wireless/p54/p54common.h | |||
@@ -84,9 +84,6 @@ struct bootrec_desc { | |||
84 | #define BR_CODE_END_OF_BRA 0xFF0000FF | 84 | #define BR_CODE_END_OF_BRA 0xFF0000FF |
85 | #define LEGACY_BR_CODE_END_OF_BRA 0xFFFFFFFF | 85 | #define LEGACY_BR_CODE_END_OF_BRA 0xFFFFFFFF |
86 | 86 | ||
87 | #define P54_HDR_FLAG_CONTROL BIT(15) | ||
88 | #define P54_HDR_FLAG_CONTROL_OPSET (BIT(15) + BIT(0)) | ||
89 | |||
90 | #define P54_HDR_FLAG_DATA_ALIGN BIT(14) | 87 | #define P54_HDR_FLAG_DATA_ALIGN BIT(14) |
91 | #define P54_HDR_FLAG_DATA_OUT_PROMISC BIT(0) | 88 | #define P54_HDR_FLAG_DATA_OUT_PROMISC BIT(0) |
92 | #define P54_HDR_FLAG_DATA_OUT_TIMESTAMP BIT(1) | 89 | #define P54_HDR_FLAG_DATA_OUT_TIMESTAMP BIT(1) |
@@ -178,6 +175,11 @@ struct pda_pa_curve_data { | |||
178 | u8 data[0]; | 175 | u8 data[0]; |
179 | } __attribute__ ((packed)); | 176 | } __attribute__ ((packed)); |
180 | 177 | ||
178 | struct pda_rssi_cal_entry { | ||
179 | __le16 mul; | ||
180 | __le16 add; | ||
181 | } __attribute__ ((packed)); | ||
182 | |||
181 | /* | 183 | /* |
182 | * this defines the PDR codes used to build PDAs as defined in document | 184 | * this defines the PDR codes used to build PDAs as defined in document |
183 | * number 553155. The current implementation mirrors version 1.1 of the | 185 | * number 553155. The current implementation mirrors version 1.1 of the |
@@ -355,6 +357,11 @@ struct p54_tx_data { | |||
355 | u8 align[0]; | 357 | u8 align[0]; |
356 | } __attribute__ ((packed)); | 358 | } __attribute__ ((packed)); |
357 | 359 | ||
360 | /* unit is ms */ | ||
361 | #define P54_TX_FRAME_LIFETIME 2000 | ||
362 | #define P54_TX_TIMEOUT 4000 | ||
363 | #define P54_STATISTICS_UPDATE 5000 | ||
364 | |||
358 | #define P54_FILTER_TYPE_NONE 0 | 365 | #define P54_FILTER_TYPE_NONE 0 |
359 | #define P54_FILTER_TYPE_STATION BIT(0) | 366 | #define P54_FILTER_TYPE_STATION BIT(0) |
360 | #define P54_FILTER_TYPE_IBSS BIT(1) | 367 | #define P54_FILTER_TYPE_IBSS BIT(1) |
@@ -424,22 +431,18 @@ struct p54_scan { | |||
424 | u8 dup_16qam; | 431 | u8 dup_16qam; |
425 | u8 dup_64qam; | 432 | u8 dup_64qam; |
426 | union { | 433 | union { |
427 | struct { | 434 | struct pda_rssi_cal_entry v1_rssi; |
428 | __le16 rssical_mul; | ||
429 | __le16 rssical_add; | ||
430 | } v1 __attribute__ ((packed)); | ||
431 | 435 | ||
432 | struct { | 436 | struct { |
433 | __le32 basic_rate_mask; | 437 | __le32 basic_rate_mask; |
434 | u8 rts_rates[8]; | 438 | u8 rts_rates[8]; |
435 | __le16 rssical_mul; | 439 | struct pda_rssi_cal_entry rssi; |
436 | __le16 rssical_add; | ||
437 | } v2 __attribute__ ((packed)); | 440 | } v2 __attribute__ ((packed)); |
438 | } __attribute__ ((packed)); | 441 | } __attribute__ ((packed)); |
439 | } __attribute__ ((packed)); | 442 | } __attribute__ ((packed)); |
440 | 443 | ||
441 | #define P54_SCAN_V1_LEN (sizeof(struct p54_scan)-12) | 444 | #define P54_SCAN_V1_LEN 0x70 |
442 | #define P54_SCAN_V2_LEN (sizeof(struct p54_scan)) | 445 | #define P54_SCAN_V2_LEN 0x7c |
443 | 446 | ||
444 | struct p54_led { | 447 | struct p54_led { |
445 | __le16 mode; | 448 | __le16 mode; |
diff --git a/drivers/net/wireless/p54/p54pci.c b/drivers/net/wireless/p54/p54pci.c index c28220e401b9..aa367a0ddc49 100644 --- a/drivers/net/wireless/p54/p54pci.c +++ b/drivers/net/wireless/p54/p54pci.c | |||
@@ -227,7 +227,9 @@ static void p54p_check_tx_ring(struct ieee80211_hw *dev, u32 *index, | |||
227 | 227 | ||
228 | while (i != idx) { | 228 | while (i != idx) { |
229 | desc = &ring[i]; | 229 | desc = &ring[i]; |
230 | p54_free_skb(dev, tx_buf[i]); | 230 | if (tx_buf[i]) |
231 | if (FREE_AFTER_TX((struct sk_buff *) tx_buf[i])) | ||
232 | p54_free_skb(dev, tx_buf[i]); | ||
231 | tx_buf[i] = NULL; | 233 | tx_buf[i] = NULL; |
232 | 234 | ||
233 | pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr), | 235 | pci_unmap_single(priv->pdev, le32_to_cpu(desc->host_addr), |
@@ -298,8 +300,7 @@ static irqreturn_t p54p_interrupt(int irq, void *dev_id) | |||
298 | return reg ? IRQ_HANDLED : IRQ_NONE; | 300 | return reg ? IRQ_HANDLED : IRQ_NONE; |
299 | } | 301 | } |
300 | 302 | ||
301 | static void p54p_tx(struct ieee80211_hw *dev, struct sk_buff *skb, | 303 | static void p54p_tx(struct ieee80211_hw *dev, struct sk_buff *skb) |
302 | int free_on_tx) | ||
303 | { | 304 | { |
304 | struct p54p_priv *priv = dev->priv; | 305 | struct p54p_priv *priv = dev->priv; |
305 | struct p54p_ring_control *ring_control = priv->ring_control; | 306 | struct p54p_ring_control *ring_control = priv->ring_control; |
@@ -314,6 +315,7 @@ static void p54p_tx(struct ieee80211_hw *dev, struct sk_buff *skb, | |||
314 | idx = le32_to_cpu(ring_control->host_idx[1]); | 315 | idx = le32_to_cpu(ring_control->host_idx[1]); |
315 | i = idx % ARRAY_SIZE(ring_control->tx_data); | 316 | i = idx % ARRAY_SIZE(ring_control->tx_data); |
316 | 317 | ||
318 | priv->tx_buf_data[i] = skb; | ||
317 | mapping = pci_map_single(priv->pdev, skb->data, skb->len, | 319 | mapping = pci_map_single(priv->pdev, skb->data, skb->len, |
318 | PCI_DMA_TODEVICE); | 320 | PCI_DMA_TODEVICE); |
319 | desc = &ring_control->tx_data[i]; | 321 | desc = &ring_control->tx_data[i]; |
@@ -324,10 +326,6 @@ static void p54p_tx(struct ieee80211_hw *dev, struct sk_buff *skb, | |||
324 | 326 | ||
325 | wmb(); | 327 | wmb(); |
326 | ring_control->host_idx[1] = cpu_to_le32(idx + 1); | 328 | ring_control->host_idx[1] = cpu_to_le32(idx + 1); |
327 | |||
328 | if (free_on_tx) | ||
329 | priv->tx_buf_data[i] = skb; | ||
330 | |||
331 | spin_unlock_irqrestore(&priv->lock, flags); | 329 | spin_unlock_irqrestore(&priv->lock, flags); |
332 | 330 | ||
333 | P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE)); | 331 | P54P_WRITE(dev_int, cpu_to_le32(ISL38XX_DEV_INT_UPDATE)); |
diff --git a/drivers/net/wireless/p54/p54usb.c b/drivers/net/wireless/p54/p54usb.c index c2789e53b984..c44a200059d2 100644 --- a/drivers/net/wireless/p54/p54usb.c +++ b/drivers/net/wireless/p54/p54usb.c | |||
@@ -138,22 +138,16 @@ static void p54u_rx_cb(struct urb *urb) | |||
138 | } | 138 | } |
139 | } | 139 | } |
140 | 140 | ||
141 | static void p54u_tx_reuse_skb_cb(struct urb *urb) | 141 | static void p54u_tx_cb(struct urb *urb) |
142 | { | ||
143 | struct sk_buff *skb = urb->context; | ||
144 | struct p54u_priv *priv = (struct p54u_priv *)((struct ieee80211_hw *) | ||
145 | usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)))->priv; | ||
146 | |||
147 | skb_pull(skb, priv->common.tx_hdr_len); | ||
148 | } | ||
149 | |||
150 | static void p54u_tx_free_skb_cb(struct urb *urb) | ||
151 | { | 142 | { |
152 | struct sk_buff *skb = urb->context; | 143 | struct sk_buff *skb = urb->context; |
153 | struct ieee80211_hw *dev = (struct ieee80211_hw *) | 144 | struct ieee80211_hw *dev = (struct ieee80211_hw *) |
154 | usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); | 145 | usb_get_intfdata(usb_ifnum_to_if(urb->dev, 0)); |
146 | struct p54u_priv *priv = dev->priv; | ||
155 | 147 | ||
156 | p54_free_skb(dev, skb); | 148 | skb_pull(skb, priv->common.tx_hdr_len); |
149 | if (FREE_AFTER_TX(skb)) | ||
150 | p54_free_skb(dev, skb); | ||
157 | } | 151 | } |
158 | 152 | ||
159 | static void p54u_tx_dummy_cb(struct urb *urb) { } | 153 | static void p54u_tx_dummy_cb(struct urb *urb) { } |
@@ -213,8 +207,7 @@ static int p54u_init_urbs(struct ieee80211_hw *dev) | |||
213 | return ret; | 207 | return ret; |
214 | } | 208 | } |
215 | 209 | ||
216 | static void p54u_tx_3887(struct ieee80211_hw *dev, struct sk_buff *skb, | 210 | static void p54u_tx_3887(struct ieee80211_hw *dev, struct sk_buff *skb) |
217 | int free_on_tx) | ||
218 | { | 211 | { |
219 | struct p54u_priv *priv = dev->priv; | 212 | struct p54u_priv *priv = dev->priv; |
220 | struct urb *addr_urb, *data_urb; | 213 | struct urb *addr_urb, *data_urb; |
@@ -236,9 +229,7 @@ static void p54u_tx_3887(struct ieee80211_hw *dev, struct sk_buff *skb, | |||
236 | p54u_tx_dummy_cb, dev); | 229 | p54u_tx_dummy_cb, dev); |
237 | usb_fill_bulk_urb(data_urb, priv->udev, | 230 | usb_fill_bulk_urb(data_urb, priv->udev, |
238 | usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), | 231 | usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), |
239 | skb->data, skb->len, | 232 | skb->data, skb->len, p54u_tx_cb, skb); |
240 | free_on_tx ? p54u_tx_free_skb_cb : | ||
241 | p54u_tx_reuse_skb_cb, skb); | ||
242 | 233 | ||
243 | usb_anchor_urb(addr_urb, &priv->submitted); | 234 | usb_anchor_urb(addr_urb, &priv->submitted); |
244 | err = usb_submit_urb(addr_urb, GFP_ATOMIC); | 235 | err = usb_submit_urb(addr_urb, GFP_ATOMIC); |
@@ -273,8 +264,7 @@ static __le32 p54u_lm87_chksum(const __le32 *data, size_t length) | |||
273 | return cpu_to_le32(chk); | 264 | return cpu_to_le32(chk); |
274 | } | 265 | } |
275 | 266 | ||
276 | static void p54u_tx_lm87(struct ieee80211_hw *dev, struct sk_buff *skb, | 267 | static void p54u_tx_lm87(struct ieee80211_hw *dev, struct sk_buff *skb) |
277 | int free_on_tx) | ||
278 | { | 268 | { |
279 | struct p54u_priv *priv = dev->priv; | 269 | struct p54u_priv *priv = dev->priv; |
280 | struct urb *data_urb; | 270 | struct urb *data_urb; |
@@ -293,9 +283,7 @@ static void p54u_tx_lm87(struct ieee80211_hw *dev, struct sk_buff *skb, | |||
293 | 283 | ||
294 | usb_fill_bulk_urb(data_urb, priv->udev, | 284 | usb_fill_bulk_urb(data_urb, priv->udev, |
295 | usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), | 285 | usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), |
296 | skb->data, skb->len, | 286 | skb->data, skb->len, p54u_tx_cb, skb); |
297 | free_on_tx ? p54u_tx_free_skb_cb : | ||
298 | p54u_tx_reuse_skb_cb, skb); | ||
299 | 287 | ||
300 | usb_anchor_urb(data_urb, &priv->submitted); | 288 | usb_anchor_urb(data_urb, &priv->submitted); |
301 | if (usb_submit_urb(data_urb, GFP_ATOMIC)) { | 289 | if (usb_submit_urb(data_urb, GFP_ATOMIC)) { |
@@ -306,14 +294,15 @@ static void p54u_tx_lm87(struct ieee80211_hw *dev, struct sk_buff *skb, | |||
306 | usb_free_urb(data_urb); | 294 | usb_free_urb(data_urb); |
307 | } | 295 | } |
308 | 296 | ||
309 | static void p54u_tx_net2280(struct ieee80211_hw *dev, struct sk_buff *skb, | 297 | static void p54u_tx_net2280(struct ieee80211_hw *dev, struct sk_buff *skb) |
310 | int free_on_tx) | ||
311 | { | 298 | { |
312 | struct p54u_priv *priv = dev->priv; | 299 | struct p54u_priv *priv = dev->priv; |
313 | struct urb *int_urb, *data_urb; | 300 | struct urb *int_urb, *data_urb; |
314 | struct net2280_tx_hdr *hdr; | 301 | struct net2280_tx_hdr *hdr; |
315 | struct net2280_reg_write *reg; | 302 | struct net2280_reg_write *reg; |
316 | int err = 0; | 303 | int err = 0; |
304 | __le32 addr = ((struct p54_hdr *) skb->data)->req_id; | ||
305 | __le16 len = cpu_to_le16(skb->len); | ||
317 | 306 | ||
318 | reg = kmalloc(sizeof(*reg), GFP_ATOMIC); | 307 | reg = kmalloc(sizeof(*reg), GFP_ATOMIC); |
319 | if (!reg) | 308 | if (!reg) |
@@ -338,8 +327,8 @@ static void p54u_tx_net2280(struct ieee80211_hw *dev, struct sk_buff *skb, | |||
338 | 327 | ||
339 | hdr = (void *)skb_push(skb, sizeof(*hdr)); | 328 | hdr = (void *)skb_push(skb, sizeof(*hdr)); |
340 | memset(hdr, 0, sizeof(*hdr)); | 329 | memset(hdr, 0, sizeof(*hdr)); |
341 | hdr->device_addr = ((struct p54_hdr *)skb->data)->req_id; | 330 | hdr->len = len; |
342 | hdr->len = cpu_to_le16(skb->len + sizeof(struct p54_hdr)); | 331 | hdr->device_addr = addr; |
343 | 332 | ||
344 | usb_fill_bulk_urb(int_urb, priv->udev, | 333 | usb_fill_bulk_urb(int_urb, priv->udev, |
345 | usb_sndbulkpipe(priv->udev, P54U_PIPE_DEV), reg, sizeof(*reg), | 334 | usb_sndbulkpipe(priv->udev, P54U_PIPE_DEV), reg, sizeof(*reg), |
@@ -354,9 +343,7 @@ static void p54u_tx_net2280(struct ieee80211_hw *dev, struct sk_buff *skb, | |||
354 | 343 | ||
355 | usb_fill_bulk_urb(data_urb, priv->udev, | 344 | usb_fill_bulk_urb(data_urb, priv->udev, |
356 | usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), | 345 | usb_sndbulkpipe(priv->udev, P54U_PIPE_DATA), |
357 | skb->data, skb->len, | 346 | skb->data, skb->len, p54u_tx_cb, skb); |
358 | free_on_tx ? p54u_tx_free_skb_cb : | ||
359 | p54u_tx_reuse_skb_cb, skb); | ||
360 | 347 | ||
361 | usb_anchor_urb(int_urb, &priv->submitted); | 348 | usb_anchor_urb(int_urb, &priv->submitted); |
362 | err = usb_submit_urb(int_urb, GFP_ATOMIC); | 349 | err = usb_submit_urb(int_urb, GFP_ATOMIC); |
diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c index 74f5449b7924..00ce3ef39abe 100644 --- a/drivers/net/wireless/rtl818x/rtl8187_dev.c +++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c | |||
@@ -213,7 +213,7 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
213 | urb = usb_alloc_urb(0, GFP_ATOMIC); | 213 | urb = usb_alloc_urb(0, GFP_ATOMIC); |
214 | if (!urb) { | 214 | if (!urb) { |
215 | kfree_skb(skb); | 215 | kfree_skb(skb); |
216 | return 0; | 216 | return -ENOMEM; |
217 | } | 217 | } |
218 | 218 | ||
219 | flags = skb->len; | 219 | flags = skb->len; |
@@ -281,7 +281,7 @@ static int rtl8187_tx(struct ieee80211_hw *dev, struct sk_buff *skb) | |||
281 | } | 281 | } |
282 | usb_free_urb(urb); | 282 | usb_free_urb(urb); |
283 | 283 | ||
284 | return 0; | 284 | return rc; |
285 | } | 285 | } |
286 | 286 | ||
287 | static void rtl8187_rx_cb(struct urb *urb) | 287 | static void rtl8187_rx_cb(struct urb *urb) |
@@ -294,15 +294,16 @@ static void rtl8187_rx_cb(struct urb *urb) | |||
294 | int rate, signal; | 294 | int rate, signal; |
295 | u32 flags; | 295 | u32 flags; |
296 | u32 quality; | 296 | u32 quality; |
297 | unsigned long f; | ||
297 | 298 | ||
298 | spin_lock(&priv->rx_queue.lock); | 299 | spin_lock_irqsave(&priv->rx_queue.lock, f); |
299 | if (skb->next) | 300 | if (skb->next) |
300 | __skb_unlink(skb, &priv->rx_queue); | 301 | __skb_unlink(skb, &priv->rx_queue); |
301 | else { | 302 | else { |
302 | spin_unlock(&priv->rx_queue.lock); | 303 | spin_unlock_irqrestore(&priv->rx_queue.lock, f); |
303 | return; | 304 | return; |
304 | } | 305 | } |
305 | spin_unlock(&priv->rx_queue.lock); | 306 | spin_unlock_irqrestore(&priv->rx_queue.lock, f); |
306 | skb_put(skb, urb->actual_length); | 307 | skb_put(skb, urb->actual_length); |
307 | 308 | ||
308 | if (unlikely(urb->status)) { | 309 | if (unlikely(urb->status)) { |
@@ -942,7 +943,6 @@ static int rtl8187_start(struct ieee80211_hw *dev) | |||
942 | static void rtl8187_stop(struct ieee80211_hw *dev) | 943 | static void rtl8187_stop(struct ieee80211_hw *dev) |
943 | { | 944 | { |
944 | struct rtl8187_priv *priv = dev->priv; | 945 | struct rtl8187_priv *priv = dev->priv; |
945 | struct rtl8187_rx_info *info; | ||
946 | struct sk_buff *skb; | 946 | struct sk_buff *skb; |
947 | u32 reg; | 947 | u32 reg; |
948 | 948 | ||
@@ -961,10 +961,6 @@ static void rtl8187_stop(struct ieee80211_hw *dev) | |||
961 | rtl818x_iowrite8(priv, &priv->map->CONFIG4, reg | RTL818X_CONFIG4_VCOOFF); | 961 | rtl818x_iowrite8(priv, &priv->map->CONFIG4, reg | RTL818X_CONFIG4_VCOOFF); |
962 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); | 962 | rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL); |
963 | 963 | ||
964 | while ((skb = skb_dequeue(&priv->rx_queue))) { | ||
965 | info = (struct rtl8187_rx_info *)skb->cb; | ||
966 | kfree_skb(skb); | ||
967 | } | ||
968 | while ((skb = skb_dequeue(&priv->b_tx_status.queue))) | 964 | while ((skb = skb_dequeue(&priv->b_tx_status.queue))) |
969 | dev_kfree_skb_any(skb); | 965 | dev_kfree_skb_any(skb); |
970 | 966 | ||
diff --git a/include/linux/nl80211.h b/include/linux/nl80211.h index 04d4516f9c71..e86ed59f9ad5 100644 --- a/include/linux/nl80211.h +++ b/include/linux/nl80211.h | |||
@@ -201,13 +201,13 @@ enum nl80211_commands { | |||
201 | * @NL80211_ATTR_WIPHY_NAME: wiphy name (used for renaming) | 201 | * @NL80211_ATTR_WIPHY_NAME: wiphy name (used for renaming) |
202 | * @NL80211_ATTR_WIPHY_TXQ_PARAMS: a nested array of TX queue parameters | 202 | * @NL80211_ATTR_WIPHY_TXQ_PARAMS: a nested array of TX queue parameters |
203 | * @NL80211_ATTR_WIPHY_FREQ: frequency of the selected channel in MHz | 203 | * @NL80211_ATTR_WIPHY_FREQ: frequency of the selected channel in MHz |
204 | * @NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET: included with NL80211_ATTR_WIPHY_FREQ | 204 | * @NL80211_ATTR_WIPHY_CHANNEL_TYPE: included with NL80211_ATTR_WIPHY_FREQ |
205 | * if HT20 or HT40 are allowed (i.e., 802.11n disabled if not included): | 205 | * if HT20 or HT40 are allowed (i.e., 802.11n disabled if not included): |
206 | * NL80211_SEC_CHAN_NO_HT = HT not allowed (i.e., same as not including | 206 | * NL80211_CHAN_NO_HT = HT not allowed (i.e., same as not including |
207 | * this attribute) | 207 | * this attribute) |
208 | * NL80211_SEC_CHAN_DISABLED = HT20 only | 208 | * NL80211_CHAN_HT20 = HT20 only |
209 | * NL80211_SEC_CHAN_BELOW = secondary channel is below the primary channel | 209 | * NL80211_CHAN_HT40MINUS = secondary channel is below the primary channel |
210 | * NL80211_SEC_CHAN_ABOVE = secondary channel is above the primary channel | 210 | * NL80211_CHAN_HT40PLUS = secondary channel is above the primary channel |
211 | * | 211 | * |
212 | * @NL80211_ATTR_IFINDEX: network interface index of the device to operate on | 212 | * @NL80211_ATTR_IFINDEX: network interface index of the device to operate on |
213 | * @NL80211_ATTR_IFNAME: network interface name | 213 | * @NL80211_ATTR_IFNAME: network interface name |
@@ -344,7 +344,7 @@ enum nl80211_attrs { | |||
344 | 344 | ||
345 | NL80211_ATTR_WIPHY_TXQ_PARAMS, | 345 | NL80211_ATTR_WIPHY_TXQ_PARAMS, |
346 | NL80211_ATTR_WIPHY_FREQ, | 346 | NL80211_ATTR_WIPHY_FREQ, |
347 | NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET, | 347 | NL80211_ATTR_WIPHY_CHANNEL_TYPE, |
348 | 348 | ||
349 | /* add attributes here, update the policy in nl80211.c */ | 349 | /* add attributes here, update the policy in nl80211.c */ |
350 | 350 | ||
@@ -425,6 +425,32 @@ enum nl80211_sta_flags { | |||
425 | }; | 425 | }; |
426 | 426 | ||
427 | /** | 427 | /** |
428 | * enum nl80211_rate_info - bitrate information | ||
429 | * | ||
430 | * These attribute types are used with %NL80211_STA_INFO_TXRATE | ||
431 | * when getting information about the bitrate of a station. | ||
432 | * | ||
433 | * @__NL80211_RATE_INFO_INVALID: attribute number 0 is reserved | ||
434 | * @NL80211_RATE_INFO_BITRATE: total bitrate (u16, 100kbit/s) | ||
435 | * @NL80211_RATE_INFO_MCS: mcs index for 802.11n (u8) | ||
436 | * @NL80211_RATE_INFO_40_MHZ_WIDTH: 40 Mhz dualchannel bitrate | ||
437 | * @NL80211_RATE_INFO_SHORT_GI: 400ns guard interval | ||
438 | * @NL80211_RATE_INFO_MAX: highest rate_info number currently defined | ||
439 | * @__NL80211_RATE_INFO_AFTER_LAST: internal use | ||
440 | */ | ||
441 | enum nl80211_rate_info { | ||
442 | __NL80211_RATE_INFO_INVALID, | ||
443 | NL80211_RATE_INFO_BITRATE, | ||
444 | NL80211_RATE_INFO_MCS, | ||
445 | NL80211_RATE_INFO_40_MHZ_WIDTH, | ||
446 | NL80211_RATE_INFO_SHORT_GI, | ||
447 | |||
448 | /* keep last */ | ||
449 | __NL80211_RATE_INFO_AFTER_LAST, | ||
450 | NL80211_RATE_INFO_MAX = __NL80211_RATE_INFO_AFTER_LAST - 1 | ||
451 | }; | ||
452 | |||
453 | /** | ||
428 | * enum nl80211_sta_info - station information | 454 | * enum nl80211_sta_info - station information |
429 | * | 455 | * |
430 | * These attribute types are used with %NL80211_ATTR_STA_INFO | 456 | * These attribute types are used with %NL80211_ATTR_STA_INFO |
@@ -436,6 +462,9 @@ enum nl80211_sta_flags { | |||
436 | * @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (u32, to this station) | 462 | * @NL80211_STA_INFO_TX_BYTES: total transmitted bytes (u32, to this station) |
437 | * @__NL80211_STA_INFO_AFTER_LAST: internal | 463 | * @__NL80211_STA_INFO_AFTER_LAST: internal |
438 | * @NL80211_STA_INFO_MAX: highest possible station info attribute | 464 | * @NL80211_STA_INFO_MAX: highest possible station info attribute |
465 | * @NL80211_STA_INFO_SIGNAL: signal strength of last received PPDU (u8, dBm) | ||
466 | * @NL80211_STA_INFO_TX_BITRATE: current unicast tx rate, nested attribute | ||
467 | * containing info as possible, see &enum nl80211_sta_info_txrate. | ||
439 | */ | 468 | */ |
440 | enum nl80211_sta_info { | 469 | enum nl80211_sta_info { |
441 | __NL80211_STA_INFO_INVALID, | 470 | __NL80211_STA_INFO_INVALID, |
@@ -445,6 +474,8 @@ enum nl80211_sta_info { | |||
445 | NL80211_STA_INFO_LLID, | 474 | NL80211_STA_INFO_LLID, |
446 | NL80211_STA_INFO_PLID, | 475 | NL80211_STA_INFO_PLID, |
447 | NL80211_STA_INFO_PLINK_STATE, | 476 | NL80211_STA_INFO_PLINK_STATE, |
477 | NL80211_STA_INFO_SIGNAL, | ||
478 | NL80211_STA_INFO_TX_BITRATE, | ||
448 | 479 | ||
449 | /* keep last */ | 480 | /* keep last */ |
450 | __NL80211_STA_INFO_AFTER_LAST, | 481 | __NL80211_STA_INFO_AFTER_LAST, |
@@ -774,10 +805,10 @@ enum nl80211_txq_q { | |||
774 | NL80211_TXQ_Q_BK | 805 | NL80211_TXQ_Q_BK |
775 | }; | 806 | }; |
776 | 807 | ||
777 | enum nl80211_sec_chan_offset { | 808 | enum nl80211_channel_type { |
778 | NL80211_SEC_CHAN_NO_HT /* No HT */, | 809 | NL80211_CHAN_NO_HT, |
779 | NL80211_SEC_CHAN_DISABLED /* HT20 only */, | 810 | NL80211_CHAN_HT20, |
780 | NL80211_SEC_CHAN_BELOW /* HT40- */, | 811 | NL80211_CHAN_HT40MINUS, |
781 | NL80211_SEC_CHAN_ABOVE /* HT40+ */ | 812 | NL80211_CHAN_HT40PLUS |
782 | }; | 813 | }; |
783 | #endif /* __LINUX_NL80211_H */ | 814 | #endif /* __LINUX_NL80211_H */ |
diff --git a/include/net/cfg80211.h b/include/net/cfg80211.h index a0c0bf19496c..23c0ab74ded6 100644 --- a/include/net/cfg80211.h +++ b/include/net/cfg80211.h | |||
@@ -169,6 +169,9 @@ struct station_parameters { | |||
169 | * @STATION_INFO_LLID: @llid filled | 169 | * @STATION_INFO_LLID: @llid filled |
170 | * @STATION_INFO_PLID: @plid filled | 170 | * @STATION_INFO_PLID: @plid filled |
171 | * @STATION_INFO_PLINK_STATE: @plink_state filled | 171 | * @STATION_INFO_PLINK_STATE: @plink_state filled |
172 | * @STATION_INFO_SIGNAL: @signal filled | ||
173 | * @STATION_INFO_TX_BITRATE: @tx_bitrate fields are filled | ||
174 | * (tx_bitrate, tx_bitrate_flags and tx_bitrate_mcs) | ||
172 | */ | 175 | */ |
173 | enum station_info_flags { | 176 | enum station_info_flags { |
174 | STATION_INFO_INACTIVE_TIME = 1<<0, | 177 | STATION_INFO_INACTIVE_TIME = 1<<0, |
@@ -177,6 +180,39 @@ enum station_info_flags { | |||
177 | STATION_INFO_LLID = 1<<3, | 180 | STATION_INFO_LLID = 1<<3, |
178 | STATION_INFO_PLID = 1<<4, | 181 | STATION_INFO_PLID = 1<<4, |
179 | STATION_INFO_PLINK_STATE = 1<<5, | 182 | STATION_INFO_PLINK_STATE = 1<<5, |
183 | STATION_INFO_SIGNAL = 1<<6, | ||
184 | STATION_INFO_TX_BITRATE = 1<<7, | ||
185 | }; | ||
186 | |||
187 | /** | ||
188 | * enum station_info_rate_flags - bitrate info flags | ||
189 | * | ||
190 | * Used by the driver to indicate the specific rate transmission | ||
191 | * type for 802.11n transmissions. | ||
192 | * | ||
193 | * @RATE_INFO_FLAGS_MCS: @tx_bitrate_mcs filled | ||
194 | * @RATE_INFO_FLAGS_40_MHZ_WIDTH: 40 Mhz width transmission | ||
195 | * @RATE_INFO_FLAGS_SHORT_GI: 400ns guard interval | ||
196 | */ | ||
197 | enum rate_info_flags { | ||
198 | RATE_INFO_FLAGS_MCS = 1<<0, | ||
199 | RATE_INFO_FLAGS_40_MHZ_WIDTH = 1<<1, | ||
200 | RATE_INFO_FLAGS_SHORT_GI = 1<<2, | ||
201 | }; | ||
202 | |||
203 | /** | ||
204 | * struct rate_info - bitrate information | ||
205 | * | ||
206 | * Information about a receiving or transmitting bitrate | ||
207 | * | ||
208 | * @flags: bitflag of flags from &enum rate_info_flags | ||
209 | * @mcs: mcs index if struct describes a 802.11n bitrate | ||
210 | * @legacy: bitrate in 100kbit/s for 802.11abg | ||
211 | */ | ||
212 | struct rate_info { | ||
213 | u8 flags; | ||
214 | u8 mcs; | ||
215 | u16 legacy; | ||
180 | }; | 216 | }; |
181 | 217 | ||
182 | /** | 218 | /** |
@@ -191,6 +227,8 @@ enum station_info_flags { | |||
191 | * @llid: mesh local link id | 227 | * @llid: mesh local link id |
192 | * @plid: mesh peer link id | 228 | * @plid: mesh peer link id |
193 | * @plink_state: mesh peer link state | 229 | * @plink_state: mesh peer link state |
230 | * @signal: signal strength of last received packet in dBm | ||
231 | * @txrate: current unicast bitrate to this station | ||
194 | */ | 232 | */ |
195 | struct station_info { | 233 | struct station_info { |
196 | u32 filled; | 234 | u32 filled; |
@@ -200,6 +238,8 @@ struct station_info { | |||
200 | u16 llid; | 238 | u16 llid; |
201 | u16 plid; | 239 | u16 plid; |
202 | u8 plink_state; | 240 | u8 plink_state; |
241 | s8 signal; | ||
242 | struct rate_info txrate; | ||
203 | }; | 243 | }; |
204 | 244 | ||
205 | /** | 245 | /** |
@@ -523,7 +563,7 @@ struct cfg80211_ops { | |||
523 | 563 | ||
524 | int (*set_channel)(struct wiphy *wiphy, | 564 | int (*set_channel)(struct wiphy *wiphy, |
525 | struct ieee80211_channel *chan, | 565 | struct ieee80211_channel *chan, |
526 | enum nl80211_sec_chan_offset); | 566 | enum nl80211_channel_type channel_type); |
527 | }; | 567 | }; |
528 | 568 | ||
529 | /* temporary wext handlers */ | 569 | /* temporary wext handlers */ |
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 046ce692a906..b3bd00a9d992 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -165,14 +165,9 @@ enum ieee80211_bss_change { | |||
165 | 165 | ||
166 | /** | 166 | /** |
167 | * struct ieee80211_bss_ht_conf - BSS's changing HT configuration | 167 | * struct ieee80211_bss_ht_conf - BSS's changing HT configuration |
168 | * @secondary_channel_offset: secondary channel offset, uses | ||
169 | * %IEEE80211_HT_PARAM_CHA_SEC_ values | ||
170 | * @width_40_ok: indicates that 40 MHz bandwidth may be used for TX | ||
171 | * @operation_mode: HT operation mode (like in &struct ieee80211_ht_info) | 168 | * @operation_mode: HT operation mode (like in &struct ieee80211_ht_info) |
172 | */ | 169 | */ |
173 | struct ieee80211_bss_ht_conf { | 170 | struct ieee80211_bss_ht_conf { |
174 | u8 secondary_channel_offset; | ||
175 | bool width_40_ok; | ||
176 | u16 operation_mode; | 171 | u16 operation_mode; |
177 | }; | 172 | }; |
178 | 173 | ||
@@ -441,6 +436,9 @@ ieee80211_tx_info_clear_status(struct ieee80211_tx_info *info) | |||
441 | * is valid. This is useful in monitor mode and necessary for beacon frames | 436 | * is valid. This is useful in monitor mode and necessary for beacon frames |
442 | * to enable IBSS merging. | 437 | * to enable IBSS merging. |
443 | * @RX_FLAG_SHORTPRE: Short preamble was used for this frame | 438 | * @RX_FLAG_SHORTPRE: Short preamble was used for this frame |
439 | * @RX_FLAG_HT: HT MCS was used and rate_idx is MCS index | ||
440 | * @RX_FLAG_40MHZ: HT40 (40 MHz) was used | ||
441 | * @RX_FLAG_SHORT_GI: Short guard interval was used | ||
444 | */ | 442 | */ |
445 | enum mac80211_rx_flags { | 443 | enum mac80211_rx_flags { |
446 | RX_FLAG_MMIC_ERROR = 1<<0, | 444 | RX_FLAG_MMIC_ERROR = 1<<0, |
@@ -451,7 +449,10 @@ enum mac80211_rx_flags { | |||
451 | RX_FLAG_FAILED_FCS_CRC = 1<<5, | 449 | RX_FLAG_FAILED_FCS_CRC = 1<<5, |
452 | RX_FLAG_FAILED_PLCP_CRC = 1<<6, | 450 | RX_FLAG_FAILED_PLCP_CRC = 1<<6, |
453 | RX_FLAG_TSFT = 1<<7, | 451 | RX_FLAG_TSFT = 1<<7, |
454 | RX_FLAG_SHORTPRE = 1<<8 | 452 | RX_FLAG_SHORTPRE = 1<<8, |
453 | RX_FLAG_HT = 1<<9, | ||
454 | RX_FLAG_40MHZ = 1<<10, | ||
455 | RX_FLAG_SHORT_GI = 1<<11, | ||
455 | }; | 456 | }; |
456 | 457 | ||
457 | /** | 458 | /** |
@@ -471,7 +472,8 @@ enum mac80211_rx_flags { | |||
471 | * @noise: noise when receiving this frame, in dBm. | 472 | * @noise: noise when receiving this frame, in dBm. |
472 | * @qual: overall signal quality indication, in percent (0-100). | 473 | * @qual: overall signal quality indication, in percent (0-100). |
473 | * @antenna: antenna used | 474 | * @antenna: antenna used |
474 | * @rate_idx: index of data rate into band's supported rates | 475 | * @rate_idx: index of data rate into band's supported rates or MCS index if |
476 | * HT rates are use (RX_FLAG_HT) | ||
475 | * @flag: %RX_FLAG_* | 477 | * @flag: %RX_FLAG_* |
476 | */ | 478 | */ |
477 | struct ieee80211_rx_status { | 479 | struct ieee80211_rx_status { |
@@ -508,9 +510,7 @@ static inline int __deprecated __IEEE80211_CONF_SHORT_SLOT_TIME(void) | |||
508 | 510 | ||
509 | struct ieee80211_ht_conf { | 511 | struct ieee80211_ht_conf { |
510 | bool enabled; | 512 | bool enabled; |
511 | int sec_chan_offset; /* 0 = HT40 disabled; -1 = HT40 enabled, secondary | 513 | enum nl80211_channel_type channel_type; |
512 | * channel below primary; 1 = HT40 enabled, | ||
513 | * secondary channel above primary */ | ||
514 | }; | 514 | }; |
515 | 515 | ||
516 | /** | 516 | /** |
@@ -854,6 +854,11 @@ enum ieee80211_tkip_key_type { | |||
854 | * | 854 | * |
855 | * @IEEE80211_HW_AMPDU_AGGREGATION: | 855 | * @IEEE80211_HW_AMPDU_AGGREGATION: |
856 | * Hardware supports 11n A-MPDU aggregation. | 856 | * Hardware supports 11n A-MPDU aggregation. |
857 | * | ||
858 | * @IEEE80211_HW_NO_STACK_DYNAMIC_PS: | ||
859 | * Hardware which has dynamic power save support, meaning | ||
860 | * that power save is enabled in idle periods, and don't need support | ||
861 | * from stack. | ||
857 | */ | 862 | */ |
858 | enum ieee80211_hw_flags { | 863 | enum ieee80211_hw_flags { |
859 | IEEE80211_HW_RX_INCLUDES_FCS = 1<<1, | 864 | IEEE80211_HW_RX_INCLUDES_FCS = 1<<1, |
@@ -866,6 +871,7 @@ enum ieee80211_hw_flags { | |||
866 | IEEE80211_HW_NOISE_DBM = 1<<8, | 871 | IEEE80211_HW_NOISE_DBM = 1<<8, |
867 | IEEE80211_HW_SPECTRUM_MGMT = 1<<9, | 872 | IEEE80211_HW_SPECTRUM_MGMT = 1<<9, |
868 | IEEE80211_HW_AMPDU_AGGREGATION = 1<<10, | 873 | IEEE80211_HW_AMPDU_AGGREGATION = 1<<10, |
874 | IEEE80211_HW_NO_STACK_DYNAMIC_PS = 1<<11, | ||
869 | }; | 875 | }; |
870 | 876 | ||
871 | /** | 877 | /** |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 7912eb14eca0..9d4e4d846ec1 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -310,12 +310,35 @@ static void sta_set_sinfo(struct sta_info *sta, struct station_info *sinfo) | |||
310 | 310 | ||
311 | sinfo->filled = STATION_INFO_INACTIVE_TIME | | 311 | sinfo->filled = STATION_INFO_INACTIVE_TIME | |
312 | STATION_INFO_RX_BYTES | | 312 | STATION_INFO_RX_BYTES | |
313 | STATION_INFO_TX_BYTES; | 313 | STATION_INFO_TX_BYTES | |
314 | STATION_INFO_TX_BITRATE; | ||
314 | 315 | ||
315 | sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx); | 316 | sinfo->inactive_time = jiffies_to_msecs(jiffies - sta->last_rx); |
316 | sinfo->rx_bytes = sta->rx_bytes; | 317 | sinfo->rx_bytes = sta->rx_bytes; |
317 | sinfo->tx_bytes = sta->tx_bytes; | 318 | sinfo->tx_bytes = sta->tx_bytes; |
318 | 319 | ||
320 | if (sta->local->hw.flags & IEEE80211_HW_SIGNAL_DBM) { | ||
321 | sinfo->filled |= STATION_INFO_SIGNAL; | ||
322 | sinfo->signal = (s8)sta->last_signal; | ||
323 | } | ||
324 | |||
325 | sinfo->txrate.flags = 0; | ||
326 | if (sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS) | ||
327 | sinfo->txrate.flags |= RATE_INFO_FLAGS_MCS; | ||
328 | if (sta->last_tx_rate.flags & IEEE80211_TX_RC_40_MHZ_WIDTH) | ||
329 | sinfo->txrate.flags |= RATE_INFO_FLAGS_40_MHZ_WIDTH; | ||
330 | if (sta->last_tx_rate.flags & IEEE80211_TX_RC_SHORT_GI) | ||
331 | sinfo->txrate.flags |= RATE_INFO_FLAGS_SHORT_GI; | ||
332 | |||
333 | if (!(sta->last_tx_rate.flags & IEEE80211_TX_RC_MCS)) { | ||
334 | struct ieee80211_supported_band *sband; | ||
335 | sband = sta->local->hw.wiphy->bands[ | ||
336 | sta->local->hw.conf.channel->band]; | ||
337 | sinfo->txrate.legacy = | ||
338 | sband->bitrates[sta->last_tx_rate.idx].bitrate; | ||
339 | } else | ||
340 | sinfo->txrate.mcs = sta->last_tx_rate.idx; | ||
341 | |||
319 | if (ieee80211_vif_is_mesh(&sdata->vif)) { | 342 | if (ieee80211_vif_is_mesh(&sdata->vif)) { |
320 | #ifdef CONFIG_MAC80211_MESH | 343 | #ifdef CONFIG_MAC80211_MESH |
321 | sinfo->filled |= STATION_INFO_LLID | | 344 | sinfo->filled |= STATION_INFO_LLID | |
@@ -663,6 +686,7 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, | |||
663 | struct sta_info *sta; | 686 | struct sta_info *sta; |
664 | struct ieee80211_sub_if_data *sdata; | 687 | struct ieee80211_sub_if_data *sdata; |
665 | int err; | 688 | int err; |
689 | int layer2_update; | ||
666 | 690 | ||
667 | /* Prevent a race with changing the rate control algorithm */ | 691 | /* Prevent a race with changing the rate control algorithm */ |
668 | if (!netif_running(dev)) | 692 | if (!netif_running(dev)) |
@@ -693,17 +717,25 @@ static int ieee80211_add_station(struct wiphy *wiphy, struct net_device *dev, | |||
693 | 717 | ||
694 | rate_control_rate_init(sta); | 718 | rate_control_rate_init(sta); |
695 | 719 | ||
720 | layer2_update = sdata->vif.type == NL80211_IFTYPE_AP_VLAN || | ||
721 | sdata->vif.type == NL80211_IFTYPE_AP; | ||
722 | |||
696 | rcu_read_lock(); | 723 | rcu_read_lock(); |
697 | 724 | ||
698 | err = sta_info_insert(sta); | 725 | err = sta_info_insert(sta); |
699 | if (err) { | 726 | if (err) { |
700 | /* STA has been freed */ | 727 | /* STA has been freed */ |
728 | if (err == -EEXIST && layer2_update) { | ||
729 | /* Need to update layer 2 devices on reassociation */ | ||
730 | sta = sta_info_get(local, mac); | ||
731 | if (sta) | ||
732 | ieee80211_send_layer2_update(sta); | ||
733 | } | ||
701 | rcu_read_unlock(); | 734 | rcu_read_unlock(); |
702 | return err; | 735 | return err; |
703 | } | 736 | } |
704 | 737 | ||
705 | if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN || | 738 | if (layer2_update) |
706 | sdata->vif.type == NL80211_IFTYPE_AP) | ||
707 | ieee80211_send_layer2_update(sta); | 739 | ieee80211_send_layer2_update(sta); |
708 | 740 | ||
709 | rcu_read_unlock(); | 741 | rcu_read_unlock(); |
@@ -1099,12 +1131,12 @@ static int ieee80211_set_txq_params(struct wiphy *wiphy, | |||
1099 | 1131 | ||
1100 | static int ieee80211_set_channel(struct wiphy *wiphy, | 1132 | static int ieee80211_set_channel(struct wiphy *wiphy, |
1101 | struct ieee80211_channel *chan, | 1133 | struct ieee80211_channel *chan, |
1102 | enum nl80211_sec_chan_offset sec_chan_offset) | 1134 | enum nl80211_channel_type channel_type) |
1103 | { | 1135 | { |
1104 | struct ieee80211_local *local = wiphy_priv(wiphy); | 1136 | struct ieee80211_local *local = wiphy_priv(wiphy); |
1105 | 1137 | ||
1106 | local->oper_channel = chan; | 1138 | local->oper_channel = chan; |
1107 | local->oper_sec_chan_offset = sec_chan_offset; | 1139 | local->oper_channel_type = channel_type; |
1108 | 1140 | ||
1109 | return ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); | 1141 | return ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_CHANNEL); |
1110 | } | 1142 | } |
diff --git a/net/mac80211/ht.c b/net/mac80211/ht.c index a1eed7032c9b..5f510a13b9f0 100644 --- a/net/mac80211/ht.c +++ b/net/mac80211/ht.c | |||
@@ -98,6 +98,7 @@ u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, | |||
98 | struct ieee80211_bss_ht_conf ht; | 98 | struct ieee80211_bss_ht_conf ht; |
99 | u32 changed = 0; | 99 | u32 changed = 0; |
100 | bool enable_ht = true, ht_changed; | 100 | bool enable_ht = true, ht_changed; |
101 | enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; | ||
101 | 102 | ||
102 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 103 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
103 | 104 | ||
@@ -112,24 +113,36 @@ u32 ieee80211_enable_ht(struct ieee80211_sub_if_data *sdata, | |||
112 | ieee80211_channel_to_frequency(hti->control_chan)) | 113 | ieee80211_channel_to_frequency(hti->control_chan)) |
113 | enable_ht = false; | 114 | enable_ht = false; |
114 | 115 | ||
115 | /* | 116 | if (enable_ht) { |
116 | * XXX: This is totally incorrect when there are multiple virtual | 117 | channel_type = NL80211_CHAN_HT20; |
117 | * interfaces, needs to be fixed later. | 118 | |
118 | */ | 119 | if (!(ap_ht_cap_flags & IEEE80211_HT_CAP_40MHZ_INTOLERANT) && |
119 | ht_changed = local->hw.conf.ht.enabled != enable_ht; | 120 | (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) && |
121 | (hti->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY)) { | ||
122 | switch(hti->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { | ||
123 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: | ||
124 | channel_type = NL80211_CHAN_HT40PLUS; | ||
125 | break; | ||
126 | case IEEE80211_HT_PARAM_CHA_SEC_BELOW: | ||
127 | channel_type = NL80211_CHAN_HT40MINUS; | ||
128 | break; | ||
129 | } | ||
130 | } | ||
131 | } | ||
132 | |||
133 | ht_changed = local->hw.conf.ht.enabled != enable_ht || | ||
134 | channel_type != local->hw.conf.ht.channel_type; | ||
135 | |||
136 | local->oper_channel_type = channel_type; | ||
120 | local->hw.conf.ht.enabled = enable_ht; | 137 | local->hw.conf.ht.enabled = enable_ht; |
138 | |||
121 | if (ht_changed) | 139 | if (ht_changed) |
122 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_HT); | 140 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_HT); |
123 | 141 | ||
124 | /* disable HT */ | 142 | /* disable HT */ |
125 | if (!enable_ht) | 143 | if (!enable_ht) |
126 | return 0; | 144 | return 0; |
127 | ht.secondary_channel_offset = | 145 | |
128 | hti->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET; | ||
129 | ht.width_40_ok = | ||
130 | !(ap_ht_cap_flags & IEEE80211_HT_CAP_40MHZ_INTOLERANT) && | ||
131 | (sband->ht_cap.cap & IEEE80211_HT_CAP_SUP_WIDTH_20_40) && | ||
132 | (hti->ht_param & IEEE80211_HT_PARAM_CHAN_WIDTH_ANY); | ||
133 | ht.operation_mode = le16_to_cpu(hti->operation_mode); | 146 | ht.operation_mode = le16_to_cpu(hti->operation_mode); |
134 | 147 | ||
135 | /* if bss configuration changed store the new one */ | 148 | /* if bss configuration changed store the new one */ |
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 6f59e11d7b33..f3eec989662b 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h | |||
@@ -538,6 +538,11 @@ enum { | |||
538 | IEEE80211_ADDBA_MSG = 4, | 538 | IEEE80211_ADDBA_MSG = 4, |
539 | }; | 539 | }; |
540 | 540 | ||
541 | enum queue_stop_reason { | ||
542 | IEEE80211_QUEUE_STOP_REASON_DRIVER, | ||
543 | IEEE80211_QUEUE_STOP_REASON_PS, | ||
544 | }; | ||
545 | |||
541 | /* maximum number of hardware queues we support. */ | 546 | /* maximum number of hardware queues we support. */ |
542 | #define QD_MAX_QUEUES (IEEE80211_MAX_AMPDU_QUEUES + IEEE80211_MAX_QUEUES) | 547 | #define QD_MAX_QUEUES (IEEE80211_MAX_AMPDU_QUEUES + IEEE80211_MAX_QUEUES) |
543 | 548 | ||
@@ -554,7 +559,8 @@ struct ieee80211_local { | |||
554 | const struct ieee80211_ops *ops; | 559 | const struct ieee80211_ops *ops; |
555 | 560 | ||
556 | unsigned long queue_pool[BITS_TO_LONGS(QD_MAX_QUEUES)]; | 561 | unsigned long queue_pool[BITS_TO_LONGS(QD_MAX_QUEUES)]; |
557 | 562 | unsigned long queue_stop_reasons[IEEE80211_MAX_QUEUES]; | |
563 | spinlock_t queue_stop_reason_lock; | ||
558 | struct net_device *mdev; /* wmaster# - "master" 802.11 device */ | 564 | struct net_device *mdev; /* wmaster# - "master" 802.11 device */ |
559 | int open_count; | 565 | int open_count; |
560 | int monitors, cooked_mntrs; | 566 | int monitors, cooked_mntrs; |
@@ -625,7 +631,7 @@ struct ieee80211_local { | |||
625 | struct delayed_work scan_work; | 631 | struct delayed_work scan_work; |
626 | struct ieee80211_sub_if_data *scan_sdata; | 632 | struct ieee80211_sub_if_data *scan_sdata; |
627 | struct ieee80211_channel *oper_channel, *scan_channel; | 633 | struct ieee80211_channel *oper_channel, *scan_channel; |
628 | enum nl80211_sec_chan_offset oper_sec_chan_offset; | 634 | enum nl80211_channel_type oper_channel_type; |
629 | u8 scan_ssid[IEEE80211_MAX_SSID_LEN]; | 635 | u8 scan_ssid[IEEE80211_MAX_SSID_LEN]; |
630 | size_t scan_ssid_len; | 636 | size_t scan_ssid_len; |
631 | struct list_head bss_list; | 637 | struct list_head bss_list; |
@@ -689,6 +695,12 @@ struct ieee80211_local { | |||
689 | int wifi_wme_noack_test; | 695 | int wifi_wme_noack_test; |
690 | unsigned int wmm_acm; /* bit field of ACM bits (BIT(802.1D tag)) */ | 696 | unsigned int wmm_acm; /* bit field of ACM bits (BIT(802.1D tag)) */ |
691 | 697 | ||
698 | bool powersave; | ||
699 | int dynamic_ps_timeout; | ||
700 | struct work_struct dynamic_ps_enable_work; | ||
701 | struct work_struct dynamic_ps_disable_work; | ||
702 | struct timer_list dynamic_ps_timer; | ||
703 | |||
692 | #ifdef CONFIG_MAC80211_DEBUGFS | 704 | #ifdef CONFIG_MAC80211_DEBUGFS |
693 | struct local_debugfsdentries { | 705 | struct local_debugfsdentries { |
694 | struct dentry *rcdir; | 706 | struct dentry *rcdir; |
@@ -971,6 +983,15 @@ int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freq); | |||
971 | u64 ieee80211_mandatory_rates(struct ieee80211_local *local, | 983 | u64 ieee80211_mandatory_rates(struct ieee80211_local *local, |
972 | enum ieee80211_band band); | 984 | enum ieee80211_band band); |
973 | 985 | ||
986 | void ieee80211_dynamic_ps_enable_work(struct work_struct *work); | ||
987 | void ieee80211_dynamic_ps_disable_work(struct work_struct *work); | ||
988 | void ieee80211_dynamic_ps_timer(unsigned long data); | ||
989 | |||
990 | void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, | ||
991 | enum queue_stop_reason reason); | ||
992 | void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw, | ||
993 | enum queue_stop_reason reason); | ||
994 | |||
974 | #ifdef CONFIG_MAC80211_NOINLINE | 995 | #ifdef CONFIG_MAC80211_NOINLINE |
975 | #define debug_noinline noinline | 996 | #define debug_noinline noinline |
976 | #else | 997 | #else |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 6d8710327d14..24b14363d6e7 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -195,37 +195,30 @@ int ieee80211_hw_config(struct ieee80211_local *local, u32 changed) | |||
195 | struct ieee80211_channel *chan; | 195 | struct ieee80211_channel *chan; |
196 | int ret = 0; | 196 | int ret = 0; |
197 | int power; | 197 | int power; |
198 | enum nl80211_sec_chan_offset sec_chan_offset; | 198 | enum nl80211_channel_type channel_type; |
199 | 199 | ||
200 | might_sleep(); | 200 | might_sleep(); |
201 | 201 | ||
202 | if (local->sw_scanning) { | 202 | if (local->sw_scanning) { |
203 | chan = local->scan_channel; | 203 | chan = local->scan_channel; |
204 | sec_chan_offset = NL80211_SEC_CHAN_NO_HT; | 204 | channel_type = NL80211_CHAN_NO_HT; |
205 | } else { | 205 | } else { |
206 | chan = local->oper_channel; | 206 | chan = local->oper_channel; |
207 | sec_chan_offset = local->oper_sec_chan_offset; | 207 | channel_type = local->oper_channel_type; |
208 | } | 208 | } |
209 | 209 | ||
210 | if (chan != local->hw.conf.channel || | 210 | if (chan != local->hw.conf.channel || |
211 | sec_chan_offset != local->hw.conf.ht.sec_chan_offset) { | 211 | channel_type != local->hw.conf.ht.channel_type) { |
212 | local->hw.conf.channel = chan; | 212 | local->hw.conf.channel = chan; |
213 | switch (sec_chan_offset) { | 213 | local->hw.conf.ht.channel_type = channel_type; |
214 | case NL80211_SEC_CHAN_NO_HT: | 214 | switch (channel_type) { |
215 | case NL80211_CHAN_NO_HT: | ||
215 | local->hw.conf.ht.enabled = false; | 216 | local->hw.conf.ht.enabled = false; |
216 | local->hw.conf.ht.sec_chan_offset = 0; | ||
217 | break; | 217 | break; |
218 | case NL80211_SEC_CHAN_DISABLED: | 218 | case NL80211_CHAN_HT20: |
219 | case NL80211_CHAN_HT40MINUS: | ||
220 | case NL80211_CHAN_HT40PLUS: | ||
219 | local->hw.conf.ht.enabled = true; | 221 | local->hw.conf.ht.enabled = true; |
220 | local->hw.conf.ht.sec_chan_offset = 0; | ||
221 | break; | ||
222 | case NL80211_SEC_CHAN_BELOW: | ||
223 | local->hw.conf.ht.enabled = true; | ||
224 | local->hw.conf.ht.sec_chan_offset = -1; | ||
225 | break; | ||
226 | case NL80211_SEC_CHAN_ABOVE: | ||
227 | local->hw.conf.ht.enabled = true; | ||
228 | local->hw.conf.ht.sec_chan_offset = 1; | ||
229 | break; | 222 | break; |
230 | } | 223 | } |
231 | changed |= IEEE80211_CONF_CHANGE_CHANNEL; | 224 | changed |= IEEE80211_CONF_CHANGE_CHANNEL; |
@@ -348,7 +341,8 @@ static void ieee80211_tasklet_handler(unsigned long data) | |||
348 | dev_kfree_skb(skb); | 341 | dev_kfree_skb(skb); |
349 | break ; | 342 | break ; |
350 | default: | 343 | default: |
351 | WARN_ON(1); | 344 | WARN(1, "mac80211: Packet is of unknown type %d\n", |
345 | skb->pkt_type); | ||
352 | dev_kfree_skb(skb); | 346 | dev_kfree_skb(skb); |
353 | break; | 347 | break; |
354 | } | 348 | } |
@@ -731,8 +725,17 @@ struct ieee80211_hw *ieee80211_alloc_hw(size_t priv_data_len, | |||
731 | 725 | ||
732 | spin_lock_init(&local->key_lock); | 726 | spin_lock_init(&local->key_lock); |
733 | 727 | ||
728 | spin_lock_init(&local->queue_stop_reason_lock); | ||
729 | |||
734 | INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work); | 730 | INIT_DELAYED_WORK(&local->scan_work, ieee80211_scan_work); |
735 | 731 | ||
732 | INIT_WORK(&local->dynamic_ps_enable_work, | ||
733 | ieee80211_dynamic_ps_enable_work); | ||
734 | INIT_WORK(&local->dynamic_ps_disable_work, | ||
735 | ieee80211_dynamic_ps_disable_work); | ||
736 | setup_timer(&local->dynamic_ps_timer, | ||
737 | ieee80211_dynamic_ps_timer, (unsigned long) local); | ||
738 | |||
736 | sta_info_init(local); | 739 | sta_info_init(local); |
737 | 740 | ||
738 | tasklet_init(&local->tx_pending_tasklet, ieee80211_tx_pending, | 741 | tasklet_init(&local->tx_pending_tasklet, ieee80211_tx_pending, |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 290b0017ef2e..5ba721b6a399 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -309,7 +309,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, | |||
309 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | 309 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
310 | IEEE80211_STYPE_ASSOC_REQ); | 310 | IEEE80211_STYPE_ASSOC_REQ); |
311 | mgmt->u.assoc_req.capab_info = cpu_to_le16(capab); | 311 | mgmt->u.assoc_req.capab_info = cpu_to_le16(capab); |
312 | mgmt->u.reassoc_req.listen_interval = | 312 | mgmt->u.assoc_req.listen_interval = |
313 | cpu_to_le16(local->hw.conf.listen_interval); | 313 | cpu_to_le16(local->hw.conf.listen_interval); |
314 | } | 314 | } |
315 | 315 | ||
@@ -744,6 +744,17 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
744 | bss_info_changed |= BSS_CHANGED_BASIC_RATES; | 744 | bss_info_changed |= BSS_CHANGED_BASIC_RATES; |
745 | ieee80211_bss_info_change_notify(sdata, bss_info_changed); | 745 | ieee80211_bss_info_change_notify(sdata, bss_info_changed); |
746 | 746 | ||
747 | if (local->powersave) { | ||
748 | if (local->dynamic_ps_timeout > 0) | ||
749 | mod_timer(&local->dynamic_ps_timer, jiffies + | ||
750 | msecs_to_jiffies(local->dynamic_ps_timeout)); | ||
751 | else { | ||
752 | conf->flags |= IEEE80211_CONF_PS; | ||
753 | ieee80211_hw_config(local, | ||
754 | IEEE80211_CONF_CHANGE_PS); | ||
755 | } | ||
756 | } | ||
757 | |||
747 | netif_tx_start_all_queues(sdata->dev); | 758 | netif_tx_start_all_queues(sdata->dev); |
748 | netif_carrier_on(sdata->dev); | 759 | netif_carrier_on(sdata->dev); |
749 | 760 | ||
@@ -812,7 +823,7 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
812 | { | 823 | { |
813 | struct ieee80211_local *local = sdata->local; | 824 | struct ieee80211_local *local = sdata->local; |
814 | struct sta_info *sta; | 825 | struct sta_info *sta; |
815 | u32 changed = 0; | 826 | u32 changed = 0, config_changed = 0; |
816 | 827 | ||
817 | rcu_read_lock(); | 828 | rcu_read_lock(); |
818 | 829 | ||
@@ -858,8 +869,18 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
858 | rcu_read_unlock(); | 869 | rcu_read_unlock(); |
859 | 870 | ||
860 | local->hw.conf.ht.enabled = false; | 871 | local->hw.conf.ht.enabled = false; |
861 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_HT); | 872 | local->oper_channel_type = NL80211_CHAN_NO_HT; |
873 | config_changed |= IEEE80211_CONF_CHANGE_HT; | ||
874 | |||
875 | del_timer_sync(&local->dynamic_ps_timer); | ||
876 | cancel_work_sync(&local->dynamic_ps_enable_work); | ||
862 | 877 | ||
878 | if (local->hw.conf.flags & IEEE80211_CONF_PS) { | ||
879 | local->hw.conf.flags &= ~IEEE80211_CONF_PS; | ||
880 | config_changed |= IEEE80211_CONF_CHANGE_PS; | ||
881 | } | ||
882 | |||
883 | ieee80211_hw_config(local, config_changed); | ||
863 | ieee80211_bss_info_change_notify(sdata, changed); | 884 | ieee80211_bss_info_change_notify(sdata, changed); |
864 | 885 | ||
865 | rcu_read_lock(); | 886 | rcu_read_lock(); |
@@ -1612,8 +1633,13 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
1612 | * e.g: at 1 MBit that means mactime is 192 usec earlier | 1633 | * e.g: at 1 MBit that means mactime is 192 usec earlier |
1613 | * (=24 bytes * 8 usecs/byte) than the beacon timestamp. | 1634 | * (=24 bytes * 8 usecs/byte) than the beacon timestamp. |
1614 | */ | 1635 | */ |
1615 | int rate = local->hw.wiphy->bands[band]-> | 1636 | int rate; |
1637 | if (rx_status->flag & RX_FLAG_HT) { | ||
1638 | rate = 65; /* TODO: HT rates */ | ||
1639 | } else { | ||
1640 | rate = local->hw.wiphy->bands[band]-> | ||
1616 | bitrates[rx_status->rate_idx].bitrate; | 1641 | bitrates[rx_status->rate_idx].bitrate; |
1642 | } | ||
1617 | rx_timestamp = rx_status->mactime + (24 * 8 * 10 / rate); | 1643 | rx_timestamp = rx_status->mactime + (24 * 8 * 10 / rate); |
1618 | } else if (local && local->ops && local->ops->get_tsf) | 1644 | } else if (local && local->ops && local->ops->get_tsf) |
1619 | /* second best option: get current TSF */ | 1645 | /* second best option: get current TSF */ |
@@ -2576,3 +2602,39 @@ void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local) | |||
2576 | ieee80211_restart_sta_timer(sdata); | 2602 | ieee80211_restart_sta_timer(sdata); |
2577 | rcu_read_unlock(); | 2603 | rcu_read_unlock(); |
2578 | } | 2604 | } |
2605 | |||
2606 | void ieee80211_dynamic_ps_disable_work(struct work_struct *work) | ||
2607 | { | ||
2608 | struct ieee80211_local *local = | ||
2609 | container_of(work, struct ieee80211_local, | ||
2610 | dynamic_ps_disable_work); | ||
2611 | |||
2612 | if (local->hw.conf.flags & IEEE80211_CONF_PS) { | ||
2613 | local->hw.conf.flags &= ~IEEE80211_CONF_PS; | ||
2614 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); | ||
2615 | } | ||
2616 | |||
2617 | ieee80211_wake_queues_by_reason(&local->hw, | ||
2618 | IEEE80211_QUEUE_STOP_REASON_PS); | ||
2619 | } | ||
2620 | |||
2621 | void ieee80211_dynamic_ps_enable_work(struct work_struct *work) | ||
2622 | { | ||
2623 | struct ieee80211_local *local = | ||
2624 | container_of(work, struct ieee80211_local, | ||
2625 | dynamic_ps_enable_work); | ||
2626 | |||
2627 | if (local->hw.conf.flags & IEEE80211_CONF_PS) | ||
2628 | return; | ||
2629 | |||
2630 | local->hw.conf.flags |= IEEE80211_CONF_PS; | ||
2631 | |||
2632 | ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); | ||
2633 | } | ||
2634 | |||
2635 | void ieee80211_dynamic_ps_timer(unsigned long data) | ||
2636 | { | ||
2637 | struct ieee80211_local *local = (void *) data; | ||
2638 | |||
2639 | queue_work(local->hw.workqueue, &local->dynamic_ps_enable_work); | ||
2640 | } | ||
diff --git a/net/mac80211/rx.c b/net/mac80211/rx.c index 73cf126cef49..7175ae80c36a 100644 --- a/net/mac80211/rx.c +++ b/net/mac80211/rx.c | |||
@@ -123,7 +123,6 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
123 | /* radiotap header, set always present flags */ | 123 | /* radiotap header, set always present flags */ |
124 | rthdr->it_present = | 124 | rthdr->it_present = |
125 | cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) | | 125 | cpu_to_le32((1 << IEEE80211_RADIOTAP_FLAGS) | |
126 | (1 << IEEE80211_RADIOTAP_RATE) | | ||
127 | (1 << IEEE80211_RADIOTAP_CHANNEL) | | 126 | (1 << IEEE80211_RADIOTAP_CHANNEL) | |
128 | (1 << IEEE80211_RADIOTAP_ANTENNA) | | 127 | (1 << IEEE80211_RADIOTAP_ANTENNA) | |
129 | (1 << IEEE80211_RADIOTAP_RX_FLAGS)); | 128 | (1 << IEEE80211_RADIOTAP_RX_FLAGS)); |
@@ -149,7 +148,19 @@ ieee80211_add_rx_radiotap_header(struct ieee80211_local *local, | |||
149 | pos++; | 148 | pos++; |
150 | 149 | ||
151 | /* IEEE80211_RADIOTAP_RATE */ | 150 | /* IEEE80211_RADIOTAP_RATE */ |
152 | *pos = rate->bitrate / 5; | 151 | if (status->flag & RX_FLAG_HT) { |
152 | /* | ||
153 | * TODO: add following information into radiotap header once | ||
154 | * suitable fields are defined for it: | ||
155 | * - MCS index (status->rate_idx) | ||
156 | * - HT40 (status->flag & RX_FLAG_40MHZ) | ||
157 | * - short-GI (status->flag & RX_FLAG_SHORT_GI) | ||
158 | */ | ||
159 | *pos = 0; | ||
160 | } else { | ||
161 | rthdr->it_present |= (1 << IEEE80211_RADIOTAP_RATE); | ||
162 | *pos = rate->bitrate / 5; | ||
163 | } | ||
153 | pos++; | 164 | pos++; |
154 | 165 | ||
155 | /* IEEE80211_RADIOTAP_CHANNEL */ | 166 | /* IEEE80211_RADIOTAP_CHANNEL */ |
@@ -1849,9 +1860,15 @@ static int prepare_for_handlers(struct ieee80211_sub_if_data *sdata, | |||
1849 | if (!(sdata->dev->flags & IFF_PROMISC)) | 1860 | if (!(sdata->dev->flags & IFF_PROMISC)) |
1850 | return 0; | 1861 | return 0; |
1851 | rx->flags &= ~IEEE80211_RX_RA_MATCH; | 1862 | rx->flags &= ~IEEE80211_RX_RA_MATCH; |
1852 | } else if (!rx->sta) | 1863 | } else if (!rx->sta) { |
1864 | int rate_idx; | ||
1865 | if (rx->status->flag & RX_FLAG_HT) | ||
1866 | rate_idx = 0; /* TODO: HT rates */ | ||
1867 | else | ||
1868 | rate_idx = rx->status->rate_idx; | ||
1853 | rx->sta = ieee80211_ibss_add_sta(sdata, bssid, hdr->addr2, | 1869 | rx->sta = ieee80211_ibss_add_sta(sdata, bssid, hdr->addr2, |
1854 | BIT(rx->status->rate_idx)); | 1870 | BIT(rate_idx)); |
1871 | } | ||
1855 | break; | 1872 | break; |
1856 | case NL80211_IFTYPE_MESH_POINT: | 1873 | case NL80211_IFTYPE_MESH_POINT: |
1857 | if (!multicast && | 1874 | if (!multicast && |
@@ -2057,7 +2074,13 @@ static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, | |||
2057 | tid_agg_rx->reorder_buf[index]->cb, | 2074 | tid_agg_rx->reorder_buf[index]->cb, |
2058 | sizeof(status)); | 2075 | sizeof(status)); |
2059 | sband = local->hw.wiphy->bands[status.band]; | 2076 | sband = local->hw.wiphy->bands[status.band]; |
2060 | rate = &sband->bitrates[status.rate_idx]; | 2077 | if (status.flag & RX_FLAG_HT) { |
2078 | /* TODO: HT rates */ | ||
2079 | rate = sband->bitrates; | ||
2080 | } else { | ||
2081 | rate = &sband->bitrates | ||
2082 | [status.rate_idx]; | ||
2083 | } | ||
2061 | __ieee80211_rx_handle_packet(hw, | 2084 | __ieee80211_rx_handle_packet(hw, |
2062 | tid_agg_rx->reorder_buf[index], | 2085 | tid_agg_rx->reorder_buf[index], |
2063 | &status, rate); | 2086 | &status, rate); |
@@ -2101,7 +2124,10 @@ static u8 ieee80211_sta_manage_reorder_buf(struct ieee80211_hw *hw, | |||
2101 | memcpy(&status, tid_agg_rx->reorder_buf[index]->cb, | 2124 | memcpy(&status, tid_agg_rx->reorder_buf[index]->cb, |
2102 | sizeof(status)); | 2125 | sizeof(status)); |
2103 | sband = local->hw.wiphy->bands[status.band]; | 2126 | sband = local->hw.wiphy->bands[status.band]; |
2104 | rate = &sband->bitrates[status.rate_idx]; | 2127 | if (status.flag & RX_FLAG_HT) |
2128 | rate = sband->bitrates; /* TODO: HT rates */ | ||
2129 | else | ||
2130 | rate = &sband->bitrates[status.rate_idx]; | ||
2105 | __ieee80211_rx_handle_packet(hw, tid_agg_rx->reorder_buf[index], | 2131 | __ieee80211_rx_handle_packet(hw, tid_agg_rx->reorder_buf[index], |
2106 | &status, rate); | 2132 | &status, rate); |
2107 | tid_agg_rx->stored_mpdu_num--; | 2133 | tid_agg_rx->stored_mpdu_num--; |
@@ -2189,15 +2215,26 @@ void __ieee80211_rx(struct ieee80211_hw *hw, struct sk_buff *skb, | |||
2189 | } | 2215 | } |
2190 | 2216 | ||
2191 | sband = local->hw.wiphy->bands[status->band]; | 2217 | sband = local->hw.wiphy->bands[status->band]; |
2192 | 2218 | if (!sband) { | |
2193 | if (!sband || | ||
2194 | status->rate_idx < 0 || | ||
2195 | status->rate_idx >= sband->n_bitrates) { | ||
2196 | WARN_ON(1); | 2219 | WARN_ON(1); |
2197 | return; | 2220 | return; |
2198 | } | 2221 | } |
2199 | 2222 | ||
2200 | rate = &sband->bitrates[status->rate_idx]; | 2223 | if (status->flag & RX_FLAG_HT) { |
2224 | /* rate_idx is MCS index */ | ||
2225 | if (WARN_ON(status->rate_idx < 0 || | ||
2226 | status->rate_idx >= 76)) | ||
2227 | return; | ||
2228 | /* HT rates are not in the table - use the highest legacy rate | ||
2229 | * for now since other parts of mac80211 may not yet be fully | ||
2230 | * MCS aware. */ | ||
2231 | rate = &sband->bitrates[sband->n_bitrates - 1]; | ||
2232 | } else { | ||
2233 | if (WARN_ON(status->rate_idx < 0 || | ||
2234 | status->rate_idx >= sband->n_bitrates)) | ||
2235 | return; | ||
2236 | rate = &sband->bitrates[status->rate_idx]; | ||
2237 | } | ||
2201 | 2238 | ||
2202 | /* | 2239 | /* |
2203 | * key references and virtual interfaces are protected using RCU | 2240 | * key references and virtual interfaces are protected using RCU |
diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c index b098c58d216f..a4af3a124cce 100644 --- a/net/mac80211/tx.c +++ b/net/mac80211/tx.c | |||
@@ -1473,6 +1473,19 @@ int ieee80211_subif_start_xmit(struct sk_buff *skb, | |||
1473 | goto fail; | 1473 | goto fail; |
1474 | } | 1474 | } |
1475 | 1475 | ||
1476 | if (!(local->hw.flags & IEEE80211_HW_NO_STACK_DYNAMIC_PS) && | ||
1477 | local->dynamic_ps_timeout > 0) { | ||
1478 | if (local->hw.conf.flags & IEEE80211_CONF_PS) { | ||
1479 | ieee80211_stop_queues_by_reason(&local->hw, | ||
1480 | IEEE80211_QUEUE_STOP_REASON_PS); | ||
1481 | queue_work(local->hw.workqueue, | ||
1482 | &local->dynamic_ps_disable_work); | ||
1483 | } | ||
1484 | |||
1485 | mod_timer(&local->dynamic_ps_timer, jiffies + | ||
1486 | msecs_to_jiffies(local->dynamic_ps_timeout)); | ||
1487 | } | ||
1488 | |||
1476 | nh_pos = skb_network_header(skb) - skb->data; | 1489 | nh_pos = skb_network_header(skb) - skb->data; |
1477 | h_pos = skb_transport_header(skb) - skb->data; | 1490 | h_pos = skb_transport_header(skb) - skb->data; |
1478 | 1491 | ||
diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 505d68f344ce..fb89e1d0aa03 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c | |||
@@ -330,10 +330,20 @@ __le16 ieee80211_ctstoself_duration(struct ieee80211_hw *hw, | |||
330 | } | 330 | } |
331 | EXPORT_SYMBOL(ieee80211_ctstoself_duration); | 331 | EXPORT_SYMBOL(ieee80211_ctstoself_duration); |
332 | 332 | ||
333 | void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue) | 333 | static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue, |
334 | enum queue_stop_reason reason) | ||
334 | { | 335 | { |
335 | struct ieee80211_local *local = hw_to_local(hw); | 336 | struct ieee80211_local *local = hw_to_local(hw); |
336 | 337 | ||
338 | /* we don't need to track ampdu queues */ | ||
339 | if (queue < ieee80211_num_regular_queues(hw)) { | ||
340 | __clear_bit(reason, &local->queue_stop_reasons[queue]); | ||
341 | |||
342 | if (local->queue_stop_reasons[queue] != 0) | ||
343 | /* someone still has this queue stopped */ | ||
344 | return; | ||
345 | } | ||
346 | |||
337 | if (test_bit(queue, local->queues_pending)) { | 347 | if (test_bit(queue, local->queues_pending)) { |
338 | set_bit(queue, local->queues_pending_run); | 348 | set_bit(queue, local->queues_pending_run); |
339 | tasklet_schedule(&local->tx_pending_tasklet); | 349 | tasklet_schedule(&local->tx_pending_tasklet); |
@@ -341,22 +351,74 @@ void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue) | |||
341 | netif_wake_subqueue(local->mdev, queue); | 351 | netif_wake_subqueue(local->mdev, queue); |
342 | } | 352 | } |
343 | } | 353 | } |
354 | |||
355 | void ieee80211_wake_queue_by_reason(struct ieee80211_hw *hw, int queue, | ||
356 | enum queue_stop_reason reason) | ||
357 | { | ||
358 | struct ieee80211_local *local = hw_to_local(hw); | ||
359 | unsigned long flags; | ||
360 | |||
361 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | ||
362 | __ieee80211_wake_queue(hw, queue, reason); | ||
363 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | ||
364 | } | ||
365 | |||
366 | void ieee80211_wake_queue(struct ieee80211_hw *hw, int queue) | ||
367 | { | ||
368 | ieee80211_wake_queue_by_reason(hw, queue, | ||
369 | IEEE80211_QUEUE_STOP_REASON_DRIVER); | ||
370 | } | ||
344 | EXPORT_SYMBOL(ieee80211_wake_queue); | 371 | EXPORT_SYMBOL(ieee80211_wake_queue); |
345 | 372 | ||
346 | void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue) | 373 | static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue, |
374 | enum queue_stop_reason reason) | ||
347 | { | 375 | { |
348 | struct ieee80211_local *local = hw_to_local(hw); | 376 | struct ieee80211_local *local = hw_to_local(hw); |
349 | 377 | ||
378 | /* we don't need to track ampdu queues */ | ||
379 | if (queue < ieee80211_num_regular_queues(hw)) | ||
380 | __set_bit(reason, &local->queue_stop_reasons[queue]); | ||
381 | |||
350 | netif_stop_subqueue(local->mdev, queue); | 382 | netif_stop_subqueue(local->mdev, queue); |
351 | } | 383 | } |
384 | |||
385 | void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue, | ||
386 | enum queue_stop_reason reason) | ||
387 | { | ||
388 | struct ieee80211_local *local = hw_to_local(hw); | ||
389 | unsigned long flags; | ||
390 | |||
391 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | ||
392 | __ieee80211_stop_queue(hw, queue, reason); | ||
393 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | ||
394 | } | ||
395 | |||
396 | void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue) | ||
397 | { | ||
398 | ieee80211_stop_queue_by_reason(hw, queue, | ||
399 | IEEE80211_QUEUE_STOP_REASON_DRIVER); | ||
400 | } | ||
352 | EXPORT_SYMBOL(ieee80211_stop_queue); | 401 | EXPORT_SYMBOL(ieee80211_stop_queue); |
353 | 402 | ||
354 | void ieee80211_stop_queues(struct ieee80211_hw *hw) | 403 | void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw, |
404 | enum queue_stop_reason reason) | ||
355 | { | 405 | { |
406 | struct ieee80211_local *local = hw_to_local(hw); | ||
407 | unsigned long flags; | ||
356 | int i; | 408 | int i; |
357 | 409 | ||
410 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | ||
411 | |||
358 | for (i = 0; i < ieee80211_num_queues(hw); i++) | 412 | for (i = 0; i < ieee80211_num_queues(hw); i++) |
359 | ieee80211_stop_queue(hw, i); | 413 | __ieee80211_stop_queue(hw, i, reason); |
414 | |||
415 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | ||
416 | } | ||
417 | |||
418 | void ieee80211_stop_queues(struct ieee80211_hw *hw) | ||
419 | { | ||
420 | ieee80211_stop_queues_by_reason(hw, | ||
421 | IEEE80211_QUEUE_STOP_REASON_DRIVER); | ||
360 | } | 422 | } |
361 | EXPORT_SYMBOL(ieee80211_stop_queues); | 423 | EXPORT_SYMBOL(ieee80211_stop_queues); |
362 | 424 | ||
@@ -367,12 +429,24 @@ int ieee80211_queue_stopped(struct ieee80211_hw *hw, int queue) | |||
367 | } | 429 | } |
368 | EXPORT_SYMBOL(ieee80211_queue_stopped); | 430 | EXPORT_SYMBOL(ieee80211_queue_stopped); |
369 | 431 | ||
370 | void ieee80211_wake_queues(struct ieee80211_hw *hw) | 432 | void ieee80211_wake_queues_by_reason(struct ieee80211_hw *hw, |
433 | enum queue_stop_reason reason) | ||
371 | { | 434 | { |
435 | struct ieee80211_local *local = hw_to_local(hw); | ||
436 | unsigned long flags; | ||
372 | int i; | 437 | int i; |
373 | 438 | ||
439 | spin_lock_irqsave(&local->queue_stop_reason_lock, flags); | ||
440 | |||
374 | for (i = 0; i < hw->queues + hw->ampdu_queues; i++) | 441 | for (i = 0; i < hw->queues + hw->ampdu_queues; i++) |
375 | ieee80211_wake_queue(hw, i); | 442 | __ieee80211_wake_queue(hw, i, reason); |
443 | |||
444 | spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags); | ||
445 | } | ||
446 | |||
447 | void ieee80211_wake_queues(struct ieee80211_hw *hw) | ||
448 | { | ||
449 | ieee80211_wake_queues_by_reason(hw, IEEE80211_QUEUE_STOP_REASON_DRIVER); | ||
376 | } | 450 | } |
377 | EXPORT_SYMBOL(ieee80211_wake_queues); | 451 | EXPORT_SYMBOL(ieee80211_wake_queues); |
378 | 452 | ||
@@ -641,7 +715,7 @@ int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freqMHz) | |||
641 | chan->flags & IEEE80211_CHAN_NO_IBSS) | 715 | chan->flags & IEEE80211_CHAN_NO_IBSS) |
642 | return ret; | 716 | return ret; |
643 | local->oper_channel = chan; | 717 | local->oper_channel = chan; |
644 | local->oper_sec_chan_offset = NL80211_SEC_CHAN_NO_HT; | 718 | local->oper_channel_type = NL80211_CHAN_NO_HT; |
645 | 719 | ||
646 | if (local->sw_scanning || local->hw_scanning) | 720 | if (local->sw_scanning || local->hw_scanning) |
647 | ret = 0; | 721 | ret = 0; |
diff --git a/net/mac80211/wext.c b/net/mac80211/wext.c index 15428048d01a..7162d5816f39 100644 --- a/net/mac80211/wext.c +++ b/net/mac80211/wext.c | |||
@@ -830,25 +830,56 @@ static int ieee80211_ioctl_siwpower(struct net_device *dev, | |||
830 | struct iw_param *wrq, | 830 | struct iw_param *wrq, |
831 | char *extra) | 831 | char *extra) |
832 | { | 832 | { |
833 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
833 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 834 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
834 | struct ieee80211_conf *conf = &local->hw.conf; | 835 | struct ieee80211_conf *conf = &local->hw.conf; |
836 | int ret = 0, timeout = 0; | ||
837 | bool ps; | ||
838 | |||
839 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | ||
840 | return -EINVAL; | ||
835 | 841 | ||
836 | if (wrq->disabled) { | 842 | if (wrq->disabled) { |
837 | conf->flags &= ~IEEE80211_CONF_PS; | 843 | ps = false; |
838 | return ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); | 844 | timeout = 0; |
845 | goto set; | ||
839 | } | 846 | } |
840 | 847 | ||
841 | switch (wrq->flags & IW_POWER_MODE) { | 848 | switch (wrq->flags & IW_POWER_MODE) { |
842 | case IW_POWER_ON: /* If not specified */ | 849 | case IW_POWER_ON: /* If not specified */ |
843 | case IW_POWER_MODE: /* If set all mask */ | 850 | case IW_POWER_MODE: /* If set all mask */ |
844 | case IW_POWER_ALL_R: /* If explicitely state all */ | 851 | case IW_POWER_ALL_R: /* If explicitely state all */ |
845 | conf->flags |= IEEE80211_CONF_PS; | 852 | ps = true; |
853 | break; | ||
854 | default: /* Otherwise we ignore */ | ||
846 | break; | 855 | break; |
847 | default: /* Otherwise we don't support it */ | ||
848 | return -EINVAL; | ||
849 | } | 856 | } |
850 | 857 | ||
851 | return ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); | 858 | if (wrq->flags & IW_POWER_TIMEOUT) |
859 | timeout = wrq->value / 1000; | ||
860 | |||
861 | set: | ||
862 | if (ps == local->powersave && timeout == local->dynamic_ps_timeout) | ||
863 | return ret; | ||
864 | |||
865 | local->powersave = ps; | ||
866 | local->dynamic_ps_timeout = timeout; | ||
867 | |||
868 | if (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) { | ||
869 | if (!(local->hw.flags & IEEE80211_HW_NO_STACK_DYNAMIC_PS) && | ||
870 | local->dynamic_ps_timeout > 0) | ||
871 | mod_timer(&local->dynamic_ps_timer, jiffies + | ||
872 | msecs_to_jiffies(local->dynamic_ps_timeout)); | ||
873 | else { | ||
874 | if (local->powersave) | ||
875 | conf->flags |= IEEE80211_CONF_PS; | ||
876 | else | ||
877 | conf->flags &= ~IEEE80211_CONF_PS; | ||
878 | } | ||
879 | ret = ieee80211_hw_config(local, IEEE80211_CONF_CHANGE_PS); | ||
880 | } | ||
881 | |||
882 | return ret; | ||
852 | } | 883 | } |
853 | 884 | ||
854 | static int ieee80211_ioctl_giwpower(struct net_device *dev, | 885 | static int ieee80211_ioctl_giwpower(struct net_device *dev, |
@@ -857,9 +888,8 @@ static int ieee80211_ioctl_giwpower(struct net_device *dev, | |||
857 | char *extra) | 888 | char *extra) |
858 | { | 889 | { |
859 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); | 890 | struct ieee80211_local *local = wdev_priv(dev->ieee80211_ptr); |
860 | struct ieee80211_conf *conf = &local->hw.conf; | ||
861 | 891 | ||
862 | wrqu->power.disabled = !(conf->flags & IEEE80211_CONF_PS); | 892 | wrqu->power.disabled = !local->powersave; |
863 | 893 | ||
864 | return 0; | 894 | return 0; |
865 | } | 895 | } |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 4335f76be71f..1e728fff474e 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
@@ -60,7 +60,7 @@ static struct nla_policy nl80211_policy[NL80211_ATTR_MAX+1] __read_mostly = { | |||
60 | .len = BUS_ID_SIZE-1 }, | 60 | .len = BUS_ID_SIZE-1 }, |
61 | [NL80211_ATTR_WIPHY_TXQ_PARAMS] = { .type = NLA_NESTED }, | 61 | [NL80211_ATTR_WIPHY_TXQ_PARAMS] = { .type = NLA_NESTED }, |
62 | [NL80211_ATTR_WIPHY_FREQ] = { .type = NLA_U32 }, | 62 | [NL80211_ATTR_WIPHY_FREQ] = { .type = NLA_U32 }, |
63 | [NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET] = { .type = NLA_U32 }, | 63 | [NL80211_ATTR_WIPHY_CHANNEL_TYPE] = { .type = NLA_U32 }, |
64 | 64 | ||
65 | [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 }, | 65 | [NL80211_ATTR_IFTYPE] = { .type = NLA_U32 }, |
66 | [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 }, | 66 | [NL80211_ATTR_IFINDEX] = { .type = NLA_U32 }, |
@@ -362,8 +362,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
362 | } | 362 | } |
363 | 363 | ||
364 | if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { | 364 | if (info->attrs[NL80211_ATTR_WIPHY_FREQ]) { |
365 | enum nl80211_sec_chan_offset sec_chan_offset = | 365 | enum nl80211_channel_type channel_type = NL80211_CHAN_NO_HT; |
366 | NL80211_SEC_CHAN_NO_HT; | ||
367 | struct ieee80211_channel *chan; | 366 | struct ieee80211_channel *chan; |
368 | struct ieee80211_sta_ht_cap *ht_cap; | 367 | struct ieee80211_sta_ht_cap *ht_cap; |
369 | u32 freq, sec_freq; | 368 | u32 freq, sec_freq; |
@@ -375,13 +374,13 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
375 | 374 | ||
376 | result = -EINVAL; | 375 | result = -EINVAL; |
377 | 376 | ||
378 | if (info->attrs[NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET]) { | 377 | if (info->attrs[NL80211_ATTR_WIPHY_CHANNEL_TYPE]) { |
379 | sec_chan_offset = nla_get_u32(info->attrs[ | 378 | channel_type = nla_get_u32(info->attrs[ |
380 | NL80211_ATTR_WIPHY_SEC_CHAN_OFFSET]); | 379 | NL80211_ATTR_WIPHY_CHANNEL_TYPE]); |
381 | if (sec_chan_offset != NL80211_SEC_CHAN_NO_HT && | 380 | if (channel_type != NL80211_CHAN_NO_HT && |
382 | sec_chan_offset != NL80211_SEC_CHAN_DISABLED && | 381 | channel_type != NL80211_CHAN_HT20 && |
383 | sec_chan_offset != NL80211_SEC_CHAN_BELOW && | 382 | channel_type != NL80211_CHAN_HT40PLUS && |
384 | sec_chan_offset != NL80211_SEC_CHAN_ABOVE) | 383 | channel_type != NL80211_CHAN_HT40MINUS) |
385 | goto bad_res; | 384 | goto bad_res; |
386 | } | 385 | } |
387 | 386 | ||
@@ -392,9 +391,9 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
392 | if (!chan || chan->flags & IEEE80211_CHAN_DISABLED) | 391 | if (!chan || chan->flags & IEEE80211_CHAN_DISABLED) |
393 | goto bad_res; | 392 | goto bad_res; |
394 | 393 | ||
395 | if (sec_chan_offset == NL80211_SEC_CHAN_BELOW) | 394 | if (channel_type == NL80211_CHAN_HT40MINUS) |
396 | sec_freq = freq - 20; | 395 | sec_freq = freq - 20; |
397 | else if (sec_chan_offset == NL80211_SEC_CHAN_ABOVE) | 396 | else if (channel_type == NL80211_CHAN_HT40PLUS) |
398 | sec_freq = freq + 20; | 397 | sec_freq = freq + 20; |
399 | else | 398 | else |
400 | sec_freq = 0; | 399 | sec_freq = 0; |
@@ -402,7 +401,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
402 | ht_cap = &rdev->wiphy.bands[chan->band]->ht_cap; | 401 | ht_cap = &rdev->wiphy.bands[chan->band]->ht_cap; |
403 | 402 | ||
404 | /* no HT capabilities */ | 403 | /* no HT capabilities */ |
405 | if (sec_chan_offset != NL80211_SEC_CHAN_NO_HT && | 404 | if (channel_type != NL80211_CHAN_NO_HT && |
406 | !ht_cap->ht_supported) | 405 | !ht_cap->ht_supported) |
407 | goto bad_res; | 406 | goto bad_res; |
408 | 407 | ||
@@ -422,7 +421,7 @@ static int nl80211_set_wiphy(struct sk_buff *skb, struct genl_info *info) | |||
422 | } | 421 | } |
423 | 422 | ||
424 | result = rdev->ops->set_channel(&rdev->wiphy, chan, | 423 | result = rdev->ops->set_channel(&rdev->wiphy, chan, |
425 | sec_chan_offset); | 424 | channel_type); |
426 | if (result) | 425 | if (result) |
427 | goto bad_res; | 426 | goto bad_res; |
428 | } | 427 | } |
@@ -1091,12 +1090,46 @@ static int parse_station_flags(struct nlattr *nla, u32 *staflags) | |||
1091 | return 0; | 1090 | return 0; |
1092 | } | 1091 | } |
1093 | 1092 | ||
1093 | static u16 nl80211_calculate_bitrate(struct rate_info *rate) | ||
1094 | { | ||
1095 | int modulation, streams, bitrate; | ||
1096 | |||
1097 | if (!(rate->flags & RATE_INFO_FLAGS_MCS)) | ||
1098 | return rate->legacy; | ||
1099 | |||
1100 | /* the formula below does only work for MCS values smaller than 32 */ | ||
1101 | if (rate->mcs >= 32) | ||
1102 | return 0; | ||
1103 | |||
1104 | modulation = rate->mcs & 7; | ||
1105 | streams = (rate->mcs >> 3) + 1; | ||
1106 | |||
1107 | bitrate = (rate->flags & RATE_INFO_FLAGS_40_MHZ_WIDTH) ? | ||
1108 | 13500000 : 6500000; | ||
1109 | |||
1110 | if (modulation < 4) | ||
1111 | bitrate *= (modulation + 1); | ||
1112 | else if (modulation == 4) | ||
1113 | bitrate *= (modulation + 2); | ||
1114 | else | ||
1115 | bitrate *= (modulation + 3); | ||
1116 | |||
1117 | bitrate *= streams; | ||
1118 | |||
1119 | if (rate->flags & RATE_INFO_FLAGS_SHORT_GI) | ||
1120 | bitrate = (bitrate / 9) * 10; | ||
1121 | |||
1122 | /* do NOT round down here */ | ||
1123 | return (bitrate + 50000) / 100000; | ||
1124 | } | ||
1125 | |||
1094 | static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq, | 1126 | static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq, |
1095 | int flags, struct net_device *dev, | 1127 | int flags, struct net_device *dev, |
1096 | u8 *mac_addr, struct station_info *sinfo) | 1128 | u8 *mac_addr, struct station_info *sinfo) |
1097 | { | 1129 | { |
1098 | void *hdr; | 1130 | void *hdr; |
1099 | struct nlattr *sinfoattr; | 1131 | struct nlattr *sinfoattr, *txrate; |
1132 | u16 bitrate; | ||
1100 | 1133 | ||
1101 | hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION); | 1134 | hdr = nl80211hdr_put(msg, pid, seq, flags, NL80211_CMD_NEW_STATION); |
1102 | if (!hdr) | 1135 | if (!hdr) |
@@ -1126,7 +1159,29 @@ static int nl80211_send_station(struct sk_buff *msg, u32 pid, u32 seq, | |||
1126 | if (sinfo->filled & STATION_INFO_PLINK_STATE) | 1159 | if (sinfo->filled & STATION_INFO_PLINK_STATE) |
1127 | NLA_PUT_U8(msg, NL80211_STA_INFO_PLINK_STATE, | 1160 | NLA_PUT_U8(msg, NL80211_STA_INFO_PLINK_STATE, |
1128 | sinfo->plink_state); | 1161 | sinfo->plink_state); |
1162 | if (sinfo->filled & STATION_INFO_SIGNAL) | ||
1163 | NLA_PUT_U8(msg, NL80211_STA_INFO_SIGNAL, | ||
1164 | sinfo->signal); | ||
1165 | if (sinfo->filled & STATION_INFO_TX_BITRATE) { | ||
1166 | txrate = nla_nest_start(msg, NL80211_STA_INFO_TX_BITRATE); | ||
1167 | if (!txrate) | ||
1168 | goto nla_put_failure; | ||
1169 | |||
1170 | /* nl80211_calculate_bitrate will return 0 for mcs >= 32 */ | ||
1171 | bitrate = nl80211_calculate_bitrate(&sinfo->txrate); | ||
1172 | if (bitrate > 0) | ||
1173 | NLA_PUT_U16(msg, NL80211_RATE_INFO_BITRATE, bitrate); | ||
1129 | 1174 | ||
1175 | if (sinfo->txrate.flags & RATE_INFO_FLAGS_MCS) | ||
1176 | NLA_PUT_U8(msg, NL80211_RATE_INFO_MCS, | ||
1177 | sinfo->txrate.mcs); | ||
1178 | if (sinfo->txrate.flags & RATE_INFO_FLAGS_40_MHZ_WIDTH) | ||
1179 | NLA_PUT_FLAG(msg, NL80211_RATE_INFO_40_MHZ_WIDTH); | ||
1180 | if (sinfo->txrate.flags & RATE_INFO_FLAGS_SHORT_GI) | ||
1181 | NLA_PUT_FLAG(msg, NL80211_RATE_INFO_SHORT_GI); | ||
1182 | |||
1183 | nla_nest_end(msg, txrate); | ||
1184 | } | ||
1130 | nla_nest_end(msg, sinfoattr); | 1185 | nla_nest_end(msg, sinfoattr); |
1131 | 1186 | ||
1132 | return genlmsg_end(msg, hdr); | 1187 | return genlmsg_end(msg, hdr); |