mac80211: refactor channel switch function
authorMichal Kazior <michal.kazior@tieto.com>
Fri, 28 Feb 2014 14:59:06 +0000 (15:59 +0100)
committerJohannes Berg <johannes.berg@intel.com>
Mon, 3 Mar 2014 14:07:29 +0000 (15:07 +0100)
The function was quite big. This splits out beacon
updating into a separate function for improved
maintenance and extension.

Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/mac80211/cfg.c

index 80534f5..aaa59d7 100644 (file)
@@ -3089,52 +3089,11 @@ unlock:
        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:
@@ -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:
@@ -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;
@@ -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)