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

Commit 96bf9ffe authored by Linux Build Service Account's avatar Linux Build Service Account Committed by Gerrit - the friendly Code Review server
Browse files

Merge "cfg80211: support virtual interfaces with different beacon intervals"

parents eac1ef36 17a35897
Loading
Loading
Loading
Loading
+15 −0
Original line number Diff line number Diff line
@@ -792,11 +792,19 @@ struct cfg80211_csa_settings {
 * @iftype_num: array with the number of interfaces of each interface
 *	type.  The index is the interface type as specified in &enum
 *	nl80211_iftype.
 * @beacon_int_gcd: a value specifying GCD of all beaconing interfaces,
 *	the GCD of a single value is considered the value itself, so for
 *	a single interface this should be set to that interface's beacon
 *	interval
 * @beacon_int_different: a flag indicating whether or not all beacon
 *	intervals (of beaconing interfaces) are different or not.
 */
struct iface_combination_params {
	int num_different_channels;
	u8 radar_detect;
	int iftype_num[NUM_NL80211_IFTYPES];
	u32 beacon_int_gcd;
	bool beacon_int_different;
};

/**
@@ -2791,6 +2799,12 @@ struct ieee80211_iface_limit {
 *	only in special cases.
 * @radar_detect_widths: bitmap of channel widths supported for radar detection
 * @radar_detect_regions: bitmap of regions supported for radar detection
 * @beacon_int_min_gcd: This interface combination supports different
 *	beacon intervals.
 *	= 0 - all beacon intervals for different interface must be same.
 *	> 0 - any beacon interval for the interface part of this combination AND
 *	      *GCD* of all beacon intervals from beaconing interfaces of this
 *	      combination must be greater or equal to this value.
 *
 * With this structure the driver can describe which interface
 * combinations it supports concurrently.
@@ -2849,6 +2863,7 @@ struct ieee80211_iface_combination {
	bool beacon_int_infra_match;
	u8 radar_detect_widths;
	u8 radar_detect_regions;
	u32 beacon_int_min_gcd;
};

struct ieee80211_txrx_stypes {
+6 −2
Original line number Diff line number Diff line
@@ -3937,6 +3937,9 @@ enum nl80211_iface_limit_attrs {
 *	of supported channel widths for radar detection.
 * @NL80211_IFACE_COMB_RADAR_DETECT_REGIONS: u32 attribute containing the bitmap
 *	of supported regulatory regions for radar detection.
 * @NL80211_IFACE_COMB_BI_MIN_GCD: u32 attribute specifying the minimum GCD of
 *	different beacon intervals supported by all the interface combinations
 *	in this group (if not present, all beacon intervals be identical).
 * @NUM_NL80211_IFACE_COMB: number of attributes
 * @MAX_NL80211_IFACE_COMB: highest attribute number
 *
@@ -3944,8 +3947,8 @@ enum nl80211_iface_limit_attrs {
 *	limits = [ #{STA} <= 1, #{AP} <= 1 ], matching BI, channels = 1, max = 2
 *	=> allows an AP and a STA that must match BIs
 *
 *	numbers = [ #{AP, P2P-GO} <= 8 ], channels = 1, max = 8
 *	=> allows 8 of AP/GO
 *	numbers = [ #{AP, P2P-GO} <= 8 ], BI min gcd, channels = 1, max = 8,
 *	=> allows 8 of AP/GO that can have BI gcd >= min gcd
 *
 *	numbers = [ #{STA} <= 2 ], channels = 2, max = 2
 *	=> allows two STAs on different channels
@@ -3971,6 +3974,7 @@ enum nl80211_if_combination_attrs {
	NL80211_IFACE_COMB_NUM_CHANNELS,
	NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS,
	NL80211_IFACE_COMB_RADAR_DETECT_REGIONS,
	NL80211_IFACE_COMB_BI_MIN_GCD,

	/* keep last */
	NUM_NL80211_IFACE_COMB,
+1 −1
Original line number Diff line number Diff line
@@ -445,7 +445,7 @@ int ieee80211_get_ratemask(struct ieee80211_supported_band *sband,
			   u32 *mask);

int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
				 u32 beacon_int);
				 enum nl80211_iftype iftype, u32 beacon_int);

void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev,
			       enum nl80211_iftype iftype, int num);
+6 −1
Original line number Diff line number Diff line
@@ -985,6 +985,10 @@ static int nl80211_put_iface_combinations(struct wiphy *wiphy,
		     nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_REGIONS,
				c->radar_detect_regions)))
			goto nla_put_failure;
		if (c->beacon_int_min_gcd &&
		    nla_put_u32(msg, NL80211_IFACE_COMB_BI_MIN_GCD,
				c->beacon_int_min_gcd))
			goto nla_put_failure;

		nla_nest_end(msg, nl_combi);
	}
@@ -3563,7 +3567,8 @@ static int nl80211_start_ap(struct sk_buff *skb, struct genl_info *info)
	params.dtim_period =
		nla_get_u32(info->attrs[NL80211_ATTR_DTIM_PERIOD]);

	err = cfg80211_validate_beacon_int(rdev, params.beacon_interval);
	err = cfg80211_validate_beacon_int(rdev, dev->ieee80211_ptr->iftype,
					   params.beacon_interval);
	if (err)
		return err;

+39 −6
Original line number Diff line number Diff line
@@ -1251,24 +1251,46 @@ bool ieee80211_operating_class_to_band(u8 operating_class,
EXPORT_SYMBOL(ieee80211_operating_class_to_band);

int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
				 u32 beacon_int)
				 enum nl80211_iftype iftype, u32 beacon_int)
{
	struct wireless_dev *wdev;
	int res = 0;
	struct iface_combination_params params = {
		.beacon_int_gcd = beacon_int,	/* GCD(n) = n */
	};

	if (!beacon_int)
		return -EINVAL;

	params.iftype_num[iftype] = 1;
	list_for_each_entry(wdev, &rdev->wdev_list, list) {
		if (!wdev->beacon_interval)
			continue;
		if (wdev->beacon_interval != beacon_int) {
			res = -EINVAL;
			break;

		params.iftype_num[wdev->iftype]++;
	}

	list_for_each_entry(wdev, &rdev->wdev_list, list) {
		u32 bi_prev = wdev->beacon_interval;

		if (!wdev->beacon_interval)
			continue;

		/* slight optimisation - skip identical BIs */
		if (wdev->beacon_interval == beacon_int)
			continue;

		params.beacon_int_different = true;

		/* Get the GCD */
		while (bi_prev != 0) {
			u32 tmp_bi = bi_prev;

			bi_prev = params.beacon_int_gcd % bi_prev;
			params.beacon_int_gcd = tmp_bi;
		}
	}

	return res;
	return cfg80211_check_combinations(&rdev->wiphy, &params);
}

int cfg80211_iter_combinations(struct wiphy *wiphy,
@@ -1344,6 +1366,17 @@ int cfg80211_iter_combinations(struct wiphy *wiphy,
		if ((all_iftypes & used_iftypes) != used_iftypes)
			goto cont;

		if (params->beacon_int_gcd) {
			if (c->beacon_int_min_gcd &&
			    params->beacon_int_gcd < c->beacon_int_min_gcd) {
				kfree(limits);
				return -EINVAL;
			}
			if (!c->beacon_int_min_gcd &&
			    params->beacon_int_different)
				goto cont;
		}

		/* This combination covered all interface types and
		 * supported the requested numbers, so we're good.
		 */