Skip to content

Commit

Permalink
mac80211: refactor channel switch function
Browse files Browse the repository at this point in the history
The function was quite big. This splits out beacon
updating into a separate function for improved
maintenance and extension.

Signed-off-by: Michal Kazior <[email protected]>
Signed-off-by: Johannes Berg <[email protected]>
  • Loading branch information
Michal Kazior authored and jmberg-intel committed Mar 3, 2014
1 parent 7c8d5e0 commit 37fa2bd
Showing 1 changed file with 63 additions and 50 deletions.
113 changes: 63 additions & 50 deletions net/mac80211/cfg.c
Original file line number Diff line number Diff line change
Expand Up @@ -3089,52 +3089,11 @@ void ieee80211_csa_finalize_work(struct work_struct *work)
sdata_unlock(sdata);
}

int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
struct cfg80211_csa_settings *params)
static int ieee80211_set_csa_beacon(struct ieee80211_sub_if_data *sdata,
struct cfg80211_csa_settings *params,
u32 *changed)
{
struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
struct ieee80211_local *local = sdata->local;
struct ieee80211_chanctx_conf *chanctx_conf;
struct ieee80211_chanctx *chanctx;
struct ieee80211_if_mesh __maybe_unused *ifmsh;
int err, num_chanctx, changed = 0;

sdata_assert_lock(sdata);

if (!list_empty(&local->roc_list) || local->scanning)
return -EBUSY;

if (sdata->wdev.cac_started)
return -EBUSY;

if (cfg80211_chandef_identical(&params->chandef,
&sdata->vif.bss_conf.chandef))
return -EINVAL;

rcu_read_lock();
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
if (!chanctx_conf) {
rcu_read_unlock();
return -EBUSY;
}

/* don't handle for multi-VIF cases */
chanctx = container_of(chanctx_conf, struct ieee80211_chanctx, conf);
if (chanctx->refcount > 1) {
rcu_read_unlock();
return -EBUSY;
}
num_chanctx = 0;
list_for_each_entry_rcu(chanctx, &local->chanctx_list, list)
num_chanctx++;
rcu_read_unlock();

if (num_chanctx > 1)
return -EBUSY;

/* don't allow another channel switch if one is already active. */
if (sdata->vif.csa_active)
return -EBUSY;
int err;

switch (sdata->vif.type) {
case NL80211_IFTYPE_AP:
Expand Down Expand Up @@ -3170,7 +3129,7 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
kfree(sdata->u.ap.next_beacon);
return err;
}
changed |= err;
*changed |= err;

break;
case NL80211_IFTYPE_ADHOC:
Expand Down Expand Up @@ -3204,15 +3163,15 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
err = ieee80211_ibss_csa_beacon(sdata, params);
if (err < 0)
return err;
changed |= err;
*changed |= err;
}

ieee80211_send_action_csa(sdata, params);

break;
#ifdef CONFIG_MAC80211_MESH
case NL80211_IFTYPE_MESH_POINT:
ifmsh = &sdata->u.mesh;
case NL80211_IFTYPE_MESH_POINT: {
struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh;

if (params->chandef.width != sdata->vif.bss_conf.chandef.width)
return -EINVAL;
Expand All @@ -3237,18 +3196,72 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
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
default:
return -EOPNOTSUPP;
}

return 0;
}

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;
struct ieee80211_chanctx_conf *chanctx_conf;
struct ieee80211_chanctx *chanctx;
int err, num_chanctx, changed = 0;

sdata_assert_lock(sdata);

if (!list_empty(&local->roc_list) || local->scanning)
return -EBUSY;

if (sdata->wdev.cac_started)
return -EBUSY;

if (cfg80211_chandef_identical(&params->chandef,
&sdata->vif.bss_conf.chandef))
return -EINVAL;

rcu_read_lock();
chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf);
if (!chanctx_conf) {
rcu_read_unlock();
return -EBUSY;
}

/* don't handle for multi-VIF cases */
chanctx = container_of(chanctx_conf, struct ieee80211_chanctx, conf);
if (chanctx->refcount > 1) {
rcu_read_unlock();
return -EBUSY;
}
num_chanctx = 0;
list_for_each_entry_rcu(chanctx, &local->chanctx_list, list)
num_chanctx++;
rcu_read_unlock();

if (num_chanctx > 1)
return -EBUSY;

/* don't allow another channel switch if one is already active. */
if (sdata->vif.csa_active)
return -EBUSY;

err = ieee80211_set_csa_beacon(sdata, params, &changed);
if (err)
return err;

sdata->csa_radar_required = params->radar_required;

if (params->block_tx)
Expand Down

0 comments on commit 37fa2bd

Please sign in to comment.