Loading drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +12 −10 Original line number Diff line number Diff line Loading @@ -414,23 +414,24 @@ static int brcmf_vif_change_validate(struct brcmf_cfg80211_info *cfg, struct brcmf_cfg80211_vif *vif, enum nl80211_iftype new_type) { int iftype_num[NUM_NL80211_IFTYPES]; struct brcmf_cfg80211_vif *pos; bool check_combos = false; int ret = 0; struct iface_combination_params params = { .num_different_channels = 1, }; memset(&iftype_num[0], 0, sizeof(iftype_num)); list_for_each_entry(pos, &cfg->vif_list, list) if (pos == vif) { iftype_num[new_type]++; params.iftype_num[new_type]++; } else { /* concurrent interfaces so need check combinations */ check_combos = true; iftype_num[pos->wdev.iftype]++; params.iftype_num[pos->wdev.iftype]++; } if (check_combos) ret = cfg80211_check_combinations(cfg->wiphy, 1, 0, iftype_num); ret = cfg80211_check_combinations(cfg->wiphy, ¶ms); return ret; } Loading @@ -438,15 +439,16 @@ static int brcmf_vif_change_validate(struct brcmf_cfg80211_info *cfg, static int brcmf_vif_add_validate(struct brcmf_cfg80211_info *cfg, enum nl80211_iftype new_type) { int iftype_num[NUM_NL80211_IFTYPES]; struct brcmf_cfg80211_vif *pos; struct iface_combination_params params = { .num_different_channels = 1, }; memset(&iftype_num[0], 0, sizeof(iftype_num)); list_for_each_entry(pos, &cfg->vif_list, list) iftype_num[pos->wdev.iftype]++; params.iftype_num[pos->wdev.iftype]++; iftype_num[new_type]++; return cfg80211_check_combinations(cfg->wiphy, 1, 0, iftype_num); params.iftype_num[new_type]++; return cfg80211_check_combinations(cfg->wiphy, ¶ms); } static void convert_key_from_CPU(struct brcmf_wsec_key *key, Loading include/net/cfg80211.h +39 −22 Original line number Diff line number Diff line Loading @@ -771,6 +771,34 @@ struct cfg80211_csa_settings { u8 count; }; /** * struct iface_combination_params - input parameters for interface combinations * * Used to pass interface combination parameters * * @num_different_channels: the number of different channels we want * to use for verification * @radar_detect: a bitmap where each bit corresponds to a channel * width where radar detection is needed, as in the definition of * &struct ieee80211_iface_combination.@radar_detect_widths * @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; }; /** * enum station_parameters_apply_mask - station parameter values to apply * @STATION_PARAM_APPLY_UAPSD: apply new uAPSD parameters (uapsd_queues, max_sp) Loading Loading @@ -3082,6 +3110,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 @@ -3147,6 +3181,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 Loading @@ -5644,36 +5679,20 @@ unsigned int ieee80211_get_num_supported_channels(struct wiphy *wiphy); * cfg80211_check_combinations - check interface combinations * * @wiphy: the wiphy * @num_different_channels: the number of different channels we want * to use for verification * @radar_detect: a bitmap where each bit corresponds to a channel * width where radar detection is needed, as in the definition of * &struct ieee80211_iface_combination.@radar_detect_widths * @iftype_num: array with the numbers of interfaces of each interface * type. The index is the interface type as specified in &enum * nl80211_iftype. * @params: the interface combinations parameter * * This function can be called by the driver to check whether a * combination of interfaces and their types are allowed according to * the interface combinations. */ int cfg80211_check_combinations(struct wiphy *wiphy, const int num_different_channels, const u8 radar_detect, const int iftype_num[NUM_NL80211_IFTYPES]); struct iface_combination_params *params); /** * cfg80211_iter_combinations - iterate over matching combinations * * @wiphy: the wiphy * @num_different_channels: the number of different channels we want * to use for verification * @radar_detect: a bitmap where each bit corresponds to a channel * width where radar detection is needed, as in the definition of * &struct ieee80211_iface_combination.@radar_detect_widths * @iftype_num: array with the numbers of interfaces of each interface * type. The index is the interface type as specified in &enum * nl80211_iftype. * @params: the interface combinations parameter * @iter: function to call for each matching combination * @data: pointer to pass to iter function * Loading @@ -5682,9 +5701,7 @@ int cfg80211_check_combinations(struct wiphy *wiphy, * purposes. */ int cfg80211_iter_combinations(struct wiphy *wiphy, const int num_different_channels, const u8 radar_detect, const int iftype_num[NUM_NL80211_IFTYPES], struct iface_combination_params *params, void (*iter)(const struct ieee80211_iface_combination *c, void *data), void *data); Loading include/uapi/linux/nl80211.h +6 −2 Original line number Diff line number Diff line Loading @@ -4285,6 +4285,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 @@ -4292,8 +4295,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 @@ -4319,6 +4322,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/mac80211/util.c +20 −24 Original line number Diff line number Diff line Loading @@ -3308,10 +3308,11 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata, 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 = 0; int total = 1; struct iface_combination_params params = { .radar_detect = radar_detect, }; lockdep_assert_held(&local->chanctx_mtx); Loading @@ -3322,9 +3323,6 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata, !chandef->chan)) return -EINVAL; if (chandef) num_different_channels = 1; if (WARN_ON(iftype >= NUM_NL80211_IFTYPES)) return -EINVAL; Loading @@ -3335,24 +3333,26 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata, return 0; } memset(num, 0, sizeof(num)); if (chandef) params.num_different_channels = 1; if (iftype != NL80211_IFTYPE_UNSPECIFIED) num[iftype] = 1; params.iftype_num[iftype] = 1; list_for_each_entry(ctx, &local->chanctx_list, list) { if (ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED) continue; radar_detect |= ieee80211_chanctx_radar_detect(local, ctx); params.radar_detect |= ieee80211_chanctx_radar_detect(local, ctx); if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE) { num_different_channels++; params.num_different_channels++; continue; } if (chandef && chanmode == IEEE80211_CHANCTX_SHARED && cfg80211_chandef_compatible(chandef, &ctx->conf.def)) continue; num_different_channels++; params.num_different_channels++; } list_for_each_entry_rcu(sdata_iter, &local->interfaces, list) { Loading @@ -3365,16 +3365,14 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata, local->hw.wiphy->software_iftypes & BIT(wdev_iter->iftype)) continue; num[wdev_iter->iftype]++; params.iftype_num[wdev_iter->iftype]++; total++; } if (total == 1 && !radar_detect) if (total == 1 && !params.radar_detect) return 0; return cfg80211_check_combinations(local->hw.wiphy, num_different_channels, radar_detect, num); return cfg80211_check_combinations(local->hw.wiphy, ¶ms); } static void Loading @@ -3390,12 +3388,10 @@ ieee80211_iter_max_chans(const struct ieee80211_iface_combination *c, int ieee80211_max_num_channels(struct ieee80211_local *local) { struct ieee80211_sub_if_data *sdata; int num[NUM_NL80211_IFTYPES] = {}; struct ieee80211_chanctx *ctx; int num_different_channels = 0; u8 radar_detect = 0; u32 max_num_different_channels = 1; int err; struct iface_combination_params params = {0}; lockdep_assert_held(&local->chanctx_mtx); Loading @@ -3403,17 +3399,17 @@ int ieee80211_max_num_channels(struct ieee80211_local *local) if (ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED) continue; num_different_channels++; params.num_different_channels++; radar_detect |= ieee80211_chanctx_radar_detect(local, ctx); params.radar_detect |= ieee80211_chanctx_radar_detect(local, ctx); } list_for_each_entry_rcu(sdata, &local->interfaces, list) num[sdata->wdev.iftype]++; params.iftype_num[sdata->wdev.iftype]++; err = cfg80211_iter_combinations(local->hw.wiphy, num_different_channels, radar_detect, num, ieee80211_iter_max_chans, err = cfg80211_iter_combinations(local->hw.wiphy, ¶ms, ieee80211_iter_max_chans, &max_num_different_channels); if (err < 0) return err; Loading net/wireless/core.h +1 −1 Original line number Diff line number Diff line Loading @@ -477,7 +477,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 Loading
drivers/net/wireless/broadcom/brcm80211/brcmfmac/cfg80211.c +12 −10 Original line number Diff line number Diff line Loading @@ -414,23 +414,24 @@ static int brcmf_vif_change_validate(struct brcmf_cfg80211_info *cfg, struct brcmf_cfg80211_vif *vif, enum nl80211_iftype new_type) { int iftype_num[NUM_NL80211_IFTYPES]; struct brcmf_cfg80211_vif *pos; bool check_combos = false; int ret = 0; struct iface_combination_params params = { .num_different_channels = 1, }; memset(&iftype_num[0], 0, sizeof(iftype_num)); list_for_each_entry(pos, &cfg->vif_list, list) if (pos == vif) { iftype_num[new_type]++; params.iftype_num[new_type]++; } else { /* concurrent interfaces so need check combinations */ check_combos = true; iftype_num[pos->wdev.iftype]++; params.iftype_num[pos->wdev.iftype]++; } if (check_combos) ret = cfg80211_check_combinations(cfg->wiphy, 1, 0, iftype_num); ret = cfg80211_check_combinations(cfg->wiphy, ¶ms); return ret; } Loading @@ -438,15 +439,16 @@ static int brcmf_vif_change_validate(struct brcmf_cfg80211_info *cfg, static int brcmf_vif_add_validate(struct brcmf_cfg80211_info *cfg, enum nl80211_iftype new_type) { int iftype_num[NUM_NL80211_IFTYPES]; struct brcmf_cfg80211_vif *pos; struct iface_combination_params params = { .num_different_channels = 1, }; memset(&iftype_num[0], 0, sizeof(iftype_num)); list_for_each_entry(pos, &cfg->vif_list, list) iftype_num[pos->wdev.iftype]++; params.iftype_num[pos->wdev.iftype]++; iftype_num[new_type]++; return cfg80211_check_combinations(cfg->wiphy, 1, 0, iftype_num); params.iftype_num[new_type]++; return cfg80211_check_combinations(cfg->wiphy, ¶ms); } static void convert_key_from_CPU(struct brcmf_wsec_key *key, Loading
include/net/cfg80211.h +39 −22 Original line number Diff line number Diff line Loading @@ -771,6 +771,34 @@ struct cfg80211_csa_settings { u8 count; }; /** * struct iface_combination_params - input parameters for interface combinations * * Used to pass interface combination parameters * * @num_different_channels: the number of different channels we want * to use for verification * @radar_detect: a bitmap where each bit corresponds to a channel * width where radar detection is needed, as in the definition of * &struct ieee80211_iface_combination.@radar_detect_widths * @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; }; /** * enum station_parameters_apply_mask - station parameter values to apply * @STATION_PARAM_APPLY_UAPSD: apply new uAPSD parameters (uapsd_queues, max_sp) Loading Loading @@ -3082,6 +3110,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 @@ -3147,6 +3181,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 Loading @@ -5644,36 +5679,20 @@ unsigned int ieee80211_get_num_supported_channels(struct wiphy *wiphy); * cfg80211_check_combinations - check interface combinations * * @wiphy: the wiphy * @num_different_channels: the number of different channels we want * to use for verification * @radar_detect: a bitmap where each bit corresponds to a channel * width where radar detection is needed, as in the definition of * &struct ieee80211_iface_combination.@radar_detect_widths * @iftype_num: array with the numbers of interfaces of each interface * type. The index is the interface type as specified in &enum * nl80211_iftype. * @params: the interface combinations parameter * * This function can be called by the driver to check whether a * combination of interfaces and their types are allowed according to * the interface combinations. */ int cfg80211_check_combinations(struct wiphy *wiphy, const int num_different_channels, const u8 radar_detect, const int iftype_num[NUM_NL80211_IFTYPES]); struct iface_combination_params *params); /** * cfg80211_iter_combinations - iterate over matching combinations * * @wiphy: the wiphy * @num_different_channels: the number of different channels we want * to use for verification * @radar_detect: a bitmap where each bit corresponds to a channel * width where radar detection is needed, as in the definition of * &struct ieee80211_iface_combination.@radar_detect_widths * @iftype_num: array with the numbers of interfaces of each interface * type. The index is the interface type as specified in &enum * nl80211_iftype. * @params: the interface combinations parameter * @iter: function to call for each matching combination * @data: pointer to pass to iter function * Loading @@ -5682,9 +5701,7 @@ int cfg80211_check_combinations(struct wiphy *wiphy, * purposes. */ int cfg80211_iter_combinations(struct wiphy *wiphy, const int num_different_channels, const u8 radar_detect, const int iftype_num[NUM_NL80211_IFTYPES], struct iface_combination_params *params, void (*iter)(const struct ieee80211_iface_combination *c, void *data), void *data); Loading
include/uapi/linux/nl80211.h +6 −2 Original line number Diff line number Diff line Loading @@ -4285,6 +4285,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 @@ -4292,8 +4295,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 @@ -4319,6 +4322,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/mac80211/util.c +20 −24 Original line number Diff line number Diff line Loading @@ -3308,10 +3308,11 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata, 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 = 0; int total = 1; struct iface_combination_params params = { .radar_detect = radar_detect, }; lockdep_assert_held(&local->chanctx_mtx); Loading @@ -3322,9 +3323,6 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata, !chandef->chan)) return -EINVAL; if (chandef) num_different_channels = 1; if (WARN_ON(iftype >= NUM_NL80211_IFTYPES)) return -EINVAL; Loading @@ -3335,24 +3333,26 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata, return 0; } memset(num, 0, sizeof(num)); if (chandef) params.num_different_channels = 1; if (iftype != NL80211_IFTYPE_UNSPECIFIED) num[iftype] = 1; params.iftype_num[iftype] = 1; list_for_each_entry(ctx, &local->chanctx_list, list) { if (ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED) continue; radar_detect |= ieee80211_chanctx_radar_detect(local, ctx); params.radar_detect |= ieee80211_chanctx_radar_detect(local, ctx); if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE) { num_different_channels++; params.num_different_channels++; continue; } if (chandef && chanmode == IEEE80211_CHANCTX_SHARED && cfg80211_chandef_compatible(chandef, &ctx->conf.def)) continue; num_different_channels++; params.num_different_channels++; } list_for_each_entry_rcu(sdata_iter, &local->interfaces, list) { Loading @@ -3365,16 +3365,14 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata, local->hw.wiphy->software_iftypes & BIT(wdev_iter->iftype)) continue; num[wdev_iter->iftype]++; params.iftype_num[wdev_iter->iftype]++; total++; } if (total == 1 && !radar_detect) if (total == 1 && !params.radar_detect) return 0; return cfg80211_check_combinations(local->hw.wiphy, num_different_channels, radar_detect, num); return cfg80211_check_combinations(local->hw.wiphy, ¶ms); } static void Loading @@ -3390,12 +3388,10 @@ ieee80211_iter_max_chans(const struct ieee80211_iface_combination *c, int ieee80211_max_num_channels(struct ieee80211_local *local) { struct ieee80211_sub_if_data *sdata; int num[NUM_NL80211_IFTYPES] = {}; struct ieee80211_chanctx *ctx; int num_different_channels = 0; u8 radar_detect = 0; u32 max_num_different_channels = 1; int err; struct iface_combination_params params = {0}; lockdep_assert_held(&local->chanctx_mtx); Loading @@ -3403,17 +3399,17 @@ int ieee80211_max_num_channels(struct ieee80211_local *local) if (ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED) continue; num_different_channels++; params.num_different_channels++; radar_detect |= ieee80211_chanctx_radar_detect(local, ctx); params.radar_detect |= ieee80211_chanctx_radar_detect(local, ctx); } list_for_each_entry_rcu(sdata, &local->interfaces, list) num[sdata->wdev.iftype]++; params.iftype_num[sdata->wdev.iftype]++; err = cfg80211_iter_combinations(local->hw.wiphy, num_different_channels, radar_detect, num, ieee80211_iter_max_chans, err = cfg80211_iter_combinations(local->hw.wiphy, ¶ms, ieee80211_iter_max_chans, &max_num_different_channels); if (err < 0) return err; Loading
net/wireless/core.h +1 −1 Original line number Diff line number Diff line Loading @@ -477,7 +477,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