diff options
-rw-r--r-- | include/net/mac80211.h | 9 | ||||
-rw-r--r-- | net/mac80211/cfg.c | 5 | ||||
-rw-r--r-- | net/mac80211/main.c | 42 | ||||
-rw-r--r-- | net/mac80211/mesh.c | 3 | ||||
-rw-r--r-- | net/mac80211/mlme.c | 3 | ||||
-rw-r--r-- | net/mac80211/scan.c | 18 |
6 files changed, 66 insertions, 14 deletions
diff --git a/include/net/mac80211.h b/include/net/mac80211.h index 634c08de6acb..35643c55827a 100644 --- a/include/net/mac80211.h +++ b/include/net/mac80211.h | |||
@@ -646,10 +646,12 @@ struct ieee80211_if_init_conf { | |||
646 | * @IEEE80211_IFCC_BSSID: The BSSID changed. | 646 | * @IEEE80211_IFCC_BSSID: The BSSID changed. |
647 | * @IEEE80211_IFCC_BEACON: The beacon for this interface changed | 647 | * @IEEE80211_IFCC_BEACON: The beacon for this interface changed |
648 | * (currently AP and MESH only), use ieee80211_beacon_get(). | 648 | * (currently AP and MESH only), use ieee80211_beacon_get(). |
649 | * @IEEE80211_IFCC_BEACON_ENABLED: The enable_beacon value changed. | ||
649 | */ | 650 | */ |
650 | enum ieee80211_if_conf_change { | 651 | enum ieee80211_if_conf_change { |
651 | IEEE80211_IFCC_BSSID = BIT(0), | 652 | IEEE80211_IFCC_BSSID = BIT(0), |
652 | IEEE80211_IFCC_BEACON = BIT(1), | 653 | IEEE80211_IFCC_BEACON = BIT(1), |
654 | IEEE80211_IFCC_BEACON_ENABLED = BIT(2), | ||
653 | }; | 655 | }; |
654 | 656 | ||
655 | /** | 657 | /** |
@@ -657,6 +659,8 @@ enum ieee80211_if_conf_change { | |||
657 | * | 659 | * |
658 | * @changed: parameters that have changed, see &enum ieee80211_if_conf_change. | 660 | * @changed: parameters that have changed, see &enum ieee80211_if_conf_change. |
659 | * @bssid: BSSID of the network we are associated to/creating. | 661 | * @bssid: BSSID of the network we are associated to/creating. |
662 | * @enable_beacon: Indicates whether beacons can be sent. | ||
663 | * This is valid only for AP/IBSS/MESH modes. | ||
660 | * | 664 | * |
661 | * This structure is passed to the config_interface() callback of | 665 | * This structure is passed to the config_interface() callback of |
662 | * &struct ieee80211_hw. | 666 | * &struct ieee80211_hw. |
@@ -664,6 +668,7 @@ enum ieee80211_if_conf_change { | |||
664 | struct ieee80211_if_conf { | 668 | struct ieee80211_if_conf { |
665 | u32 changed; | 669 | u32 changed; |
666 | const u8 *bssid; | 670 | const u8 *bssid; |
671 | bool enable_beacon; | ||
667 | }; | 672 | }; |
668 | 673 | ||
669 | /** | 674 | /** |
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 3527de22cafb..a1a1344c5c4b 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -523,7 +523,8 @@ static int ieee80211_config_beacon(struct ieee80211_sub_if_data *sdata, | |||
523 | 523 | ||
524 | kfree(old); | 524 | kfree(old); |
525 | 525 | ||
526 | return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); | 526 | return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON | |
527 | IEEE80211_IFCC_BEACON_ENABLED); | ||
527 | } | 528 | } |
528 | 529 | ||
529 | static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, | 530 | static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, |
@@ -583,7 +584,7 @@ static int ieee80211_del_beacon(struct wiphy *wiphy, struct net_device *dev) | |||
583 | synchronize_rcu(); | 584 | synchronize_rcu(); |
584 | kfree(old); | 585 | kfree(old); |
585 | 586 | ||
586 | return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); | 587 | return ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON_ENABLED); |
587 | } | 588 | } |
588 | 589 | ||
589 | /* Layer 2 Update frame (802.2 Type 1 LLC XID Update response) */ | 590 | /* Layer 2 Update frame (802.2 Type 1 LLC XID Update response) */ |
diff --git a/net/mac80211/main.c b/net/mac80211/main.c index 6f0fe3564ca4..8d5c19e4a1bc 100644 --- a/net/mac80211/main.c +++ b/net/mac80211/main.c | |||
@@ -168,7 +168,6 @@ int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed) | |||
168 | return 0; | 168 | return 0; |
169 | 169 | ||
170 | memset(&conf, 0, sizeof(conf)); | 170 | memset(&conf, 0, sizeof(conf)); |
171 | conf.changed = changed; | ||
172 | 171 | ||
173 | if (sdata->vif.type == NL80211_IFTYPE_STATION || | 172 | if (sdata->vif.type == NL80211_IFTYPE_STATION || |
174 | sdata->vif.type == NL80211_IFTYPE_ADHOC) | 173 | sdata->vif.type == NL80211_IFTYPE_ADHOC) |
@@ -183,9 +182,50 @@ int ieee80211_if_config(struct ieee80211_sub_if_data *sdata, u32 changed) | |||
183 | return -EINVAL; | 182 | return -EINVAL; |
184 | } | 183 | } |
185 | 184 | ||
185 | switch (sdata->vif.type) { | ||
186 | case NL80211_IFTYPE_AP: | ||
187 | case NL80211_IFTYPE_ADHOC: | ||
188 | case NL80211_IFTYPE_MESH_POINT: | ||
189 | break; | ||
190 | default: | ||
191 | /* do not warn to simplify caller in scan.c */ | ||
192 | changed &= ~IEEE80211_IFCC_BEACON_ENABLED; | ||
193 | if (WARN_ON(changed & IEEE80211_IFCC_BEACON)) | ||
194 | return -EINVAL; | ||
195 | changed &= ~IEEE80211_IFCC_BEACON; | ||
196 | break; | ||
197 | } | ||
198 | |||
199 | if (changed & IEEE80211_IFCC_BEACON_ENABLED) { | ||
200 | if (local->sw_scanning) { | ||
201 | conf.enable_beacon = false; | ||
202 | } else { | ||
203 | /* | ||
204 | * Beacon should be enabled, but AP mode must | ||
205 | * check whether there is a beacon configured. | ||
206 | */ | ||
207 | switch (sdata->vif.type) { | ||
208 | case NL80211_IFTYPE_AP: | ||
209 | conf.enable_beacon = | ||
210 | !!rcu_dereference(sdata->u.ap.beacon); | ||
211 | break; | ||
212 | case NL80211_IFTYPE_ADHOC: | ||
213 | case NL80211_IFTYPE_MESH_POINT: | ||
214 | conf.enable_beacon = true; | ||
215 | break; | ||
216 | default: | ||
217 | /* not reached */ | ||
218 | WARN_ON(1); | ||
219 | break; | ||
220 | } | ||
221 | } | ||
222 | } | ||
223 | |||
186 | if (WARN_ON(!conf.bssid && (changed & IEEE80211_IFCC_BSSID))) | 224 | if (WARN_ON(!conf.bssid && (changed & IEEE80211_IFCC_BSSID))) |
187 | return -EINVAL; | 225 | return -EINVAL; |
188 | 226 | ||
227 | conf.changed = changed; | ||
228 | |||
189 | return local->ops->config_interface(local_to_hw(local), | 229 | return local->ops->config_interface(local_to_hw(local), |
190 | &sdata->vif, &conf); | 230 | &sdata->vif, &conf); |
191 | } | 231 | } |
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c index 2d573f8470d0..8a1fcaeee4f2 100644 --- a/net/mac80211/mesh.c +++ b/net/mac80211/mesh.c | |||
@@ -442,7 +442,8 @@ void ieee80211_start_mesh(struct ieee80211_sub_if_data *sdata) | |||
442 | 442 | ||
443 | ifmsh->housekeeping = true; | 443 | ifmsh->housekeeping = true; |
444 | queue_work(local->hw.workqueue, &ifmsh->work); | 444 | queue_work(local->hw.workqueue, &ifmsh->work); |
445 | ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); | 445 | ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON | |
446 | IEEE80211_IFCC_BEACON_ENABLED); | ||
446 | } | 447 | } |
447 | 448 | ||
448 | void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) | 449 | void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) |
diff --git a/net/mac80211/mlme.c b/net/mac80211/mlme.c index 9852da54f5e7..ec400479c5f6 100644 --- a/net/mac80211/mlme.c +++ b/net/mac80211/mlme.c | |||
@@ -1599,7 +1599,8 @@ static int ieee80211_sta_join_ibss(struct ieee80211_sub_if_data *sdata, | |||
1599 | 1599 | ||
1600 | ifsta->probe_resp = skb; | 1600 | ifsta->probe_resp = skb; |
1601 | 1601 | ||
1602 | ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON); | 1602 | ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON | |
1603 | IEEE80211_IFCC_BEACON_ENABLED); | ||
1603 | 1604 | ||
1604 | 1605 | ||
1605 | rates = 0; | 1606 | rates = 0; |
diff --git a/net/mac80211/scan.c b/net/mac80211/scan.c index a2caeed57f4e..8248d7b6ae82 100644 --- a/net/mac80211/scan.c +++ b/net/mac80211/scan.c | |||
@@ -20,6 +20,7 @@ | |||
20 | 20 | ||
21 | #include <linux/wireless.h> | 21 | #include <linux/wireless.h> |
22 | #include <linux/if_arp.h> | 22 | #include <linux/if_arp.h> |
23 | #include <linux/rtnetlink.h> | ||
23 | #include <net/mac80211.h> | 24 | #include <net/mac80211.h> |
24 | #include <net/iw_handler.h> | 25 | #include <net/iw_handler.h> |
25 | 26 | ||
@@ -472,8 +473,8 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw) | |||
472 | netif_addr_unlock(local->mdev); | 473 | netif_addr_unlock(local->mdev); |
473 | netif_tx_unlock_bh(local->mdev); | 474 | netif_tx_unlock_bh(local->mdev); |
474 | 475 | ||
475 | rcu_read_lock(); | 476 | mutex_lock(&local->iflist_mtx); |
476 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 477 | list_for_each_entry(sdata, &local->interfaces, list) { |
477 | /* Tell AP we're back */ | 478 | /* Tell AP we're back */ |
478 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | 479 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { |
479 | if (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) { | 480 | if (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) { |
@@ -482,8 +483,10 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw) | |||
482 | } | 483 | } |
483 | } else | 484 | } else |
484 | netif_tx_wake_all_queues(sdata->dev); | 485 | netif_tx_wake_all_queues(sdata->dev); |
486 | |||
487 | ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON_ENABLED); | ||
485 | } | 488 | } |
486 | rcu_read_unlock(); | 489 | mutex_unlock(&local->iflist_mtx); |
487 | 490 | ||
488 | done: | 491 | done: |
489 | ieee80211_mlme_notify_scan_completed(local); | 492 | ieee80211_mlme_notify_scan_completed(local); |
@@ -491,7 +494,6 @@ void ieee80211_scan_completed(struct ieee80211_hw *hw) | |||
491 | } | 494 | } |
492 | EXPORT_SYMBOL(ieee80211_scan_completed); | 495 | EXPORT_SYMBOL(ieee80211_scan_completed); |
493 | 496 | ||
494 | |||
495 | void ieee80211_scan_work(struct work_struct *work) | 497 | void ieee80211_scan_work(struct work_struct *work) |
496 | { | 498 | { |
497 | struct ieee80211_local *local = | 499 | struct ieee80211_local *local = |
@@ -633,8 +635,10 @@ int ieee80211_start_scan(struct ieee80211_sub_if_data *scan_sdata, | |||
633 | 635 | ||
634 | local->sw_scanning = true; | 636 | local->sw_scanning = true; |
635 | 637 | ||
636 | rcu_read_lock(); | 638 | mutex_lock(&local->iflist_mtx); |
637 | list_for_each_entry_rcu(sdata, &local->interfaces, list) { | 639 | list_for_each_entry(sdata, &local->interfaces, list) { |
640 | ieee80211_if_config(sdata, IEEE80211_IFCC_BEACON_ENABLED); | ||
641 | |||
638 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { | 642 | if (sdata->vif.type == NL80211_IFTYPE_STATION) { |
639 | if (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) { | 643 | if (sdata->u.sta.flags & IEEE80211_STA_ASSOCIATED) { |
640 | netif_tx_stop_all_queues(sdata->dev); | 644 | netif_tx_stop_all_queues(sdata->dev); |
@@ -643,7 +647,7 @@ int ieee80211_start_scan(struct ieee80211_sub_if_data *scan_sdata, | |||
643 | } else | 647 | } else |
644 | netif_tx_stop_all_queues(sdata->dev); | 648 | netif_tx_stop_all_queues(sdata->dev); |
645 | } | 649 | } |
646 | rcu_read_unlock(); | 650 | mutex_unlock(&local->iflist_mtx); |
647 | 651 | ||
648 | if (ssid) { | 652 | if (ssid) { |
649 | local->scan_ssid_len = ssid_len; | 653 | local->scan_ssid_len = ssid_len; |