aboutsummaryrefslogtreecommitdiffstats
path: root/net/mac80211/util.c
diff options
context:
space:
mode:
Diffstat (limited to 'net/mac80211/util.c')
-rw-r--r--net/mac80211/util.c72
1 files changed, 72 insertions, 0 deletions
diff --git a/net/mac80211/util.c b/net/mac80211/util.c
index 73af7398850b..436f98870066 100644
--- a/net/mac80211/util.c
+++ b/net/mac80211/util.c
@@ -2797,3 +2797,75 @@ void ieee80211_recalc_dtim(struct ieee80211_local *local,
2797 2797
2798 ps->dtim_count = dtim_count; 2798 ps->dtim_count = dtim_count;
2799} 2799}
2800
2801int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata,
2802 const struct cfg80211_chan_def *chandef,
2803 enum ieee80211_chanctx_mode chanmode,
2804 u8 radar_detect)
2805{
2806 struct ieee80211_local *local = sdata->local;
2807 struct ieee80211_sub_if_data *sdata_iter;
2808 enum nl80211_iftype iftype = sdata->wdev.iftype;
2809 int num[NUM_NL80211_IFTYPES];
2810 struct ieee80211_chanctx *ctx;
2811 int num_different_channels = 1;
2812 int total = 1;
2813
2814 lockdep_assert_held(&local->chanctx_mtx);
2815
2816 if (WARN_ON(hweight32(radar_detect) > 1))
2817 return -EINVAL;
2818
2819 if (WARN_ON(chanmode == IEEE80211_CHANCTX_SHARED && !chandef->chan))
2820 return -EINVAL;
2821
2822 if (WARN_ON(iftype >= NUM_NL80211_IFTYPES))
2823 return -EINVAL;
2824
2825 /* Always allow software iftypes */
2826 if (local->hw.wiphy->software_iftypes & BIT(iftype)) {
2827 if (radar_detect)
2828 return -EINVAL;
2829 return 0;
2830 }
2831
2832 memset(num, 0, sizeof(num));
2833
2834 if (iftype != NL80211_IFTYPE_UNSPECIFIED)
2835 num[iftype] = 1;
2836
2837 list_for_each_entry(ctx, &local->chanctx_list, list) {
2838 if (ctx->conf.radar_enabled)
2839 radar_detect |= BIT(ctx->conf.def.width);
2840 if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE) {
2841 num_different_channels++;
2842 continue;
2843 }
2844 if ((chanmode == IEEE80211_CHANCTX_SHARED) &&
2845 cfg80211_chandef_compatible(chandef,
2846 &ctx->conf.def))
2847 continue;
2848 num_different_channels++;
2849 }
2850
2851 list_for_each_entry_rcu(sdata_iter, &local->interfaces, list) {
2852 struct wireless_dev *wdev_iter;
2853
2854 wdev_iter = &sdata_iter->wdev;
2855
2856 if (sdata_iter == sdata ||
2857 rcu_access_pointer(sdata_iter->vif.chanctx_conf) == NULL ||
2858 local->hw.wiphy->software_iftypes & BIT(wdev_iter->iftype))
2859 continue;
2860
2861 num[wdev_iter->iftype]++;
2862 total++;
2863 }
2864
2865 if (total == 1 && !radar_detect)
2866 return 0;
2867
2868 return cfg80211_check_combinations(local->hw.wiphy,
2869 num_different_channels,
2870 radar_detect, num);
2871}