Merge "cfg80211: support virtual interfaces with different beacon intervals"
This commit is contained in:
commit
875dca44ef
5 changed files with 67 additions and 10 deletions
|
@ -796,11 +796,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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -2894,6 +2902,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.
|
||||
|
@ -2952,6 +2966,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 {
|
||||
|
|
|
@ -4101,6 +4101,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
|
||||
*
|
||||
|
@ -4108,8 +4111,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
|
||||
|
@ -4135,6 +4138,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,
|
||||
|
|
|
@ -466,7 +466,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);
|
||||
|
|
|
@ -1003,6 +1003,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);
|
||||
}
|
||||
|
@ -3656,7 +3660,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;
|
||||
|
||||
|
|
|
@ -1483,24 +1483,46 @@ bool ieee80211_chandef_to_operating_class(struct cfg80211_chan_def *chandef,
|
|||
EXPORT_SYMBOL(ieee80211_chandef_to_operating_class);
|
||||
|
||||
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, ¶ms);
|
||||
}
|
||||
|
||||
int cfg80211_iter_combinations(struct wiphy *wiphy,
|
||||
|
@ -1576,6 +1598,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.
|
||||
*/
|
||||
|
|
Loading…
Add table
Reference in a new issue