aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/mlme.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/mlme.c')
-rw-r--r--net/mac80211/mlme.c606
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
571static u32 ieee80211_handle_protect_preamb(struct ieee80211_sub_if_data *sdata, 571static 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()) {
613static 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
623static 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
703static void ieee80211_set_associated(struct ieee80211_sub_if_data *sdata, 701static 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,
760static void ieee80211_direct_probe(struct ieee80211_sub_if_data *sdata, 764static 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,
791static void ieee80211_authenticate(struct ieee80211_sub_if_data *sdata, 794static 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 */
814static void ieee80211_set_disassoc(struct ieee80211_sub_if_data *sdata, 820static 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,
914static void ieee80211_associate(struct ieee80211_sub_if_data *sdata, 939static 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 */
2340struct sta_info *ieee80211_ibss_add_sta(struct ieee80211_sub_if_data *sdata, 2398struct 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,
2408int ieee80211_sta_set_ssid(struct ieee80211_sub_if_data *sdata, char *ssid, size_t len) 2464int 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
2606void 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
2621void 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
2635void 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}