Signed-off-by: Felix Fietkau <[email protected]>
---
net/mac80211/cfg.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 5c61677..a5d4361 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -998,8 +998,10 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
old_probe_resp = rtnl_dereference(sdata->u.ap.probe_resp);
/* turn off carrier for this interface and dependent VLANs */
- list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
+ list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) {
+ sta_info_flush(local, vlan);
netif_carrier_off(vlan->dev);
+ }
netif_carrier_off(dev);
/* remove beacon and probe response */
--
1.7.12.2
On Tue, 2012-12-11 at 20:20 +0100, Johannes Berg wrote:
> Applied.
Ok looking at the code I changed my mind ... I don't love the double
iteration but I think it's better than getting the ordering wrong so I
changed the patch a bit.
johannes
When .start_ap is called, copy the channel context to all active AP VLANs.
Also copy the channel context when bringing up/down an AP VLAN if the AP
has been started already.
Signed-off-by: Felix Fietkau <[email protected]>
---
net/mac80211/cfg.c | 5 +++++
net/mac80211/iface.c | 13 ++++++++++---
2 files changed, 15 insertions(+), 3 deletions(-)
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index a5d4361..b0a20ac 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -915,6 +915,10 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
if (err)
return err;
+ list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list)
+ rcu_assign_pointer(vlan->vif.chanctx_conf,
+ rcu_access_pointer(sdata->vif.chanctx_conf));
+
/*
* Apply control port protocol, this allows us to
* not encrypt dynamic WEP control frames.
@@ -1001,6 +1005,7 @@ static int ieee80211_stop_ap(struct wiphy *wiphy, struct net_device *dev)
list_for_each_entry(vlan, &sdata->u.ap.vlans, u.vlan.list) {
sta_info_flush(local, vlan);
netif_carrier_off(vlan->dev);
+ rcu_assign_pointer(sdata->vif.chanctx_conf, NULL);
}
netif_carrier_off(dev);
diff --git a/net/mac80211/iface.c b/net/mac80211/iface.c
index 40c36d5..c2deb2a 100644
--- a/net/mac80211/iface.c
+++ b/net/mac80211/iface.c
@@ -508,6 +508,7 @@ static void ieee80211_del_virtual_monitor(struct ieee80211_local *local)
int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_WDEV_TO_SUB_IF(wdev);
+ struct ieee80211_sub_if_data *ap;
struct net_device *dev = wdev->netdev;
struct ieee80211_local *local = sdata->local;
struct sta_info *sta;
@@ -587,10 +588,15 @@ int ieee80211_do_open(struct wireless_dev *wdev, bool coming_up)
switch (sdata->vif.type) {
case NL80211_IFTYPE_AP_VLAN:
/* no need to tell driver, but set carrier */
- if (rtnl_dereference(sdata->bss->beacon))
- netif_carrier_on(dev);
- else
+ if (!rtnl_dereference(sdata->bss->beacon)) {
netif_carrier_off(dev);
+ break;
+ }
+
+ ap = get_bss_sdata(sdata);
+ rcu_assign_pointer(sdata->vif.chanctx_conf,
+ rcu_access_pointer(ap->vif.chanctx_conf));
+ netif_carrier_on(dev);
break;
case NL80211_IFTYPE_MONITOR:
if (sdata->u.mntr_flags & MONITOR_FLAG_COOK_FRAMES) {
@@ -839,6 +845,7 @@ static void ieee80211_do_stop(struct ieee80211_sub_if_data *sdata,
switch (sdata->vif.type) {
case NL80211_IFTYPE_AP_VLAN:
list_del(&sdata->u.vlan.list);
+ rcu_assign_pointer(sdata->vif.chanctx_conf, NULL);
/* no need to tell driver */
break;
case NL80211_IFTYPE_MONITOR:
--
1.7.12.2
Applied.
johannes