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.c363
1 files changed, 283 insertions, 80 deletions
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index e6c08da8da26..53af57047435 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -18,7 +18,6 @@
18#include <linux/skbuff.h> 18#include <linux/skbuff.h>
19#include <linux/etherdevice.h> 19#include <linux/etherdevice.h>
20#include <linux/if_arp.h> 20#include <linux/if_arp.h>
21#include <linux/wireless.h>
22#include <linux/bitmap.h> 21#include <linux/bitmap.h>
23#include <linux/crc32.h> 22#include <linux/crc32.h>
24#include <net/net_namespace.h> 23#include <net/net_namespace.h>
@@ -269,6 +268,7 @@ static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue,
269 enum queue_stop_reason reason) 268 enum queue_stop_reason reason)
270{ 269{
271 struct ieee80211_local *local = hw_to_local(hw); 270 struct ieee80211_local *local = hw_to_local(hw);
271 struct ieee80211_sub_if_data *sdata;
272 272
273 if (WARN_ON(queue >= hw->queues)) 273 if (WARN_ON(queue >= hw->queues))
274 return; 274 return;
@@ -279,7 +279,12 @@ static void __ieee80211_wake_queue(struct ieee80211_hw *hw, int queue,
279 /* someone still has this queue stopped */ 279 /* someone still has this queue stopped */
280 return; 280 return;
281 281
282 if (!skb_queue_empty(&local->pending[queue])) 282 if (skb_queue_empty(&local->pending[queue])) {
283 rcu_read_lock();
284 list_for_each_entry_rcu(sdata, &local->interfaces, list)
285 netif_tx_wake_queue(netdev_get_tx_queue(sdata->dev, queue));
286 rcu_read_unlock();
287 } else
283 tasklet_schedule(&local->tx_pending_tasklet); 288 tasklet_schedule(&local->tx_pending_tasklet);
284} 289}
285 290
@@ -305,11 +310,17 @@ static void __ieee80211_stop_queue(struct ieee80211_hw *hw, int queue,
305 enum queue_stop_reason reason) 310 enum queue_stop_reason reason)
306{ 311{
307 struct ieee80211_local *local = hw_to_local(hw); 312 struct ieee80211_local *local = hw_to_local(hw);
313 struct ieee80211_sub_if_data *sdata;
308 314
309 if (WARN_ON(queue >= hw->queues)) 315 if (WARN_ON(queue >= hw->queues))
310 return; 316 return;
311 317
312 __set_bit(reason, &local->queue_stop_reasons[queue]); 318 __set_bit(reason, &local->queue_stop_reasons[queue]);
319
320 rcu_read_lock();
321 list_for_each_entry_rcu(sdata, &local->interfaces, list)
322 netif_tx_stop_queue(netdev_get_tx_queue(sdata->dev, queue));
323 rcu_read_unlock();
313} 324}
314 325
315void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue, 326void ieee80211_stop_queue_by_reason(struct ieee80211_hw *hw, int queue,
@@ -468,8 +479,8 @@ void ieee80211_iterate_active_interfaces(
468 case NL80211_IFTYPE_MESH_POINT: 479 case NL80211_IFTYPE_MESH_POINT:
469 break; 480 break;
470 } 481 }
471 if (netif_running(sdata->dev)) 482 if (ieee80211_sdata_running(sdata))
472 iterator(data, sdata->dev->dev_addr, 483 iterator(data, sdata->vif.addr,
473 &sdata->vif); 484 &sdata->vif);
474 } 485 }
475 486
@@ -502,8 +513,8 @@ void ieee80211_iterate_active_interfaces_atomic(
502 case NL80211_IFTYPE_MESH_POINT: 513 case NL80211_IFTYPE_MESH_POINT:
503 break; 514 break;
504 } 515 }
505 if (netif_running(sdata->dev)) 516 if (ieee80211_sdata_running(sdata))
506 iterator(data, sdata->dev->dev_addr, 517 iterator(data, sdata->vif.addr,
507 &sdata->vif); 518 &sdata->vif);
508 } 519 }
509 520
@@ -579,7 +590,7 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
579 if (elen > left) 590 if (elen > left)
580 break; 591 break;
581 592
582 if (calc_crc && id < 64 && (filter & BIT(id))) 593 if (calc_crc && id < 64 && (filter & (1ULL << id)))
583 crc = crc32_be(crc, pos - 2, elen + 2); 594 crc = crc32_be(crc, pos - 2, elen + 2);
584 595
585 switch (id) { 596 switch (id) {
@@ -666,8 +677,8 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
666 elems->mesh_id_len = elen; 677 elems->mesh_id_len = elen;
667 break; 678 break;
668 case WLAN_EID_MESH_CONFIG: 679 case WLAN_EID_MESH_CONFIG:
669 elems->mesh_config = pos; 680 if (elen >= sizeof(struct ieee80211_meshconf_ie))
670 elems->mesh_config_len = elen; 681 elems->mesh_config = (void *)pos;
671 break; 682 break;
672 case WLAN_EID_PEER_LINK: 683 case WLAN_EID_PEER_LINK:
673 elems->peer_link = pos; 684 elems->peer_link = pos;
@@ -685,6 +696,10 @@ u32 ieee802_11_parse_elems_crc(u8 *start, size_t len,
685 elems->perr = pos; 696 elems->perr = pos;
686 elems->perr_len = elen; 697 elems->perr_len = elen;
687 break; 698 break;
699 case WLAN_EID_RANN:
700 if (elen >= sizeof(struct ieee80211_rann_ie))
701 elems->rann = (void *)pos;
702 break;
688 case WLAN_EID_CHANNEL_SWITCH: 703 case WLAN_EID_CHANNEL_SWITCH:
689 elems->ch_switch_elem = pos; 704 elems->ch_switch_elem = pos;
690 elems->ch_switch_elem_len = elen; 705 elems->ch_switch_elem_len = elen;
@@ -777,6 +792,8 @@ void ieee80211_set_wmm_default(struct ieee80211_sub_if_data *sdata)
777 break; 792 break;
778 } 793 }
779 794
795 qparam.uapsd = false;
796
780 drv_conf_tx(local, queue, &qparam); 797 drv_conf_tx(local, queue, &qparam);
781 } 798 }
782} 799}
@@ -844,7 +861,7 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
844 sizeof(*mgmt) + 6 + extra_len); 861 sizeof(*mgmt) + 6 + extra_len);
845 if (!skb) { 862 if (!skb) {
846 printk(KERN_DEBUG "%s: failed to allocate buffer for auth " 863 printk(KERN_DEBUG "%s: failed to allocate buffer for auth "
847 "frame\n", sdata->dev->name); 864 "frame\n", sdata->name);
848 return; 865 return;
849 } 866 }
850 skb_reserve(skb, local->hw.extra_tx_headroom); 867 skb_reserve(skb, local->hw.extra_tx_headroom);
@@ -854,7 +871,7 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
854 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | 871 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
855 IEEE80211_STYPE_AUTH); 872 IEEE80211_STYPE_AUTH);
856 memcpy(mgmt->da, bssid, ETH_ALEN); 873 memcpy(mgmt->da, bssid, ETH_ALEN);
857 memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); 874 memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
858 memcpy(mgmt->bssid, bssid, ETH_ALEN); 875 memcpy(mgmt->bssid, bssid, ETH_ALEN);
859 mgmt->u.auth.auth_alg = cpu_to_le16(auth_alg); 876 mgmt->u.auth.auth_alg = cpu_to_le16(auth_alg);
860 mgmt->u.auth.auth_transaction = cpu_to_le16(transaction); 877 mgmt->u.auth.auth_transaction = cpu_to_le16(transaction);
@@ -868,50 +885,96 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
868 WARN_ON(err); 885 WARN_ON(err);
869 } 886 }
870 887
871 ieee80211_tx_skb(sdata, skb, 0); 888 IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
889 ieee80211_tx_skb(sdata, skb);
872} 890}
873 891
874int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer, 892int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
875 const u8 *ie, size_t ie_len) 893 const u8 *ie, size_t ie_len,
894 enum ieee80211_band band)
876{ 895{
877 struct ieee80211_supported_band *sband; 896 struct ieee80211_supported_band *sband;
878 u8 *pos, *supp_rates_len, *esupp_rates_len = NULL; 897 u8 *pos;
879 int i; 898 size_t offset = 0, noffset;
899 int supp_rates_len, i;
880 900
881 sband = local->hw.wiphy->bands[local->hw.conf.channel->band]; 901 sband = local->hw.wiphy->bands[band];
882 902
883 pos = buffer; 903 pos = buffer;
884 904
905 supp_rates_len = min_t(int, sband->n_bitrates, 8);
906
885 *pos++ = WLAN_EID_SUPP_RATES; 907 *pos++ = WLAN_EID_SUPP_RATES;
886 supp_rates_len = pos; 908 *pos++ = supp_rates_len;
887 *pos++ = 0;
888
889 for (i = 0; i < sband->n_bitrates; i++) {
890 struct ieee80211_rate *rate = &sband->bitrates[i];
891
892 if (esupp_rates_len) {
893 *esupp_rates_len += 1;
894 } else if (*supp_rates_len == 8) {
895 *pos++ = WLAN_EID_EXT_SUPP_RATES;
896 esupp_rates_len = pos;
897 *pos++ = 1;
898 } else
899 *supp_rates_len += 1;
900 909
901 *pos++ = rate->bitrate / 5; 910 for (i = 0; i < supp_rates_len; i++) {
911 int rate = sband->bitrates[i].bitrate;
912 *pos++ = (u8) (rate / 5);
913 }
914
915 /* insert "request information" if in custom IEs */
916 if (ie && ie_len) {
917 static const u8 before_extrates[] = {
918 WLAN_EID_SSID,
919 WLAN_EID_SUPP_RATES,
920 WLAN_EID_REQUEST,
921 };
922 noffset = ieee80211_ie_split(ie, ie_len,
923 before_extrates,
924 ARRAY_SIZE(before_extrates),
925 offset);
926 memcpy(pos, ie + offset, noffset - offset);
927 pos += noffset - offset;
928 offset = noffset;
929 }
930
931 if (sband->n_bitrates > i) {
932 *pos++ = WLAN_EID_EXT_SUPP_RATES;
933 *pos++ = sband->n_bitrates - i;
934
935 for (; i < sband->n_bitrates; i++) {
936 int rate = sband->bitrates[i].bitrate;
937 *pos++ = (u8) (rate / 5);
938 }
939 }
940
941 /* insert custom IEs that go before HT */
942 if (ie && ie_len) {
943 static const u8 before_ht[] = {
944 WLAN_EID_SSID,
945 WLAN_EID_SUPP_RATES,
946 WLAN_EID_REQUEST,
947 WLAN_EID_EXT_SUPP_RATES,
948 WLAN_EID_DS_PARAMS,
949 WLAN_EID_SUPPORTED_REGULATORY_CLASSES,
950 };
951 noffset = ieee80211_ie_split(ie, ie_len,
952 before_ht, ARRAY_SIZE(before_ht),
953 offset);
954 memcpy(pos, ie + offset, noffset - offset);
955 pos += noffset - offset;
956 offset = noffset;
902 } 957 }
903 958
904 if (sband->ht_cap.ht_supported) { 959 if (sband->ht_cap.ht_supported) {
905 __le16 tmp = cpu_to_le16(sband->ht_cap.cap); 960 u16 cap = sband->ht_cap.cap;
961 __le16 tmp;
962
963 if (ieee80211_disable_40mhz_24ghz &&
964 sband->band == IEEE80211_BAND_2GHZ) {
965 cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
966 cap &= ~IEEE80211_HT_CAP_SGI_40;
967 }
906 968
907 *pos++ = WLAN_EID_HT_CAPABILITY; 969 *pos++ = WLAN_EID_HT_CAPABILITY;
908 *pos++ = sizeof(struct ieee80211_ht_cap); 970 *pos++ = sizeof(struct ieee80211_ht_cap);
909 memset(pos, 0, sizeof(struct ieee80211_ht_cap)); 971 memset(pos, 0, sizeof(struct ieee80211_ht_cap));
972 tmp = cpu_to_le16(cap);
910 memcpy(pos, &tmp, sizeof(u16)); 973 memcpy(pos, &tmp, sizeof(u16));
911 pos += sizeof(u16); 974 pos += sizeof(u16);
912 /* TODO: needs a define here for << 2 */
913 *pos++ = sband->ht_cap.ampdu_factor | 975 *pos++ = sband->ht_cap.ampdu_factor |
914 (sband->ht_cap.ampdu_density << 2); 976 (sband->ht_cap.ampdu_density <<
977 IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT);
915 memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs)); 978 memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs));
916 pos += sizeof(sband->ht_cap.mcs); 979 pos += sizeof(sband->ht_cap.mcs);
917 pos += 2 + 4 + 1; /* ext info, BF cap, antsel */ 980 pos += 2 + 4 + 1; /* ext info, BF cap, antsel */
@@ -922,9 +985,11 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
922 * that calculates local->scan_ies_len. 985 * that calculates local->scan_ies_len.
923 */ 986 */
924 987
925 if (ie) { 988 /* add any remaining custom IEs */
926 memcpy(pos, ie, ie_len); 989 if (ie && ie_len) {
927 pos += ie_len; 990 noffset = ie_len;
991 memcpy(pos, ie + offset, noffset - offset);
992 pos += noffset - offset;
928 } 993 }
929 994
930 return pos - buffer; 995 return pos - buffer;
@@ -937,38 +1002,33 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
937 struct ieee80211_local *local = sdata->local; 1002 struct ieee80211_local *local = sdata->local;
938 struct sk_buff *skb; 1003 struct sk_buff *skb;
939 struct ieee80211_mgmt *mgmt; 1004 struct ieee80211_mgmt *mgmt;
940 u8 *pos; 1005 size_t buf_len;
941 1006 u8 *buf;
942 skb = dev_alloc_skb(local->hw.extra_tx_headroom + sizeof(*mgmt) + 200 + 1007
943 ie_len); 1008 /* FIXME: come up with a proper value */
944 if (!skb) { 1009 buf = kmalloc(200 + ie_len, GFP_KERNEL);
945 printk(KERN_DEBUG "%s: failed to allocate buffer for probe " 1010 if (!buf) {
946 "request\n", sdata->dev->name); 1011 printk(KERN_DEBUG "%s: failed to allocate temporary IE "
1012 "buffer\n", sdata->name);
947 return; 1013 return;
948 } 1014 }
949 skb_reserve(skb, local->hw.extra_tx_headroom);
950 1015
951 mgmt = (struct ieee80211_mgmt *) skb_put(skb, 24); 1016 buf_len = ieee80211_build_preq_ies(local, buf, ie, ie_len,
952 memset(mgmt, 0, 24); 1017 local->hw.conf.channel->band);
953 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | 1018
954 IEEE80211_STYPE_PROBE_REQ); 1019 skb = ieee80211_probereq_get(&local->hw, &sdata->vif,
955 memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); 1020 ssid, ssid_len,
1021 buf, buf_len);
1022
956 if (dst) { 1023 if (dst) {
1024 mgmt = (struct ieee80211_mgmt *) skb->data;
957 memcpy(mgmt->da, dst, ETH_ALEN); 1025 memcpy(mgmt->da, dst, ETH_ALEN);
958 memcpy(mgmt->bssid, dst, ETH_ALEN); 1026 memcpy(mgmt->bssid, dst, ETH_ALEN);
959 } else {
960 memset(mgmt->da, 0xff, ETH_ALEN);
961 memset(mgmt->bssid, 0xff, ETH_ALEN);
962 } 1027 }
963 pos = skb_put(skb, 2 + ssid_len);
964 *pos++ = WLAN_EID_SSID;
965 *pos++ = ssid_len;
966 memcpy(pos, ssid, ssid_len);
967 pos += ssid_len;
968 1028
969 skb_put(skb, ieee80211_build_preq_ies(local, pos, ie, ie_len)); 1029 IEEE80211_SKB_CB(skb)->flags |= IEEE80211_TX_INTFL_DONT_ENCRYPT;
970 1030 ieee80211_tx_skb(sdata, skb);
971 ieee80211_tx_skb(sdata, skb, 0); 1031 kfree(buf);
972} 1032}
973 1033
974u32 ieee80211_sta_get_rates(struct ieee80211_local *local, 1034u32 ieee80211_sta_get_rates(struct ieee80211_local *local,
@@ -1012,18 +1072,16 @@ void ieee80211_stop_device(struct ieee80211_local *local)
1012 ieee80211_led_radio(local, false); 1072 ieee80211_led_radio(local, false);
1013 1073
1014 cancel_work_sync(&local->reconfig_filter); 1074 cancel_work_sync(&local->reconfig_filter);
1015 drv_stop(local);
1016 1075
1017 flush_workqueue(local->workqueue); 1076 flush_workqueue(local->workqueue);
1077 drv_stop(local);
1018} 1078}
1019 1079
1020int ieee80211_reconfig(struct ieee80211_local *local) 1080int ieee80211_reconfig(struct ieee80211_local *local)
1021{ 1081{
1022 struct ieee80211_hw *hw = &local->hw; 1082 struct ieee80211_hw *hw = &local->hw;
1023 struct ieee80211_sub_if_data *sdata; 1083 struct ieee80211_sub_if_data *sdata;
1024 struct ieee80211_if_init_conf conf;
1025 struct sta_info *sta; 1084 struct sta_info *sta;
1026 unsigned long flags;
1027 int res; 1085 int res;
1028 1086
1029 if (local->suspended) 1087 if (local->suspended)
@@ -1031,7 +1089,19 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1031 1089
1032 /* restart hardware */ 1090 /* restart hardware */
1033 if (local->open_count) { 1091 if (local->open_count) {
1092 /*
1093 * Upon resume hardware can sometimes be goofy due to
1094 * various platform / driver / bus issues, so restarting
1095 * the device may at times not work immediately. Propagate
1096 * the error.
1097 */
1034 res = drv_start(local); 1098 res = drv_start(local);
1099 if (res) {
1100 WARN(local->suspended, "Hardware became unavailable "
1101 "upon resume. This could be a software issue "
1102 "prior to suspend or a hardware issue.\n");
1103 return res;
1104 }
1035 1105
1036 ieee80211_led_radio(local, true); 1106 ieee80211_led_radio(local, true);
1037 } 1107 }
@@ -1040,29 +1110,24 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1040 list_for_each_entry(sdata, &local->interfaces, list) { 1110 list_for_each_entry(sdata, &local->interfaces, list) {
1041 if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN && 1111 if (sdata->vif.type != NL80211_IFTYPE_AP_VLAN &&
1042 sdata->vif.type != NL80211_IFTYPE_MONITOR && 1112 sdata->vif.type != NL80211_IFTYPE_MONITOR &&
1043 netif_running(sdata->dev)) { 1113 ieee80211_sdata_running(sdata))
1044 conf.vif = &sdata->vif; 1114 res = drv_add_interface(local, &sdata->vif);
1045 conf.type = sdata->vif.type;
1046 conf.mac_addr = sdata->dev->dev_addr;
1047 res = drv_add_interface(local, &conf);
1048 }
1049 } 1115 }
1050 1116
1051 /* add STAs back */ 1117 /* add STAs back */
1052 if (local->ops->sta_notify) { 1118 mutex_lock(&local->sta_mtx);
1053 spin_lock_irqsave(&local->sta_lock, flags); 1119 list_for_each_entry(sta, &local->sta_list, list) {
1054 list_for_each_entry(sta, &local->sta_list, list) { 1120 if (sta->uploaded) {
1055 sdata = sta->sdata; 1121 sdata = sta->sdata;
1056 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN) 1122 if (sdata->vif.type == NL80211_IFTYPE_AP_VLAN)
1057 sdata = container_of(sdata->bss, 1123 sdata = container_of(sdata->bss,
1058 struct ieee80211_sub_if_data, 1124 struct ieee80211_sub_if_data,
1059 u.ap); 1125 u.ap);
1060 1126
1061 drv_sta_notify(local, &sdata->vif, STA_NOTIFY_ADD, 1127 WARN_ON(drv_sta_add(local, sdata, &sta->sta));
1062 &sta->sta);
1063 } 1128 }
1064 spin_unlock_irqrestore(&local->sta_lock, flags);
1065 } 1129 }
1130 mutex_unlock(&local->sta_mtx);
1066 1131
1067 /* Clear Suspend state so that ADDBA requests can be processed */ 1132 /* Clear Suspend state so that ADDBA requests can be processed */
1068 1133
@@ -1087,7 +1152,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1087 /* Finally also reconfigure all the BSS information */ 1152 /* Finally also reconfigure all the BSS information */
1088 list_for_each_entry(sdata, &local->interfaces, list) { 1153 list_for_each_entry(sdata, &local->interfaces, list) {
1089 u32 changed = ~0; 1154 u32 changed = ~0;
1090 if (!netif_running(sdata->dev)) 1155 if (!ieee80211_sdata_running(sdata))
1091 continue; 1156 continue;
1092 switch (sdata->vif.type) { 1157 switch (sdata->vif.type) {
1093 case NL80211_IFTYPE_STATION: 1158 case NL80211_IFTYPE_STATION:
@@ -1113,9 +1178,17 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1113 } 1178 }
1114 } 1179 }
1115 1180
1181 rcu_read_lock();
1182 if (hw->flags & IEEE80211_HW_AMPDU_AGGREGATION) {
1183 list_for_each_entry_rcu(sta, &local->sta_list, list) {
1184 ieee80211_sta_tear_down_BA_sessions(sta);
1185 }
1186 }
1187 rcu_read_unlock();
1188
1116 /* add back keys */ 1189 /* add back keys */
1117 list_for_each_entry(sdata, &local->interfaces, list) 1190 list_for_each_entry(sdata, &local->interfaces, list)
1118 if (netif_running(sdata->dev)) 1191 if (ieee80211_sdata_running(sdata))
1119 ieee80211_enable_keys(sdata); 1192 ieee80211_enable_keys(sdata);
1120 1193
1121 ieee80211_wake_queues_by_reason(hw, 1194 ieee80211_wake_queues_by_reason(hw,
@@ -1152,13 +1225,143 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1152 1225
1153 add_timer(&local->sta_cleanup); 1226 add_timer(&local->sta_cleanup);
1154 1227
1155 spin_lock_irqsave(&local->sta_lock, flags); 1228 mutex_lock(&local->sta_mtx);
1156 list_for_each_entry(sta, &local->sta_list, list) 1229 list_for_each_entry(sta, &local->sta_list, list)
1157 mesh_plink_restart(sta); 1230 mesh_plink_restart(sta);
1158 spin_unlock_irqrestore(&local->sta_lock, flags); 1231 mutex_unlock(&local->sta_mtx);
1159#else 1232#else
1160 WARN_ON(1); 1233 WARN_ON(1);
1161#endif 1234#endif
1162 return 0; 1235 return 0;
1163} 1236}
1164 1237
1238static int check_mgd_smps(struct ieee80211_if_managed *ifmgd,
1239 enum ieee80211_smps_mode *smps_mode)
1240{
1241 if (ifmgd->associated) {
1242 *smps_mode = ifmgd->ap_smps;
1243
1244 if (*smps_mode == IEEE80211_SMPS_AUTOMATIC) {
1245 if (ifmgd->powersave)
1246 *smps_mode = IEEE80211_SMPS_DYNAMIC;
1247 else
1248 *smps_mode = IEEE80211_SMPS_OFF;
1249 }
1250
1251 return 1;
1252 }
1253
1254 return 0;
1255}
1256
1257/* must hold iflist_mtx */
1258void ieee80211_recalc_smps(struct ieee80211_local *local,
1259 struct ieee80211_sub_if_data *forsdata)
1260{
1261 struct ieee80211_sub_if_data *sdata;
1262 enum ieee80211_smps_mode smps_mode = IEEE80211_SMPS_OFF;
1263 int count = 0;
1264
1265 if (forsdata)
1266 WARN_ON(!mutex_is_locked(&forsdata->u.mgd.mtx));
1267
1268 WARN_ON(!mutex_is_locked(&local->iflist_mtx));
1269
1270 /*
1271 * This function could be improved to handle multiple
1272 * interfaces better, but right now it makes any
1273 * non-station interfaces force SM PS to be turned
1274 * off. If there are multiple station interfaces it
1275 * could also use the best possible mode, e.g. if
1276 * one is in static and the other in dynamic then
1277 * dynamic is ok.
1278 */
1279
1280 list_for_each_entry(sdata, &local->interfaces, list) {
1281 if (!netif_running(sdata->dev))
1282 continue;
1283 if (sdata->vif.type != NL80211_IFTYPE_STATION)
1284 goto set;
1285 if (sdata != forsdata) {
1286 /*
1287 * This nested is ok -- we are holding the iflist_mtx
1288 * so can't get here twice or so. But it's required
1289 * since normally we acquire it first and then the
1290 * iflist_mtx.
1291 */
1292 mutex_lock_nested(&sdata->u.mgd.mtx, SINGLE_DEPTH_NESTING);
1293 count += check_mgd_smps(&sdata->u.mgd, &smps_mode);
1294 mutex_unlock(&sdata->u.mgd.mtx);
1295 } else
1296 count += check_mgd_smps(&sdata->u.mgd, &smps_mode);
1297
1298 if (count > 1) {
1299 smps_mode = IEEE80211_SMPS_OFF;
1300 break;
1301 }
1302 }
1303
1304 if (smps_mode == local->smps_mode)
1305 return;
1306
1307 set:
1308 local->smps_mode = smps_mode;
1309 /* changed flag is auto-detected for this */
1310 ieee80211_hw_config(local, 0);
1311}
1312
1313static bool ieee80211_id_in_list(const u8 *ids, int n_ids, u8 id)
1314{
1315 int i;
1316
1317 for (i = 0; i < n_ids; i++)
1318 if (ids[i] == id)
1319 return true;
1320 return false;
1321}
1322
1323/**
1324 * ieee80211_ie_split - split an IE buffer according to ordering
1325 *
1326 * @ies: the IE buffer
1327 * @ielen: the length of the IE buffer
1328 * @ids: an array with element IDs that are allowed before
1329 * the split
1330 * @n_ids: the size of the element ID array
1331 * @offset: offset where to start splitting in the buffer
1332 *
1333 * This function splits an IE buffer by updating the @offset
1334 * variable to point to the location where the buffer should be
1335 * split.
1336 *
1337 * It assumes that the given IE buffer is well-formed, this
1338 * has to be guaranteed by the caller!
1339 *
1340 * It also assumes that the IEs in the buffer are ordered
1341 * correctly, if not the result of using this function will not
1342 * be ordered correctly either, i.e. it does no reordering.
1343 *
1344 * The function returns the offset where the next part of the
1345 * buffer starts, which may be @ielen if the entire (remainder)
1346 * of the buffer should be used.
1347 */
1348size_t ieee80211_ie_split(const u8 *ies, size_t ielen,
1349 const u8 *ids, int n_ids, size_t offset)
1350{
1351 size_t pos = offset;
1352
1353 while (pos < ielen && ieee80211_id_in_list(ids, n_ids, ies[pos]))
1354 pos += 2 + ies[pos + 1];
1355
1356 return pos;
1357}
1358
1359size_t ieee80211_ie_split_vendor(const u8 *ies, size_t ielen, size_t offset)
1360{
1361 size_t pos = offset;
1362
1363 while (pos < ielen && ies[pos] != WLAN_EID_VENDOR_SPECIFIC)
1364 pos += 2 + ies[pos + 1];
1365
1366 return pos;
1367}