|
@@ -2873,3 +2873,45 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata,
|
|
|
num_different_channels,
|
|
|
radar_detect, num);
|
|
|
}
|
|
|
+
|
|
|
+static void
|
|
|
+ieee80211_iter_max_chans(const struct ieee80211_iface_combination *c,
|
|
|
+ void *data)
|
|
|
+{
|
|
|
+ u32 *max_num_different_channels = data;
|
|
|
+
|
|
|
+ *max_num_different_channels = max(*max_num_different_channels,
|
|
|
+ c->num_different_channels);
|
|
|
+}
|
|
|
+
|
|
|
+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;
|
|
|
+
|
|
|
+ lockdep_assert_held(&local->chanctx_mtx);
|
|
|
+
|
|
|
+ list_for_each_entry(ctx, &local->chanctx_list, list) {
|
|
|
+ num_different_channels++;
|
|
|
+
|
|
|
+ if (ctx->conf.radar_enabled)
|
|
|
+ radar_detect |= BIT(ctx->conf.def.width);
|
|
|
+ }
|
|
|
+
|
|
|
+ list_for_each_entry_rcu(sdata, &local->interfaces, list)
|
|
|
+ num[sdata->wdev.iftype]++;
|
|
|
+
|
|
|
+ err = cfg80211_iter_combinations(local->hw.wiphy,
|
|
|
+ num_different_channels, radar_detect,
|
|
|
+ num, ieee80211_iter_max_chans,
|
|
|
+ &max_num_different_channels);
|
|
|
+ if (err < 0)
|
|
|
+ return err;
|
|
|
+
|
|
|
+ return max_num_different_channels;
|
|
|
+}
|