diff options
Diffstat (limited to 'net/wireless')
| -rw-r--r-- | net/wireless/core.c | 19 | ||||
| -rw-r--r-- | net/wireless/core.h | 4 | ||||
| -rw-r--r-- | net/wireless/nl80211.c | 32 | ||||
| -rw-r--r-- | net/wireless/nl80211.h | 8 | ||||
| -rw-r--r-- | net/wireless/reg.c | 12 | ||||
| -rw-r--r-- | net/wireless/scan.c | 40 | ||||
| -rw-r--r-- | net/wireless/sme.c | 2 |
7 files changed, 65 insertions, 52 deletions
diff --git a/net/wireless/core.c b/net/wireless/core.c index d89dee2259b5..a3bf18d11609 100644 --- a/net/wireless/core.c +++ b/net/wireless/core.c | |||
| @@ -203,8 +203,11 @@ void cfg80211_stop_p2p_device(struct cfg80211_registered_device *rdev, | |||
| 203 | 203 | ||
| 204 | rdev->opencount--; | 204 | rdev->opencount--; |
| 205 | 205 | ||
| 206 | WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev && | 206 | if (rdev->scan_req && rdev->scan_req->wdev == wdev) { |
| 207 | !rdev->scan_req->notified); | 207 | if (WARN_ON(!rdev->scan_req->notified)) |
| 208 | rdev->scan_req->aborted = true; | ||
| 209 | ___cfg80211_scan_done(rdev, false); | ||
| 210 | } | ||
| 208 | } | 211 | } |
| 209 | 212 | ||
| 210 | static int cfg80211_rfkill_set_block(void *data, bool blocked) | 213 | static int cfg80211_rfkill_set_block(void *data, bool blocked) |
| @@ -440,9 +443,6 @@ int wiphy_register(struct wiphy *wiphy) | |||
| 440 | int i; | 443 | int i; |
| 441 | u16 ifmodes = wiphy->interface_modes; | 444 | u16 ifmodes = wiphy->interface_modes; |
| 442 | 445 | ||
| 443 | /* support for 5/10 MHz is broken due to nl80211 API mess - disable */ | ||
| 444 | wiphy->flags &= ~WIPHY_FLAG_SUPPORTS_5_10_MHZ; | ||
| 445 | |||
| 446 | /* | 446 | /* |
| 447 | * There are major locking problems in nl80211/mac80211 for CSA, | 447 | * There are major locking problems in nl80211/mac80211 for CSA, |
| 448 | * disable for all drivers until this has been reworked. | 448 | * disable for all drivers until this has been reworked. |
| @@ -788,8 +788,6 @@ void cfg80211_leave(struct cfg80211_registered_device *rdev, | |||
| 788 | default: | 788 | default: |
| 789 | break; | 789 | break; |
| 790 | } | 790 | } |
| 791 | |||
| 792 | wdev->beacon_interval = 0; | ||
| 793 | } | 791 | } |
| 794 | 792 | ||
| 795 | static int cfg80211_netdev_notifier_call(struct notifier_block *nb, | 793 | static int cfg80211_netdev_notifier_call(struct notifier_block *nb, |
| @@ -859,8 +857,11 @@ static int cfg80211_netdev_notifier_call(struct notifier_block *nb, | |||
| 859 | break; | 857 | break; |
| 860 | case NETDEV_DOWN: | 858 | case NETDEV_DOWN: |
| 861 | cfg80211_update_iface_num(rdev, wdev->iftype, -1); | 859 | cfg80211_update_iface_num(rdev, wdev->iftype, -1); |
| 862 | WARN_ON(rdev->scan_req && rdev->scan_req->wdev == wdev && | 860 | if (rdev->scan_req && rdev->scan_req->wdev == wdev) { |
| 863 | !rdev->scan_req->notified); | 861 | if (WARN_ON(!rdev->scan_req->notified)) |
| 862 | rdev->scan_req->aborted = true; | ||
| 863 | ___cfg80211_scan_done(rdev, false); | ||
| 864 | } | ||
| 864 | 865 | ||
| 865 | if (WARN_ON(rdev->sched_scan_req && | 866 | if (WARN_ON(rdev->sched_scan_req && |
| 866 | rdev->sched_scan_req->dev == wdev->netdev)) { | 867 | rdev->sched_scan_req->dev == wdev->netdev)) { |
diff --git a/net/wireless/core.h b/net/wireless/core.h index 37ec16d7bb1a..f1d193b557b6 100644 --- a/net/wireless/core.h +++ b/net/wireless/core.h | |||
| @@ -62,6 +62,7 @@ struct cfg80211_registered_device { | |||
| 62 | struct rb_root bss_tree; | 62 | struct rb_root bss_tree; |
| 63 | u32 bss_generation; | 63 | u32 bss_generation; |
| 64 | struct cfg80211_scan_request *scan_req; /* protected by RTNL */ | 64 | struct cfg80211_scan_request *scan_req; /* protected by RTNL */ |
| 65 | struct sk_buff *scan_msg; | ||
| 65 | struct cfg80211_sched_scan_request *sched_scan_req; | 66 | struct cfg80211_sched_scan_request *sched_scan_req; |
| 66 | unsigned long suspend_at; | 67 | unsigned long suspend_at; |
| 67 | struct work_struct scan_done_wk; | 68 | struct work_struct scan_done_wk; |
| @@ -361,7 +362,8 @@ int cfg80211_validate_key_settings(struct cfg80211_registered_device *rdev, | |||
| 361 | struct key_params *params, int key_idx, | 362 | struct key_params *params, int key_idx, |
| 362 | bool pairwise, const u8 *mac_addr); | 363 | bool pairwise, const u8 *mac_addr); |
| 363 | void __cfg80211_scan_done(struct work_struct *wk); | 364 | void __cfg80211_scan_done(struct work_struct *wk); |
| 364 | void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev); | 365 | void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, |
| 366 | bool send_message); | ||
| 365 | void __cfg80211_sched_scan_results(struct work_struct *wk); | 367 | void __cfg80211_sched_scan_results(struct work_struct *wk); |
| 366 | int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev, | 368 | int __cfg80211_stop_sched_scan(struct cfg80211_registered_device *rdev, |
| 367 | bool driver_initiated); | 369 | bool driver_initiated); |
diff --git a/net/wireless/nl80211.c b/net/wireless/nl80211.c index 7a742594916e..4fe2e6e2bc76 100644 --- a/net/wireless/nl80211.c +++ b/net/wireless/nl80211.c | |||
| @@ -1719,9 +1719,10 @@ static int nl80211_dump_wiphy(struct sk_buff *skb, struct netlink_callback *cb) | |||
| 1719 | * We can then retry with the larger buffer. | 1719 | * We can then retry with the larger buffer. |
| 1720 | */ | 1720 | */ |
| 1721 | if ((ret == -ENOBUFS || ret == -EMSGSIZE) && | 1721 | if ((ret == -ENOBUFS || ret == -EMSGSIZE) && |
| 1722 | !skb->len && | 1722 | !skb->len && !state->split && |
| 1723 | cb->min_dump_alloc < 4096) { | 1723 | cb->min_dump_alloc < 4096) { |
| 1724 | cb->min_dump_alloc = 4096; | 1724 | cb->min_dump_alloc = 4096; |
| 1725 | state->split_start = 0; | ||
| 1725 | rtnl_unlock(); | 1726 | rtnl_unlock(); |
| 1726 | return 1; | 1727 | return 1; |
| 1727 | } | 1728 | } |
| @@ -5244,7 +5245,7 @@ static int nl80211_trigger_scan(struct sk_buff *skb, struct genl_info *info) | |||
| 5244 | if (!rdev->ops->scan) | 5245 | if (!rdev->ops->scan) |
| 5245 | return -EOPNOTSUPP; | 5246 | return -EOPNOTSUPP; |
| 5246 | 5247 | ||
| 5247 | if (rdev->scan_req) { | 5248 | if (rdev->scan_req || rdev->scan_msg) { |
| 5248 | err = -EBUSY; | 5249 | err = -EBUSY; |
| 5249 | goto unlock; | 5250 | goto unlock; |
| 5250 | } | 5251 | } |
| @@ -10011,40 +10012,31 @@ void nl80211_send_scan_start(struct cfg80211_registered_device *rdev, | |||
| 10011 | NL80211_MCGRP_SCAN, GFP_KERNEL); | 10012 | NL80211_MCGRP_SCAN, GFP_KERNEL); |
| 10012 | } | 10013 | } |
| 10013 | 10014 | ||
| 10014 | void nl80211_send_scan_done(struct cfg80211_registered_device *rdev, | 10015 | struct sk_buff *nl80211_build_scan_msg(struct cfg80211_registered_device *rdev, |
| 10015 | struct wireless_dev *wdev) | 10016 | struct wireless_dev *wdev, bool aborted) |
| 10016 | { | 10017 | { |
| 10017 | struct sk_buff *msg; | 10018 | struct sk_buff *msg; |
| 10018 | 10019 | ||
| 10019 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | 10020 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); |
| 10020 | if (!msg) | 10021 | if (!msg) |
| 10021 | return; | 10022 | return NULL; |
| 10022 | 10023 | ||
| 10023 | if (nl80211_send_scan_msg(msg, rdev, wdev, 0, 0, 0, | 10024 | if (nl80211_send_scan_msg(msg, rdev, wdev, 0, 0, 0, |
| 10024 | NL80211_CMD_NEW_SCAN_RESULTS) < 0) { | 10025 | aborted ? NL80211_CMD_SCAN_ABORTED : |
| 10026 | NL80211_CMD_NEW_SCAN_RESULTS) < 0) { | ||
| 10025 | nlmsg_free(msg); | 10027 | nlmsg_free(msg); |
| 10026 | return; | 10028 | return NULL; |
| 10027 | } | 10029 | } |
| 10028 | 10030 | ||
| 10029 | genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0, | 10031 | return msg; |
| 10030 | NL80211_MCGRP_SCAN, GFP_KERNEL); | ||
| 10031 | } | 10032 | } |
| 10032 | 10033 | ||
| 10033 | void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev, | 10034 | void nl80211_send_scan_result(struct cfg80211_registered_device *rdev, |
| 10034 | struct wireless_dev *wdev) | 10035 | struct sk_buff *msg) |
| 10035 | { | 10036 | { |
| 10036 | struct sk_buff *msg; | ||
| 10037 | |||
| 10038 | msg = nlmsg_new(NLMSG_DEFAULT_SIZE, GFP_KERNEL); | ||
| 10039 | if (!msg) | 10037 | if (!msg) |
| 10040 | return; | 10038 | return; |
| 10041 | 10039 | ||
| 10042 | if (nl80211_send_scan_msg(msg, rdev, wdev, 0, 0, 0, | ||
| 10043 | NL80211_CMD_SCAN_ABORTED) < 0) { | ||
| 10044 | nlmsg_free(msg); | ||
| 10045 | return; | ||
| 10046 | } | ||
| 10047 | |||
| 10048 | genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0, | 10040 | genlmsg_multicast_netns(&nl80211_fam, wiphy_net(&rdev->wiphy), msg, 0, |
| 10049 | NL80211_MCGRP_SCAN, GFP_KERNEL); | 10041 | NL80211_MCGRP_SCAN, GFP_KERNEL); |
| 10050 | } | 10042 | } |
diff --git a/net/wireless/nl80211.h b/net/wireless/nl80211.h index b1b231324e10..75799746d845 100644 --- a/net/wireless/nl80211.h +++ b/net/wireless/nl80211.h | |||
| @@ -8,10 +8,10 @@ void nl80211_exit(void); | |||
| 8 | void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev); | 8 | void nl80211_notify_dev_rename(struct cfg80211_registered_device *rdev); |
| 9 | void nl80211_send_scan_start(struct cfg80211_registered_device *rdev, | 9 | void nl80211_send_scan_start(struct cfg80211_registered_device *rdev, |
| 10 | struct wireless_dev *wdev); | 10 | struct wireless_dev *wdev); |
| 11 | void nl80211_send_scan_done(struct cfg80211_registered_device *rdev, | 11 | struct sk_buff *nl80211_build_scan_msg(struct cfg80211_registered_device *rdev, |
| 12 | struct wireless_dev *wdev); | 12 | struct wireless_dev *wdev, bool aborted); |
| 13 | void nl80211_send_scan_aborted(struct cfg80211_registered_device *rdev, | 13 | void nl80211_send_scan_result(struct cfg80211_registered_device *rdev, |
| 14 | struct wireless_dev *wdev); | 14 | struct sk_buff *msg); |
| 15 | void nl80211_send_sched_scan(struct cfg80211_registered_device *rdev, | 15 | void nl80211_send_sched_scan(struct cfg80211_registered_device *rdev, |
| 16 | struct net_device *netdev, u32 cmd); | 16 | struct net_device *netdev, u32 cmd); |
| 17 | void nl80211_send_sched_scan_results(struct cfg80211_registered_device *rdev, | 17 | void nl80211_send_sched_scan_results(struct cfg80211_registered_device *rdev, |
diff --git a/net/wireless/reg.c b/net/wireless/reg.c index 9b897fca7487..f0541370e68e 100644 --- a/net/wireless/reg.c +++ b/net/wireless/reg.c | |||
| @@ -1700,7 +1700,7 @@ static void reg_process_hint(struct regulatory_request *reg_request) | |||
| 1700 | return; | 1700 | return; |
| 1701 | case NL80211_REGDOM_SET_BY_USER: | 1701 | case NL80211_REGDOM_SET_BY_USER: |
| 1702 | treatment = reg_process_hint_user(reg_request); | 1702 | treatment = reg_process_hint_user(reg_request); |
| 1703 | if (treatment == REG_REQ_OK || | 1703 | if (treatment == REG_REQ_IGNORE || |
| 1704 | treatment == REG_REQ_ALREADY_SET) | 1704 | treatment == REG_REQ_ALREADY_SET) |
| 1705 | return; | 1705 | return; |
| 1706 | schedule_delayed_work(®_timeout, msecs_to_jiffies(3142)); | 1706 | schedule_delayed_work(®_timeout, msecs_to_jiffies(3142)); |
| @@ -2373,6 +2373,7 @@ static int reg_set_rd_country_ie(const struct ieee80211_regdomain *rd, | |||
| 2373 | int set_regdom(const struct ieee80211_regdomain *rd) | 2373 | int set_regdom(const struct ieee80211_regdomain *rd) |
| 2374 | { | 2374 | { |
| 2375 | struct regulatory_request *lr; | 2375 | struct regulatory_request *lr; |
| 2376 | bool user_reset = false; | ||
| 2376 | int r; | 2377 | int r; |
| 2377 | 2378 | ||
| 2378 | if (!reg_is_valid_request(rd->alpha2)) { | 2379 | if (!reg_is_valid_request(rd->alpha2)) { |
| @@ -2389,6 +2390,7 @@ int set_regdom(const struct ieee80211_regdomain *rd) | |||
| 2389 | break; | 2390 | break; |
| 2390 | case NL80211_REGDOM_SET_BY_USER: | 2391 | case NL80211_REGDOM_SET_BY_USER: |
| 2391 | r = reg_set_rd_user(rd, lr); | 2392 | r = reg_set_rd_user(rd, lr); |
| 2393 | user_reset = true; | ||
| 2392 | break; | 2394 | break; |
| 2393 | case NL80211_REGDOM_SET_BY_DRIVER: | 2395 | case NL80211_REGDOM_SET_BY_DRIVER: |
| 2394 | r = reg_set_rd_driver(rd, lr); | 2396 | r = reg_set_rd_driver(rd, lr); |
| @@ -2402,8 +2404,14 @@ int set_regdom(const struct ieee80211_regdomain *rd) | |||
| 2402 | } | 2404 | } |
| 2403 | 2405 | ||
| 2404 | if (r) { | 2406 | if (r) { |
| 2405 | if (r == -EALREADY) | 2407 | switch (r) { |
| 2408 | case -EALREADY: | ||
| 2406 | reg_set_request_processed(); | 2409 | reg_set_request_processed(); |
| 2410 | break; | ||
| 2411 | default: | ||
| 2412 | /* Back to world regulatory in case of errors */ | ||
| 2413 | restore_regulatory_settings(user_reset); | ||
| 2414 | } | ||
| 2407 | 2415 | ||
| 2408 | kfree(rd); | 2416 | kfree(rd); |
| 2409 | return r; | 2417 | return r; |
diff --git a/net/wireless/scan.c b/net/wireless/scan.c index b528e31da2cf..d1ed4aebbbb7 100644 --- a/net/wireless/scan.c +++ b/net/wireless/scan.c | |||
| @@ -161,18 +161,25 @@ static void __cfg80211_bss_expire(struct cfg80211_registered_device *dev, | |||
| 161 | dev->bss_generation++; | 161 | dev->bss_generation++; |
| 162 | } | 162 | } |
| 163 | 163 | ||
| 164 | void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev) | 164 | void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev, |
| 165 | bool send_message) | ||
| 165 | { | 166 | { |
| 166 | struct cfg80211_scan_request *request; | 167 | struct cfg80211_scan_request *request; |
| 167 | struct wireless_dev *wdev; | 168 | struct wireless_dev *wdev; |
| 169 | struct sk_buff *msg; | ||
| 168 | #ifdef CONFIG_CFG80211_WEXT | 170 | #ifdef CONFIG_CFG80211_WEXT |
| 169 | union iwreq_data wrqu; | 171 | union iwreq_data wrqu; |
| 170 | #endif | 172 | #endif |
| 171 | 173 | ||
| 172 | ASSERT_RTNL(); | 174 | ASSERT_RTNL(); |
| 173 | 175 | ||
| 174 | request = rdev->scan_req; | 176 | if (rdev->scan_msg) { |
| 177 | nl80211_send_scan_result(rdev, rdev->scan_msg); | ||
| 178 | rdev->scan_msg = NULL; | ||
| 179 | return; | ||
| 180 | } | ||
| 175 | 181 | ||
| 182 | request = rdev->scan_req; | ||
| 176 | if (!request) | 183 | if (!request) |
| 177 | return; | 184 | return; |
| 178 | 185 | ||
| @@ -186,18 +193,16 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev) | |||
| 186 | if (wdev->netdev) | 193 | if (wdev->netdev) |
| 187 | cfg80211_sme_scan_done(wdev->netdev); | 194 | cfg80211_sme_scan_done(wdev->netdev); |
| 188 | 195 | ||
| 189 | if (request->aborted) { | 196 | if (!request->aborted && |
| 190 | nl80211_send_scan_aborted(rdev, wdev); | 197 | request->flags & NL80211_SCAN_FLAG_FLUSH) { |
| 191 | } else { | 198 | /* flush entries from previous scans */ |
| 192 | if (request->flags & NL80211_SCAN_FLAG_FLUSH) { | 199 | spin_lock_bh(&rdev->bss_lock); |
| 193 | /* flush entries from previous scans */ | 200 | __cfg80211_bss_expire(rdev, request->scan_start); |
| 194 | spin_lock_bh(&rdev->bss_lock); | 201 | spin_unlock_bh(&rdev->bss_lock); |
| 195 | __cfg80211_bss_expire(rdev, request->scan_start); | ||
| 196 | spin_unlock_bh(&rdev->bss_lock); | ||
| 197 | } | ||
| 198 | nl80211_send_scan_done(rdev, wdev); | ||
| 199 | } | 202 | } |
| 200 | 203 | ||
| 204 | msg = nl80211_build_scan_msg(rdev, wdev, request->aborted); | ||
| 205 | |||
| 201 | #ifdef CONFIG_CFG80211_WEXT | 206 | #ifdef CONFIG_CFG80211_WEXT |
| 202 | if (wdev->netdev && !request->aborted) { | 207 | if (wdev->netdev && !request->aborted) { |
| 203 | memset(&wrqu, 0, sizeof(wrqu)); | 208 | memset(&wrqu, 0, sizeof(wrqu)); |
| @@ -211,6 +216,11 @@ void ___cfg80211_scan_done(struct cfg80211_registered_device *rdev) | |||
| 211 | 216 | ||
| 212 | rdev->scan_req = NULL; | 217 | rdev->scan_req = NULL; |
| 213 | kfree(request); | 218 | kfree(request); |
| 219 | |||
| 220 | if (!send_message) | ||
| 221 | rdev->scan_msg = msg; | ||
| 222 | else | ||
| 223 | nl80211_send_scan_result(rdev, msg); | ||
| 214 | } | 224 | } |
| 215 | 225 | ||
| 216 | void __cfg80211_scan_done(struct work_struct *wk) | 226 | void __cfg80211_scan_done(struct work_struct *wk) |
| @@ -221,7 +231,7 @@ void __cfg80211_scan_done(struct work_struct *wk) | |||
| 221 | scan_done_wk); | 231 | scan_done_wk); |
| 222 | 232 | ||
| 223 | rtnl_lock(); | 233 | rtnl_lock(); |
| 224 | ___cfg80211_scan_done(rdev); | 234 | ___cfg80211_scan_done(rdev, true); |
| 225 | rtnl_unlock(); | 235 | rtnl_unlock(); |
| 226 | } | 236 | } |
| 227 | 237 | ||
| @@ -1079,7 +1089,7 @@ int cfg80211_wext_siwscan(struct net_device *dev, | |||
| 1079 | if (IS_ERR(rdev)) | 1089 | if (IS_ERR(rdev)) |
| 1080 | return PTR_ERR(rdev); | 1090 | return PTR_ERR(rdev); |
| 1081 | 1091 | ||
| 1082 | if (rdev->scan_req) { | 1092 | if (rdev->scan_req || rdev->scan_msg) { |
| 1083 | err = -EBUSY; | 1093 | err = -EBUSY; |
| 1084 | goto out; | 1094 | goto out; |
| 1085 | } | 1095 | } |
| @@ -1481,7 +1491,7 @@ int cfg80211_wext_giwscan(struct net_device *dev, | |||
| 1481 | if (IS_ERR(rdev)) | 1491 | if (IS_ERR(rdev)) |
| 1482 | return PTR_ERR(rdev); | 1492 | return PTR_ERR(rdev); |
| 1483 | 1493 | ||
| 1484 | if (rdev->scan_req) | 1494 | if (rdev->scan_req || rdev->scan_msg) |
| 1485 | return -EAGAIN; | 1495 | return -EAGAIN; |
| 1486 | 1496 | ||
| 1487 | res = ieee80211_scan_results(rdev, info, extra, data->length); | 1497 | res = ieee80211_scan_results(rdev, info, extra, data->length); |
diff --git a/net/wireless/sme.c b/net/wireless/sme.c index a63509118508..f04d4c32e96e 100644 --- a/net/wireless/sme.c +++ b/net/wireless/sme.c | |||
| @@ -67,7 +67,7 @@ static int cfg80211_conn_scan(struct wireless_dev *wdev) | |||
| 67 | ASSERT_RDEV_LOCK(rdev); | 67 | ASSERT_RDEV_LOCK(rdev); |
| 68 | ASSERT_WDEV_LOCK(wdev); | 68 | ASSERT_WDEV_LOCK(wdev); |
| 69 | 69 | ||
| 70 | if (rdev->scan_req) | 70 | if (rdev->scan_req || rdev->scan_msg) |
| 71 | return -EBUSY; | 71 | return -EBUSY; |
| 72 | 72 | ||
| 73 | if (wdev->conn->params.channel) | 73 | if (wdev->conn->params.channel) |
