wifi: mac80211: add an option to filter out a channel in combinations check

Sometimes, ieee80211_check_combinations fails, but it is hard to know
why exactly. We will have to return an array of reasons, one per
combination.

In cases where we want to check if it failed because there are not
enough chanctxs (and maybe remove one if needed), we can just not fill
in that chanctx(s) in iface_combination_params::num_different_channels
in ieee80211_fill_ifcomb_params, so that chanctx(s) won't be taken into
account.

To allow that, add an option to pass a callback to
ieee80211_fill_ifcomb_params. This callback will be called for each
chanctx we consider to count in num_different_channels and will return
whether or not this chanctx should be skipped and not counted.

This mechanism will be used later.

Signed-off-by: Miri Korenblit <miriam.rachel.korenblit@intel.com>
Link: https://patch.msgid.link/20260527224745.0042232f996e.I5d323125e34f3b253510e85ceb7a770d59f689fb@changeid
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
This commit is contained in:
Miri Korenblit 2026-05-27 22:51:43 +03:00 committed by Johannes Berg
parent 847f7ead7b
commit 8facc23dc2
2 changed files with 51 additions and 17 deletions

View File

@ -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,

View File

@ -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, &params,
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, &params, NULL, NULL);
ieee80211_fill_ifcomb_params(local, &params, NULL, NULL, NULL, NULL);
err = cfg80211_iter_combinations(local->hw.wiphy, &params,
ieee80211_iter_max_chans,