Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 37fa2bdd authored by Michal Kazior's avatar Michal Kazior Committed by Johannes Berg
Browse files

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: default avatarMichal Kazior <michal.kazior@tieto.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 7c8d5e03
Loading
Loading
Loading
Loading
+63 −50
Original line number Original line Diff line number Diff line
@@ -3089,52 +3089,11 @@ unlock:
	sdata_unlock(sdata);
	sdata_unlock(sdata);
}
}


int ieee80211_channel_switch(struct wiphy *wiphy, struct net_device *dev,
static int ieee80211_set_csa_beacon(struct ieee80211_sub_if_data *sdata,
			     struct cfg80211_csa_settings *params)
				    struct cfg80211_csa_settings *params,
				    u32 *changed)
{
{
	struct ieee80211_sub_if_data *sdata = IEEE80211_DEV_TO_SUB_IF(dev);
	int err;
	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;


	switch (sdata->vif.type) {
	switch (sdata->vif.type) {
	case NL80211_IFTYPE_AP:
	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);
			kfree(sdata->u.ap.next_beacon);
			return err;
			return err;
		}
		}
		changed |= err;
		*changed |= err;


		break;
		break;
	case NL80211_IFTYPE_ADHOC:
	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);
			err = ieee80211_ibss_csa_beacon(sdata, params);
			if (err < 0)
			if (err < 0)
				return err;
				return err;
			changed |= err;
			*changed |= err;
		}
		}


		ieee80211_send_action_csa(sdata, params);
		ieee80211_send_action_csa(sdata, params);


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


		if (params->chandef.width != sdata->vif.bss_conf.chandef.width)
		if (params->chandef.width != sdata->vif.bss_conf.chandef.width)
			return -EINVAL;
			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;
				ifmsh->csa_role = IEEE80211_MESH_CSA_ROLE_NONE;
				return err;
				return err;
			}
			}
			changed |= err;
			*changed |= err;
		}
		}


		if (ifmsh->csa_role == IEEE80211_MESH_CSA_ROLE_INIT)
		if (ifmsh->csa_role == IEEE80211_MESH_CSA_ROLE_INIT)
			ieee80211_send_action_csa(sdata, params);
			ieee80211_send_action_csa(sdata, params);


		break;
		break;
		}
#endif
#endif
	default:
	default:
		return -EOPNOTSUPP;
		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;
	sdata->csa_radar_required = params->radar_required;


	if (params->block_tx)
	if (params->block_tx)