aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/net/mac80211.h9
-rw-r--r--net/mac80211/cfg.c5
-rw-r--r--net/mac80211/main.c42
-rw-r--r--net/mac80211/mesh.c3
-rw-r--r--net/mac80211/mlme.c3
-rw-r--r--net/mac80211/scan.c18
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 */
650enum ieee80211_if_conf_change { 651enum 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 {
664struct ieee80211_if_conf { 668struct 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
529static int ieee80211_add_beacon(struct wiphy *wiphy, struct net_device *dev, 530static 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
448void ieee80211_stop_mesh(struct ieee80211_sub_if_data *sdata) 449void 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}
492EXPORT_SYMBOL(ieee80211_scan_completed); 495EXPORT_SYMBOL(ieee80211_scan_completed);
493 496
494
495void ieee80211_scan_work(struct work_struct *work) 497void 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;