2013-11-14 12:10:11

by Luciano Coelho

[permalink] [raw]
Subject: [PATCH v5 1/5] mac80211: refactor ieee80211_ibss_process_chanswitch()

Refactor ieee80211_ibss_process_chanswitch() to use
ieee80211_channel_switch() and avoid code duplication.

Change-Id: I265a12c7f825dc20535bad1197a81437310d0086
Signed-off-by: Luciano Coelho <[email protected]>
---
net/mac80211/cfg.c | 4 ++--
net/mac80211/ibss.c | 58 +++++++---------------------------------------
net/mac80211/ieee80211_i.h | 2 ++
3 files changed, 12 insertions(+), 52 deletions(-)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 3bc92d0..a98dc6b 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -3035,8 +3035,8 @@ void ieee80211_csa_finalize_work(struct work_struct *work)
cfg80211_ch_switch_notify(sdata->dev, &sdata->csa_chandef);
}

-static int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
- struct cfg80211_csa_settings *params)
+int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_csa_settings *params)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct ieee80211_local *local = sdata->local;
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 0f1fb5d..3514aab 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -784,18 +784,10 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata,
struct cfg80211_csa_settings params;
struct ieee80211_csa_ie csa_ie;
struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
- struct ieee80211_chanctx_conf *chanctx_conf;
- struct ieee80211_chanctx *chanctx;
enum nl80211_channel_type ch_type;
- int err, num_chanctx;
+ int err;
u32 sta_flags;

- if (sdata->vif.csa_active)
- return true;
-
- if (!sdata->vif.bss_conf.ibss_joined)
- return false;
-
sta_flags = IEEE80211_STA_DISABLE_VHT;
switch (ifibss->chandef.width) {
case NL80211_CHAN_WIDTH_5:
@@ -826,9 +818,6 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata,
params.count = csa_ie.count;
params.chandef = csa_ie.chandef;

- if (ifibss->chandef.chan->band != params.chandef.chan->band)
- goto disconnect;
-
switch (ifibss->chandef.width) {
case NL80211_CHAN_WIDTH_20_NOHT:
case NL80211_CHAN_WIDTH_20:
@@ -884,29 +873,6 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata,
params.radar_required = true;
}

- rcu_read_lock();
- chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
- if (!chanctx_conf) {
- rcu_read_unlock();
- goto disconnect;
- }
-
- /* don't handle for multi-VIF cases */
- chanctx = container_of(chanctx_conf, struct ieee80211_chanctx, conf);
- if (chanctx->refcount > 1) {
- rcu_read_unlock();
- goto disconnect;
- }
- num_chanctx = 0;
- list_for_each_entry_rcu(chanctx, &sdata->local->chanctx_list, list)
- num_chanctx++;
-
- if (num_chanctx > 1) {
- rcu_read_unlock();
- goto disconnect;
- }
- rcu_read_unlock();
-
/* all checks done, now perform the channel switch. */
ibss_dbg(sdata,
"received channel switch announcement to go to channel %d MHz\n",
@@ -914,19 +880,9 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata,

params.block_tx = !!csa_ie.mode;

- ieee80211_ibss_csa_beacon(sdata, &params);
- sdata->csa_radar_required = params.radar_required;
-
- if (params.block_tx)
- ieee80211_stop_queues_by_reason(&sdata->local->hw,
- IEEE80211_MAX_QUEUE_MAP,
- IEEE80211_QUEUE_STOP_REASON_CSA);
-
- sdata->csa_chandef = params.chandef;
- sdata->vif.csa_active = true;
-
- ieee80211_bss_info_change_notify(sdata, err);
- drv_channel_switch_beacon(sdata, &params.chandef);
+ if (ieee80211_channel_switch(sdata->local->hw.wiphy, sdata->dev,
+ &params))
+ goto disconnect;

ieee80211_ibss_csa_mark_radar(sdata);

@@ -962,7 +918,8 @@ ieee80211_rx_mgmt_spectrum_mgmt(struct ieee80211_sub_if_data *sdata,
if (len < required_len)
return;

- ieee80211_ibss_process_chanswitch(sdata, elems, false);
+ if (!sdata->vif.csa_active)
+ ieee80211_ibss_process_chanswitch(sdata, elems, false);
}

static void ieee80211_rx_mgmt_deauth_ibss(struct ieee80211_sub_if_data *sdata,
@@ -1143,7 +1100,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
goto put_bss;

/* process channel switch */
- if (ieee80211_ibss_process_chanswitch(sdata, elems, true))
+ if (sdata->vif.csa_active ||
+ ieee80211_ibss_process_chanswitch(sdata, elems, true))
goto put_bss;

/* same BSSID */
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 0edc1fb..3a77ed1 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1412,6 +1412,8 @@ void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc);

/* channel switch handling */
void ieee80211_csa_finalize_work(struct work_struct *work);
+int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
+ struct cfg80211_csa_settings *params);

/* interface handling */
int ieee80211_iface_init(void);
--
1.8.4.rc3



2013-11-14 12:10:13

by Luciano Coelho

[permalink] [raw]
Subject: [PATCH v5 5/5] mac80211: only set CSA beacon when at least one beacon must be transmitted

A beacon should never have a Channel Switch Announcement information
element with a count of 0, because a count of 1 means switch just
before the next beacon. So, if a count of 0 was valid in a beacon, it
would have been transmitted in the next channel already, which is
useless. A CSA count equal to zero is only meaningful in action
frames or probe_responses.

Fix the ieee80211_csa_is_complete() and ieee80211_update_csa()
functions accordingly.

With a CSA count of 0, we won't transmit any CSA beacons, because the
switch will happen before the next TBTT. To avoid extra work and
potential confusion in the drivers, complete the CSA immediately,
instead of waiting for the driver to call ieee80211_csa_finish().

To keep things simpler, we also switch immediately when the CSA count
is 1, while in theory we should delay the switch until just before the
next TBTT.

Additionally, move the ieee80211_csa_finish() function to cfg.c,
where it makes more sense.

Signed-off-by: Luciano Coelho <[email protected]>
---

In v5:

* use csa_role instead of chsw_init (to match the changes in the mesh patches);

include/net/mac80211.h | 10 +++--
net/mac80211/cfg.c | 96 +++++++++++++++++++++++++++++++++++-----------
net/mac80211/ibss.c | 6 ---
net/mac80211/ieee80211_i.h | 3 +-
net/mac80211/mesh.c | 6 +--
net/mac80211/tx.c | 19 ++++-----
6 files changed, 89 insertions(+), 51 deletions(-)

diff --git a/include/net/mac80211.h b/include/net/mac80211.h
index 3cd408b..535bda3 100644
--- a/include/net/mac80211.h
+++ b/include/net/mac80211.h
@@ -2720,11 +2720,13 @@ enum ieee80211_roc_type {
* @channel_switch_beacon: Starts a channel switch to a new channel.
* Beacons are modified to include CSA or ECSA IEs before calling this
* function. The corresponding count fields in these IEs must be
- * decremented, and when they reach zero the driver must call
+ * decremented, and when they reach 1 the driver must call
* ieee80211_csa_finish(). Drivers which use ieee80211_beacon_get()
* get the csa counter decremented by mac80211, but must check if it is
- * zero using ieee80211_csa_is_complete() after the beacon has been
+ * 1 using ieee80211_csa_is_complete() after the beacon has been
* transmitted and then call ieee80211_csa_finish().
+ * If the CSA count starts as zero or 1, this function will not be called,
+ * since there won't be any time to beacon before the switch anyway.
*
* @join_ibss: Join an IBSS (on an IBSS interface); this is called after all
* information in bss_conf is set up and the beacon can be retrieved. A
@@ -3423,13 +3425,13 @@ static inline struct sk_buff *ieee80211_beacon_get(struct ieee80211_hw *hw,
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
*
* After a channel switch announcement was scheduled and the counter in this
- * announcement hit zero, this function must be called by the driver to
+ * announcement hits 1, this function must be called by the driver to
* notify mac80211 that the channel can be changed.
*/
void ieee80211_csa_finish(struct ieee80211_vif *vif);

/**
- * ieee80211_csa_is_complete - find out if counters reached zero
+ * ieee80211_csa_is_complete - find out if counters reached 1
* @vif: &struct ieee80211_vif pointer from the add_interface callback.
*
* This function returns whether the channel switch counters reached zero.
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index 6eb8e08..48faf6a 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -2978,17 +2978,20 @@ cfg80211_beacon_dup(struct cfg80211_beacon_data *beacon)
return new_beacon;
}

-void ieee80211_csa_finalize_work(struct work_struct *work)
+void ieee80211_csa_finish(struct ieee80211_vif *vif)
+{
+ struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
+
+ ieee80211_queue_work(&sdata->local->hw,
+ &sdata->csa_finalize_work);
+}
+EXPORT_SYMBOL(ieee80211_csa_finish);
+
+static void ieee80211_csa_finalize(struct ieee80211_sub_if_data *sdata)
{
- struct ieee80211_sub_if_data *sdata =
- container_of(work, struct ieee80211_sub_if_data,
- csa_finalize_work);
struct ieee80211_local *local = sdata->local;
int err, changed = 0;

- if (!ieee80211_sdata_running(sdata))
- return;
-
sdata->radar_required = sdata->csa_radar_required;
err = ieee80211_vif_change_channel(sdata, &changed);
if (WARN_ON(err < 0))
@@ -3035,6 +3038,18 @@ void ieee80211_csa_finalize_work(struct work_struct *work)
cfg80211_ch_switch_notify(sdata->dev, &sdata->csa_chandef);
}

+void ieee80211_csa_finalize_work(struct work_struct *work)
+{
+ struct ieee80211_sub_if_data *sdata =
+ container_of(work, struct ieee80211_sub_if_data,
+ csa_finalize_work);
+
+ if (!ieee80211_sdata_running(sdata))
+ return;
+
+ ieee80211_csa_finalize(sdata);
+}
+
int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_csa_settings *params)
{
@@ -3043,7 +3058,7 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
struct ieee80211_chanctx_conf *chanctx_conf;
struct ieee80211_chanctx *chanctx;
struct ieee80211_if_mesh __maybe_unused *ifmsh;
- int err, num_chanctx;
+ int err, num_chanctx, changed = 0;

if (!list_empty(&local->roc_list) || local->scanning)
return -EBUSY;
@@ -3082,19 +3097,40 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,

switch (sdata->vif.type) {
case NL80211_IFTYPE_AP:
- sdata->csa_counter_offset_beacon =
- params->counter_offset_beacon;
- sdata->csa_counter_offset_presp = params->counter_offset_presp;
sdata->u.ap.next_beacon =
cfg80211_beacon_dup(&params->beacon_after);
if (!sdata->u.ap.next_beacon)
return -ENOMEM;

+ /*
+ * With a count of 0, we don't have to wait for any
+ * TBTT before switching, so complete the CSA
+ * immediately. In theory, with a count == 1 we
+ * should delay the switch until just before the next
+ * TBTT, but that would complicate things so we switch
+ * immediately too. If we would delay the switch
+ * until the next TBTT, we would have to set the probe
+ * response here.
+ *
+ * TODO: A channel switch with count <= 1 without
+ * sending a CSA action frame is kind of useless,
+ * because the clients won't know we're changing
+ * channels. The action frame must be implemented
+ * either here or in the userspace.
+ */
+ if (params->count <= 1)
+ break;
+
+ sdata->csa_counter_offset_beacon =
+ params->counter_offset_beacon;
+ sdata->csa_counter_offset_presp = params->counter_offset_presp;
err = ieee80211_assign_beacon(sdata, &params->beacon_csa);
if (err < 0) {
kfree(sdata->u.ap.next_beacon);
return err;
}
+ changed |= err;
+
break;
case NL80211_IFTYPE_ADHOC:
if (!sdata->vif.bss_conf.ibss_joined)
@@ -3122,9 +3158,16 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
params->chandef.chan->band)
return -EINVAL;

- err = ieee80211_ibss_csa_beacon(sdata, params);
- if (err < 0)
- return err;
+ /* see comments and TODO in the NL80211_IFTYPE_AP block */
+ if (params->count > 1) {
+ err = ieee80211_ibss_csa_beacon(sdata, params);
+ if (err < 0)
+ return err;
+ changed |= err;
+ }
+
+ ieee80211_send_action_csa(sdata, params);
+
break;
#ifdef CONFIG_MAC80211_MESH
case NL80211_IFTYPE_MESH_POINT:
@@ -3149,13 +3192,17 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
ifmsh->pre_value++;
}

- err = ieee80211_mesh_csa_beacon(sdata, params,
- (ifmsh->csa_role == IEEE80211_MESH_CSA_ROLE_INIT));
- if (err < 0) {
- ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_NONE;
- return err;
+ if (params->count > 1) {
+ err = ieee80211_mesh_csa_beacon(sdata, params);
+ if (err < 0) {
+ ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_NONE;
+ return err;
+ }
+ changed |= err;
}
- changed |= err;
+
+ if (ifmsh->csa_role == IEEE80211_MESH_CSA_ROLE_INIT)
+ ieee80211_send_action_csa(sdata, params);

break;
#endif
@@ -3173,8 +3220,13 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
sdata->csa_chandef = params->chandef;
sdata->vif.csa_active = true;

- ieee80211_bss_info_change_notify(sdata, err);
- drv_channel_switch_beacon(sdata, &params->chandef);
+ if (changed) {
+ ieee80211_bss_info_change_notify(sdata, changed);
+ drv_channel_switch_beacon(sdata, &params->chandef);
+ } else {
+ /* if the beacon didn't change, we can finalize immediately */
+ ieee80211_csa_finalize(sdata);
+ }

return 0;
}
diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 23e035f..595902c 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -516,12 +516,6 @@ int ieee80211_ibss_csa_beacon(struct ieee80211_sub_if_data *sdata,
if (old_presp)
kfree_rcu(old_presp, rcu_head);

- /* it might not send the beacon for a while. send an action frame
- * immediately to announce the channel switch.
- */
- if (csa_settings)
- ieee80211_send_action_csa(sdata, csa_settings);
-
return BSS_CHANGED_BEACON;
out:
return ret;
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 15c9c39..6252ee7 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -1370,8 +1370,7 @@ void ieee80211_mesh_work(struct ieee80211_sub_if_data *sdata);
void ieee80211_mesh_rx_queued_mgmt(struct ieee80211_sub_if_data *sdata,
struct sk_buff *skb);
int ieee80211_mesh_csa_beacon(struct ieee80211_sub_if_data *sdata,
- struct cfg80211_csa_settings *csa_settings,
- bool csa_action);
+ struct cfg80211_csa_settings *csa_settings);
int ieee80211_mesh_finish_csa(struct ieee80211_sub_if_data *sdata);

/* scan/BSS handling */
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 94dff7f..9628bda 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -1066,8 +1066,7 @@ int ieee80211_mesh_finish_csa(struct ieee80211_sub_if_data *sdata)
}

int ieee80211_mesh_csa_beacon(struct ieee80211_sub_if_data *sdata,
- struct cfg80211_csa_settings *csa_settings,
- bool csa_action)
+ struct cfg80211_csa_settings *csa_settings)
{
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
struct mesh_csa_settings *tmp_csa_settings;
@@ -1091,9 +1090,6 @@ int ieee80211_mesh_csa_beacon(struct ieee80211_sub_if_data *sdata,
return ret;
}

- if (csa_action)
- ieee80211_send_action_csa(sdata, csa_settings);
-
return BSS_CHANGED_BEACON;
}

diff --git a/net/mac80211/tx.c b/net/mac80211/tx.c
index ec1726a..0b5dbc3 100644
--- a/net/mac80211/tx.c
+++ b/net/mac80211/tx.c
@@ -2372,15 +2372,6 @@ static int ieee80211_beacon_add_tim(struct ieee80211_sub_if_data *sdata,
return 0;
}

-void ieee80211_csa_finish(struct ieee80211_vif *vif)
-{
- struct ieee80211_sub_if_data *sdata = vif_to_sdata(vif);
-
- ieee80211_queue_work(&sdata->local->hw,
- &sdata->csa_finalize_work);
-}
-EXPORT_SYMBOL(ieee80211_csa_finish);
-
static void ieee80211_update_csa(struct ieee80211_sub_if_data *sdata,
struct beacon_data *beacon)
{
@@ -2409,8 +2400,12 @@ static void ieee80211_update_csa(struct ieee80211_sub_if_data *sdata,
if (WARN_ON(counter_offset_beacon >= beacon_data_len))
return;

- /* warn if the driver did not check for/react to csa completeness */
- if (WARN_ON(beacon_data[counter_offset_beacon] == 0))
+ /* Warn if the driver did not check for/react to csa
+ * completeness. A beacon with CSA counter set to 0 should
+ * never occur, because a counter of 1 means switch just
+ * before the next beacon.
+ */
+ if (WARN_ON(beacon_data[counter_offset_beacon] == 1))
return;

beacon_data[counter_offset_beacon]--;
@@ -2476,7 +2471,7 @@ bool ieee80211_csa_is_complete(struct ieee80211_vif *vif)
if (WARN_ON(counter_beacon > beacon_data_len))
goto out;

- if (beacon_data[counter_beacon] == 0)
+ if (beacon_data[counter_beacon] == 1)
ret = true;
out:
rcu_read_unlock();
--
1.8.4.rc3


2013-11-14 12:12:23

by Luca Coelho

[permalink] [raw]
Subject: Re: [PATCH v5 1/5] mac80211: refactor ieee80211_ibss_process_chanswitch()

Hi,

Just to clarify, these patches are now based on mac80211-next (thanks
Simon), so we don't need to apply anything manually (as with the
previous patch set that was based on wireless-testing).

Please review and test, especially the MESH and IBSS parts!

--
Cheers,
Luca.

On Thu, 2013-11-14 at 14:09 +0200, Luciano Coelho wrote:
> Refactor ieee80211_ibss_process_chanswitch() to use
> ieee80211_channel_switch() and avoid code duplication.
>
> Change-Id: I265a12c7f825dc20535bad1197a81437310d0086
> Signed-off-by: Luciano Coelho <[email protected]>
> ---
> net/mac80211/cfg.c | 4 ++--
> net/mac80211/ibss.c | 58 +++++++---------------------------------------
> net/mac80211/ieee80211_i.h | 2 ++
> 3 files changed, 12 insertions(+), 52 deletions(-)
>
> diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
> index 3bc92d0..a98dc6b 100644
> --- a/net/mac80211/cfg.c
> +++ b/net/mac80211/cfg.c
> @@ -3035,8 +3035,8 @@ void ieee80211_csa_finalize_work(struct work_struct *work)
> cfg80211_ch_switch_notify(sdata->dev, &sdata->csa_chandef);
> }
>
> -static int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
> - struct cfg80211_csa_settings *params)
> +int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
> + struct cfg80211_csa_settings *params)
> {
> struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
> struct ieee80211_local *local = sdata->local;
> diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
> index 0f1fb5d..3514aab 100644
> --- a/net/mac80211/ibss.c
> +++ b/net/mac80211/ibss.c
> @@ -784,18 +784,10 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata,
> struct cfg80211_csa_settings params;
> struct ieee80211_csa_ie csa_ie;
> struct ieee80211_if_ibss *ifibss = &sdata->u.ibss;
> - struct ieee80211_chanctx_conf *chanctx_conf;
> - struct ieee80211_chanctx *chanctx;
> enum nl80211_channel_type ch_type;
> - int err, num_chanctx;
> + int err;
> u32 sta_flags;
>
> - if (sdata->vif.csa_active)
> - return true;
> -
> - if (!sdata->vif.bss_conf.ibss_joined)
> - return false;
> -
> sta_flags = IEEE80211_STA_DISABLE_VHT;
> switch (ifibss->chandef.width) {
> case NL80211_CHAN_WIDTH_5:
> @@ -826,9 +818,6 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata,
> params.count = csa_ie.count;
> params.chandef = csa_ie.chandef;
>
> - if (ifibss->chandef.chan->band != params.chandef.chan->band)
> - goto disconnect;
> -
> switch (ifibss->chandef.width) {
> case NL80211_CHAN_WIDTH_20_NOHT:
> case NL80211_CHAN_WIDTH_20:
> @@ -884,29 +873,6 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata,
> params.radar_required = true;
> }
>
> - rcu_read_lock();
> - chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
> - if (!chanctx_conf) {
> - rcu_read_unlock();
> - goto disconnect;
> - }
> -
> - /* don't handle for multi-VIF cases */
> - chanctx = container_of(chanctx_conf, struct ieee80211_chanctx, conf);
> - if (chanctx->refcount > 1) {
> - rcu_read_unlock();
> - goto disconnect;
> - }
> - num_chanctx = 0;
> - list_for_each_entry_rcu(chanctx, &sdata->local->chanctx_list, list)
> - num_chanctx++;
> -
> - if (num_chanctx > 1) {
> - rcu_read_unlock();
> - goto disconnect;
> - }
> - rcu_read_unlock();
> -
> /* all checks done, now perform the channel switch. */
> ibss_dbg(sdata,
> "received channel switch announcement to go to channel %d MHz\n",
> @@ -914,19 +880,9 @@ ieee80211_ibss_process_chanswitch(struct ieee80211_sub_if_data *sdata,
>
> params.block_tx = !!csa_ie.mode;
>
> - ieee80211_ibss_csa_beacon(sdata, &params);
> - sdata->csa_radar_required = params.radar_required;
> -
> - if (params.block_tx)
> - ieee80211_stop_queues_by_reason(&sdata->local->hw,
> - IEEE80211_MAX_QUEUE_MAP,
> - IEEE80211_QUEUE_STOP_REASON_CSA);
> -
> - sdata->csa_chandef = params.chandef;
> - sdata->vif.csa_active = true;
> -
> - ieee80211_bss_info_change_notify(sdata, err);
> - drv_channel_switch_beacon(sdata, &params.chandef);
> + if (ieee80211_channel_switch(sdata->local->hw.wiphy, sdata->dev,
> + &params))
> + goto disconnect;
>
> ieee80211_ibss_csa_mark_radar(sdata);
>
> @@ -962,7 +918,8 @@ ieee80211_rx_mgmt_spectrum_mgmt(struct ieee80211_sub_if_data *sdata,
> if (len < required_len)
> return;
>
> - ieee80211_ibss_process_chanswitch(sdata, elems, false);
> + if (!sdata->vif.csa_active)
> + ieee80211_ibss_process_chanswitch(sdata, elems, false);
> }
>
> static void ieee80211_rx_mgmt_deauth_ibss(struct ieee80211_sub_if_data *sdata,
> @@ -1143,7 +1100,8 @@ static void ieee80211_rx_bss_info(struct ieee80211_sub_if_data *sdata,
> goto put_bss;
>
> /* process channel switch */
> - if (ieee80211_ibss_process_chanswitch(sdata, elems, true))
> + if (sdata->vif.csa_active ||
> + ieee80211_ibss_process_chanswitch(sdata, elems, true))
> goto put_bss;
>
> /* same BSSID */
> diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
> index 0edc1fb..3a77ed1 100644
> --- a/net/mac80211/ieee80211_i.h
> +++ b/net/mac80211/ieee80211_i.h
> @@ -1412,6 +1412,8 @@ void ieee80211_handle_roc_started(struct ieee80211_roc_work *roc);
>
> /* channel switch handling */
> void ieee80211_csa_finalize_work(struct work_struct *work);
> +int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
> + struct cfg80211_csa_settings *params);
>
> /* interface handling */
> int ieee80211_iface_init(void);



2013-11-14 15:08:53

by Luciano Coelho

[permalink] [raw]
Subject: Re: [PATCH v5 5/5] mac80211: only set CSA beacon when at least one beacon must be transmitted

T24gVGh1LCAyMDEzLTExLTE0IGF0IDE1OjUzICswMTAwLCBTaW1vbiBXdW5kZXJsaWNoIHdyb3Rl
Og0KPiA+IEBAIC0zMTIyLDkgKzMxNTgsMTYgQEAgaW50IGllZWU4MDIxMV9jaGFubmVsX3N3aXRj
aChzdHJ1Y3Qgd2lwaHkgKndpcGh5LA0KPiA+IHN0cnVjdCBuZXRfZGV2aWNlICpkZXYsIHBhcmFt
cy0+Y2hhbmRlZi5jaGFuLT5iYW5kKQ0KPiA+ICAJCQlyZXR1cm4gLUVJTlZBTDsNCj4gPiANCj4g
PiAtCQllcnIgPSBpZWVlODAyMTFfaWJzc19jc2FfYmVhY29uKHNkYXRhLCBwYXJhbXMpOw0KPiA+
IC0JCWlmIChlcnIgPCAwKQ0KPiA+IC0JCQlyZXR1cm4gZXJyOw0KPiA+ICsJCS8qIHNlZSBjb21t
ZW50cyBhbmQgVE9ETyBpbiB0aGUgTkw4MDIxMV9JRlRZUEVfQVAgYmxvY2sgKi8NCj4gDQo+IFNp
bmNlIHlvdSBhcmUgc2VuZGluZyBhbiBhY3Rpb24gZnJhbWUgYmVsb3csIHRoaXMgVE9ETyBhcHBl
YXJzIHRvIGJlIG9ic29sZXRlPw0KDQpSaWdodC4uLiBUaGUgY29tbWVudHMgYXJlIHN0aWxsIHZh
bGlkLCBidXQgdGhlIFRPRE8gb25seSBhcHBsaWVzIHRvIEFQLA0Kc2luY2UgSUJTUyBhbmQgTUVT
SCBzZW5kIHRoZSBhY3Rpb24gZnJhbWUsIGFzIHlvdSBwb2ludGVkIG91dC4NCg0KSSdsbCBmaXgg
aXQuDQoNCg0KDQo+ID4gQEAgLTMxNzMsOCArMzIyMCwxMyBAQCBpbnQgaWVlZTgwMjExX2NoYW5u
ZWxfc3dpdGNoKHN0cnVjdCB3aXBoeSAqd2lwaHksDQo+ID4gc3RydWN0IG5ldF9kZXZpY2UgKmRl
diwgc2RhdGEtPmNzYV9jaGFuZGVmID0gcGFyYW1zLT5jaGFuZGVmOw0KPiA+ICAJc2RhdGEtPnZp
Zi5jc2FfYWN0aXZlID0gdHJ1ZTsNCj4gPiANCj4gPiAtCWllZWU4MDIxMV9ic3NfaW5mb19jaGFu
Z2Vfbm90aWZ5KHNkYXRhLCBlcnIpOw0KPiA+IC0JZHJ2X2NoYW5uZWxfc3dpdGNoX2JlYWNvbihz
ZGF0YSwgJnBhcmFtcy0+Y2hhbmRlZik7DQo+ID4gKwlpZiAoY2hhbmdlZCkgew0KPiA+ICsJCWll
ZWU4MDIxMV9ic3NfaW5mb19jaGFuZ2Vfbm90aWZ5KHNkYXRhLCBjaGFuZ2VkKTsNCj4gPiArCQlk
cnZfY2hhbm5lbF9zd2l0Y2hfYmVhY29uKHNkYXRhLCAmcGFyYW1zLT5jaGFuZGVmKTsNCj4gPiAr
CX0gZWxzZSB7DQo+ID4gKwkJLyogaWYgdGhlIGJlYWNvbiBkaWRuJ3QgY2hhbmdlLCB3ZSBjYW4g
ZmluYWxpemUgaW1tZWRpYXRlbHkgKi8NCj4gPiArCQlpZWVlODAyMTFfY3NhX2ZpbmFsaXplKHNk
YXRhKTsNCj4gPiArCX0NCj4gDQo+IEkgdGhpbmsgc2V0dGluZyBjc2FfYWN0aXZlID09IHRydWUg
Zm9yIGNvdW50IDAgb3IgMSBpcyB3cm9uZy4gDQo+IA0KPiBXaGVuIGEgYmVhY29uIGlzIGdlbmVy
YXRlZC91cGRhdGVkIGluIGllZWU4MDIxMV9iZWFjb25fZ2V0X3RpbSgpLCBpdCB3aWwgY2FsbCAN
Cj4gaWVlZTgwMjExX3VwZGF0ZV9jc2EoKSB3aGljaCB3aWxsIHRocm93IGEgd2FybmluZyBpbiBi
ZXN0IGNhc2UsIGJ1dCBhbHNvIA0KPiBtb2RpZmllcyByYW5kb20gZGF0YSBpbiB0aGUgYmVhY29u
L3ByZXNwIGF0IHRoZSBwb3NpdGlvbiB3aGVyZSB0aGUgY291bnQgb2Zmc2V0IA0KPiBwb2ludHMg
dG8gKHdlIGhhdmUgbm8gQ1NBIElFIGluIHRoaXMgY2FzZSkuDQoNCkhtbW0uLi4gSSBndWVzcyB5
b3UncmUgcmlnaHQuICBJIHdhcyBzZXR0aW5nIHRoZSBjc2FfYWN0aXZlIHRvIHRydWUgYXQNCmZp
cnN0IGJlY2F1c2UgSSB3YXMgcHV0dGluZyB0aGUgd29yayBpbiBhIHdvcmtxdWV1ZSwgc28gSSB3
YXMgdHJ5aW5nIHRvDQphdm9pZCBwb3RlbnRpYWwgcmFjZXMuICBJJ2xsIGluc3BlY3QgdGhpcyBt
b3JlIGNhcmVmdWxseSBhbmQgZml4IGl0Lg0KDQoNCg0KPiBJJ3ZlIGFsc28gc2VlbiB3YXJuaW5n
cyBpbiBteSBJQlNTIHRlc3RzIChXQVJOSU5HOiBDUFU6IDAgUElEOiAwIGF0IA0KPiBuZXQvbWFj
ODAyMTEvdHguYzoyNDA4IGllZWU4MDIxMV91cGRhdGVfY3NhKSwgd2hlbiBkb2luZyBhIENTQSB3
aXRoIGNvdW50IDAgDQo+IGZyb20gdXNlcnNwYWNlLiBBbHRob3VnaCBsaWtlbHksIEknbSBub3Qg
c3VyZSBpZiB0aGlzIGlzIHJlbGF0ZWQgdG8gdGhlIA0KPiBwcm9ibGVtIGRlc2NyaWJlZCBhYm92
ZSwgYnV0IHRoaXMgZnVuY3Rpb24gc2hvdWxkbid0IGJlIGNhbGxlZCBhdCBhbGwgaW4gdGhlIA0K
PiBjb3VudD0wIGNhc2UuDQoNClllcywgdGhpcyBpcyBtb3N0IGxpa2VseSByZWxhdGVkLiAgSSds
bCB0cnkgdG8gZmlndXJlIG91dCB3aGF0IGlzIGdvaW5nDQp3cm9uZyBoZXJlLg0KDQpUaGFua3Mg
YSBsb3QgZm9yIHlvdXIgdGVzdHMhDQoNCi0tDQpDaGVlcnMsDQpMdWNhLg0K

2013-11-14 12:10:11

by Luciano Coelho

[permalink] [raw]
Subject: [PATCH v5 2/5] mac80211: align ieee80211_ibss_csa_beacon() with ieee80211_csa_beacon()

The return value of ieee80211_ibss_csa_beacon is not aligned with the
return value of ieee80211_csa_beacon(). For consistency and to be
able to use both functions with similar code, change
ieee80211_ibss_csa_beacon() not to send the bss changed notification
itself, but return what has changed so the caller can send the
notification instead.

Signed-off-by: Luciano Coelho <[email protected]>
---
net/mac80211/ibss.c | 14 ++++++++++----
1 file changed, 10 insertions(+), 4 deletions(-)

diff --git a/net/mac80211/ibss.c b/net/mac80211/ibss.c
index 3514aab..23e035f 100644
--- a/net/mac80211/ibss.c
+++ b/net/mac80211/ibss.c
@@ -522,7 +522,7 @@ int ieee80211_ibss_csa_beacon(struct ieee80211_sub_if_data *sdata,
if (csa_settings)
ieee80211_send_action_csa(sdata, csa_settings);

- ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
+ return BSS_CHANGED_BEACON;
out:
return ret;
}
@@ -559,11 +559,17 @@ int ieee80211_ibss_finish_csa(struct ieee80211_sub_if_data *sdata)

/* generate the beacon */
err = ieee80211_ibss_csa_beacon(sdata, NULL);
- sdata_unlock(sdata);
if (err < 0)
- return err;
+ goto out;

- return 0;
+ if (err) {
+ ieee80211_bss_info_change_notify(sdata, err);
+ err = 0;
+ }
+out:
+ sdata_unlock(sdata);
+
+ return err;
}

void ieee80211_ibss_stop(struct ieee80211_sub_if_data *sdata)
--
1.8.4.rc3


2013-11-14 12:10:12

by Luciano Coelho

[permalink] [raw]
Subject: [PATCH v5 3/5] mac80211: refactor ieee80211_mesh_process_chanswitch()

Refactor ieee80211_mesh_process_chanswitch() to use
ieee80211_channel_switch() and avoid code duplication.

Signed-off-by: Luciano Coelho <[email protected]>
---
In v5:

* combine chsw_init and csa_repeater into a single csa_role enumeration;

* rebased on top of mac80211, so no need to apply Chun-Yeow's patch
manually (it's already applied);

net/mac80211/cfg.c | 17 +++++++-----
net/mac80211/ieee80211_i.h | 6 +++-
net/mac80211/mesh.c | 69 +++++++++-------------------------------------
3 files changed, 28 insertions(+), 64 deletions(-)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index a98dc6b..a5aa766 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -3141,15 +3141,18 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
params->chandef.chan->band)
return -EINVAL;

- ifmsh->chsw_init = true;
- if (!ifmsh->pre_value)
- ifmsh->pre_value = 1;
- else
- ifmsh->pre_value++;
+ if (ifmsh->csa_role == IEEE80211_MESH_CSA_ROLE_NONE) {
+ ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_INIT;
+ if (!ifmsh->pre_value)
+ ifmsh->pre_value = 1;
+ else
+ ifmsh->pre_value++;
+ }

- err = ieee80211_mesh_csa_beacon(sdata, params, true);
+ err = ieee80211_mesh_csa_beacon(sdata, params,
+ (ifmsh->csa_role == IEEE80211_MESH_CSA_ROLE_INIT));
if (err < 0) {
- ifmsh->chsw_init = false;
+ ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_NONE;
return err;
}
break;
diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h
index 3a77ed1..15c9c39 100644
--- a/net/mac80211/ieee80211_i.h
+++ b/net/mac80211/ieee80211_i.h
@@ -610,7 +610,11 @@ struct ieee80211_if_mesh {
struct ps_data ps;
/* Channel Switching Support */
struct mesh_csa_settings __rcu *csa;
- bool chsw_init;
+ enum {
+ IEEE80211_MESH_CSA_ROLE_NONE,
+ IEEE80211_MESH_CSA_ROLE_INIT,
+ IEEE80211_MESH_CSA_ROLE_REPEATER,
+ } csa_role;
u8 chsw_ttl;
u16 pre_value;
};
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 89df62b..5852080 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -685,7 +685,7 @@ ieee80211_mesh_build_beacon(struct ieee80211_if_mesh *ifmsh)
*pos++ = csa->settings.count;
*pos++ = WLAN_EID_CHAN_SWITCH_PARAM;
*pos++ = 6;
- if (ifmsh->chsw_init) {
+ if (ifmsh->csa_role == IEEE80211_MESH_CSA_ROLE_INIT) {
*pos++ = ifmsh->mshcfg.dot11MeshTTL;
*pos |= WLAN_EID_CHAN_SWITCH_PARAM_INITIATOR;
} else {
@@ -853,19 +853,11 @@ ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata,
{
struct cfg80211_csa_settings params;
struct ieee80211_csa_ie csa_ie;
- struct ieee80211_chanctx_conf *chanctx_conf;
- struct ieee80211_chanctx *chanctx;
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;
enum ieee80211_band band = ieee80211_get_sdata_band(sdata);
- int err, num_chanctx;
+ int err;
u32 sta_flags;

- if (sdata->vif.csa_active)
- return true;
-
- if (!ifmsh->mesh_id)
- return false;
-
sta_flags = IEEE80211_STA_DISABLE_VHT;
switch (sdata->vif.bss_conf.chandef.width) {
case NL80211_CHAN_WIDTH_20_NOHT:
@@ -890,10 +882,6 @@ ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata,
params.chandef = csa_ie.chandef;
params.count = csa_ie.count;

- if (sdata->vif.bss_conf.chandef.chan->band !=
- params.chandef.chan->band)
- return false;
-
if (!cfg80211_chandef_usable(sdata->local->hw.wiphy, &params.chandef,
IEEE80211_CHAN_DISABLED)) {
sdata_info(sdata,
@@ -916,25 +904,6 @@ ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata,
return false;
}

- rcu_read_lock();
- chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
- if (!chanctx_conf)
- goto failed_chswitch;
-
- /* don't handle for multi-VIF cases */
- chanctx = container_of(chanctx_conf, struct ieee80211_chanctx, conf);
- if (chanctx->refcount > 1)
- goto failed_chswitch;
-
- num_chanctx = 0;
- list_for_each_entry_rcu(chanctx, &sdata->local->chanctx_list, list)
- num_chanctx++;
-
- if (num_chanctx > 1)
- goto failed_chswitch;
-
- rcu_read_unlock();
-
mcsa_dbg(sdata,
"received channel switch announcement to go to channel %d MHz\n",
params.chandef.chan->center_freq);
@@ -947,30 +916,16 @@ ieee80211_mesh_process_chnswitch(struct ieee80211_sub_if_data *sdata,
ifmsh->pre_value = csa_ie.pre_value;
}

- if (ifmsh->chsw_ttl < ifmsh->mshcfg.dot11MeshTTL) {
- if (ieee80211_mesh_csa_beacon(sdata, &params, false) < 0)
- return false;
- } else {
+ if (ifmsh->chsw_ttl >= ifmsh->mshcfg.dot11MeshTTL)
return false;
- }
-
- sdata->csa_radar_required = params.radar_required;
-
- if (params.block_tx)
- ieee80211_stop_queues_by_reason(&sdata->local->hw,
- IEEE80211_MAX_QUEUE_MAP,
- IEEE80211_QUEUE_STOP_REASON_CSA);

- sdata->csa_chandef = params.chandef;
- sdata->vif.csa_active = true;
+ ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_REPEATER;

- ieee80211_bss_info_change_notify(sdata, err);
- drv_channel_switch_beacon(sdata, &params.chandef);
+ if (ieee80211_channel_switch(sdata->local->hw.wiphy, sdata->dev,
+ &params) < 0)
+ return false;

return true;
-failed_chswitch:
- rcu_read_unlock();
- return false;
}

static void
@@ -1080,7 +1035,8 @@ static void ieee80211_mesh_rx_bcn_presp(struct ieee80211_sub_if_data *sdata,
ifmsh->sync_ops->rx_bcn_presp(sdata,
stype, mgmt, &elems, rx_status);

- if (!ifmsh->chsw_init)
+ if (ifmsh->csa_role != IEEE80211_MESH_CSA_ROLE_INIT &&
+ !sdata->vif.csa_active)
ieee80211_mesh_process_chnswitch(sdata, &elems, true);
}

@@ -1091,7 +1047,7 @@ int ieee80211_mesh_finish_csa(struct ieee80211_sub_if_data *sdata)
int ret = 0;

/* Reset the TTL value and Initiator flag */
- ifmsh->chsw_init = false;
+ ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_NONE;
ifmsh->chsw_ttl = 0;

/* Remove the CSA and MCSP elements from the beacon */
@@ -1204,7 +1160,8 @@ static void mesh_rx_csa_frame(struct ieee80211_sub_if_data *sdata,

ifmsh->pre_value = pre_value;

- if (!ieee80211_mesh_process_chnswitch(sdata, &elems, false)) {
+ if (!sdata->vif.csa_active &&
+ !ieee80211_mesh_process_chnswitch(sdata, &elems, false)) {
mcsa_dbg(sdata, "Failed to process CSA action frame");
return;
}
@@ -1359,7 +1316,7 @@ void ieee80211_mesh_init_sdata(struct ieee80211_sub_if_data *sdata)
mesh_rmc_init(sdata);
ifmsh->last_preq = jiffies;
ifmsh->next_perr = jiffies;
- ifmsh->chsw_init = false;
+ ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_NONE;
/* Allocate all mesh structures when creating the first mesh interface. */
if (!mesh_allocated)
ieee80211s_init();
--
1.8.4.rc3


2013-11-16 19:01:01

by Luciano Coelho

[permalink] [raw]
Subject: Re: [PATCH v5 5/5] mac80211: only set CSA beacon when at least one beacon must be transmitted

T24gU2F0LCAyMDEzLTExLTE2IGF0IDE5OjU0ICswODAwLCBZZW9oIENodW4tWWVvdyB3cm90ZToN
Cj4gSSBoYXZlIHNlZW4gdGhlIGZvbGxvd2luZyBrZXJuZWwgb29wcyBpZiBzZXQgdGhlIGNvdW50
IHRvIDAgb3IgMSBpbg0KPiB1c2Vyc3BhY2UuIE90aGVyIHRoYW4gdGhhdCwgc2VlbXMgYWxyaWdo
dC4NCg0KT3VjaCEgVGhpcyBkb2Vzbid0IGxvb2sgZ29vZC4gIEkgaGF2ZSB0byBjaGVjayB3aGF0
IGlzIGhhcHBlbmluZy4NCg0KSSdsbCBsb29rIGludG8gaXQgb24gTW9uZGF5Lg0KDQpUaGFua3Mg
Zm9yIHRlc3RpbmchDQoNCi0tDQpMdWNhLg0KDQo=

2013-11-14 14:53:19

by Simon Wunderlich

[permalink] [raw]
Subject: Re: [PATCH v5 5/5] mac80211: only set CSA beacon when at least one beacon must be transmitted

> @@ -3122,9 +3158,16 @@ int ieee80211_channel_switch(struct wiphy *wiphy,
> struct net_device *dev, params->chandef.chan->band)
> return -EINVAL;
>
> - err = ieee80211_ibss_csa_beacon(sdata, params);
> - if (err < 0)
> - return err;
> + /* see comments and TODO in the NL80211_IFTYPE_AP block */

Since you are sending an action frame below, this TODO appears to be obsolete?

> + if (params->count > 1) {
> + err = ieee80211_ibss_csa_beacon(sdata, params);
> + if (err < 0)
> + return err;
> + changed |= err;
> + }
> +
> + ieee80211_send_action_csa(sdata, params);
> +
> break;
> #ifdef CONFIG_MAC80211_MESH
> case NL80211_IFTYPE_MESH_POINT:
> @@ -3173,8 +3220,13 @@ int ieee80211_channel_switch(struct wiphy *wiphy,
> struct net_device *dev, sdata->csa_chandef = params->chandef;
> sdata->vif.csa_active = true;
>
> - ieee80211_bss_info_change_notify(sdata, err);
> - drv_channel_switch_beacon(sdata, &params->chandef);
> + if (changed) {
> + ieee80211_bss_info_change_notify(sdata, changed);
> + drv_channel_switch_beacon(sdata, &params->chandef);
> + } else {
> + /* if the beacon didn't change, we can finalize immediately */
> + ieee80211_csa_finalize(sdata);
> + }

I think setting csa_active == true for count 0 or 1 is wrong.

When a beacon is generated/updated in ieee80211_beacon_get_tim(), it wil call
ieee80211_update_csa() which will throw a warning in best case, but also
modifies random data in the beacon/presp at the position where the count offset
points to (we have no CSA IE in this case).

I've also seen warnings in my IBSS tests (WARNING: CPU: 0 PID: 0 at
net/mac80211/tx.c:2408 ieee80211_update_csa), when doing a CSA with count 0
from userspace. Although likely, I'm not sure if this is related to the
problem described above, but this function shouldn't be called at all in the
count=0 case.

Cheers,
Simon

2013-11-14 12:10:12

by Luciano Coelho

[permalink] [raw]
Subject: [PATCH v5 4/5] mac80211: align ieee80211_mesh_csa_beacon() with ieee80211_csa_beacon()

The return value of ieee80211_mesh_csa_beacon is not aligned with the
return value of ieee80211_csa_beacon() and
ieee80211_ibss_csa_beacon(). For consistency and to be able to use
both functions with similar code, change ieee80211_mesh_csa_beacon()
not to send the bss changed notification itself, but return what has
changed so the caller can send the notification instead.

Change-Id: If4c111fd874a3e17a5df98d306f7f1c8fcaa6a1a
Signed-off-by: Luciano Coelho <[email protected]>
---
net/mac80211/cfg.c | 2 ++
net/mac80211/mesh.c | 4 +---
2 files changed, 3 insertions(+), 3 deletions(-)

diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c
index a5aa766..6eb8e08 100644
--- a/net/mac80211/cfg.c
+++ b/net/mac80211/cfg.c
@@ -3155,6 +3155,8 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_NONE;
return err;
}
+ changed |= err;
+
break;
#endif
default:
diff --git a/net/mac80211/mesh.c b/net/mac80211/mesh.c
index 5852080..94dff7f 100644
--- a/net/mac80211/mesh.c
+++ b/net/mac80211/mesh.c
@@ -1091,12 +1091,10 @@ int ieee80211_mesh_csa_beacon(struct ieee80211_sub_if_data *sdata,
return ret;
}

- ieee80211_bss_info_change_notify(sdata, BSS_CHANGED_BEACON);
-
if (csa_action)
ieee80211_send_action_csa(sdata, csa_settings);

- return 0;
+ return BSS_CHANGED_BEACON;
}

static int mesh_fwd_csa_frame(struct ieee80211_sub_if_data *sdata,
--
1.8.4.rc3