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.c104
1 files changed, 93 insertions, 11 deletions
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 78a6e924c7e1..b01972579c7c 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -469,7 +469,7 @@ void ieee80211_iterate_active_interfaces(
469 break; 469 break;
470 } 470 }
471 if (netif_running(sdata->dev)) 471 if (netif_running(sdata->dev))
472 iterator(data, sdata->dev->dev_addr, 472 iterator(data, sdata->vif.addr,
473 &sdata->vif); 473 &sdata->vif);
474 } 474 }
475 475
@@ -503,7 +503,7 @@ void ieee80211_iterate_active_interfaces_atomic(
503 break; 503 break;
504 } 504 }
505 if (netif_running(sdata->dev)) 505 if (netif_running(sdata->dev))
506 iterator(data, sdata->dev->dev_addr, 506 iterator(data, sdata->vif.addr,
507 &sdata->vif); 507 &sdata->vif);
508 } 508 }
509 509
@@ -848,7 +848,7 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
848 sizeof(*mgmt) + 6 + extra_len); 848 sizeof(*mgmt) + 6 + extra_len);
849 if (!skb) { 849 if (!skb) {
850 printk(KERN_DEBUG "%s: failed to allocate buffer for auth " 850 printk(KERN_DEBUG "%s: failed to allocate buffer for auth "
851 "frame\n", sdata->dev->name); 851 "frame\n", sdata->name);
852 return; 852 return;
853 } 853 }
854 skb_reserve(skb, local->hw.extra_tx_headroom); 854 skb_reserve(skb, local->hw.extra_tx_headroom);
@@ -858,7 +858,7 @@ void ieee80211_send_auth(struct ieee80211_sub_if_data *sdata,
858 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | 858 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
859 IEEE80211_STYPE_AUTH); 859 IEEE80211_STYPE_AUTH);
860 memcpy(mgmt->da, bssid, ETH_ALEN); 860 memcpy(mgmt->da, bssid, ETH_ALEN);
861 memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); 861 memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
862 memcpy(mgmt->bssid, bssid, ETH_ALEN); 862 memcpy(mgmt->bssid, bssid, ETH_ALEN);
863 mgmt->u.auth.auth_alg = cpu_to_le16(auth_alg); 863 mgmt->u.auth.auth_alg = cpu_to_le16(auth_alg);
864 mgmt->u.auth.auth_transaction = cpu_to_le16(transaction); 864 mgmt->u.auth.auth_transaction = cpu_to_le16(transaction);
@@ -908,16 +908,24 @@ int ieee80211_build_preq_ies(struct ieee80211_local *local, u8 *buffer,
908 } 908 }
909 909
910 if (sband->ht_cap.ht_supported) { 910 if (sband->ht_cap.ht_supported) {
911 __le16 tmp = cpu_to_le16(sband->ht_cap.cap); 911 u16 cap = sband->ht_cap.cap;
912 __le16 tmp;
913
914 if (ieee80211_disable_40mhz_24ghz &&
915 sband->band == IEEE80211_BAND_2GHZ) {
916 cap &= ~IEEE80211_HT_CAP_SUP_WIDTH_20_40;
917 cap &= ~IEEE80211_HT_CAP_SGI_40;
918 }
912 919
913 *pos++ = WLAN_EID_HT_CAPABILITY; 920 *pos++ = WLAN_EID_HT_CAPABILITY;
914 *pos++ = sizeof(struct ieee80211_ht_cap); 921 *pos++ = sizeof(struct ieee80211_ht_cap);
915 memset(pos, 0, sizeof(struct ieee80211_ht_cap)); 922 memset(pos, 0, sizeof(struct ieee80211_ht_cap));
923 tmp = cpu_to_le16(cap);
916 memcpy(pos, &tmp, sizeof(u16)); 924 memcpy(pos, &tmp, sizeof(u16));
917 pos += sizeof(u16); 925 pos += sizeof(u16);
918 /* TODO: needs a define here for << 2 */
919 *pos++ = sband->ht_cap.ampdu_factor | 926 *pos++ = sband->ht_cap.ampdu_factor |
920 (sband->ht_cap.ampdu_density << 2); 927 (sband->ht_cap.ampdu_density <<
928 IEEE80211_HT_AMPDU_PARM_DENSITY_SHIFT);
921 memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs)); 929 memcpy(pos, &sband->ht_cap.mcs, sizeof(sband->ht_cap.mcs));
922 pos += sizeof(sband->ht_cap.mcs); 930 pos += sizeof(sband->ht_cap.mcs);
923 pos += 2 + 4 + 1; /* ext info, BF cap, antsel */ 931 pos += 2 + 4 + 1; /* ext info, BF cap, antsel */
@@ -949,7 +957,7 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
949 ie_len); 957 ie_len);
950 if (!skb) { 958 if (!skb) {
951 printk(KERN_DEBUG "%s: failed to allocate buffer for probe " 959 printk(KERN_DEBUG "%s: failed to allocate buffer for probe "
952 "request\n", sdata->dev->name); 960 "request\n", sdata->name);
953 return; 961 return;
954 } 962 }
955 skb_reserve(skb, local->hw.extra_tx_headroom); 963 skb_reserve(skb, local->hw.extra_tx_headroom);
@@ -958,7 +966,7 @@ void ieee80211_send_probe_req(struct ieee80211_sub_if_data *sdata, u8 *dst,
958 memset(mgmt, 0, 24); 966 memset(mgmt, 0, 24);
959 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT | 967 mgmt->frame_control = cpu_to_le16(IEEE80211_FTYPE_MGMT |
960 IEEE80211_STYPE_PROBE_REQ); 968 IEEE80211_STYPE_PROBE_REQ);
961 memcpy(mgmt->sa, sdata->dev->dev_addr, ETH_ALEN); 969 memcpy(mgmt->sa, sdata->vif.addr, ETH_ALEN);
962 if (dst) { 970 if (dst) {
963 memcpy(mgmt->da, dst, ETH_ALEN); 971 memcpy(mgmt->da, dst, ETH_ALEN);
964 memcpy(mgmt->bssid, dst, ETH_ALEN); 972 memcpy(mgmt->bssid, dst, ETH_ALEN);
@@ -1051,7 +1059,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1051 netif_running(sdata->dev)) { 1059 netif_running(sdata->dev)) {
1052 conf.vif = &sdata->vif; 1060 conf.vif = &sdata->vif;
1053 conf.type = sdata->vif.type; 1061 conf.type = sdata->vif.type;
1054 conf.mac_addr = sdata->dev->dev_addr; 1062 conf.mac_addr = sdata->vif.addr;
1055 res = drv_add_interface(local, &conf); 1063 res = drv_add_interface(local, &conf);
1056 } 1064 }
1057 } 1065 }
@@ -1066,7 +1074,7 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1066 struct ieee80211_sub_if_data, 1074 struct ieee80211_sub_if_data,
1067 u.ap); 1075 u.ap);
1068 1076
1069 drv_sta_notify(local, &sdata->vif, STA_NOTIFY_ADD, 1077 drv_sta_notify(local, sdata, STA_NOTIFY_ADD,
1070 &sta->sta); 1078 &sta->sta);
1071 } 1079 }
1072 spin_unlock_irqrestore(&local->sta_lock, flags); 1080 spin_unlock_irqrestore(&local->sta_lock, flags);
@@ -1170,3 +1178,77 @@ int ieee80211_reconfig(struct ieee80211_local *local)
1170 return 0; 1178 return 0;
1171} 1179}
1172 1180
1181static int check_mgd_smps(struct ieee80211_if_managed *ifmgd,
1182 enum ieee80211_smps_mode *smps_mode)
1183{
1184 if (ifmgd->associated) {
1185 *smps_mode = ifmgd->ap_smps;
1186
1187 if (*smps_mode == IEEE80211_SMPS_AUTOMATIC) {
1188 if (ifmgd->powersave)
1189 *smps_mode = IEEE80211_SMPS_DYNAMIC;
1190 else
1191 *smps_mode = IEEE80211_SMPS_OFF;
1192 }
1193
1194 return 1;
1195 }
1196
1197 return 0;
1198}
1199
1200/* must hold iflist_mtx */
1201void ieee80211_recalc_smps(struct ieee80211_local *local,
1202 struct ieee80211_sub_if_data *forsdata)
1203{
1204 struct ieee80211_sub_if_data *sdata;
1205 enum ieee80211_smps_mode smps_mode = IEEE80211_SMPS_OFF;
1206 int count = 0;
1207
1208 if (forsdata)
1209 WARN_ON(!mutex_is_locked(&forsdata->u.mgd.mtx));
1210
1211 WARN_ON(!mutex_is_locked(&local->iflist_mtx));
1212
1213 /*
1214 * This function could be improved to handle multiple
1215 * interfaces better, but right now it makes any
1216 * non-station interfaces force SM PS to be turned
1217 * off. If there are multiple station interfaces it
1218 * could also use the best possible mode, e.g. if
1219 * one is in static and the other in dynamic then
1220 * dynamic is ok.
1221 */
1222
1223 list_for_each_entry(sdata, &local->interfaces, list) {
1224 if (!netif_running(sdata->dev))
1225 continue;
1226 if (sdata->vif.type != NL80211_IFTYPE_STATION)
1227 goto set;
1228 if (sdata != forsdata) {
1229 /*
1230 * This nested is ok -- we are holding the iflist_mtx
1231 * so can't get here twice or so. But it's required
1232 * since normally we acquire it first and then the
1233 * iflist_mtx.
1234 */
1235 mutex_lock_nested(&sdata->u.mgd.mtx, SINGLE_DEPTH_NESTING);
1236 count += check_mgd_smps(&sdata->u.mgd, &smps_mode);
1237 mutex_unlock(&sdata->u.mgd.mtx);
1238 } else
1239 count += check_mgd_smps(&sdata->u.mgd, &smps_mode);
1240
1241 if (count > 1) {
1242 smps_mode = IEEE80211_SMPS_OFF;
1243 break;
1244 }
1245 }
1246
1247 if (smps_mode == local->smps_mode)
1248 return;
1249
1250 set:
1251 local->smps_mode = smps_mode;
1252 /* changed flag is auto-detected for this */
1253 ieee80211_hw_config(local, 0);
1254}