aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/util.c')
-rw-r--r--net/mac80211/util.c476
1 files changed, 333 insertions, 143 deletions
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index fdf432f14554..915e77769312 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -20,27 +20,21 @@
20#include <linux/if_arp.h> 20#include <linux/if_arp.h>
21#include <linux/wireless.h> 21#include <linux/wireless.h>
22#include <linux/bitmap.h> 22#include <linux/bitmap.h>
23#include <linux/crc32.h>
23#include <net/net_namespace.h> 24#include <net/net_namespace.h>
24#include <net/cfg80211.h> 25#include <net/cfg80211.h>
25#include <net/rtnetlink.h> 26#include <net/rtnetlink.h>
26 27
27#include "ieee80211_i.h" 28#include "ieee80211_i.h"
29#include "driver-ops.h"
28#include "rate.h" 30#include "rate.h"
29#include "mesh.h" 31#include "mesh.h"
30#include "wme.h" 32#include "wme.h"
33#include "led.h"
31 34
32/* privid for wiphys to determine whether they belong to us or not */ 35/* privid for wiphys to determine whether they belong to us or not */
33void *mac80211_wiphy_privid = &mac80211_wiphy_privid; 36void *mac80211_wiphy_privid = &mac80211_wiphy_privid;
34 37
35/* See IEEE 802.1H for LLC/SNAP encapsulation/decapsulation */
36/* Ethernet-II snap header (RFC1042 for most EtherTypes) */
37const unsigned char rfc1042_header[] __aligned(2) =
38 { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0x00 };
39
40/* Bridge-Tunnel header (for EtherTypes ETH_P_AARP and ETH_P_IPX) */
41const unsigned char bridge_tunnel_header[] __aligned(2) =
42 { 0xaa, 0xaa, 0x03, 0x00, 0x00, 0xf8 };
43
44struct ieee80211_hw *wiphy_to_ieee80211_hw(struct wiphy *wiphy) 38struct ieee80211_hw *wiphy_to_ieee80211_hw(struct wiphy *wiphy)
45{ 39{
46 struct ieee80211_local *local; 40 struct ieee80211_local *local;
@@ -100,70 +94,6 @@ u8 *ieee80211_get_bssid(struct ieee80211_hdr *hdr, size_t len,
100 return NULL; 94 return NULL;
101} 95}
102 96
103unsigned int ieee80211_hdrlen(__le16 fc)
104{
105 unsigned int hdrlen = 24;
106
107 if (ieee80211_is_data(fc)) {
108 if (ieee80211_has_a4(fc))
109 hdrlen = 30;
110 if (ieee80211_is_data_qos(fc))
111 hdrlen += IEEE80211_QOS_CTL_LEN;
112 goto out;
113 }
114
115 if (ieee80211_is_ctl(fc)) {
116 /*
117 * ACK and CTS are 10 bytes, all others 16. To see how
118 * to get this condition consider
119 * subtype mask: 0b0000000011110000 (0x00F0)
120 * ACK subtype: 0b0000000011010000 (0x00D0)
121 * CTS subtype: 0b0000000011000000 (0x00C0)
122 * bits that matter: ^^^ (0x00E0)
123 * value of those: 0b0000000011000000 (0x00C0)
124 */
125 if ((fc & cpu_to_le16(0x00E0)) == cpu_to_le16(0x00C0))
126 hdrlen = 10;
127 else
128 hdrlen = 16;
129 }
130out:
131 return hdrlen;
132}
133EXPORT_SYMBOL(ieee80211_hdrlen);
134
135unsigned int ieee80211_get_hdrlen_from_skb(const struct sk_buff *skb)
136{
137 const struct ieee80211_hdr *hdr = (const struct ieee80211_hdr *)skb->data;
138 unsigned int hdrlen;
139
140 if (unlikely(skb->len < 10))
141 return 0;
142 hdrlen = ieee80211_hdrlen(hdr->frame_control);
143 if (unlikely(hdrlen > skb->len))
144 return 0;
145 return hdrlen;
146}
147EXPORT_SYMBOL(ieee80211_get_hdrlen_from_skb);
148
149int ieee80211_get_mesh_hdrlen(struct ieee80211s_hdr *meshhdr)
150{
151 int ae = meshhdr->flags & IEEE80211S_FLAGS_AE;
152 /* 7.1.3.5a.2 */
153 switch (ae) {
154 case 0:
155 return 6;
156 case 1:
157 return 12;
158 case 2:
159 return 18;
160 case 3:
161 return 24;
162 default:
163 return 6;
164 }
165}
166
167void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx) 97void ieee80211_tx_set_protected(struct ieee80211_tx_data *tx)
168{ 98{
169 struct sk_buff *skb = tx->skb; 99 struct sk_buff *skb = tx->skb;
@@ -411,6 +341,52 @@ void ieee80211_stop_queue(struct ieee80211_hw *hw, int queue)
411} 341}
412EXPORT_SYMBOL(ieee80211_stop_queue); 342EXPORT_SYMBOL(ieee80211_stop_queue);
413 343
344void ieee80211_add_pending_skb(struct ieee80211_local *local,
345 struct sk_buff *skb)
346{
347 struct ieee80211_hw *hw = &local->hw;
348 unsigned long flags;
349 int queue = skb_get_queue_mapping(skb);
350
351 spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
352 __ieee80211_stop_queue(hw, queue, IEEE80211_QUEUE_STOP_REASON_SKB_ADD);
353 __ieee80211_stop_queue(hw, queue, IEEE80211_QUEUE_STOP_REASON_PENDING);
354 skb_queue_tail(&local->pending[queue], skb);
355 __ieee80211_wake_queue(hw, queue, IEEE80211_QUEUE_STOP_REASON_SKB_ADD);
356 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
357}
358
359int ieee80211_add_pending_skbs(struct ieee80211_local *local,
360 struct sk_buff_head *skbs)
361{
362 struct ieee80211_hw *hw = &local->hw;
363 struct sk_buff *skb;
364 unsigned long flags;
365 int queue, ret = 0, i;
366
367 spin_lock_irqsave(&local->queue_stop_reason_lock, flags);
368 for (i = 0; i < hw->queues; i++)
369 __ieee80211_stop_queue(hw, i,
370 IEEE80211_QUEUE_STOP_REASON_SKB_ADD);
371
372 while ((skb = skb_dequeue(skbs))) {
373 ret++;
374 queue = skb_get_queue_mapping(skb);
375 skb_queue_tail(&local->pending[queue], skb);
376 }
377
378 for (i = 0; i < hw->queues; i++) {
379 if (ret)
380 __ieee80211_stop_queue(hw, i,
381 IEEE80211_QUEUE_STOP_REASON_PENDING);
382 __ieee80211_wake_queue(hw, i,
383 IEEE80211_QUEUE_STOP_REASON_SKB_ADD);
384 }
385 spin_unlock_irqrestore(&local->queue_stop_reason_lock, flags);
386
387 return ret;
388}
389
414void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw, 390void ieee80211_stop_queues_by_reason(struct ieee80211_hw *hw,
415 enum queue_stop_reason reason) 391 enum queue_stop_reason reason)
416{ 392{
@@ -536,8 +512,16 @@ EXPORT_SYMBOL_GPL(ieee80211_iterate_active_interfaces_atomic);
536void ieee802_11_parse_elems(u8 *start, size_t len, 512void ieee802_11_parse_elems(u8 *start, size_t len,
537 struct ieee802_11_elems *elems) 513 struct ieee802_11_elems *elems)
538{ 514{
515 ieee802_11_parse_elems_crc(start, len, elems, 0, 0);
516}
517
518u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
519 struct ieee802_11_elems *elems,
520 u64 filter, u32 crc)
521{
539 size_t left = len; 522 size_t left = len;
540 u8 *pos = start; 523 u8 *pos = start;
524 bool calc_crc = filter != 0;
541 525
542 memset(elems, 0, sizeof(*elems)); 526 memset(elems, 0, sizeof(*elems));
543 elems->ie_start = start; 527 elems->ie_start = start;
@@ -551,7 +535,10 @@ void ieee802_11_parse_elems(u8 *start, size_t len,
551 left -= 2; 535 left -= 2;
552 536
553 if (elen > left) 537 if (elen > left)
554 return; 538 break;
539
540 if (calc_crc && id < 64 && (filter & BIT(id)))
541 crc = crc32_be(crc, pos - 2, elen + 2);
555 542
556 switch (id) { 543 switch (id) {
557 case WLAN_EID_SSID: 544 case WLAN_EID_SSID:
@@ -575,8 +562,10 @@ void ieee802_11_parse_elems(u8 *start, size_t len,
575 elems->cf_params_len = elen; 562 elems->cf_params_len = elen;
576 break; 563 break;
577 case WLAN_EID_TIM: 564 case WLAN_EID_TIM:
578 elems->tim = pos; 565 if (elen >= sizeof(struct ieee80211_tim_ie)) {
579 elems->tim_len = elen; 566 elems->tim = (void *)pos;
567 elems->tim_len = elen;
568 }
580 break; 569 break;
581 case WLAN_EID_IBSS_PARAMS: 570 case WLAN_EID_IBSS_PARAMS:
582 elems->ibss_params = pos; 571 elems->ibss_params = pos;
@@ -586,15 +575,20 @@ void ieee802_11_parse_elems(u8 *start, size_t len,
586 elems->challenge = pos; 575 elems->challenge = pos;
587 elems->challenge_len = elen; 576 elems->challenge_len = elen;
588 break; 577 break;
589 case WLAN_EID_WPA: 578 case WLAN_EID_VENDOR_SPECIFIC:
590 if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 && 579 if (elen >= 4 && pos[0] == 0x00 && pos[1] == 0x50 &&
591 pos[2] == 0xf2) { 580 pos[2] == 0xf2) {
592 /* Microsoft OUI (00:50:F2) */ 581 /* Microsoft OUI (00:50:F2) */
582
583 if (calc_crc)
584 crc = crc32_be(crc, pos - 2, elen + 2);
585
593 if (pos[3] == 1) { 586 if (pos[3] == 1) {
594 /* OUI Type 1 - WPA IE */ 587 /* OUI Type 1 - WPA IE */
595 elems->wpa = pos; 588 elems->wpa = pos;
596 elems->wpa_len = elen; 589 elems->wpa_len = elen;
597 } else if (elen >= 5 && pos[3] == 2) { 590 } else if (elen >= 5 && pos[3] == 2) {
591 /* OUI Type 2 - WMM IE */
598 if (pos[4] == 0) { 592 if (pos[4] == 0) {
599 elems->wmm_info = pos; 593 elems->wmm_info = pos;
600 elems->wmm_info_len = elen; 594 elems->wmm_info_len = elen;
@@ -679,32 +673,70 @@ void ieee802_11_parse_elems(u8 *start, size_t len,
679 left -= elen; 673 left -= elen;
680 pos += elen; 674 pos += elen;
681 } 675 }
676
677 return crc;
682} 678}
683 679
684void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata) 680void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata)
685{ 681{
686 struct ieee80211_local *local = sdata->local; 682 struct ieee80211_local *local = sdata->local;
687 struct ieee80211_tx_queue_params qparam; 683 struct ieee80211_tx_queue_params qparam;
688 int i; 684 int queue;
685 bool use_11b;
686 int aCWmin, aCWmax;
689 687
690 if (!local->ops->conf_tx) 688 if (!local->ops->conf_tx)
691 return; 689 return;
692 690
693 memset(&qparam, 0, sizeof(qparam)); 691 memset(&qparam, 0, sizeof(qparam));
694 692
695 qparam.aifs = 2; 693 use_11b = (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ) &&
696 694 !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE);
697 if (local->hw.conf.channel->band == IEEE80211_BAND_2GHZ &&
698 !(sdata->flags & IEEE80211_SDATA_OPERATING_GMODE))
699 qparam.cw_min = 31;
700 else
701 qparam.cw_min = 15;
702 695
703 qparam.cw_max = 1023; 696 for (queue = 0; queue < local_to_hw(local)->queues; queue++) {
704 qparam.txop = 0; 697 /* Set defaults according to 802.11-2007 Table 7-37 */
698 aCWmax = 1023;
699 if (use_11b)
700 aCWmin = 31;
701 else
702 aCWmin = 15;
703
704 switch (queue) {
705 case 3: /* AC_BK */
706 qparam.cw_max = aCWmax;
707 qparam.cw_min = aCWmin;
708 qparam.txop = 0;
709 qparam.aifs = 7;
710 break;
711 default: /* never happens but let's not leave undefined */
712 case 2: /* AC_BE */
713 qparam.cw_max = aCWmax;
714 qparam.cw_min = aCWmin;
715 qparam.txop = 0;
716 qparam.aifs = 3;
717 break;
718 case 1: /* AC_VI */
719 qparam.cw_max = aCWmin;
720 qparam.cw_min = (aCWmin + 1) / 2 - 1;
721 if (use_11b)
722 qparam.txop = 6016/32;
723 else
724 qparam.txop = 3008/32;
725 qparam.aifs = 2;
726 break;
727 case 0: /* AC_VO */
728 qparam.cw_max = (aCWmin + 1) / 2 - 1;
729 qparam.cw_min = (aCWmin + 1) / 4 - 1;
730 if (use_11b)
731 qparam.txop = 3264/32;
732 else
733 qparam.txop = 1504/32;
734 qparam.aifs = 2;
735 break;
736 }
705 737
706 for (i = 0; i < local_to_hw(local)->queues; i++) 738 drv_conf_tx(local, queue, &qparam);
707 local->ops->conf_tx(local_to_hw(local), i, &qparam); 739 }
708} 740}
709 741
710void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata, 742void ieee80211_sta_def_wmm_params(struct ieee80211_sub_if_data *sdata,
@@ -742,31 +774,6 @@ void ieee80211_tx_skb(struct ieee80211_sub_if_data *sdata, struct sk_buff *skb,
742 dev_queue_xmit(skb); 774 dev_queue_xmit(skb);
743} 775}
744 776
745int ieee80211_set_freq(struct ieee80211_sub_if_data *sdata, int freqMHz)
746{
747 int ret = -EINVAL;
748 struct ieee80211_channel *chan;
749 struct ieee80211_local *local = sdata->local;
750
751 chan = ieee80211_get_channel(local->hw.wiphy, freqMHz);
752
753 if (chan && !(chan->flags & IEEE80211_CHAN_DISABLED)) {
754 if (sdata->vif.type == NL80211_IFTYPE_ADHOC &&
755 chan->flags & IEEE80211_CHAN_NO_IBSS)
756 return ret;
757 local->oper_channel = chan;
758 local->oper_channel_type = NL80211_CHAN_NO_HT;
759
760 if (local->sw_scanning || local->hw_scanning)
761 ret = 0;
762 else
763 ret = ieee80211_hw_config(
764 local, IEEE80211_CONF_CHANGE_CHANNEL);
765 }
766
767 return ret;
768}
769
770u32 ieee80211_mandatory_rates(struct ieee80211_local *local, 777u32 ieee80211_mandatory_rates(struct ieee80211_local *local,
771 enum ieee80211_band band) 778 enum ieee80211_band band)
772{ 779{
@@ -831,16 +838,73 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
831 ieee80211_tx_skb(sdata, skb, encrypt); 838 ieee80211_tx_skb(sdata, skb, encrypt);
832} 839}
833 840
841int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
842 const u8 *ie, size_t ie_len)
843{
844 struct ieee80211_supported_band *sband;
845 u8 *pos, *supp_rates_len, *esupp_rates_len = NULL;
846 int i;
847
848 sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
849
850 pos = buffer;
851
852 *pos++ = WLAN_EID_SUPP_RATES;
853 supp_rates_len = pos;
854 *pos++ = 0;
855
856 for (i = 0; i < sband->n_bitrates; i++) {
857 struct ieee80211_rate *rate = &sband->bitrates[i];
858
859 if (esupp_rates_len) {
860 *esupp_rates_len += 1;
861 } else if (*supp_rates_len == 8) {
862 *pos++ = WLAN_EID_EXT_SUPP_RATES;
863 esupp_rates_len = pos;
864 *pos++ = 1;
865 } else
866 *supp_rates_len += 1;
867
868 *pos++ = rate->bitrate / 5;
869 }
870
871 if (sband->ht_cap.ht_supported) {
872 __le16 tmp = cpu_to_le16(sband->ht_cap.cap);
873
874 *pos++ = WLAN_EID_HT_CAPABILITY;
875 *pos++ = sizeof(struct ieee80211_ht_cap);
876 memset(pos, 0, sizeof(struct ieee80211_ht_cap));
877 memcpy(pos, &tmp, sizeof(u16));
878 pos += sizeof(u16);
879 /* TODO: needs a define here for << 2 */
880 *pos++ = sband->ht_cap.ampdu_factor |
881 (sband->ht_cap.ampdu_density << 2);
882 memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs));
883 pos += sizeof(sband->ht_cap.mcs);
884 pos += 2 + 4 + 1; /* ext info, BF cap, antsel */
885 }
886
887 /*
888 * If adding more here, adjust code in main.c
889 * that calculates local->scan_ies_len.
890 */
891
892 if (ie) {
893 memcpy(pos, ie, ie_len);
894 pos += ie_len;
895 }
896
897 return pos - buffer;
898}
899
834void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst, 900void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
835 u8 *ssid, size_t ssid_len, 901 const u8 *ssid, size_t ssid_len,
836 u8 *ie, size_t ie_len) 902 const u8 *ie, size_t ie_len)
837{ 903{
838 struct ieee80211_local *local = sdata->local; 904 struct ieee80211_local *local = sdata->local;
839 struct ieee80211_supported_band *sband;
840 struct sk_buff *skb; 905 struct sk_buff *skb;
841 struct ieee80211_mgmt *mgmt; 906 struct ieee80211_mgmt *mgmt;
842 u8 *pos, *supp_rates, *esupp_rates = NULL; 907 u8 *pos;
843 int i;
844 908
845 skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + 200 + 909 skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + 200 +
846 ie_len); 910 ie_len);
@@ -867,31 +931,9 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
867 *pos++ = WLAN_EID_SSID; 931 *pos++ = WLAN_EID_SSID;
868 *pos++ = ssid_len; 932 *pos++ = ssid_len;
869 memcpy(pos, ssid, ssid_len); 933 memcpy(pos, ssid, ssid_len);
934 pos += ssid_len;
870 935
871 supp_rates = skb_put(skb, 2); 936 skb_put(skb, ieee80211_build_preq_ies(local, pos, ie, ie_len));
872 supp_rates[0] = WLAN_EID_SUPP_RATES;
873 supp_rates[1] = 0;
874 sband = local->hw.wiphy->bands[local->hw.conf.channel->band];
875
876 for (i = 0; i < sband->n_bitrates; i++) {
877 struct ieee80211_rate *rate = &sband->bitrates[i];
878 if (esupp_rates) {
879 pos = skb_put(skb, 1);
880 esupp_rates[1]++;
881 } else if (supp_rates[1] == 8) {
882 esupp_rates = skb_put(skb, 3);
883 esupp_rates[0] = WLAN_EID_EXT_SUPP_RATES;
884 esupp_rates[1] = 1;
885 pos = &esupp_rates[2];
886 } else {
887 pos = skb_put(skb, 1);
888 supp_rates[1]++;
889 }
890 *pos = rate->bitrate / 5;
891 }
892
893 if (ie)
894 memcpy(skb_put(skb, ie_len), ie, ie_len);
895 937
896 ieee80211_tx_skb(sdata, skb, 0); 938 ieee80211_tx_skb(sdata, skb, 0);
897} 939}
@@ -931,3 +973,151 @@ u32 ieee80211_sta_get_rates(struct ieee80211_local *local,
931 } 973 }
932 return supp_rates; 974 return supp_rates;
933} 975}
976
977int ieee80211_reconfig(struct ieee80211_local *local)
978{
979 struct ieee80211_hw *hw = &local->hw;
980 struct ieee80211_sub_if_data *sdata;
981 struct ieee80211_if_init_conf conf;
982 struct sta_info *sta;
983 unsigned long flags;
984 int res;
985 bool from_suspend = local->suspended;
986
987 /*
988 * We're going to start the hardware, at that point
989 * we are no longer suspended and can RX frames.
990 */
991 local->suspended = false;
992
993 /* restart hardware */
994 if (local->open_count) {
995 res = drv_start(local);
996
997 ieee80211_led_radio(local, true);
998 }
999
1000 /* add interfaces */
1001 list_for_each_entry(sdata, &local->interfaces, list) {
1002 if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
1003 sdata->vif.type != NL80211_IFTYPE_MONITOR &&
1004 netif_running(sdata->dev)) {
1005 conf.vif = &sdata->vif;
1006 conf.type = sdata->vif.type;
1007 conf.mac_addr = sdata->dev->dev_addr;
1008 res = drv_add_interface(local, &conf);
1009 }
1010 }
1011
1012 /* add STAs back */
1013 if (local->ops->sta_notify) {
1014 spin_lock_irqsave(&local->sta_lock, flags);
1015 list_for_each_entry(sta, &local->sta_list, list) {
1016 sdata = sta->sdata;
1017 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
1018 sdata = container_of(sdata->bss,
1019 struct ieee80211_sub_if_data,
1020 u.ap);
1021
1022 drv_sta_notify(local, &sdata->vif, STA_NOTIFY_ADD,
1023 &sta->sta);
1024 }
1025 spin_unlock_irqrestore(&local->sta_lock, flags);
1026 }
1027
1028 /* Clear Suspend state so that ADDBA requests can be processed */
1029
1030 rcu_read_lock();
1031
1032 if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) {
1033 list_for_each_entry_rcu(sta, &local->sta_list, list) {
1034 clear_sta_flags(sta, WLAN_STA_SUSPEND);
1035 }
1036 }
1037
1038 rcu_read_unlock();
1039
1040 /* setup RTS threshold */
1041 drv_set_rts_threshold(local, hw->wiphy->rts_threshold);
1042
1043 /* reconfigure hardware */
1044 ieee80211_hw_config(local, ~0);
1045
1046 netif_addr_lock_bh(local->mdev);
1047 ieee80211_configure_filter(local);
1048 netif_addr_unlock_bh(local->mdev);
1049
1050 /* Finally also reconfigure all the BSS information */
1051 list_for_each_entry(sdata, &local->interfaces, list) {
1052 u32 changed = ~0;
1053 if (!netif_running(sdata->dev))
1054 continue;
1055 switch (sdata->vif.type) {
1056 case NL80211_IFTYPE_STATION:
1057 /* disable beacon change bits */
1058 changed &= ~(BSS_CHANGED_BEACON |
1059 BSS_CHANGED_BEACON_ENABLED);
1060 /* fall through */
1061 case NL80211_IFTYPE_ADHOC:
1062 case NL80211_IFTYPE_AP:
1063 case NL80211_IFTYPE_MESH_POINT:
1064 ieee80211_bss_info_change_notify(sdata, changed);
1065 break;
1066 case NL80211_IFTYPE_WDS:
1067 break;
1068 case NL80211_IFTYPE_AP_VLAN:
1069 case NL80211_IFTYPE_MONITOR:
1070 /* ignore virtual */
1071 break;
1072 case NL80211_IFTYPE_UNSPECIFIED:
1073 case __NL80211_IFTYPE_AFTER_LAST:
1074 WARN_ON(1);
1075 break;
1076 }
1077 }
1078
1079 /* add back keys */
1080 list_for_each_entry(sdata, &local->interfaces, list)
1081 if (netif_running(sdata->dev))
1082 ieee80211_enable_keys(sdata);
1083
1084 ieee80211_wake_queues_by_reason(hw,
1085 IEEE80211_QUEUE_STOP_REASON_SUSPEND);
1086
1087 /*
1088 * If this is for hw restart things are still running.
1089 * We may want to change that later, however.
1090 */
1091 if (!from_suspend)
1092 return 0;
1093
1094#ifdef CONFIG_PM
1095 local->suspended = false;
1096
1097 list_for_each_entry(sdata, &local->interfaces, list) {
1098 switch(sdata->vif.type) {
1099 case NL80211_IFTYPE_STATION:
1100 ieee80211_sta_restart(sdata);
1101 break;
1102 case NL80211_IFTYPE_ADHOC:
1103 ieee80211_ibss_restart(sdata);
1104 break;
1105 case NL80211_IFTYPE_MESH_POINT:
1106 ieee80211_mesh_restart(sdata);
1107 break;
1108 default:
1109 break;
1110 }
1111 }
1112
1113 add_timer(&local->sta_cleanup);
1114
1115 spin_lock_irqsave(&local->sta_lock, flags);
1116 list_for_each_entry(sta, &local->sta_list, list)
1117 mesh_plink_restart(sta);
1118 spin_unlock_irqrestore(&local->sta_lock, flags);
1119#else
1120 WARN_ON(1);
1121#endif
1122 return 0;
1123}