diff options
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r-- | net/mac80211/mlme.c | 606 |
1 files changed, 342 insertions, 264 deletions
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 409bb7716236..5ba721b6a399 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -14,7 +14,6 @@ | |||
14 | #include <linux/delay.h> | 14 | #include <linux/delay.h> |
15 | #include <linux/if_ether.h> | 15 | #include <linux/if_ether.h> |
16 | #include <linux/skbuff.h> | 16 | #include <linux/skbuff.h> |
17 | #include <linux/netdevice.h> | ||
18 | #include <linux/if_arp.h> | 17 | #include <linux/if_arp.h> |
19 | #include <linux/wireless.h> | 18 | #include <linux/wireless.h> |
20 | #include <linux/random.h> | 19 | #include <linux/random.h> |
@@ -236,7 +235,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, | |||
236 | struct ieee80211_local *local = sdata->local; | 235 | struct ieee80211_local *local = sdata->local; |
237 | struct sk_buff *skb; | 236 | struct sk_buff *skb; |
238 | struct ieee80211_mgmt *mgmt; | 237 | struct ieee80211_mgmt *mgmt; |
239 | u8 *pos, *ies, *ht_add_ie; | 238 | u8 *pos, *ies, *ht_ie; |
240 | int i, len, count, rates_len, supp_rates_len; | 239 | int i, len, count, rates_len, supp_rates_len; |
241 | u16 capab; | 240 | u16 capab; |
242 | struct ieee80211_bss *bss; | 241 | struct ieee80211_bss *bss; |
@@ -310,7 +309,7 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, | |||
310 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | 309 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
311 | IEEE80211_STYPE_ASSOC_REQ); | 310 | IEEE80211_STYPE_ASSOC_REQ); |
312 | mgmt->u.assoc_req.capab_info = cpu_to_le16(capab); | 311 | mgmt->u.assoc_req.capab_info = cpu_to_le16(capab); |
313 | mgmt->u.reassoc_req.listen_interval = | 312 | mgmt->u.assoc_req.listen_interval = |
314 | cpu_to_le16(local->hw.conf.listen_interval); | 313 | cpu_to_le16(local->hw.conf.listen_interval); |
315 | } | 314 | } |
316 | 315 | ||
@@ -393,24 +392,25 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, | |||
393 | 392 | ||
394 | /* wmm support is a must to HT */ | 393 | /* wmm support is a must to HT */ |
395 | if (wmm && (ifsta->flags & IEEE80211_STA_WMM_ENABLED) && | 394 | if (wmm && (ifsta->flags & IEEE80211_STA_WMM_ENABLED) && |
396 | sband->ht_info.ht_supported && | 395 | sband->ht_cap.ht_supported && |
397 | (ht_add_ie = ieee80211_bss_get_ie(bss, WLAN_EID_HT_EXTRA_INFO))) { | 396 | (ht_ie = ieee80211_bss_get_ie(bss, WLAN_EID_HT_INFORMATION)) && |
398 | struct ieee80211_ht_addt_info *ht_add_info = | 397 | ht_ie[1] >= sizeof(struct ieee80211_ht_info)) { |
399 | (struct ieee80211_ht_addt_info *)ht_add_ie; | 398 | struct ieee80211_ht_info *ht_info = |
400 | u16 cap = sband->ht_info.cap; | 399 | (struct ieee80211_ht_info *)(ht_ie + 2); |
400 | u16 cap = sband->ht_cap.cap; | ||
401 | __le16 tmp; | 401 | __le16 tmp; |
402 | u32 flags = local->hw.conf.channel->flags; | 402 | u32 flags = local->hw.conf.channel->flags; |
403 | 403 | ||
404 | switch (ht_add_info->ht_param & IEEE80211_HT_IE_CHA_SEC_OFFSET) { | 404 | switch (ht_info->ht_param & IEEE80211_HT_PARAM_CHA_SEC_OFFSET) { |
405 | case IEEE80211_HT_IE_CHA_SEC_ABOVE: | 405 | case IEEE80211_HT_PARAM_CHA_SEC_ABOVE: |
406 | if (flags & IEEE80211_CHAN_NO_FAT_ABOVE) { | 406 | if (flags & IEEE80211_CHAN_NO_FAT_ABOVE) { |
407 | cap &= ~IEEE80211_HT_CAP_SUP_WIDTH; | 407 | cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; |
408 | cap &= ~IEEE80211_HT_CAP_SGI_40; | 408 | cap &= ~IEEE80211_HT_CAP_SGI_40; |
409 | } | 409 | } |
410 | break; | 410 | break; |
411 | case IEEE80211_HT_IE_CHA_SEC_BELOW: | 411 | case IEEE80211_HT_PARAM_CHA_SEC_BELOW: |
412 | if (flags & IEEE80211_CHAN_NO_FAT_BELOW) { | 412 | if (flags & IEEE80211_CHAN_NO_FAT_BELOW) { |
413 | cap &= ~IEEE80211_HT_CAP_SUP_WIDTH; | 413 | cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40; |
414 | cap &= ~IEEE80211_HT_CAP_SGI_40; | 414 | cap &= ~IEEE80211_HT_CAP_SGI_40; |
415 | } | 415 | } |
416 | break; | 416 | break; |
@@ -424,9 +424,9 @@ static void ieee80211_send_assoc(struct ieee80211_sub_if_data *sdata, | |||
424 | memcpy(pos, &tmp, sizeof(u16)); | 424 | memcpy(pos, &tmp, sizeof(u16)); |
425 | pos += sizeof(u16); | 425 | pos += sizeof(u16); |
426 | /* TODO: needs a define here for << 2 */ | 426 | /* TODO: needs a define here for << 2 */ |
427 | *pos++ = sband->ht_info.ampdu_factor | | 427 | *pos++ = sband->ht_cap.ampdu_factor | |
428 | (sband->ht_info.ampdu_density << 2); | 428 | (sband->ht_cap.ampdu_density << 2); |
429 | memcpy(pos, sband->ht_info.supp_mcs_set, 16); | 429 | memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs)); |
430 | } | 430 | } |
431 | 431 | ||
432 | kfree(ifsta->assocreq_ies); | 432 | kfree(ifsta->assocreq_ies); |
@@ -568,25 +568,35 @@ static void ieee80211_sta_wmm_params(struct ieee80211_local *local, | |||
568 | } | 568 | } |
569 | } | 569 | } |
570 | 570 | ||
571 | static u32 ieee80211_handle_protect_preamb(struct ieee80211_sub_if_data *sdata, | 571 | static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata, |
572 | bool use_protection, | 572 | u16 capab, bool erp_valid, u8 erp) |
573 | bool use_short_preamble) | ||
574 | { | 573 | { |
575 | struct ieee80211_bss_conf *bss_conf = &sdata->bss_conf; | 574 | struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; |
576 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 575 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
577 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; | 576 | struct ieee80211_if_sta *ifsta = &sdata->u.sta; |
578 | DECLARE_MAC_BUF(mac); | ||
579 | #endif | 577 | #endif |
580 | u32 changed = 0; | 578 | u32 changed = 0; |
579 | bool use_protection; | ||
580 | bool use_short_preamble; | ||
581 | bool use_short_slot; | ||
582 | |||
583 | if (erp_valid) { | ||
584 | use_protection = (erp & WLAN_ERP_USE_PROTECTION) != 0; | ||
585 | use_short_preamble = (erp & WLAN_ERP_BARKER_PREAMBLE) == 0; | ||
586 | } else { | ||
587 | use_protection = false; | ||
588 | use_short_preamble = !!(capab & WLAN_CAPABILITY_SHORT_PREAMBLE); | ||
589 | } | ||
590 | |||
591 | use_short_slot = !!(capab & WLAN_CAPABILITY_SHORT_SLOT_TIME); | ||
581 | 592 | ||
582 | if (use_protection != bss_conf->use_cts_prot) { | 593 | if (use_protection != bss_conf->use_cts_prot) { |
583 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 594 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
584 | if (net_ratelimit()) { | 595 | if (net_ratelimit()) { |
585 | printk(KERN_DEBUG "%s: CTS protection %s (BSSID=" | 596 | printk(KERN_DEBUG "%s: CTS protection %s (BSSID=%pM)\n", |
586 | "%s)\n", | ||
587 | sdata->dev->name, | 597 | sdata->dev->name, |
588 | use_protection ? "enabled" : "disabled", | 598 | use_protection ? "enabled" : "disabled", |
589 | print_mac(mac, ifsta->bssid)); | 599 | ifsta->bssid); |
590 | } | 600 | } |
591 | #endif | 601 | #endif |
592 | bss_conf->use_cts_prot = use_protection; | 602 | bss_conf->use_cts_prot = use_protection; |
@@ -597,40 +607,28 @@ static u32 ieee80211_handle_protect_preamb(struct ieee80211_sub_if_data *sdata, | |||
597 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 607 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
598 | if (net_ratelimit()) { | 608 | if (net_ratelimit()) { |
599 | printk(KERN_DEBUG "%s: switched to %s barker preamble" | 609 | printk(KERN_DEBUG "%s: switched to %s barker preamble" |
600 | " (BSSID=%s)\n", | 610 | " (BSSID=%pM)\n", |
601 | sdata->dev->name, | 611 | sdata->dev->name, |
602 | use_short_preamble ? "short" : "long", | 612 | use_short_preamble ? "short" : "long", |
603 | print_mac(mac, ifsta->bssid)); | 613 | ifsta->bssid); |
604 | } | 614 | } |
605 | #endif | 615 | #endif |
606 | bss_conf->use_short_preamble = use_short_preamble; | 616 | bss_conf->use_short_preamble = use_short_preamble; |
607 | changed |= BSS_CHANGED_ERP_PREAMBLE; | 617 | changed |= BSS_CHANGED_ERP_PREAMBLE; |
608 | } | 618 | } |
609 | 619 | ||
610 | return changed; | 620 | if (use_short_slot != bss_conf->use_short_slot) { |
611 | } | 621 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
612 | 622 | if (net_ratelimit()) { | |
613 | static u32 ieee80211_handle_erp_ie(struct ieee80211_sub_if_data *sdata, | 623 | printk(KERN_DEBUG "%s: switched to %s slot" |
614 | u8 erp_value) | 624 | " (BSSID=%s)\n", |
615 | { | 625 | sdata->dev->name, |
616 | bool use_protection = (erp_value & WLAN_ERP_USE_PROTECTION) != 0; | 626 | use_short_slot ? "short" : "long", |
617 | bool use_short_preamble = (erp_value & WLAN_ERP_BARKER_PREAMBLE) == 0; | 627 | ifsta->bssid); |
618 | 628 | } | |
619 | return ieee80211_handle_protect_preamb(sdata, | 629 | #endif |
620 | use_protection, use_short_preamble); | 630 | bss_conf->use_short_slot = use_short_slot; |
621 | } | 631 | changed |= BSS_CHANGED_ERP_SLOT; |
622 | |||
623 | static u32 ieee80211_handle_bss_capability(struct ieee80211_sub_if_data *sdata, | ||
624 | struct ieee80211_bss *bss) | ||
625 | { | ||
626 | u32 changed = 0; | ||
627 | |||
628 | if (bss->has_erp_value) | ||
629 | changed |= ieee80211_handle_erp_ie(sdata, bss->erp_value); | ||
630 | else { | ||
631 | u16 capab = bss->capability; | ||
632 | changed |= ieee80211_handle_protect_preamb(sdata, false, | ||
633 | (capab & WLAN_CAPABILITY_SHORT_PREAMBLE) != 0); | ||
634 | } | 632 | } |
635 | 633 | ||
636 | return changed; | 634 | return changed; |
@@ -701,14 +699,15 @@ static void ieee80211_sta_send_associnfo(struct ieee80211_sub_if_data *sdata, | |||
701 | 699 | ||
702 | 700 | ||
703 | static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | 701 | static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, |
704 | struct ieee80211_if_sta *ifsta) | 702 | struct ieee80211_if_sta *ifsta, |
703 | u32 bss_info_changed) | ||
705 | { | 704 | { |
706 | struct ieee80211_local *local = sdata->local; | 705 | struct ieee80211_local *local = sdata->local; |
707 | struct ieee80211_conf *conf = &local_to_hw(local)->conf; | 706 | struct ieee80211_conf *conf = &local_to_hw(local)->conf; |
708 | u32 changed = BSS_CHANGED_ASSOC; | ||
709 | 707 | ||
710 | struct ieee80211_bss *bss; | 708 | struct ieee80211_bss *bss; |
711 | 709 | ||
710 | bss_info_changed |= BSS_CHANGED_ASSOC; | ||
712 | ifsta->flags |= IEEE80211_STA_ASSOCIATED; | 711 | ifsta->flags |= IEEE80211_STA_ASSOCIATED; |
713 | 712 | ||
714 | if (sdata->vif.type != NL80211_IFTYPE_STATION) | 713 | if (sdata->vif.type != NL80211_IFTYPE_STATION) |
@@ -719,22 +718,16 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
719 | ifsta->ssid, ifsta->ssid_len); | 718 | ifsta->ssid, ifsta->ssid_len); |
720 | if (bss) { | 719 | if (bss) { |
721 | /* set timing information */ | 720 | /* set timing information */ |
722 | sdata->bss_conf.beacon_int = bss->beacon_int; | 721 | sdata->vif.bss_conf.beacon_int = bss->beacon_int; |
723 | sdata->bss_conf.timestamp = bss->timestamp; | 722 | sdata->vif.bss_conf.timestamp = bss->timestamp; |
724 | sdata->bss_conf.dtim_period = bss->dtim_period; | 723 | sdata->vif.bss_conf.dtim_period = bss->dtim_period; |
725 | 724 | ||
726 | changed |= ieee80211_handle_bss_capability(sdata, bss); | 725 | bss_info_changed |= ieee80211_handle_bss_capability(sdata, |
726 | bss->capability, bss->has_erp_value, bss->erp_value); | ||
727 | 727 | ||
728 | ieee80211_rx_bss_put(local, bss); | 728 | ieee80211_rx_bss_put(local, bss); |
729 | } | 729 | } |
730 | 730 | ||
731 | if (conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) { | ||
732 | changed |= BSS_CHANGED_HT; | ||
733 | sdata->bss_conf.assoc_ht = 1; | ||
734 | sdata->bss_conf.ht_conf = &conf->ht_conf; | ||
735 | sdata->bss_conf.ht_bss_conf = &conf->ht_bss_conf; | ||
736 | } | ||
737 | |||
738 | ifsta->flags |= IEEE80211_STA_PREV_BSSID_SET; | 731 | ifsta->flags |= IEEE80211_STA_PREV_BSSID_SET; |
739 | memcpy(ifsta->prev_bssid, sdata->u.sta.bssid, ETH_ALEN); | 732 | memcpy(ifsta->prev_bssid, sdata->u.sta.bssid, ETH_ALEN); |
740 | ieee80211_sta_send_associnfo(sdata, ifsta); | 733 | ieee80211_sta_send_associnfo(sdata, ifsta); |
@@ -742,14 +735,25 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
742 | ifsta->last_probe = jiffies; | 735 | ifsta->last_probe = jiffies; |
743 | ieee80211_led_assoc(local, 1); | 736 | ieee80211_led_assoc(local, 1); |
744 | 737 | ||
745 | sdata->bss_conf.assoc = 1; | 738 | sdata->vif.bss_conf.assoc = 1; |
746 | /* | 739 | /* |
747 | * For now just always ask the driver to update the basic rateset | 740 | * For now just always ask the driver to update the basic rateset |
748 | * when we have associated, we aren't checking whether it actually | 741 | * when we have associated, we aren't checking whether it actually |
749 | * changed or not. | 742 | * changed or not. |
750 | */ | 743 | */ |
751 | changed |= BSS_CHANGED_BASIC_RATES; | 744 | bss_info_changed |= BSS_CHANGED_BASIC_RATES; |
752 | ieee80211_bss_info_change_notify(sdata, changed); | 745 | ieee80211_bss_info_change_notify(sdata, bss_info_changed); |
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 | } | ||
753 | 757 | ||
754 | netif_tx_start_all_queues(sdata->dev); | 758 | netif_tx_start_all_queues(sdata->dev); |
755 | netif_carrier_on(sdata->dev); | 759 | netif_carrier_on(sdata->dev); |
@@ -760,18 +764,17 @@ static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, | |||
760 | static void ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata, | 764 | static void ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata, |
761 | struct ieee80211_if_sta *ifsta) | 765 | struct ieee80211_if_sta *ifsta) |
762 | { | 766 | { |
763 | DECLARE_MAC_BUF(mac); | ||
764 | |||
765 | ifsta->direct_probe_tries++; | 767 | ifsta->direct_probe_tries++; |
766 | if (ifsta->direct_probe_tries > IEEE80211_AUTH_MAX_TRIES) { | 768 | if (ifsta->direct_probe_tries > IEEE80211_AUTH_MAX_TRIES) { |
767 | printk(KERN_DEBUG "%s: direct probe to AP %s timed out\n", | 769 | printk(KERN_DEBUG "%s: direct probe to AP %pM timed out\n", |
768 | sdata->dev->name, print_mac(mac, ifsta->bssid)); | 770 | sdata->dev->name, ifsta->bssid); |
769 | ifsta->state = IEEE80211_STA_MLME_DISABLED; | 771 | ifsta->state = IEEE80211_STA_MLME_DISABLED; |
772 | ieee80211_sta_send_apinfo(sdata, ifsta); | ||
770 | return; | 773 | return; |
771 | } | 774 | } |
772 | 775 | ||
773 | printk(KERN_DEBUG "%s: direct probe to AP %s try %d\n", | 776 | printk(KERN_DEBUG "%s: direct probe to AP %pM try %d\n", |
774 | sdata->dev->name, print_mac(mac, ifsta->bssid), | 777 | sdata->dev->name, ifsta->bssid, |
775 | ifsta->direct_probe_tries); | 778 | ifsta->direct_probe_tries); |
776 | 779 | ||
777 | ifsta->state = IEEE80211_STA_MLME_DIRECT_PROBE; | 780 | ifsta->state = IEEE80211_STA_MLME_DIRECT_PROBE; |
@@ -791,33 +794,36 @@ static void ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata, | |||
791 | static void ieee80211_authenticate(struct ieee80211_sub_if_data *sdata, | 794 | static void ieee80211_authenticate(struct ieee80211_sub_if_data *sdata, |
792 | struct ieee80211_if_sta *ifsta) | 795 | struct ieee80211_if_sta *ifsta) |
793 | { | 796 | { |
794 | DECLARE_MAC_BUF(mac); | ||
795 | |||
796 | ifsta->auth_tries++; | 797 | ifsta->auth_tries++; |
797 | if (ifsta->auth_tries > IEEE80211_AUTH_MAX_TRIES) { | 798 | if (ifsta->auth_tries > IEEE80211_AUTH_MAX_TRIES) { |
798 | printk(KERN_DEBUG "%s: authentication with AP %s" | 799 | printk(KERN_DEBUG "%s: authentication with AP %pM" |
799 | " timed out\n", | 800 | " timed out\n", |
800 | sdata->dev->name, print_mac(mac, ifsta->bssid)); | 801 | sdata->dev->name, ifsta->bssid); |
801 | ifsta->state = IEEE80211_STA_MLME_DISABLED; | 802 | ifsta->state = IEEE80211_STA_MLME_DISABLED; |
803 | ieee80211_sta_send_apinfo(sdata, ifsta); | ||
802 | return; | 804 | return; |
803 | } | 805 | } |
804 | 806 | ||
805 | ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE; | 807 | ifsta->state = IEEE80211_STA_MLME_AUTHENTICATE; |
806 | printk(KERN_DEBUG "%s: authenticate with AP %s\n", | 808 | printk(KERN_DEBUG "%s: authenticate with AP %pM\n", |
807 | sdata->dev->name, print_mac(mac, ifsta->bssid)); | 809 | sdata->dev->name, ifsta->bssid); |
808 | 810 | ||
809 | ieee80211_send_auth(sdata, ifsta, 1, NULL, 0, 0); | 811 | ieee80211_send_auth(sdata, ifsta, 1, NULL, 0, 0); |
810 | 812 | ||
811 | mod_timer(&ifsta->timer, jiffies + IEEE80211_AUTH_TIMEOUT); | 813 | mod_timer(&ifsta->timer, jiffies + IEEE80211_AUTH_TIMEOUT); |
812 | } | 814 | } |
813 | 815 | ||
816 | /* | ||
817 | * The disassoc 'reason' argument can be either our own reason | ||
818 | * if self disconnected or a reason code from the AP. | ||
819 | */ | ||
814 | static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | 820 | static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, |
815 | struct ieee80211_if_sta *ifsta, bool deauth, | 821 | struct ieee80211_if_sta *ifsta, bool deauth, |
816 | bool self_disconnected, u16 reason) | 822 | bool self_disconnected, u16 reason) |
817 | { | 823 | { |
818 | struct ieee80211_local *local = sdata->local; | 824 | struct ieee80211_local *local = sdata->local; |
819 | struct sta_info *sta; | 825 | struct sta_info *sta; |
820 | u32 changed = BSS_CHANGED_ASSOC; | 826 | u32 changed = 0, config_changed = 0; |
821 | 827 | ||
822 | rcu_read_lock(); | 828 | rcu_read_lock(); |
823 | 829 | ||
@@ -851,21 +857,40 @@ static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, | |||
851 | ifsta->flags &= ~IEEE80211_STA_ASSOCIATED; | 857 | ifsta->flags &= ~IEEE80211_STA_ASSOCIATED; |
852 | changed |= ieee80211_reset_erp_info(sdata); | 858 | changed |= ieee80211_reset_erp_info(sdata); |
853 | 859 | ||
854 | if (sdata->bss_conf.assoc_ht) | ||
855 | changed |= BSS_CHANGED_HT; | ||
856 | |||
857 | sdata->bss_conf.assoc_ht = 0; | ||
858 | sdata->bss_conf.ht_conf = NULL; | ||
859 | sdata->bss_conf.ht_bss_conf = NULL; | ||
860 | |||
861 | ieee80211_led_assoc(local, 0); | 860 | ieee80211_led_assoc(local, 0); |
862 | sdata->bss_conf.assoc = 0; | 861 | changed |= BSS_CHANGED_ASSOC; |
862 | sdata->vif.bss_conf.assoc = false; | ||
863 | 863 | ||
864 | ieee80211_sta_send_apinfo(sdata, ifsta); | 864 | ieee80211_sta_send_apinfo(sdata, ifsta); |
865 | 865 | ||
866 | if (self_disconnected) | 866 | if (self_disconnected || reason == WLAN_REASON_DISASSOC_STA_HAS_LEFT) |
867 | ifsta->state = IEEE80211_STA_MLME_DISABLED; | 867 | ifsta->state = IEEE80211_STA_MLME_DISABLED; |
868 | 868 | ||
869 | rcu_read_unlock(); | ||
870 | |||
871 | local->hw.conf.ht.enabled = false; | ||
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); | ||
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); | ||
884 | ieee80211_bss_info_change_notify(sdata, changed); | ||
885 | |||
886 | rcu_read_lock(); | ||
887 | |||
888 | sta = sta_info_get(local, ifsta->bssid); | ||
889 | if (!sta) { | ||
890 | rcu_read_unlock(); | ||
891 | return; | ||
892 | } | ||
893 | |||
869 | sta_info_unlink(&sta); | 894 | sta_info_unlink(&sta); |
870 | 895 | ||
871 | rcu_read_unlock(); | 896 | rcu_read_unlock(); |
@@ -914,20 +939,19 @@ static int ieee80211_privacy_mismatch(struct ieee80211_sub_if_data *sdata, | |||
914 | static void ieee80211_associate(struct ieee80211_sub_if_data *sdata, | 939 | static void ieee80211_associate(struct ieee80211_sub_if_data *sdata, |
915 | struct ieee80211_if_sta *ifsta) | 940 | struct ieee80211_if_sta *ifsta) |
916 | { | 941 | { |
917 | DECLARE_MAC_BUF(mac); | ||
918 | |||
919 | ifsta->assoc_tries++; | 942 | ifsta->assoc_tries++; |
920 | if (ifsta->assoc_tries > IEEE80211_ASSOC_MAX_TRIES) { | 943 | if (ifsta->assoc_tries > IEEE80211_ASSOC_MAX_TRIES) { |
921 | printk(KERN_DEBUG "%s: association with AP %s" | 944 | printk(KERN_DEBUG "%s: association with AP %pM" |
922 | " timed out\n", | 945 | " timed out\n", |
923 | sdata->dev->name, print_mac(mac, ifsta->bssid)); | 946 | sdata->dev->name, ifsta->bssid); |
924 | ifsta->state = IEEE80211_STA_MLME_DISABLED; | 947 | ifsta->state = IEEE80211_STA_MLME_DISABLED; |
948 | ieee80211_sta_send_apinfo(sdata, ifsta); | ||
925 | return; | 949 | return; |
926 | } | 950 | } |
927 | 951 | ||
928 | ifsta->state = IEEE80211_STA_MLME_ASSOCIATE; | 952 | ifsta->state = IEEE80211_STA_MLME_ASSOCIATE; |
929 | printk(KERN_DEBUG "%s: associate with AP %s\n", | 953 | printk(KERN_DEBUG "%s: associate with AP %pM\n", |
930 | sdata->dev->name, print_mac(mac, ifsta->bssid)); | 954 | sdata->dev->name, ifsta->bssid); |
931 | if (ieee80211_privacy_mismatch(sdata, ifsta)) { | 955 | if (ieee80211_privacy_mismatch(sdata, ifsta)) { |
932 | printk(KERN_DEBUG "%s: mismatch in privacy configuration and " | 956 | printk(KERN_DEBUG "%s: mismatch in privacy configuration and " |
933 | "mixed-cell disabled - abort association\n", sdata->dev->name); | 957 | "mixed-cell disabled - abort association\n", sdata->dev->name); |
@@ -947,7 +971,6 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata, | |||
947 | struct ieee80211_local *local = sdata->local; | 971 | struct ieee80211_local *local = sdata->local; |
948 | struct sta_info *sta; | 972 | struct sta_info *sta; |
949 | int disassoc; | 973 | int disassoc; |
950 | DECLARE_MAC_BUF(mac); | ||
951 | 974 | ||
952 | /* TODO: start monitoring current AP signal quality and number of | 975 | /* TODO: start monitoring current AP signal quality and number of |
953 | * missed beacons. Scan other channels every now and then and search | 976 | * missed beacons. Scan other channels every now and then and search |
@@ -960,8 +983,8 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata, | |||
960 | 983 | ||
961 | sta = sta_info_get(local, ifsta->bssid); | 984 | sta = sta_info_get(local, ifsta->bssid); |
962 | if (!sta) { | 985 | if (!sta) { |
963 | printk(KERN_DEBUG "%s: No STA entry for own AP %s\n", | 986 | printk(KERN_DEBUG "%s: No STA entry for own AP %pM\n", |
964 | sdata->dev->name, print_mac(mac, ifsta->bssid)); | 987 | sdata->dev->name, ifsta->bssid); |
965 | disassoc = 1; | 988 | disassoc = 1; |
966 | } else { | 989 | } else { |
967 | disassoc = 0; | 990 | disassoc = 0; |
@@ -969,9 +992,9 @@ static void ieee80211_associated(struct ieee80211_sub_if_data *sdata, | |||
969 | sta->last_rx + IEEE80211_MONITORING_INTERVAL)) { | 992 | sta->last_rx + IEEE80211_MONITORING_INTERVAL)) { |
970 | if (ifsta->flags & IEEE80211_STA_PROBEREQ_POLL) { | 993 | if (ifsta->flags & IEEE80211_STA_PROBEREQ_POLL) { |
971 | printk(KERN_DEBUG "%s: No ProbeResp from " | 994 | printk(KERN_DEBUG "%s: No ProbeResp from " |
972 | "current AP %s - assume out of " | 995 | "current AP %pM - assume out of " |
973 | "range\n", | 996 | "range\n", |
974 | sdata->dev->name, print_mac(mac, ifsta->bssid)); | 997 | sdata->dev->name, ifsta->bssid); |
975 | disassoc = 1; | 998 | disassoc = 1; |
976 | } else | 999 | } else |
977 | ieee80211_send_probe_req(sdata, ifsta->bssid, | 1000 | ieee80211_send_probe_req(sdata, ifsta->bssid, |
@@ -1032,7 +1055,6 @@ static void ieee80211_rx_mgmt_auth(struct ieee80211_sub_if_data *sdata, | |||
1032 | size_t len) | 1055 | size_t len) |
1033 | { | 1056 | { |
1034 | u16 auth_alg, auth_transaction, status_code; | 1057 | u16 auth_alg, auth_transaction, status_code; |
1035 | DECLARE_MAC_BUF(mac); | ||
1036 | 1058 | ||
1037 | if (ifsta->state != IEEE80211_STA_MLME_AUTHENTICATE && | 1059 | if (ifsta->state != IEEE80211_STA_MLME_AUTHENTICATE && |
1038 | sdata->vif.type != NL80211_IFTYPE_ADHOC) | 1060 | sdata->vif.type != NL80211_IFTYPE_ADHOC) |
@@ -1125,7 +1147,6 @@ static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, | |||
1125 | size_t len) | 1147 | size_t len) |
1126 | { | 1148 | { |
1127 | u16 reason_code; | 1149 | u16 reason_code; |
1128 | DECLARE_MAC_BUF(mac); | ||
1129 | 1150 | ||
1130 | if (len < 24 + 2) | 1151 | if (len < 24 + 2) |
1131 | return; | 1152 | return; |
@@ -1136,7 +1157,8 @@ static void ieee80211_rx_mgmt_deauth(struct ieee80211_sub_if_data *sdata, | |||
1136 | reason_code = le16_to_cpu(mgmt->u.deauth.reason_code); | 1157 | reason_code = le16_to_cpu(mgmt->u.deauth.reason_code); |
1137 | 1158 | ||
1138 | if (ifsta->flags & IEEE80211_STA_AUTHENTICATED) | 1159 | if (ifsta->flags & IEEE80211_STA_AUTHENTICATED) |
1139 | printk(KERN_DEBUG "%s: deauthenticated\n", sdata->dev->name); | 1160 | printk(KERN_DEBUG "%s: deauthenticated (Reason: %u)\n", |
1161 | sdata->dev->name, reason_code); | ||
1140 | 1162 | ||
1141 | if (ifsta->state == IEEE80211_STA_MLME_AUTHENTICATE || | 1163 | if (ifsta->state == IEEE80211_STA_MLME_AUTHENTICATE || |
1142 | ifsta->state == IEEE80211_STA_MLME_ASSOCIATE || | 1164 | ifsta->state == IEEE80211_STA_MLME_ASSOCIATE || |
@@ -1157,7 +1179,6 @@ static void ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1157 | size_t len) | 1179 | size_t len) |
1158 | { | 1180 | { |
1159 | u16 reason_code; | 1181 | u16 reason_code; |
1160 | DECLARE_MAC_BUF(mac); | ||
1161 | 1182 | ||
1162 | if (len < 24 + 2) | 1183 | if (len < 24 + 2) |
1163 | return; | 1184 | return; |
@@ -1168,7 +1189,8 @@ static void ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1168 | reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); | 1189 | reason_code = le16_to_cpu(mgmt->u.disassoc.reason_code); |
1169 | 1190 | ||
1170 | if (ifsta->flags & IEEE80211_STA_ASSOCIATED) | 1191 | if (ifsta->flags & IEEE80211_STA_ASSOCIATED) |
1171 | printk(KERN_DEBUG "%s: disassociated\n", sdata->dev->name); | 1192 | printk(KERN_DEBUG "%s: disassociated (Reason: %u)\n", |
1193 | sdata->dev->name, reason_code); | ||
1172 | 1194 | ||
1173 | if (ifsta->state == IEEE80211_STA_MLME_ASSOCIATED) { | 1195 | if (ifsta->state == IEEE80211_STA_MLME_ASSOCIATED) { |
1174 | ifsta->state = IEEE80211_STA_MLME_ASSOCIATE; | 1196 | ifsta->state = IEEE80211_STA_MLME_ASSOCIATE; |
@@ -1176,7 +1198,7 @@ static void ieee80211_rx_mgmt_disassoc(struct ieee80211_sub_if_data *sdata, | |||
1176 | IEEE80211_RETRY_AUTH_INTERVAL); | 1198 | IEEE80211_RETRY_AUTH_INTERVAL); |
1177 | } | 1199 | } |
1178 | 1200 | ||
1179 | ieee80211_set_disassoc(sdata, ifsta, false, false, 0); | 1201 | ieee80211_set_disassoc(sdata, ifsta, false, false, reason_code); |
1180 | } | 1202 | } |
1181 | 1203 | ||
1182 | 1204 | ||
@@ -1192,11 +1214,12 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
1192 | u64 rates, basic_rates; | 1214 | u64 rates, basic_rates; |
1193 | u16 capab_info, status_code, aid; | 1215 | u16 capab_info, status_code, aid; |
1194 | struct ieee802_11_elems elems; | 1216 | struct ieee802_11_elems elems; |
1195 | struct ieee80211_bss_conf *bss_conf = &sdata->bss_conf; | 1217 | struct ieee80211_bss_conf *bss_conf = &sdata->vif.bss_conf; |
1196 | u8 *pos; | 1218 | u8 *pos; |
1219 | u32 changed = 0; | ||
1197 | int i, j; | 1220 | int i, j; |
1198 | DECLARE_MAC_BUF(mac); | 1221 | bool have_higher_than_11mbit = false, newsta = false; |
1199 | bool have_higher_than_11mbit = false; | 1222 | u16 ap_ht_cap_flags; |
1200 | 1223 | ||
1201 | /* AssocResp and ReassocResp have identical structure, so process both | 1224 | /* AssocResp and ReassocResp have identical structure, so process both |
1202 | * of them in this function. */ | 1225 | * of them in this function. */ |
@@ -1214,9 +1237,9 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
1214 | status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code); | 1237 | status_code = le16_to_cpu(mgmt->u.assoc_resp.status_code); |
1215 | aid = le16_to_cpu(mgmt->u.assoc_resp.aid); | 1238 | aid = le16_to_cpu(mgmt->u.assoc_resp.aid); |
1216 | 1239 | ||
1217 | printk(KERN_DEBUG "%s: RX %sssocResp from %s (capab=0x%x " | 1240 | printk(KERN_DEBUG "%s: RX %sssocResp from %pM (capab=0x%x " |
1218 | "status=%d aid=%d)\n", | 1241 | "status=%d aid=%d)\n", |
1219 | sdata->dev->name, reassoc ? "Rea" : "A", print_mac(mac, mgmt->sa), | 1242 | sdata->dev->name, reassoc ? "Rea" : "A", mgmt->sa, |
1220 | capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14)))); | 1243 | capab_info, status_code, (u16)(aid & ~(BIT(15) | BIT(14)))); |
1221 | 1244 | ||
1222 | if (status_code != WLAN_STATUS_SUCCESS) { | 1245 | if (status_code != WLAN_STATUS_SUCCESS) { |
@@ -1259,7 +1282,8 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
1259 | sta = sta_info_get(local, ifsta->bssid); | 1282 | sta = sta_info_get(local, ifsta->bssid); |
1260 | if (!sta) { | 1283 | if (!sta) { |
1261 | struct ieee80211_bss *bss; | 1284 | struct ieee80211_bss *bss; |
1262 | int err; | 1285 | |
1286 | newsta = true; | ||
1263 | 1287 | ||
1264 | sta = sta_info_alloc(sdata, ifsta->bssid, GFP_ATOMIC); | 1288 | sta = sta_info_alloc(sdata, ifsta->bssid, GFP_ATOMIC); |
1265 | if (!sta) { | 1289 | if (!sta) { |
@@ -1278,13 +1302,6 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
1278 | ieee80211_rx_bss_put(local, bss); | 1302 | ieee80211_rx_bss_put(local, bss); |
1279 | } | 1303 | } |
1280 | 1304 | ||
1281 | err = sta_info_insert(sta); | ||
1282 | if (err) { | ||
1283 | printk(KERN_DEBUG "%s: failed to insert STA entry for" | ||
1284 | " the AP (error %d)\n", sdata->dev->name, err); | ||
1285 | rcu_read_unlock(); | ||
1286 | return; | ||
1287 | } | ||
1288 | /* update new sta with its last rx activity */ | 1305 | /* update new sta with its last rx activity */ |
1289 | sta->last_rx = jiffies; | 1306 | sta->last_rx = jiffies; |
1290 | } | 1307 | } |
@@ -1308,34 +1325,40 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
1308 | 1325 | ||
1309 | for (i = 0; i < elems.supp_rates_len; i++) { | 1326 | for (i = 0; i < elems.supp_rates_len; i++) { |
1310 | int rate = (elems.supp_rates[i] & 0x7f) * 5; | 1327 | int rate = (elems.supp_rates[i] & 0x7f) * 5; |
1328 | bool is_basic = !!(elems.supp_rates[i] & 0x80); | ||
1311 | 1329 | ||
1312 | if (rate > 110) | 1330 | if (rate > 110) |
1313 | have_higher_than_11mbit = true; | 1331 | have_higher_than_11mbit = true; |
1314 | 1332 | ||
1315 | for (j = 0; j < sband->n_bitrates; j++) { | 1333 | for (j = 0; j < sband->n_bitrates; j++) { |
1316 | if (sband->bitrates[j].bitrate == rate) | 1334 | if (sband->bitrates[j].bitrate == rate) { |
1317 | rates |= BIT(j); | 1335 | rates |= BIT(j); |
1318 | if (elems.supp_rates[i] & 0x80) | 1336 | if (is_basic) |
1319 | basic_rates |= BIT(j); | 1337 | basic_rates |= BIT(j); |
1338 | break; | ||
1339 | } | ||
1320 | } | 1340 | } |
1321 | } | 1341 | } |
1322 | 1342 | ||
1323 | for (i = 0; i < elems.ext_supp_rates_len; i++) { | 1343 | for (i = 0; i < elems.ext_supp_rates_len; i++) { |
1324 | int rate = (elems.ext_supp_rates[i] & 0x7f) * 5; | 1344 | int rate = (elems.ext_supp_rates[i] & 0x7f) * 5; |
1345 | bool is_basic = !!(elems.supp_rates[i] & 0x80); | ||
1325 | 1346 | ||
1326 | if (rate > 110) | 1347 | if (rate > 110) |
1327 | have_higher_than_11mbit = true; | 1348 | have_higher_than_11mbit = true; |
1328 | 1349 | ||
1329 | for (j = 0; j < sband->n_bitrates; j++) { | 1350 | for (j = 0; j < sband->n_bitrates; j++) { |
1330 | if (sband->bitrates[j].bitrate == rate) | 1351 | if (sband->bitrates[j].bitrate == rate) { |
1331 | rates |= BIT(j); | 1352 | rates |= BIT(j); |
1332 | if (elems.ext_supp_rates[i] & 0x80) | 1353 | if (is_basic) |
1333 | basic_rates |= BIT(j); | 1354 | basic_rates |= BIT(j); |
1355 | break; | ||
1356 | } | ||
1334 | } | 1357 | } |
1335 | } | 1358 | } |
1336 | 1359 | ||
1337 | sta->sta.supp_rates[local->hw.conf.channel->band] = rates; | 1360 | sta->sta.supp_rates[local->hw.conf.channel->band] = rates; |
1338 | sdata->bss_conf.basic_rates = basic_rates; | 1361 | sdata->vif.bss_conf.basic_rates = basic_rates; |
1339 | 1362 | ||
1340 | /* cf. IEEE 802.11 9.2.12 */ | 1363 | /* cf. IEEE 802.11 9.2.12 */ |
1341 | if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ && | 1364 | if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ && |
@@ -1344,31 +1367,43 @@ static void ieee80211_rx_mgmt_assoc_resp(struct ieee80211_sub_if_data *sdata, | |||
1344 | else | 1367 | else |
1345 | sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE; | 1368 | sdata->flags &= ~IEEE80211_SDATA_OPERATING_GMODE; |
1346 | 1369 | ||
1347 | if (elems.ht_cap_elem && elems.ht_info_elem && elems.wmm_param && | 1370 | if (elems.ht_cap_elem) |
1348 | (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) { | 1371 | ieee80211_ht_cap_ie_to_sta_ht_cap(sband, |
1349 | struct ieee80211_ht_bss_info bss_info; | 1372 | elems.ht_cap_elem, &sta->sta.ht_cap); |
1350 | ieee80211_ht_cap_ie_to_ht_info( | 1373 | |
1351 | elems.ht_cap_elem, &sta->sta.ht_info); | 1374 | ap_ht_cap_flags = sta->sta.ht_cap.cap; |
1352 | ieee80211_ht_addt_info_ie_to_ht_bss_info( | ||
1353 | elems.ht_info_elem, &bss_info); | ||
1354 | ieee80211_handle_ht(local, 1, &sta->sta.ht_info, &bss_info); | ||
1355 | } | ||
1356 | 1375 | ||
1357 | rate_control_rate_init(sta); | 1376 | rate_control_rate_init(sta); |
1358 | 1377 | ||
1359 | if (elems.wmm_param) { | 1378 | if (elems.wmm_param) |
1360 | set_sta_flags(sta, WLAN_STA_WME); | 1379 | set_sta_flags(sta, WLAN_STA_WME); |
1361 | rcu_read_unlock(); | 1380 | |
1381 | if (newsta) { | ||
1382 | int err = sta_info_insert(sta); | ||
1383 | if (err) { | ||
1384 | printk(KERN_DEBUG "%s: failed to insert STA entry for" | ||
1385 | " the AP (error %d)\n", sdata->dev->name, err); | ||
1386 | rcu_read_unlock(); | ||
1387 | return; | ||
1388 | } | ||
1389 | } | ||
1390 | |||
1391 | rcu_read_unlock(); | ||
1392 | |||
1393 | if (elems.wmm_param) | ||
1362 | ieee80211_sta_wmm_params(local, ifsta, elems.wmm_param, | 1394 | ieee80211_sta_wmm_params(local, ifsta, elems.wmm_param, |
1363 | elems.wmm_param_len); | 1395 | elems.wmm_param_len); |
1364 | } else | 1396 | |
1365 | rcu_read_unlock(); | 1397 | if (elems.ht_info_elem && elems.wmm_param && |
1398 | (ifsta->flags & IEEE80211_STA_WMM_ENABLED)) | ||
1399 | changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem, | ||
1400 | ap_ht_cap_flags); | ||
1366 | 1401 | ||
1367 | /* set AID and assoc capability, | 1402 | /* set AID and assoc capability, |
1368 | * ieee80211_set_associated() will tell the driver */ | 1403 | * ieee80211_set_associated() will tell the driver */ |
1369 | bss_conf->aid = aid; | 1404 | bss_conf->aid = aid; |
1370 | bss_conf->assoc_capability = capab_info; | 1405 | bss_conf->assoc_capability = capab_info; |
1371 | ieee80211_set_associated(sdata, ifsta); | 1406 | ieee80211_set_associated(sdata, ifsta, changed); |
1372 | 1407 | ||
1373 | ieee80211_associated(sdata, ifsta); | 1408 | ieee80211_associated(sdata, ifsta); |
1374 | } | 1409 | } |
@@ -1386,6 +1421,13 @@ static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
1386 | struct ieee80211_supported_band *sband; | 1421 | struct ieee80211_supported_band *sband; |
1387 | union iwreq_data wrqu; | 1422 | union iwreq_data wrqu; |
1388 | 1423 | ||
1424 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400); | ||
1425 | if (!skb) { | ||
1426 | printk(KERN_DEBUG "%s: failed to allocate buffer for probe " | ||
1427 | "response\n", sdata->dev->name); | ||
1428 | return -ENOMEM; | ||
1429 | } | ||
1430 | |||
1389 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 1431 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
1390 | 1432 | ||
1391 | /* Remove possible STA entries from other IBSS networks. */ | 1433 | /* Remove possible STA entries from other IBSS networks. */ |
@@ -1411,63 +1453,62 @@ static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
1411 | return res; | 1453 | return res; |
1412 | 1454 | ||
1413 | /* Build IBSS probe response */ | 1455 | /* Build IBSS probe response */ |
1414 | skb = dev_alloc_skb(local->hw.extra_tx_headroom + 400); | ||
1415 | if (skb) { | ||
1416 | skb_reserve(skb, local->hw.extra_tx_headroom); | ||
1417 | 1456 | ||
1418 | mgmt = (struct ieee80211_mgmt *) | 1457 | skb_reserve(skb, local->hw.extra_tx_headroom); |
1419 | skb_put(skb, 24 + sizeof(mgmt->u.beacon)); | ||
1420 | memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon)); | ||
1421 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | | ||
1422 | IEEE80211_STYPE_PROBE_RESP); | ||
1423 | memset(mgmt->da, 0xff, ETH_ALEN); | ||
1424 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); | ||
1425 | memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); | ||
1426 | mgmt->u.beacon.beacon_int = | ||
1427 | cpu_to_le16(local->hw.conf.beacon_int); | ||
1428 | mgmt->u.beacon.timestamp = cpu_to_le64(bss->timestamp); | ||
1429 | mgmt->u.beacon.capab_info = cpu_to_le16(bss->capability); | ||
1430 | |||
1431 | pos = skb_put(skb, 2 + ifsta->ssid_len); | ||
1432 | *pos++ = WLAN_EID_SSID; | ||
1433 | *pos++ = ifsta->ssid_len; | ||
1434 | memcpy(pos, ifsta->ssid, ifsta->ssid_len); | ||
1435 | |||
1436 | rates = bss->supp_rates_len; | ||
1437 | if (rates > 8) | ||
1438 | rates = 8; | ||
1439 | pos = skb_put(skb, 2 + rates); | ||
1440 | *pos++ = WLAN_EID_SUPP_RATES; | ||
1441 | *pos++ = rates; | ||
1442 | memcpy(pos, bss->supp_rates, rates); | ||
1443 | 1458 | ||
1444 | if (bss->band == IEEE80211_BAND_2GHZ) { | 1459 | mgmt = (struct ieee80211_mgmt *) |
1445 | pos = skb_put(skb, 2 + 1); | 1460 | skb_put(skb, 24 + sizeof(mgmt->u.beacon)); |
1446 | *pos++ = WLAN_EID_DS_PARAMS; | 1461 | memset(mgmt, 0, 24 + sizeof(mgmt->u.beacon)); |
1447 | *pos++ = 1; | 1462 | mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | |
1448 | *pos++ = ieee80211_frequency_to_channel(bss->freq); | 1463 | IEEE80211_STYPE_PROBE_RESP); |
1449 | } | 1464 | memset(mgmt->da, 0xff, ETH_ALEN); |
1465 | memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); | ||
1466 | memcpy(mgmt->bssid, ifsta->bssid, ETH_ALEN); | ||
1467 | mgmt->u.beacon.beacon_int = | ||
1468 | cpu_to_le16(local->hw.conf.beacon_int); | ||
1469 | mgmt->u.beacon.timestamp = cpu_to_le64(bss->timestamp); | ||
1470 | mgmt->u.beacon.capab_info = cpu_to_le16(bss->capability); | ||
1450 | 1471 | ||
1451 | pos = skb_put(skb, 2 + 2); | 1472 | pos = skb_put(skb, 2 + ifsta->ssid_len); |
1452 | *pos++ = WLAN_EID_IBSS_PARAMS; | 1473 | *pos++ = WLAN_EID_SSID; |
1453 | *pos++ = 2; | 1474 | *pos++ = ifsta->ssid_len; |
1454 | /* FIX: set ATIM window based on scan results */ | 1475 | memcpy(pos, ifsta->ssid, ifsta->ssid_len); |
1455 | *pos++ = 0; | ||
1456 | *pos++ = 0; | ||
1457 | 1476 | ||
1458 | if (bss->supp_rates_len > 8) { | 1477 | rates = bss->supp_rates_len; |
1459 | rates = bss->supp_rates_len - 8; | 1478 | if (rates > 8) |
1460 | pos = skb_put(skb, 2 + rates); | 1479 | rates = 8; |
1461 | *pos++ = WLAN_EID_EXT_SUPP_RATES; | 1480 | pos = skb_put(skb, 2 + rates); |
1462 | *pos++ = rates; | 1481 | *pos++ = WLAN_EID_SUPP_RATES; |
1463 | memcpy(pos, &bss->supp_rates[8], rates); | 1482 | *pos++ = rates; |
1464 | } | 1483 | memcpy(pos, bss->supp_rates, rates); |
1465 | 1484 | ||
1466 | ifsta->probe_resp = skb; | 1485 | if (bss->band == IEEE80211_BAND_2GHZ) { |
1486 | pos = skb_put(skb, 2 + 1); | ||
1487 | *pos++ = WLAN_EID_DS_PARAMS; | ||
1488 | *pos++ = 1; | ||
1489 | *pos++ = ieee80211_frequency_to_channel(bss->freq); | ||
1490 | } | ||
1491 | |||
1492 | pos = skb_put(skb, 2 + 2); | ||
1493 | *pos++ = WLAN_EID_IBSS_PARAMS; | ||
1494 | *pos++ = 2; | ||
1495 | /* FIX: set ATIM window based on scan results */ | ||
1496 | *pos++ = 0; | ||
1497 | *pos++ = 0; | ||
1467 | 1498 | ||
1468 | ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); | 1499 | if (bss->supp_rates_len > 8) { |
1500 | rates = bss->supp_rates_len - 8; | ||
1501 | pos = skb_put(skb, 2 + rates); | ||
1502 | *pos++ = WLAN_EID_EXT_SUPP_RATES; | ||
1503 | *pos++ = rates; | ||
1504 | memcpy(pos, &bss->supp_rates[8], rates); | ||
1469 | } | 1505 | } |
1470 | 1506 | ||
1507 | ifsta->probe_resp = skb; | ||
1508 | |||
1509 | ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); | ||
1510 | |||
1511 | |||
1471 | rates = 0; | 1512 | rates = 0; |
1472 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | 1513 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; |
1473 | for (i = 0; i < bss->supp_rates_len; i++) { | 1514 | for (i = 0; i < bss->supp_rates_len; i++) { |
@@ -1507,8 +1548,6 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
1507 | u64 beacon_timestamp, rx_timestamp; | 1548 | u64 beacon_timestamp, rx_timestamp; |
1508 | u64 supp_rates = 0; | 1549 | u64 supp_rates = 0; |
1509 | enum ieee80211_band band = rx_status->band; | 1550 | enum ieee80211_band band = rx_status->band; |
1510 | DECLARE_MAC_BUF(mac); | ||
1511 | DECLARE_MAC_BUF(mac2); | ||
1512 | 1551 | ||
1513 | if (elems->ds_params && elems->ds_params_len == 1) | 1552 | if (elems->ds_params && elems->ds_params_len == 1) |
1514 | freq = ieee80211_channel_to_frequency(elems->ds_params[0]); | 1553 | freq = ieee80211_channel_to_frequency(elems->ds_params[0]); |
@@ -1538,17 +1577,16 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
1538 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 1577 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
1539 | if (sta->sta.supp_rates[band] != prev_rates) | 1578 | if (sta->sta.supp_rates[band] != prev_rates) |
1540 | printk(KERN_DEBUG "%s: updated supp_rates set " | 1579 | printk(KERN_DEBUG "%s: updated supp_rates set " |
1541 | "for %s based on beacon info (0x%llx | " | 1580 | "for %pM based on beacon info (0x%llx | " |
1542 | "0x%llx -> 0x%llx)\n", | 1581 | "0x%llx -> 0x%llx)\n", |
1543 | sdata->dev->name, | 1582 | sdata->dev->name, |
1544 | print_mac(mac, sta->sta.addr), | 1583 | sta->sta.addr, |
1545 | (unsigned long long) prev_rates, | 1584 | (unsigned long long) prev_rates, |
1546 | (unsigned long long) supp_rates, | 1585 | (unsigned long long) supp_rates, |
1547 | (unsigned long long) sta->sta.supp_rates[band]); | 1586 | (unsigned long long) sta->sta.supp_rates[band]); |
1548 | #endif | 1587 | #endif |
1549 | } else { | 1588 | } else { |
1550 | ieee80211_ibss_add_sta(sdata, NULL, mgmt->bssid, | 1589 | ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, supp_rates); |
1551 | mgmt->sa, supp_rates); | ||
1552 | } | 1590 | } |
1553 | 1591 | ||
1554 | rcu_read_unlock(); | 1592 | rcu_read_unlock(); |
@@ -1595,8 +1633,13 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
1595 | * 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 |
1596 | * (=24 bytes * 8 usecs/byte) than the beacon timestamp. | 1634 | * (=24 bytes * 8 usecs/byte) than the beacon timestamp. |
1597 | */ | 1635 | */ |
1598 | 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]-> | ||
1599 | bitrates[rx_status->rate_idx].bitrate; | 1641 | bitrates[rx_status->rate_idx].bitrate; |
1642 | } | ||
1600 | rx_timestamp = rx_status->mactime + (24 * 8 * 10 / rate); | 1643 | rx_timestamp = rx_status->mactime + (24 * 8 * 10 / rate); |
1601 | } else if (local && local->ops && local->ops->get_tsf) | 1644 | } else if (local && local->ops && local->ops->get_tsf) |
1602 | /* second best option: get current TSF */ | 1645 | /* second best option: get current TSF */ |
@@ -1605,10 +1648,9 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
1605 | /* can't merge without knowing the TSF */ | 1648 | /* can't merge without knowing the TSF */ |
1606 | rx_timestamp = -1LLU; | 1649 | rx_timestamp = -1LLU; |
1607 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 1650 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
1608 | printk(KERN_DEBUG "RX beacon SA=%s BSSID=" | 1651 | printk(KERN_DEBUG "RX beacon SA=%pM BSSID=" |
1609 | "%s TSF=0x%llx BCN=0x%llx diff=%lld @%lu\n", | 1652 | "%pM TSF=0x%llx BCN=0x%llx diff=%lld @%lu\n", |
1610 | print_mac(mac, mgmt->sa), | 1653 | mgmt->sa, mgmt->bssid, |
1611 | print_mac(mac2, mgmt->bssid), | ||
1612 | (unsigned long long)rx_timestamp, | 1654 | (unsigned long long)rx_timestamp, |
1613 | (unsigned long long)beacon_timestamp, | 1655 | (unsigned long long)beacon_timestamp, |
1614 | (unsigned long long)(rx_timestamp - beacon_timestamp), | 1656 | (unsigned long long)(rx_timestamp - beacon_timestamp), |
@@ -1617,13 +1659,11 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata, | |||
1617 | if (beacon_timestamp > rx_timestamp) { | 1659 | if (beacon_timestamp > rx_timestamp) { |
1618 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 1660 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
1619 | printk(KERN_DEBUG "%s: beacon TSF higher than " | 1661 | printk(KERN_DEBUG "%s: beacon TSF higher than " |
1620 | "local TSF - IBSS merge with BSSID %s\n", | 1662 | "local TSF - IBSS merge with BSSID %pM\n", |
1621 | sdata->dev->name, print_mac(mac, mgmt->bssid)); | 1663 | sdata->dev->name, mgmt->bssid); |
1622 | #endif | 1664 | #endif |
1623 | ieee80211_sta_join_ibss(sdata, &sdata->u.sta, bss); | 1665 | ieee80211_sta_join_ibss(sdata, &sdata->u.sta, bss); |
1624 | ieee80211_ibss_add_sta(sdata, NULL, | 1666 | ieee80211_ibss_add_sta(sdata, mgmt->bssid, mgmt->sa, supp_rates); |
1625 | mgmt->bssid, mgmt->sa, | ||
1626 | supp_rates); | ||
1627 | } | 1667 | } |
1628 | } | 1668 | } |
1629 | 1669 | ||
@@ -1671,8 +1711,9 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
1671 | size_t baselen; | 1711 | size_t baselen; |
1672 | struct ieee802_11_elems elems; | 1712 | struct ieee802_11_elems elems; |
1673 | struct ieee80211_local *local = sdata->local; | 1713 | struct ieee80211_local *local = sdata->local; |
1674 | struct ieee80211_conf *conf = &local->hw.conf; | ||
1675 | u32 changed = 0; | 1714 | u32 changed = 0; |
1715 | bool erp_valid; | ||
1716 | u8 erp_value = 0; | ||
1676 | 1717 | ||
1677 | /* Process beacon from the current BSS */ | 1718 | /* Process beacon from the current BSS */ |
1678 | baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt; | 1719 | baselen = (u8 *) mgmt->u.beacon.variable - (u8 *) mgmt; |
@@ -1694,22 +1735,49 @@ static void ieee80211_rx_mgmt_beacon(struct ieee80211_sub_if_data *sdata, | |||
1694 | ieee80211_sta_wmm_params(local, ifsta, elems.wmm_param, | 1735 | ieee80211_sta_wmm_params(local, ifsta, elems.wmm_param, |
1695 | elems.wmm_param_len); | 1736 | elems.wmm_param_len); |
1696 | 1737 | ||
1697 | if (elems.erp_info && elems.erp_info_len >= 1) | 1738 | |
1698 | changed |= ieee80211_handle_erp_ie(sdata, elems.erp_info[0]); | 1739 | if (elems.erp_info && elems.erp_info_len >= 1) { |
1699 | else { | 1740 | erp_valid = true; |
1700 | u16 capab = le16_to_cpu(mgmt->u.beacon.capab_info); | 1741 | erp_value = elems.erp_info[0]; |
1701 | changed |= ieee80211_handle_protect_preamb(sdata, false, | 1742 | } else { |
1702 | (capab & WLAN_CAPABILITY_SHORT_PREAMBLE) != 0); | 1743 | erp_valid = false; |
1703 | } | 1744 | } |
1745 | changed |= ieee80211_handle_bss_capability(sdata, | ||
1746 | le16_to_cpu(mgmt->u.beacon.capab_info), | ||
1747 | erp_valid, erp_value); | ||
1748 | |||
1749 | |||
1750 | if (elems.ht_cap_elem && elems.ht_info_elem && elems.wmm_param) { | ||
1751 | struct sta_info *sta; | ||
1752 | struct ieee80211_supported_band *sband; | ||
1753 | u16 ap_ht_cap_flags; | ||
1754 | |||
1755 | rcu_read_lock(); | ||
1704 | 1756 | ||
1705 | if (elems.ht_cap_elem && elems.ht_info_elem && | 1757 | sta = sta_info_get(local, ifsta->bssid); |
1706 | elems.wmm_param && conf->flags & IEEE80211_CONF_SUPPORT_HT_MODE) { | 1758 | if (!sta) { |
1707 | struct ieee80211_ht_bss_info bss_info; | 1759 | rcu_read_unlock(); |
1760 | return; | ||
1761 | } | ||
1762 | |||
1763 | sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; | ||
1708 | 1764 | ||
1709 | ieee80211_ht_addt_info_ie_to_ht_bss_info( | 1765 | ieee80211_ht_cap_ie_to_sta_ht_cap(sband, |
1710 | elems.ht_info_elem, &bss_info); | 1766 | elems.ht_cap_elem, &sta->sta.ht_cap); |
1711 | changed |= ieee80211_handle_ht(local, 1, &conf->ht_conf, | 1767 | |
1712 | &bss_info); | 1768 | ap_ht_cap_flags = sta->sta.ht_cap.cap; |
1769 | |||
1770 | rcu_read_unlock(); | ||
1771 | |||
1772 | changed |= ieee80211_enable_ht(sdata, elems.ht_info_elem, | ||
1773 | ap_ht_cap_flags); | ||
1774 | } | ||
1775 | |||
1776 | if (elems.country_elem) { | ||
1777 | /* Note we are only reviewing this on beacons | ||
1778 | * for the BSSID we are associated to */ | ||
1779 | regulatory_hint_11d(local->hw.wiphy, | ||
1780 | elems.country_elem, elems.country_elem_len); | ||
1713 | } | 1781 | } |
1714 | 1782 | ||
1715 | ieee80211_bss_info_change_notify(sdata, changed); | 1783 | ieee80211_bss_info_change_notify(sdata, changed); |
@@ -1727,11 +1795,6 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, | |||
1727 | struct sk_buff *skb; | 1795 | struct sk_buff *skb; |
1728 | struct ieee80211_mgmt *resp; | 1796 | struct ieee80211_mgmt *resp; |
1729 | u8 *pos, *end; | 1797 | u8 *pos, *end; |
1730 | DECLARE_MAC_BUF(mac); | ||
1731 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | ||
1732 | DECLARE_MAC_BUF(mac2); | ||
1733 | DECLARE_MAC_BUF(mac3); | ||
1734 | #endif | ||
1735 | 1798 | ||
1736 | if (sdata->vif.type != NL80211_IFTYPE_ADHOC || | 1799 | if (sdata->vif.type != NL80211_IFTYPE_ADHOC || |
1737 | ifsta->state != IEEE80211_STA_MLME_IBSS_JOINED || | 1800 | ifsta->state != IEEE80211_STA_MLME_IBSS_JOINED || |
@@ -1744,10 +1807,10 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, | |||
1744 | tx_last_beacon = 1; | 1807 | tx_last_beacon = 1; |
1745 | 1808 | ||
1746 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 1809 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
1747 | printk(KERN_DEBUG "%s: RX ProbeReq SA=%s DA=%s BSSID=" | 1810 | printk(KERN_DEBUG "%s: RX ProbeReq SA=%pM DA=%pM BSSID=%pM" |
1748 | "%s (tx_last_beacon=%d)\n", | 1811 | " (tx_last_beacon=%d)\n", |
1749 | sdata->dev->name, print_mac(mac, mgmt->sa), print_mac(mac2, mgmt->da), | 1812 | sdata->dev->name, mgmt->sa, mgmt->da, |
1750 | print_mac(mac3, mgmt->bssid), tx_last_beacon); | 1813 | mgmt->bssid, tx_last_beacon); |
1751 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ | 1814 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ |
1752 | 1815 | ||
1753 | if (!tx_last_beacon) | 1816 | if (!tx_last_beacon) |
@@ -1763,8 +1826,8 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, | |||
1763 | pos + 2 + pos[1] > end) { | 1826 | pos + 2 + pos[1] > end) { |
1764 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 1827 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
1765 | printk(KERN_DEBUG "%s: Invalid SSID IE in ProbeReq " | 1828 | printk(KERN_DEBUG "%s: Invalid SSID IE in ProbeReq " |
1766 | "from %s\n", | 1829 | "from %pM\n", |
1767 | sdata->dev->name, print_mac(mac, mgmt->sa)); | 1830 | sdata->dev->name, mgmt->sa); |
1768 | #endif | 1831 | #endif |
1769 | return; | 1832 | return; |
1770 | } | 1833 | } |
@@ -1783,8 +1846,8 @@ static void ieee80211_rx_mgmt_probe_req(struct ieee80211_sub_if_data *sdata, | |||
1783 | resp = (struct ieee80211_mgmt *) skb->data; | 1846 | resp = (struct ieee80211_mgmt *) skb->data; |
1784 | memcpy(resp->da, mgmt->sa, ETH_ALEN); | 1847 | memcpy(resp->da, mgmt->sa, ETH_ALEN); |
1785 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 1848 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
1786 | printk(KERN_DEBUG "%s: Sending ProbeResp to %s\n", | 1849 | printk(KERN_DEBUG "%s: Sending ProbeResp to %pM\n", |
1787 | sdata->dev->name, print_mac(mac, resp->da)); | 1850 | sdata->dev->name, resp->da); |
1788 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ | 1851 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ |
1789 | ieee80211_tx_skb(sdata, skb, 0); | 1852 | ieee80211_tx_skb(sdata, skb, 0); |
1790 | } | 1853 | } |
@@ -1972,7 +2035,7 @@ static int ieee80211_sta_match_ssid(struct ieee80211_if_sta *ifsta, | |||
1972 | } | 2035 | } |
1973 | } | 2036 | } |
1974 | 2037 | ||
1975 | if (hidden_ssid && ifsta->ssid_len == ssid_len) | 2038 | if (hidden_ssid && (ifsta->ssid_len == ssid_len || ssid_len == 0)) |
1976 | return 1; | 2039 | return 1; |
1977 | 2040 | ||
1978 | if (ssid_len == 1 && ssid[0] == ' ') | 2041 | if (ssid_len == 1 && ssid[0] == ' ') |
@@ -1990,7 +2053,6 @@ static int ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata, | |||
1990 | u8 bssid[ETH_ALEN], *pos; | 2053 | u8 bssid[ETH_ALEN], *pos; |
1991 | int i; | 2054 | int i; |
1992 | int ret; | 2055 | int ret; |
1993 | DECLARE_MAC_BUF(mac); | ||
1994 | 2056 | ||
1995 | #if 0 | 2057 | #if 0 |
1996 | /* Easier testing, use fixed BSSID. */ | 2058 | /* Easier testing, use fixed BSSID. */ |
@@ -2006,8 +2068,8 @@ static int ieee80211_sta_create_ibss(struct ieee80211_sub_if_data *sdata, | |||
2006 | bssid[0] |= 0x02; | 2068 | bssid[0] |= 0x02; |
2007 | #endif | 2069 | #endif |
2008 | 2070 | ||
2009 | printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %s\n", | 2071 | printk(KERN_DEBUG "%s: Creating new IBSS network, BSSID %pM\n", |
2010 | sdata->dev->name, print_mac(mac, bssid)); | 2072 | sdata->dev->name, bssid); |
2011 | 2073 | ||
2012 | bss = ieee80211_rx_bss_add(local, bssid, | 2074 | bss = ieee80211_rx_bss_add(local, bssid, |
2013 | local->hw.conf.channel->center_freq, | 2075 | local->hw.conf.channel->center_freq, |
@@ -2050,8 +2112,6 @@ static int ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata, | |||
2050 | int found = 0; | 2112 | int found = 0; |
2051 | u8 bssid[ETH_ALEN]; | 2113 | u8 bssid[ETH_ALEN]; |
2052 | int active_ibss; | 2114 | int active_ibss; |
2053 | DECLARE_MAC_BUF(mac); | ||
2054 | DECLARE_MAC_BUF(mac2); | ||
2055 | 2115 | ||
2056 | if (ifsta->ssid_len == 0) | 2116 | if (ifsta->ssid_len == 0) |
2057 | return -EINVAL; | 2117 | return -EINVAL; |
@@ -2068,8 +2128,7 @@ static int ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata, | |||
2068 | || !(bss->capability & WLAN_CAPABILITY_IBSS)) | 2128 | || !(bss->capability & WLAN_CAPABILITY_IBSS)) |
2069 | continue; | 2129 | continue; |
2070 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 2130 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
2071 | printk(KERN_DEBUG " bssid=%s found\n", | 2131 | printk(KERN_DEBUG " bssid=%pM found\n", bss->bssid); |
2072 | print_mac(mac, bss->bssid)); | ||
2073 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ | 2132 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ |
2074 | memcpy(bssid, bss->bssid, ETH_ALEN); | 2133 | memcpy(bssid, bss->bssid, ETH_ALEN); |
2075 | found = 1; | 2134 | found = 1; |
@@ -2080,9 +2139,8 @@ static int ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata, | |||
2080 | 2139 | ||
2081 | #ifdef CONFIG_MAC80211_IBSS_DEBUG | 2140 | #ifdef CONFIG_MAC80211_IBSS_DEBUG |
2082 | if (found) | 2141 | if (found) |
2083 | printk(KERN_DEBUG " sta_find_ibss: selected %s current " | 2142 | printk(KERN_DEBUG " sta_find_ibss: selected %pM current " |
2084 | "%s\n", print_mac(mac, bssid), | 2143 | "%pM\n", bssid, ifsta->bssid); |
2085 | print_mac(mac2, ifsta->bssid)); | ||
2086 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ | 2144 | #endif /* CONFIG_MAC80211_IBSS_DEBUG */ |
2087 | 2145 | ||
2088 | if (found && memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0) { | 2146 | if (found && memcmp(ifsta->bssid, bssid, ETH_ALEN) != 0) { |
@@ -2099,9 +2157,9 @@ static int ieee80211_sta_find_ibss(struct ieee80211_sub_if_data *sdata, | |||
2099 | if (!bss) | 2157 | if (!bss) |
2100 | goto dont_join; | 2158 | goto dont_join; |
2101 | 2159 | ||
2102 | printk(KERN_DEBUG "%s: Selected IBSS BSSID %s" | 2160 | printk(KERN_DEBUG "%s: Selected IBSS BSSID %pM" |
2103 | " based on configured SSID\n", | 2161 | " based on configured SSID\n", |
2104 | sdata->dev->name, print_mac(mac, bssid)); | 2162 | sdata->dev->name, bssid); |
2105 | ret = ieee80211_sta_join_ibss(sdata, ifsta, bss); | 2163 | ret = ieee80211_sta_join_ibss(sdata, ifsta, bss); |
2106 | ieee80211_rx_bss_put(local, bss); | 2164 | ieee80211_rx_bss_put(local, bss); |
2107 | return ret; | 2165 | return ret; |
@@ -2338,12 +2396,10 @@ void ieee80211_sta_setup_sdata(struct ieee80211_sub_if_data *sdata) | |||
2338 | * must be callable in atomic context. | 2396 | * must be callable in atomic context. |
2339 | */ | 2397 | */ |
2340 | struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | 2398 | struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, |
2341 | struct sk_buff *skb, u8 *bssid, | 2399 | u8 *bssid,u8 *addr, u64 supp_rates) |
2342 | u8 *addr, u64 supp_rates) | ||
2343 | { | 2400 | { |
2344 | struct ieee80211_local *local = sdata->local; | 2401 | struct ieee80211_local *local = sdata->local; |
2345 | struct sta_info *sta; | 2402 | struct sta_info *sta; |
2346 | DECLARE_MAC_BUF(mac); | ||
2347 | int band = local->hw.conf.channel->band; | 2403 | int band = local->hw.conf.channel->band; |
2348 | 2404 | ||
2349 | /* TODO: Could consider removing the least recently used entry and | 2405 | /* TODO: Could consider removing the least recently used entry and |
@@ -2351,7 +2407,7 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | |||
2351 | if (local->num_sta >= IEEE80211_IBSS_MAX_STA_ENTRIES) { | 2407 | if (local->num_sta >= IEEE80211_IBSS_MAX_STA_ENTRIES) { |
2352 | if (net_ratelimit()) { | 2408 | if (net_ratelimit()) { |
2353 | printk(KERN_DEBUG "%s: No room for a new IBSS STA " | 2409 | printk(KERN_DEBUG "%s: No room for a new IBSS STA " |
2354 | "entry %s\n", sdata->dev->name, print_mac(mac, addr)); | 2410 | "entry %pM\n", sdata->dev->name, addr); |
2355 | } | 2411 | } |
2356 | return NULL; | 2412 | return NULL; |
2357 | } | 2413 | } |
@@ -2360,8 +2416,8 @@ struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, | |||
2360 | return NULL; | 2416 | return NULL; |
2361 | 2417 | ||
2362 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG | 2418 | #ifdef CONFIG_MAC80211_VERBOSE_DEBUG |
2363 | printk(KERN_DEBUG "%s: Adding new IBSS station %s (dev=%s)\n", | 2419 | printk(KERN_DEBUG "%s: Adding new IBSS station %pM (dev=%s)\n", |
2364 | wiphy_name(local->hw.wiphy), print_mac(mac, addr), sdata->dev->name); | 2420 | wiphy_name(local->hw.wiphy), addr, sdata->dev->name); |
2365 | #endif | 2421 | #endif |
2366 | 2422 | ||
2367 | sta = sta_info_alloc(sdata, addr, GFP_ATOMIC); | 2423 | sta = sta_info_alloc(sdata, addr, GFP_ATOMIC); |
@@ -2408,7 +2464,6 @@ void ieee80211_sta_req_auth(struct ieee80211_sub_if_data *sdata, | |||
2408 | int ieee80211_sta_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t len) | 2464 | int ieee80211_sta_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t len) |
2409 | { | 2465 | { |
2410 | struct ieee80211_if_sta *ifsta; | 2466 | struct ieee80211_if_sta *ifsta; |
2411 | int res; | ||
2412 | 2467 | ||
2413 | if (len > IEEE80211_MAX_SSID_LEN) | 2468 | if (len > IEEE80211_MAX_SSID_LEN) |
2414 | return -EINVAL; | 2469 | return -EINVAL; |
@@ -2420,19 +2475,6 @@ int ieee80211_sta_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size | |||
2420 | memcpy(ifsta->ssid, ssid, len); | 2475 | memcpy(ifsta->ssid, ssid, len); |
2421 | ifsta->ssid_len = len; | 2476 | ifsta->ssid_len = len; |
2422 | ifsta->flags &= ~IEEE80211_STA_PREV_BSSID_SET; | 2477 | ifsta->flags &= ~IEEE80211_STA_PREV_BSSID_SET; |
2423 | |||
2424 | res = 0; | ||
2425 | /* | ||
2426 | * Hack! MLME code needs to be cleaned up to have different | ||
2427 | * entry points for configuration and internal selection change | ||
2428 | */ | ||
2429 | if (netif_running(sdata->dev)) | ||
2430 | res = ieee80211_if_config(sdata, IEEE80211_IFCC_SSID); | ||
2431 | if (res) { | ||
2432 | printk(KERN_DEBUG "%s: Failed to config new SSID to " | ||
2433 | "the low-level driver\n", sdata->dev->name); | ||
2434 | return res; | ||
2435 | } | ||
2436 | } | 2478 | } |
2437 | 2479 | ||
2438 | if (len) | 2480 | if (len) |
@@ -2560,3 +2602,39 @@ void ieee80211_mlme_notify_scan_completed(struct ieee80211_local *local) | |||
2560 | ieee80211_restart_sta_timer(sdata); | 2602 | ieee80211_restart_sta_timer(sdata); |
2561 | rcu_read_unlock(); | 2603 | rcu_read_unlock(); |
2562 | } | 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 | } | ||