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
|
* @iftype_num: array with the number of interfaces of each interface
|
||||||
* type. The index is the interface type as specified in &enum
|
* type. The index is the interface type as specified in &enum
|
||||||
* nl80211_iftype.
|
* 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 {
|
struct iface_combination_params {
|
||||||
int num_different_channels;
|
int num_different_channels;
|
||||||
u8 radar_detect;
|
u8 radar_detect;
|
||||||
int iftype_num[NUM_NL80211_IFTYPES];
|
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.
|
* only in special cases.
|
||||||
* @radar_detect_widths: bitmap of channel widths supported for radar detection
|
* @radar_detect_widths: bitmap of channel widths supported for radar detection
|
||||||
* @radar_detect_regions: bitmap of regions 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
|
* With this structure the driver can describe which interface
|
||||||
* combinations it supports concurrently.
|
* combinations it supports concurrently.
|
||||||
|
@ -2952,6 +2966,7 @@ struct ieee80211_iface_combination {
|
||||||
bool beacon_int_infra_match;
|
bool beacon_int_infra_match;
|
||||||
u8 radar_detect_widths;
|
u8 radar_detect_widths;
|
||||||
u8 radar_detect_regions;
|
u8 radar_detect_regions;
|
||||||
|
u32 beacon_int_min_gcd;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ieee80211_txrx_stypes {
|
struct ieee80211_txrx_stypes {
|
||||||
|
|
|
@ -4101,6 +4101,9 @@ enum nl80211_iface_limit_attrs {
|
||||||
* of supported channel widths for radar detection.
|
* of supported channel widths for radar detection.
|
||||||
* @NL80211_IFACE_COMB_RADAR_DETECT_REGIONS: u32 attribute containing the bitmap
|
* @NL80211_IFACE_COMB_RADAR_DETECT_REGIONS: u32 attribute containing the bitmap
|
||||||
* of supported regulatory regions for radar detection.
|
* 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
|
* @NUM_NL80211_IFACE_COMB: number of attributes
|
||||||
* @MAX_NL80211_IFACE_COMB: highest attribute number
|
* @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
|
* limits = [ #{STA} <= 1, #{AP} <= 1 ], matching BI, channels = 1, max = 2
|
||||||
* => allows an AP and a STA that must match BIs
|
* => allows an AP and a STA that must match BIs
|
||||||
*
|
*
|
||||||
* numbers = [ #{AP, P2P-GO} <= 8 ], channels = 1, max = 8
|
* numbers = [ #{AP, P2P-GO} <= 8 ], BI min gcd, channels = 1, max = 8,
|
||||||
* => allows 8 of AP/GO
|
* => allows 8 of AP/GO that can have BI gcd >= min gcd
|
||||||
*
|
*
|
||||||
* numbers = [ #{STA} <= 2 ], channels = 2, max = 2
|
* numbers = [ #{STA} <= 2 ], channels = 2, max = 2
|
||||||
* => allows two STAs on different channels
|
* => allows two STAs on different channels
|
||||||
|
@ -4135,6 +4138,7 @@ enum nl80211_if_combination_attrs {
|
||||||
NL80211_IFACE_COMB_NUM_CHANNELS,
|
NL80211_IFACE_COMB_NUM_CHANNELS,
|
||||||
NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS,
|
NL80211_IFACE_COMB_RADAR_DETECT_WIDTHS,
|
||||||
NL80211_IFACE_COMB_RADAR_DETECT_REGIONS,
|
NL80211_IFACE_COMB_RADAR_DETECT_REGIONS,
|
||||||
|
NL80211_IFACE_COMB_BI_MIN_GCD,
|
||||||
|
|
||||||
/* keep last */
|
/* keep last */
|
||||||
NUM_NL80211_IFACE_COMB,
|
NUM_NL80211_IFACE_COMB,
|
||||||
|
|
|
@ -466,7 +466,7 @@ int ieee80211_get_ratemask(struct ieee80211_supported_band *sband,
|
||||||
u32 *mask);
|
u32 *mask);
|
||||||
|
|
||||||
int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
|
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,
|
void cfg80211_update_iface_num(struct cfg80211_registered_device *rdev,
|
||||||
enum nl80211_iftype iftype, int num);
|
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,
|
nla_put_u32(msg, NL80211_IFACE_COMB_RADAR_DETECT_REGIONS,
|
||||||
c->radar_detect_regions)))
|
c->radar_detect_regions)))
|
||||||
goto nla_put_failure;
|
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);
|
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 =
|
params.dtim_period =
|
||||||
nla_get_u32(info->attrs[NL80211_ATTR_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)
|
if (err)
|
||||||
return 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);
|
EXPORT_SYMBOL(ieee80211_chandef_to_operating_class);
|
||||||
|
|
||||||
int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
|
int cfg80211_validate_beacon_int(struct cfg80211_registered_device *rdev,
|
||||||
u32 beacon_int)
|
enum nl80211_iftype iftype, u32 beacon_int)
|
||||||
{
|
{
|
||||||
struct wireless_dev *wdev;
|
struct wireless_dev *wdev;
|
||||||
int res = 0;
|
struct iface_combination_params params = {
|
||||||
|
.beacon_int_gcd = beacon_int, /* GCD(n) = n */
|
||||||
|
};
|
||||||
|
|
||||||
if (!beacon_int)
|
if (!beacon_int)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
|
params.iftype_num[iftype] = 1;
|
||||||
list_for_each_entry(wdev, &rdev->wdev_list, list) {
|
list_for_each_entry(wdev, &rdev->wdev_list, list) {
|
||||||
if (!wdev->beacon_interval)
|
if (!wdev->beacon_interval)
|
||||||
continue;
|
continue;
|
||||||
if (wdev->beacon_interval != beacon_int) {
|
|
||||||
res = -EINVAL;
|
params.iftype_num[wdev->iftype]++;
|
||||||
break;
|
}
|
||||||
|
|
||||||
|
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,
|
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)
|
if ((all_iftypes & used_iftypes) != used_iftypes)
|
||||||
goto cont;
|
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
|
/* This combination covered all interface types and
|
||||||
* supported the requested numbers, so we're good.
|
* supported the requested numbers, so we're good.
|
||||||
*/
|
*/
|
||||||
|
|
Loading…
Add table
Reference in a new issue