diff options
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r-- | net/mac80211/mlme.c | 64 |
1 files changed, 50 insertions, 14 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index a5e5c31c23ab..4adba09e80ca 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -665,6 +665,26 @@ static void ieee80211_authenticate(struct net_device *dev, | |||
665 | mod_timer(&ifsta->timer, jiffies + IEEE80211_AUTH_TIMEOUT); | 665 | mod_timer(&ifsta->timer, jiffies + IEEE80211_AUTH_TIMEOUT); |
666 | } | 666 | } |
667 | 667 | ||
668 | static int ieee80211_compatible_rates(struct ieee80211_sta_bss *bss, | ||
669 | struct ieee80211_supported_band *sband, | ||
670 | u64 *rates) | ||
671 | { | ||
672 | int i, j, count; | ||
673 | *rates = 0; | ||
674 | count = 0; | ||
675 | for (i = 0; i < bss->supp_rates_len; i++) { | ||
676 | int rate = (bss->supp_rates[i] & 0x7F) * 5; | ||
677 | |||
678 | for (j = 0; j < sband->n_bitrates; j++) | ||
679 | if (sband->bitrates[j].bitrate == rate) { | ||
680 | *rates |= BIT(j); | ||
681 | count++; | ||
682 | break; | ||
683 | } | ||
684 | } | ||
685 | |||
686 | return count; | ||
687 | } | ||
668 | 688 | ||
669 | static void ieee80211_send_assoc(struct net_device *dev, | 689 | static void ieee80211_send_assoc(struct net_device *dev, |
670 | struct ieee80211_if_sta *ifsta) | 690 | struct ieee80211_if_sta *ifsta) |
@@ -673,11 +693,12 @@ static void ieee80211_send_assoc(struct net_device *dev, | |||
673 | struct sk_buff *skb; | 693 | struct sk_buff *skb; |
674 | struct ieee80211_mgmt *mgmt; | 694 | struct ieee80211_mgmt *mgmt; |
675 | u8 *pos, *ies; | 695 | u8 *pos, *ies; |
676 | int i, len; | 696 | int i, len, count, rates_len, supp_rates_len; |
677 | u16 capab; | 697 | u16 capab; |
678 | struct ieee80211_sta_bss *bss; | 698 | struct ieee80211_sta_bss *bss; |
679 | int wmm = 0; | 699 | int wmm = 0; |
680 | struct ieee80211_supported_band *sband; | 700 | struct ieee80211_supported_band *sband; |
701 | u64 rates = 0; | ||
681 | 702 | ||
682 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + | 703 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + |
683 | sizeof(*mgmt) + 200 + ifsta->extra_ie_len + | 704 | sizeof(*mgmt) + 200 + ifsta->extra_ie_len + |
@@ -740,24 +761,39 @@ static void ieee80211_send_assoc(struct net_device *dev, | |||
740 | *pos++ = ifsta->ssid_len; | 761 | *pos++ = ifsta->ssid_len; |
741 | memcpy(pos, ifsta->ssid, ifsta->ssid_len); | 762 | memcpy(pos, ifsta->ssid, ifsta->ssid_len); |
742 | 763 | ||
764 | /* all supported rates should be added here but some APs | ||
765 | * (e.g. D-Link DAP 1353 in b-only mode) don't like that | ||
766 | * Therefore only add rates the AP supports */ | ||
767 | rates_len = ieee80211_compatible_rates(bss, sband, &rates); | ||
768 | supp_rates_len = rates_len; | ||
769 | if (supp_rates_len > 8) | ||
770 | supp_rates_len = 8; | ||
771 | |||
743 | len = sband->n_bitrates; | 772 | len = sband->n_bitrates; |
744 | if (len > 8) | 773 | pos = skb_put(skb, supp_rates_len + 2); |
745 | len = 8; | ||
746 | pos = skb_put(skb, len + 2); | ||
747 | *pos++ = WLAN_EID_SUPP_RATES; | 774 | *pos++ = WLAN_EID_SUPP_RATES; |
748 | *pos++ = len; | 775 | *pos++ = supp_rates_len; |
749 | for (i = 0; i < len; i++) { | ||
750 | int rate = sband->bitrates[i].bitrate; | ||
751 | *pos++ = (u8) (rate / 5); | ||
752 | } | ||
753 | 776 | ||
754 | if (sband->n_bitrates > len) { | 777 | count = 0; |
755 | pos = skb_put(skb, sband->n_bitrates - len + 2); | 778 | for (i = 0; i < sband->n_bitrates; i++) { |
756 | *pos++ = WLAN_EID_EXT_SUPP_RATES; | 779 | if (BIT(i) & rates) { |
757 | *pos++ = sband->n_bitrates - len; | ||
758 | for (i = len; i < sband->n_bitrates; i++) { | ||
759 | int rate = sband->bitrates[i].bitrate; | 780 | int rate = sband->bitrates[i].bitrate; |
760 | *pos++ = (u8) (rate / 5); | 781 | *pos++ = (u8) (rate / 5); |
782 | if (++count == 8) | ||
783 | break; | ||
784 | } | ||
785 | } | ||
786 | |||
787 | if (count == 8) { | ||
788 | pos = skb_put(skb, rates_len - count + 2); | ||
789 | *pos++ = WLAN_EID_EXT_SUPP_RATES; | ||
790 | *pos++ = rates_len - count; | ||
791 | |||
792 | for (i++; i < sband->n_bitrates; i++) { | ||
793 | if (BIT(i) & rates) { | ||
794 | int rate = sband->bitrates[i].bitrate; | ||
795 | *pos++ = (u8) (rate / 5); | ||
796 | } | ||
761 | } | 797 | } |
762 | } | 798 | } |
763 | 799 | ||