Loading include/net/cfg80211.h +15 −0 Original line number Diff line number Diff line Loading @@ -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; }; /** Loading Loading @@ -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. Loading Loading @@ -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 { Loading include/uapi/linux/nl80211.h +6 −2 Original line number Diff line number Diff line Loading @@ -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 * Loading @@ -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 Loading @@ -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, Loading net/wireless/core.h +1 −1 Original line number Diff line number Diff line Loading @@ -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); Loading net/wireless/nl80211.c +6 −1 Original line number Diff line number Diff line Loading @@ -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); } Loading Loading @@ -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; Loading net/wireless/util.c +39 −6 Original line number Diff line number Diff line Loading @@ -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, ¶ms); } int cfg80211_iter_combinations(struct wiphy *wiphy, Loading Loading @@ -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. */ Loading Loading
include/net/cfg80211.h +15 −0 Original line number Diff line number Diff line Loading @@ -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; }; /** Loading Loading @@ -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. Loading Loading @@ -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 { Loading
include/uapi/linux/nl80211.h +6 −2 Original line number Diff line number Diff line Loading @@ -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 * Loading @@ -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 Loading @@ -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, Loading
net/wireless/core.h +1 −1 Original line number Diff line number Diff line Loading @@ -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); Loading
net/wireless/nl80211.c +6 −1 Original line number Diff line number Diff line Loading @@ -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); } Loading Loading @@ -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; Loading
net/wireless/util.c +39 −6 Original line number Diff line number Diff line Loading @@ -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, ¶ms); } int cfg80211_iter_combinations(struct wiphy *wiphy, Loading Loading @@ -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. */ Loading