aboutsummaryrefslogtreecommitdiffstats
path: root/net/wireless
diff options
context:
space:
mode:
Diffstat (limited to 'net/wireless')
-rw-r--r--net/wireless/core.h2
-rw-r--r--net/wireless/nl80211.c4
-rw-r--r--net/wireless/reg.c22
-rw-r--r--net/wireless/scan.c41
4 files changed, 55 insertions, 14 deletions
diff --git a/net/wireless/core.h b/net/wireless/core.h
index d43daa236ef9..0a592e4295f0 100644
--- a/net/wireless/core.h
+++ b/net/wireless/core.h
@@ -90,7 +90,7 @@ struct cfg80211_internal_bss {
90 struct rb_node rbn; 90 struct rb_node rbn;
91 unsigned long ts; 91 unsigned long ts;
92 struct kref ref; 92 struct kref ref;
93 bool hold; 93 bool hold, ies_allocated;
94 94
95 /* must be last because of priv member */ 95 /* must be last because of priv member */
96 struct cfg80211_bss pub; 96 struct cfg80211_bss pub;
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c
index 353e1a4ece83..2456e4ee445e 100644
--- a/net/wireless/nl80211.c
+++ b/net/wireless/nl80211.c
@@ -3334,7 +3334,7 @@ static void nl80211_send_mlme_event(struct cfg80211_registered_device *rdev,
3334 struct sk_buff *msg; 3334 struct sk_buff *msg;
3335 void *hdr; 3335 void *hdr;
3336 3336
3337 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_KERNEL); 3337 msg = nlmsg_new(NLMSG_GOODSIZE, GFP_ATOMIC);
3338 if (!msg) 3338 if (!msg)
3339 return; 3339 return;
3340 3340
@@ -3353,7 +3353,7 @@ static void nl80211_send_mlme_event(struct cfg80211_registered_device *rdev,
3353 return; 3353 return;
3354 } 3354 }
3355 3355
3356 genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, GFP_KERNEL); 3356 genlmsg_multicast(msg, 0, nl80211_mlme_mcgrp.id, GFP_ATOMIC);
3357 return; 3357 return;
3358 3358
3359 nla_put_failure: 3359 nla_put_failure:
diff --git a/net/wireless/reg.c b/net/wireless/reg.c
index 6327e1617acb..08265ca15785 100644
--- a/net/wireless/reg.c
+++ b/net/wireless/reg.c
@@ -907,6 +907,7 @@ EXPORT_SYMBOL(freq_reg_info);
907int freq_reg_info(struct wiphy *wiphy, u32 center_freq, u32 *bandwidth, 907int freq_reg_info(struct wiphy *wiphy, u32 center_freq, u32 *bandwidth,
908 const struct ieee80211_reg_rule **reg_rule) 908 const struct ieee80211_reg_rule **reg_rule)
909{ 909{
910 assert_cfg80211_lock();
910 return freq_reg_info_regd(wiphy, center_freq, 911 return freq_reg_info_regd(wiphy, center_freq,
911 bandwidth, reg_rule, NULL); 912 bandwidth, reg_rule, NULL);
912} 913}
@@ -1133,7 +1134,8 @@ static bool reg_is_world_roaming(struct wiphy *wiphy)
1133 if (is_world_regdom(cfg80211_regdomain->alpha2) || 1134 if (is_world_regdom(cfg80211_regdomain->alpha2) ||
1134 (wiphy->regd && is_world_regdom(wiphy->regd->alpha2))) 1135 (wiphy->regd && is_world_regdom(wiphy->regd->alpha2)))
1135 return true; 1136 return true;
1136 if (last_request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE && 1137 if (last_request &&
1138 last_request->initiator != NL80211_REGDOM_SET_BY_COUNTRY_IE &&
1137 wiphy->custom_regulatory) 1139 wiphy->custom_regulatory)
1138 return true; 1140 return true;
1139 return false; 1141 return false;
@@ -1142,6 +1144,12 @@ static bool reg_is_world_roaming(struct wiphy *wiphy)
1142/* Reap the advantages of previously found beacons */ 1144/* Reap the advantages of previously found beacons */
1143static void reg_process_beacons(struct wiphy *wiphy) 1145static void reg_process_beacons(struct wiphy *wiphy)
1144{ 1146{
1147 /*
1148 * Means we are just firing up cfg80211, so no beacons would
1149 * have been processed yet.
1150 */
1151 if (!last_request)
1152 return;
1145 if (!reg_is_world_roaming(wiphy)) 1153 if (!reg_is_world_roaming(wiphy))
1146 return; 1154 return;
1147 wiphy_update_beacon_reg(wiphy); 1155 wiphy_update_beacon_reg(wiphy);
@@ -1176,6 +1184,8 @@ static void handle_channel_custom(struct wiphy *wiphy,
1176 struct ieee80211_supported_band *sband; 1184 struct ieee80211_supported_band *sband;
1177 struct ieee80211_channel *chan; 1185 struct ieee80211_channel *chan;
1178 1186
1187 assert_cfg80211_lock();
1188
1179 sband = wiphy->bands[band]; 1189 sband = wiphy->bands[band];
1180 BUG_ON(chan_idx >= sband->n_channels); 1190 BUG_ON(chan_idx >= sband->n_channels);
1181 chan = &sband->channels[chan_idx]; 1191 chan = &sband->channels[chan_idx];
@@ -1214,10 +1224,13 @@ void wiphy_apply_custom_regulatory(struct wiphy *wiphy,
1214 const struct ieee80211_regdomain *regd) 1224 const struct ieee80211_regdomain *regd)
1215{ 1225{
1216 enum ieee80211_band band; 1226 enum ieee80211_band band;
1227
1228 mutex_lock(&cfg80211_mutex);
1217 for (band = 0; band < IEEE80211_NUM_BANDS; band++) { 1229 for (band = 0; band < IEEE80211_NUM_BANDS; band++) {
1218 if (wiphy->bands[band]) 1230 if (wiphy->bands[band])
1219 handle_band_custom(wiphy, band, regd); 1231 handle_band_custom(wiphy, band, regd);
1220 } 1232 }
1233 mutex_unlock(&cfg80211_mutex);
1221} 1234}
1222EXPORT_SYMBOL(wiphy_apply_custom_regulatory); 1235EXPORT_SYMBOL(wiphy_apply_custom_regulatory);
1223 1236
@@ -1423,7 +1436,7 @@ new_request:
1423 return call_crda(last_request->alpha2); 1436 return call_crda(last_request->alpha2);
1424} 1437}
1425 1438
1426/* This currently only processes user and driver regulatory hints */ 1439/* This processes *all* regulatory hints */
1427static void reg_process_hint(struct regulatory_request *reg_request) 1440static void reg_process_hint(struct regulatory_request *reg_request)
1428{ 1441{
1429 int r = 0; 1442 int r = 0;
@@ -2095,11 +2108,12 @@ int set_regdom(const struct ieee80211_regdomain *rd)
2095/* Caller must hold cfg80211_mutex */ 2108/* Caller must hold cfg80211_mutex */
2096void reg_device_remove(struct wiphy *wiphy) 2109void reg_device_remove(struct wiphy *wiphy)
2097{ 2110{
2098 struct wiphy *request_wiphy; 2111 struct wiphy *request_wiphy = NULL;
2099 2112
2100 assert_cfg80211_lock(); 2113 assert_cfg80211_lock();
2101 2114
2102 request_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx); 2115 if (last_request)
2116 request_wiphy = wiphy_idx_to_wiphy(last_request->wiphy_idx);
2103 2117
2104 kfree(wiphy->regd); 2118 kfree(wiphy->regd);
2105 if (!last_request || !request_wiphy) 2119 if (!last_request || !request_wiphy)
diff --git a/net/wireless/scan.c b/net/wireless/scan.c
index 2a00e362f5fe..1f260c40b6ca 100644
--- a/net/wireless/scan.c
+++ b/net/wireless/scan.c
@@ -58,6 +58,10 @@ static void bss_release(struct kref *ref)
58 bss = container_of(ref, struct cfg80211_internal_bss, ref); 58 bss = container_of(ref, struct cfg80211_internal_bss, ref);
59 if (bss->pub.free_priv) 59 if (bss->pub.free_priv)
60 bss->pub.free_priv(&bss->pub); 60 bss->pub.free_priv(&bss->pub);
61
62 if (bss->ies_allocated)
63 kfree(bss->pub.information_elements);
64
61 kfree(bss); 65 kfree(bss);
62} 66}
63 67
@@ -360,19 +364,42 @@ cfg80211_bss_update(struct cfg80211_registered_device *dev,
360 364
361 found = rb_find_bss(dev, res); 365 found = rb_find_bss(dev, res);
362 366
363 if (found && overwrite) { 367 if (found) {
364 list_replace(&found->list, &res->list);
365 rb_replace_node(&found->rbn, &res->rbn,
366 &dev->bss_tree);
367 kref_put(&found->ref, bss_release);
368 found = res;
369 } else if (found) {
370 kref_get(&found->ref); 368 kref_get(&found->ref);
371 found->pub.beacon_interval = res->pub.beacon_interval; 369 found->pub.beacon_interval = res->pub.beacon_interval;
372 found->pub.tsf = res->pub.tsf; 370 found->pub.tsf = res->pub.tsf;
373 found->pub.signal = res->pub.signal; 371 found->pub.signal = res->pub.signal;
374 found->pub.capability = res->pub.capability; 372 found->pub.capability = res->pub.capability;
375 found->ts = res->ts; 373 found->ts = res->ts;
374
375 /* overwrite IEs */
376 if (overwrite) {
377 size_t used = dev->wiphy.bss_priv_size + sizeof(*res);
378 size_t ielen = res->pub.len_information_elements;
379
380 if (ksize(found) >= used + ielen) {
381 memcpy(found->pub.information_elements,
382 res->pub.information_elements, ielen);
383 found->pub.len_information_elements = ielen;
384 } else {
385 u8 *ies = found->pub.information_elements;
386
387 if (found->ies_allocated) {
388 if (ksize(ies) < ielen)
389 ies = krealloc(ies, ielen,
390 GFP_ATOMIC);
391 } else
392 ies = kmalloc(ielen, GFP_ATOMIC);
393
394 if (ies) {
395 memcpy(ies, res->pub.information_elements, ielen);
396 found->ies_allocated = true;
397 found->pub.information_elements = ies;
398 found->pub.len_information_elements = ielen;
399 }
400 }
401 }
402
376 kref_put(&res->ref, bss_release); 403 kref_put(&res->ref, bss_release);
377 } else { 404 } else {
378 /* this "consumes" the reference */ 405 /* this "consumes" the reference */