mac80211: make check_combinations() aware of chanctx reservation
authorMichal Kazior <michal.kazior@tieto.com>
Wed, 25 Jun 2014 10:35:07 +0000 (12:35 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Wed, 25 Jun 2014 16:06:20 +0000 (18:06 +0200)
The ieee80211_check_combinations() computes
radar_detect accordingly depending on chanctx
reservation status.

This makes it possible to use the function for
channel_switch validation.

Signed-off-by: Michal Kazior <michal.kazior@tieto.com>
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/mac80211/util.c

index 1b42aa16ec03e903755279117974dbbd3a20c59f..ea79668c2e5ff67844470e98149dd6fd9edb0e4c 100644 (file)
@@ -2933,6 +2933,35 @@ void ieee80211_recalc_dtim(struct ieee80211_local *local,
        ps->dtim_count = dtim_count;
 }
 
+static u8 ieee80211_chanctx_radar_detect(struct ieee80211_local *local,
+                                        struct ieee80211_chanctx *ctx)
+{
+       struct ieee80211_sub_if_data *sdata;
+       u8 radar_detect = 0;
+
+       lockdep_assert_held(&local->chanctx_mtx);
+
+       if (WARN_ON(ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED))
+               return 0;
+
+       list_for_each_entry(sdata, &ctx->reserved_vifs, reserved_chanctx_list)
+               if (sdata->reserved_radar_required)
+                       radar_detect |= BIT(sdata->reserved_chandef.width);
+
+       /*
+        * An in-place reservation context should not have any assigned vifs
+        * until it replaces the other context.
+        */
+       WARN_ON(ctx->replace_state == IEEE80211_CHANCTX_REPLACES_OTHER &&
+               !list_empty(&ctx->assigned_vifs));
+
+       list_for_each_entry(sdata, &ctx->assigned_vifs, assigned_chanctx_list)
+               if (sdata->radar_required)
+                       radar_detect |= BIT(sdata->vif.bss_conf.chandef.width);
+
+       return radar_detect;
+}
+
 int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata,
                                 const struct cfg80211_chan_def *chandef,
                                 enum ieee80211_chanctx_mode chanmode,
@@ -2976,8 +3005,7 @@ int ieee80211_check_combinations(struct ieee80211_sub_if_data *sdata,
        list_for_each_entry(ctx, &local->chanctx_list, list) {
                if (ctx->replace_state == IEEE80211_CHANCTX_WILL_BE_REPLACED)
                        continue;
-               if (ctx->conf.radar_enabled)
-                       radar_detect |= BIT(ctx->conf.def.width);
+               radar_detect |= ieee80211_chanctx_radar_detect(local, ctx);
                if (ctx->mode == IEEE80211_CHANCTX_EXCLUSIVE) {
                        num_different_channels++;
                        continue;
@@ -3039,8 +3067,7 @@ int ieee80211_max_num_channels(struct ieee80211_local *local)
 
                num_different_channels++;
 
-               if (ctx->conf.radar_enabled)
-                       radar_detect |= BIT(ctx->conf.def.width);
+               radar_detect |= ieee80211_chanctx_radar_detect(local, ctx);
        }
 
        list_for_each_entry_rcu(sdata, &local->interfaces, list)