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

Commit 73de86a3 authored by Luciano Coelho's avatar Luciano Coelho Committed by Johannes Berg
Browse files

cfg80211/mac80211: move interface counting for combination check to mac80211



Move the counting part of the interface combination check from
cfg80211 to mac80211.

This is needed to simplify locking when the driver has to perform a
combination check by itself (eg. with channel-switch).

Signed-off-by: default avatarLuciano Coelho <luciano.coelho@intel.com>
Signed-off-by: default avatarJohannes Berg <johannes.berg@intel.com>
parent 2beb6dab
Loading
Loading
Loading
Loading
+0 −2
Original line number Diff line number Diff line
@@ -662,7 +662,6 @@ struct cfg80211_acl_data {
 * @p2p_opp_ps: P2P opportunistic PS
 * @acl: ACL configuration used by the drivers which has support for
 *	MAC address based access control
 * @radar_required: set if radar detection is required
 */
struct cfg80211_ap_settings {
	struct cfg80211_chan_def chandef;
@@ -680,7 +679,6 @@ struct cfg80211_ap_settings {
	u8 p2p_ctwindow;
	bool p2p_opp_ps;
	const struct cfg80211_acl_data *acl;
	bool radar_required;
};

/**
+0 −2
Original line number Diff line number Diff line
@@ -972,7 +972,6 @@ static int ieee80211_start_ap(struct wiphy *wiphy, struct net_device *dev,
	sdata->needed_rx_chains = sdata->local->rx_chains;

	mutex_lock(&local->mtx);
	sdata->radar_required = params->radar_required;
	err = ieee80211_vif_use_channel(sdata, &params->chandef,
					IEEE80211_CHANCTX_SHARED);
	mutex_unlock(&local->mtx);
@@ -2930,7 +2929,6 @@ static int ieee80211_start_radar_detection(struct wiphy *wiphy,
	/* whatever, but channel contexts should not complain about that one */
	sdata->smps_mode = IEEE80211_SMPS_OFF;
	sdata->needed_rx_chains = local->rx_chains;
	sdata->radar_required = true;

	err = ieee80211_vif_use_channel(sdata, chandef,
					IEEE80211_CHANCTX_SHARED);
+17 −0
Original line number Diff line number Diff line
@@ -519,6 +519,7 @@ int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
{
	struct ieee80211_local *local = sdata->local;
	struct ieee80211_chanctx *ctx;
	u8 radar_detect_width = 0;
	int ret;

	lockdep_assert_held(&local->mtx);
@@ -526,6 +527,22 @@ int ieee80211_vif_use_channel(struct ieee80211_sub_if_data *sdata,
	WARN_ON(sdata->dev && netif_carrier_ok(sdata->dev));

	mutex_lock(&local->chanctx_mtx);

	ret = cfg80211_chandef_dfs_required(local->hw.wiphy,
					    chandef,
					    sdata->wdev.iftype);
	if (ret < 0)
		goto out;
	if (ret > 0)
		radar_detect_width = BIT(chandef->width);

	sdata->radar_required = ret;

	ret = ieee80211_check_combinations(sdata, chandef, mode,
					   radar_detect_width);
	if (ret < 0)
		goto out;

	__ieee80211_vif_release_channel(sdata);

	ctx = ieee80211_find_chanctx(local, chandef, mode);
+4 −0
Original line number Diff line number Diff line
@@ -1805,6 +1805,10 @@ int ieee80211_cs_headroom(struct ieee80211_local *local,
			  enum nl80211_iftype iftype);
void ieee80211_recalc_dtim(struct ieee80211_local *local,
			   struct ieee80211_sub_if_data *sdata);
int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata,
				 const struct cfg80211_chan_def *chandef,
				 enum ieee80211_chanctx_mode chanmode,
				 u8 radar_detect);

#ifdef CONFIG_MAC80211_NOINLINE
#define debug_noinline noinline
+72 −0
Original line number Diff line number Diff line
@@ -2797,3 +2797,75 @@ void ieee80211_recalc_dtim(struct ieee80211_local *local,

	ps->dtim_count = dtim_count;
}

int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata,
				 const struct cfg80211_chan_def *chandef,
				 enum ieee80211_chanctx_mode chanmode,
				 u8 radar_detect)
{
	struct ieee80211_local *local = sdata->local;
	struct ieee80211_sub_if_data *sdata_iter;
	enum nl80211_iftype iftype = sdata->wdev.iftype;
	int num[NUM_NL80211_IFTYPES];
	struct ieee80211_chanctx *ctx;
	int num_different_channels = 1;
	int total = 1;

	lockdep_assert_held(&local->chanctx_mtx);

	if (WARN_ON(hweight32(radar_detect) > 1))
		return -EINVAL;

	if (WARN_ON(chanmode == IEEE80211_CHANCTX_SHARED && !chandef->chan))
		return -EINVAL;

	if (WARN_ON(iftype >= NUM_NL80211_IFTYPES))
		return -EINVAL;

	/* Always allow software iftypes */
	if (local->hw.wiphy->software_iftypes & BIT(iftype)) {
		if (radar_detect)
			return -EINVAL;
		return 0;
	}

	memset(num, 0, sizeof(num));

	if (iftype != NL80211_IFTYPE_UNSPECIFIED)
		num[iftype] = 1;

	list_for_each_entry(ctx, &local->chanctx_list, list) {
		if (ctx->conf.radar_enabled)
			radar_detect |= BIT(ctx->conf.def.width);
		if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE) {
			num_different_channels++;
			continue;
		}
		if ((chanmode == IEEE80211_CHANCTX_SHARED) &&
		    cfg80211_chandef_compatible(chandef,
						&ctx->conf.def))
			continue;
		num_different_channels++;
	}

	list_for_each_entry_rcu(sdata_iter, &local->interfaces, list) {
		struct wireless_dev *wdev_iter;

		wdev_iter = &sdata_iter->wdev;

		if (sdata_iter == sdata ||
		    rcu_access_pointer(sdata_iter->vif.chanctx_conf) == NULL ||
		    local->hw.wiphy->software_iftypes & BIT(wdev_iter->iftype))
			continue;

		num[wdev_iter->iftype]++;
		total++;
	}

	if (total == 1 && !radar_detect)
		return 0;

	return cfg80211_check_combinations(local->hw.wiphy,
					   num_different_channels,
					   radar_detect, num);
}
Loading