diff options
author | Michal Kazior <michal.kazior@tieto.com> | 2014-02-28 09:59:06 -0500 |
---|---|---|
committer | Johannes Berg <johannes.berg@intel.com> | 2014-03-03 09:07:29 -0500 |
commit | 37fa2bdd16a12fef7804606f56525ba5747bf172 (patch) | |
tree | 42f90bba49c690ba64e79bfcd61c959324c35f0b /net/mac80211 | |
parent | 7c8d5e03acc680eb433b0d5dbacbb6cc9db663a1 (diff) |
mac80211: refactor channel switch function
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>
Diffstat (limited to 'net/mac80211')
-rw-r--r-- | net/mac80211/cfg.c | 113 |
1 files changed, 63 insertions, 50 deletions
diff --git a/net/mac80211/cfg.c b/net/mac80211/cfg.c index 80534f524fd6..aaa59d719592 100644 --- a/net/mac80211/cfg.c +++ b/net/mac80211/cfg.c | |||
@@ -3089,52 +3089,11 @@ unlock: | |||
3089 | sdata_unlock(sdata); | 3089 | sdata_unlock(sdata); |
3090 | } | 3090 | } |
3091 | 3091 | ||
3092 | int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | 3092 | static int ieee80211_set_csa_beacon(struct ieee80211_sub_if_data *sdata, |
3093 | struct cfg80211_csa_settings *params) | 3093 | struct cfg80211_csa_settings *params, |
3094 | u32 *changed) | ||
3094 | { | 3095 | { |
3095 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | 3096 | int err; |
3096 | struct ieee80211_local *local = sdata->local; | ||
3097 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
3098 | struct ieee80211_chanctx *chanctx; | ||
3099 | struct ieee80211_if_mesh __maybe_unused *ifmsh; | ||
3100 | int err, num_chanctx, changed = 0; | ||
3101 | |||
3102 | sdata_assert_lock(sdata); | ||
3103 | |||
3104 | if (!list_empty(&local->roc_list) || local->scanning) | ||
3105 | return -EBUSY; | ||
3106 | |||
3107 | if (sdata->wdev.cac_started) | ||
3108 | return -EBUSY; | ||
3109 | |||
3110 | if (cfg80211_chandef_identical(¶ms->chandef, | ||
3111 | &sdata->vif.bss_conf.chandef)) | ||
3112 | return -EINVAL; | ||
3113 | |||
3114 | rcu_read_lock(); | ||
3115 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | ||
3116 | if (!chanctx_conf) { | ||
3117 | rcu_read_unlock(); | ||
3118 | return -EBUSY; | ||
3119 | } | ||
3120 | |||
3121 | /* don't handle for multi-VIF cases */ | ||
3122 | chanctx = container_of(chanctx_conf, struct ieee80211_chanctx, conf); | ||
3123 | if (chanctx->refcount > 1) { | ||
3124 | rcu_read_unlock(); | ||
3125 | return -EBUSY; | ||
3126 | } | ||
3127 | num_chanctx = 0; | ||
3128 | list_for_each_entry_rcu(chanctx, &local->chanctx_list, list) | ||
3129 | num_chanctx++; | ||
3130 | rcu_read_unlock(); | ||
3131 | |||
3132 | if (num_chanctx > 1) | ||
3133 | return -EBUSY; | ||
3134 | |||
3135 | /* don't allow another channel switch if one is already active. */ | ||
3136 | if (sdata->vif.csa_active) | ||
3137 | return -EBUSY; | ||
3138 | 3097 | ||
3139 | switch (sdata->vif.type) { | 3098 | switch (sdata->vif.type) { |
3140 | case NL80211_IFTYPE_AP: | 3099 | case NL80211_IFTYPE_AP: |
@@ -3170,7 +3129,7 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | |||
3170 | kfree(sdata->u.ap.next_beacon); | 3129 | kfree(sdata->u.ap.next_beacon); |
3171 | return err; | 3130 | return err; |
3172 | } | 3131 | } |
3173 | changed |= err; | 3132 | *changed |= err; |
3174 | 3133 | ||
3175 | break; | 3134 | break; |
3176 | case NL80211_IFTYPE_ADHOC: | 3135 | case NL80211_IFTYPE_ADHOC: |
@@ -3204,15 +3163,15 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | |||
3204 | err = ieee80211_ibss_csa_beacon(sdata, params); | 3163 | err = ieee80211_ibss_csa_beacon(sdata, params); |
3205 | if (err < 0) | 3164 | if (err < 0) |
3206 | return err; | 3165 | return err; |
3207 | changed |= err; | 3166 | *changed |= err; |
3208 | } | 3167 | } |
3209 | 3168 | ||
3210 | ieee80211_send_action_csa(sdata, params); | 3169 | ieee80211_send_action_csa(sdata, params); |
3211 | 3170 | ||
3212 | break; | 3171 | break; |
3213 | #ifdef CONFIG_MAC80211_MESH | 3172 | #ifdef CONFIG_MAC80211_MESH |
3214 | case NL80211_IFTYPE_MESH_POINT: | 3173 | case NL80211_IFTYPE_MESH_POINT: { |
3215 | ifmsh = &sdata->u.mesh; | 3174 | struct ieee80211_if_mesh *ifmsh = &sdata->u.mesh; |
3216 | 3175 | ||
3217 | if (params->chandef.width != sdata->vif.bss_conf.chandef.width) | 3176 | if (params->chandef.width != sdata->vif.bss_conf.chandef.width) |
3218 | return -EINVAL; | 3177 | return -EINVAL; |
@@ -3237,18 +3196,72 @@ int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | |||
3237 | ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_NONE; | 3196 | ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_NONE; |
3238 | return err; | 3197 | return err; |
3239 | } | 3198 | } |
3240 | changed |= err; | 3199 | *changed |= err; |
3241 | } | 3200 | } |
3242 | 3201 | ||
3243 | if (ifmsh->csa_role == IEEE80211_MESH_CSA_ROLE_INIT) | 3202 | if (ifmsh->csa_role == IEEE80211_MESH_CSA_ROLE_INIT) |
3244 | ieee80211_send_action_csa(sdata, params); | 3203 | ieee80211_send_action_csa(sdata, params); |
3245 | 3204 | ||
3246 | break; | 3205 | break; |
3206 | } | ||
3247 | #endif | 3207 | #endif |
3248 | default: | 3208 | default: |
3249 | return -EOPNOTSUPP; | 3209 | return -EOPNOTSUPP; |
3250 | } | 3210 | } |
3251 | 3211 | ||
3212 | return 0; | ||
3213 | } | ||
3214 | |||
3215 | int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev, | ||
3216 | struct cfg80211_csa_settings *params) | ||
3217 | { | ||
3218 | struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev); | ||
3219 | struct ieee80211_local *local = sdata->local; | ||
3220 | struct ieee80211_chanctx_conf *chanctx_conf; | ||
3221 | struct ieee80211_chanctx *chanctx; | ||
3222 | int err, num_chanctx, changed = 0; | ||
3223 | |||
3224 | sdata_assert_lock(sdata); | ||
3225 | |||
3226 | if (!list_empty(&local->roc_list) || local->scanning) | ||
3227 | return -EBUSY; | ||
3228 | |||
3229 | if (sdata->wdev.cac_started) | ||
3230 | return -EBUSY; | ||
3231 | |||
3232 | if (cfg80211_chandef_identical(¶ms->chandef, | ||
3233 | &sdata->vif.bss_conf.chandef)) | ||
3234 | return -EINVAL; | ||
3235 | |||
3236 | rcu_read_lock(); | ||
3237 | chanctx_conf = rcu_dereference(sdata->vif.chanctx_conf); | ||
3238 | if (!chanctx_conf) { | ||
3239 | rcu_read_unlock(); | ||
3240 | return -EBUSY; | ||
3241 | } | ||
3242 | |||
3243 | /* don't handle for multi-VIF cases */ | ||
3244 | chanctx = container_of(chanctx_conf, struct ieee80211_chanctx, conf); | ||
3245 | if (chanctx->refcount > 1) { | ||
3246 | rcu_read_unlock(); | ||
3247 | return -EBUSY; | ||
3248 | } | ||
3249 | num_chanctx = 0; | ||
3250 | list_for_each_entry_rcu(chanctx, &local->chanctx_list, list) | ||
3251 | num_chanctx++; | ||
3252 | rcu_read_unlock(); | ||
3253 | |||
3254 | if (num_chanctx > 1) | ||
3255 | return -EBUSY; | ||
3256 | |||
3257 | /* don't allow another channel switch if one is already active. */ | ||
3258 | if (sdata->vif.csa_active) | ||
3259 | return -EBUSY; | ||
3260 | |||
3261 | err = ieee80211_set_csa_beacon(sdata, params, &changed); | ||
3262 | if (err) | ||
3263 | return err; | ||
3264 | |||
3252 | sdata->csa_radar_required = params->radar_required; | 3265 | sdata->csa_radar_required = params->radar_required; |
3253 | 3266 | ||
3254 | if (params->block_tx) | 3267 | if (params->block_tx) |