diff --git a/net/mac80211/ieee80211_i.h b/net/mac80211/ieee80211_i.h index 1360522649c2..20b27c8f7d4e 100644 --- a/net/mac80211/ieee80211_i.h +++ b/net/mac80211/ieee80211_i.h @@ -2818,10 +2818,36 @@ int ieee80211_send_action_csa(struct ieee80211_sub_if_data *sdata, struct cfg80211_csa_settings *csa_settings); void ieee80211_recalc_sb_count(struct ieee80211_sub_if_data *sdata, u64 tsf); void ieee80211_recalc_dtim(struct ieee80211_sub_if_data *sdata, u64 tsf); -int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata, - const struct cfg80211_chan_def *chandef, - enum ieee80211_chanctx_mode chanmode, - u8 radar_detect, int radio_idx); + +struct ieee80211_check_combinations_data { + const struct cfg80211_chan_def *chandef; + enum ieee80211_chanctx_mode chanmode; + u8 radar_detect; + int radio_idx; + bool (*chanctx_filter)(struct ieee80211_chanctx *ctx, + void *filter_data); + void *filter_data; +}; + +int ieee80211_check_combinations_ext(struct ieee80211_sub_if_data *sdata, + struct ieee80211_check_combinations_data *data); + +static inline int +ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata, + const struct cfg80211_chan_def *chandef, + enum ieee80211_chanctx_mode chanmode, + u8 radar_detect, int radio_idx) +{ + struct ieee80211_check_combinations_data data = { + .chandef = chandef, + .chanmode = chanmode, + .radar_detect = radar_detect, + .radio_idx = radio_idx, + }; + + return ieee80211_check_combinations_ext(sdata, &data); +} + int ieee80211_max_num_channels(struct ieee80211_local *local, int radio_idx); u32 ieee80211_get_radio_mask(struct wiphy *wiphy, struct net_device *dev); void ieee80211_recalc_chanctx_chantype(struct ieee80211_local *local, diff --git a/net/mac80211/util.c b/net/mac80211/util.c index 255905f971c8..2a7ab269687a 100644 --- a/net/mac80211/util.c +++ b/net/mac80211/util.c @@ -4260,7 +4260,10 @@ static int ieee80211_fill_ifcomb_params(struct ieee80211_local *local, struct iface_combination_params *params, const struct cfg80211_chan_def *chandef, - struct ieee80211_sub_if_data *sdata) + struct ieee80211_sub_if_data *sdata, + bool (*chanctx_filter)(struct ieee80211_chanctx *ctx, + void *filter_data), + void *filter_data) { struct ieee80211_sub_if_data *sdata_iter; struct ieee80211_chanctx *ctx; @@ -4281,6 +4284,10 @@ ieee80211_fill_ifcomb_params(struct ieee80211_local *local, cfg80211_chandef_compatible(chandef, &ctx->conf.def)) continue; + if (chanctx_filter && + chanctx_filter(ctx, filter_data)) + continue; + params->num_different_channels++; } @@ -4305,26 +4312,25 @@ ieee80211_fill_ifcomb_params(struct ieee80211_local *local, return total; } -int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata, - const struct cfg80211_chan_def *chandef, - enum ieee80211_chanctx_mode chanmode, - u8 radar_detect, int radio_idx) +int ieee80211_check_combinations_ext(struct ieee80211_sub_if_data *sdata, + struct ieee80211_check_combinations_data *data) { - bool shared = chanmode == IEEE80211_CHANCTX_SHARED; + const struct cfg80211_chan_def *chandef = data->chandef; + bool shared = data->chanmode == IEEE80211_CHANCTX_SHARED; struct ieee80211_local *local = sdata->local; enum nl80211_iftype iftype = sdata->wdev.iftype; struct iface_combination_params params = { - .radar_detect = radar_detect, - .radio_idx = radio_idx, + .radar_detect = data->radar_detect, + .radio_idx = data->radio_idx, }; int total; lockdep_assert_wiphy(local->hw.wiphy); - if (WARN_ON(hweight32(radar_detect) > 1)) + if (WARN_ON(hweight32(data->radar_detect) > 1)) return -EINVAL; - if (WARN_ON(chandef && chanmode == IEEE80211_CHANCTX_SHARED && + if (WARN_ON(chandef && data->chanmode == IEEE80211_CHANCTX_SHARED && !chandef->chan)) return -EINVAL; @@ -4343,7 +4349,7 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata, /* Always allow software iftypes */ if (cfg80211_iftype_allowed(local->hw.wiphy, iftype, 0, 1)) { - if (radar_detect) + if (data->radar_detect) return -EINVAL; return 0; } @@ -4356,7 +4362,9 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata, total = ieee80211_fill_ifcomb_params(local, ¶ms, shared ? chandef : NULL, - sdata); + sdata, + data->chanctx_filter, + data->filter_data); if (total == 1 && !params.radar_detect) return 0; @@ -4383,7 +4391,7 @@ int ieee80211_max_num_channels(struct ieee80211_local *local, int radio_idx) lockdep_assert_wiphy(local->hw.wiphy); - ieee80211_fill_ifcomb_params(local, ¶ms, NULL, NULL); + ieee80211_fill_ifcomb_params(local, ¶ms, NULL, NULL, NULL, NULL); err = cfg80211_iter_combinations(local->hw.wiphy, ¶ms, ieee80211_iter_max_chans,