wifi: mac80211: add support for DFS with multiple radios
authorFelix Fietkau <nbd@nbd.name>
Tue, 9 Jul 2024 08:38:33 +0000 (10:38 +0200)
committerJohannes Berg <johannes.berg@intel.com>
Tue, 9 Jul 2024 09:36:12 +0000 (11:36 +0200)
DFS can be supported with multi-channel combinations, as long as each DFS
capable radio only supports one channel.

Signed-off-by: Felix Fietkau <nbd@nbd.name>
Link: https://patch.msgid.link/4d27a4adca99fa832af1f7cda4f2e71016bd9fda.1720514221.git-series.nbd@nbd.name
Signed-off-by: Johannes Berg <johannes.berg@intel.com>
net/mac80211/main.c

index 85a267bdb3e3dd000482c620908888b08eede7d6..a3104b6ea6f0b989d0b468f51de50304099ffc82 100644 (file)
@@ -1091,6 +1091,27 @@ static int ieee80211_init_cipher_suites(struct ieee80211_local *local)
        return 0;
 }
 
+static bool
+ieee80211_ifcomb_check(const struct ieee80211_iface_combination *c, int n_comb)
+{
+       int i, j;
+
+       for (i = 0; i < n_comb; i++, c++) {
+               /* DFS is not supported with multi-channel combinations yet */
+               if (c->radar_detect_widths &&
+                   c->num_different_channels > 1)
+                       return false;
+
+               /* mac80211 doesn't support more than one IBSS interface */
+               for (j = 0; j < c->n_limits; j++)
+                       if ((c->limits[j].types & BIT(NL80211_IFTYPE_ADHOC)) &&
+                           c->limits[j].max > 1)
+                               return false;
+       }
+
+       return true;
+}
+
 int ieee80211_register_hw(struct ieee80211_hw *hw)
 {
        struct ieee80211_local *local = hw_to_local(hw);
@@ -1177,17 +1198,20 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
                        if (comb->num_different_channels > 1)
                                return -EINVAL;
                }
-       } else {
-               /* DFS is not supported with multi-channel combinations yet */
-               for (i = 0; i < local->hw.wiphy->n_iface_combinations; i++) {
-                       const struct ieee80211_iface_combination *comb;
+       }
 
-                       comb = &local->hw.wiphy->iface_combinations[i];
+       if (hw->wiphy->n_radio) {
+               for (i = 0; i < hw->wiphy->n_radio; i++) {
+                       const struct wiphy_radio *radio = &hw->wiphy->radio[i];
 
-                       if (comb->radar_detect_widths &&
-                           comb->num_different_channels > 1)
+                       if (!ieee80211_ifcomb_check(radio->iface_combinations,
+                                                   radio->n_iface_combinations))
                                return -EINVAL;
                }
+       } else {
+               if (!ieee80211_ifcomb_check(hw->wiphy->iface_combinations,
+                                           hw->wiphy->n_iface_combinations))
+                       return -EINVAL;
        }
 
        /* Only HW csum features are currently compatible with mac80211 */
@@ -1317,18 +1341,6 @@ int ieee80211_register_hw(struct ieee80211_hw *hw)
        hw->wiphy->interface_modes |= BIT(NL80211_IFTYPE_MONITOR);
        hw->wiphy->software_iftypes |= BIT(NL80211_IFTYPE_MONITOR);
 
-       /* mac80211 doesn't support more than one IBSS interface right now */
-       for (i = 0; i < hw->wiphy->n_iface_combinations; i++) {
-               const struct ieee80211_iface_combination *c;
-               int j;
-
-               c = &hw->wiphy->iface_combinations[i];
-
-               for (j = 0; j < c->n_limits; j++)
-                       if ((c->limits[j].types & BIT(NL80211_IFTYPE_ADHOC)) &&
-                           c->limits[j].max > 1)
-                               return -EINVAL;
-       }
 
        local->int_scan_req = kzalloc(sizeof(*local->int_scan_req) +
                                      sizeof(void *) * channels, GFP_KERNEL);