]> git.ipfire.org Git - thirdparty/linux.git/commitdiff
wifi: ath12k: bring DFS support back for WCN7850
authorBaochen Qiang <baochen.qiang@oss.qualcomm.com>
Mon, 21 Jul 2025 02:27:26 +0000 (10:27 +0800)
committerJeff Johnson <jeff.johnson@oss.qualcomm.com>
Mon, 21 Jul 2025 21:34:01 +0000 (14:34 -0700)
Due to the restrict in MAC80211 that DFS (Dynamic Frequency Selection)
can't be enabled on multiple channels, commit 176f3009ae59 ("wifi: ath12k:
support 2 channels for single pdev device") removes DFS support in order
to support 2 channels concurrently, making AP mode not working on DFS
channels [1].

Revert portions of that commit to bring DFS back, and add a new
combination to support 2-channels concurrency. This is valid because the
MAC80211 restrict works on each individual combination, but does not care
about them as a whole, as far as DFS is concerned.

This change applies to WCN7850 only, other chips are not affected.

Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.1.c5-00284.1-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3

Fixes: 176f3009ae59 ("wifi: ath12k: support 2 channels for single pdev device")
Reported-by: Mihai Moldovan <ionic@ionic.de>
Closes: https://bugzilla.kernel.org/show_bug.cgi?id=220346 # 1
Signed-off-by: Baochen Qiang <baochen.qiang@oss.qualcomm.com>
Reviewed-by: Vasanthakumar Thiagarajan <vasanthakumar.thiagarajan@oss.qualcomm.com>
Tested-by: Mihai Moldovan <ionic@ionic.de>
Link: https://patch.msgid.link/20250721-ath12k-dfs-v1-1-065c31454f91@oss.qualcomm.com
Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
drivers/net/wireless/ath/ath12k/mac.c

index 7f80c72611c8ebb440d23e34da2e050f7195e504..bd1ec3b2c084169b841146931c54b6106f7006f6 100644 (file)
@@ -13365,16 +13365,12 @@ ath12k_mac_setup_radio_iface_comb(struct ath12k *ar,
        comb[0].beacon_int_infra_match = true;
        comb[0].beacon_int_min_gcd = 100;
 
-       if (ar->ab->hw_params->single_pdev_only) {
-               comb[0].num_different_channels = 2;
-       } else {
-               comb[0].num_different_channels = 1;
-               comb[0].radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) |
-                                               BIT(NL80211_CHAN_WIDTH_20) |
-                                               BIT(NL80211_CHAN_WIDTH_40) |
-                                               BIT(NL80211_CHAN_WIDTH_80) |
-                                               BIT(NL80211_CHAN_WIDTH_160);
-       }
+       comb[0].num_different_channels = 1;
+       comb[0].radar_detect_widths = BIT(NL80211_CHAN_WIDTH_20_NOHT) |
+                                     BIT(NL80211_CHAN_WIDTH_20) |
+                                     BIT(NL80211_CHAN_WIDTH_40) |
+                                     BIT(NL80211_CHAN_WIDTH_80) |
+                                     BIT(NL80211_CHAN_WIDTH_160);
 
        return 0;
 }
@@ -13457,25 +13453,42 @@ static int ath12k_mac_setup_iface_combinations(struct ath12k_hw *ah)
        struct ieee80211_iface_combination *combinations, *comb;
        struct wiphy *wiphy = ah->hw->wiphy;
        struct wiphy_radio *radio;
+       int n_combinations = 1;
        struct ath12k *ar;
        int i, ret;
 
-       combinations = kzalloc(sizeof(*combinations), GFP_KERNEL);
-       if (!combinations)
-               return -ENOMEM;
-
        if (ah->num_radio == 1) {
-               ret = ath12k_mac_setup_radio_iface_comb(&ah->radio[0],
-                                                       combinations);
+               ar = &ah->radio[0];
+
+               if (ar->ab->hw_params->single_pdev_only)
+                       n_combinations = 2;
+
+               combinations = kcalloc(n_combinations, sizeof(*combinations),
+                                      GFP_KERNEL);
+               if (!combinations)
+                       return -ENOMEM;
+
+               ret = ath12k_mac_setup_radio_iface_comb(ar, combinations);
                if (ret) {
                        ath12k_hw_warn(ah, "failed to setup radio interface combinations for one radio: %d",
                                       ret);
                        goto err_free_combinations;
                }
 
+               if (ar->ab->hw_params->single_pdev_only) {
+                       comb = combinations + 1;
+                       memcpy(comb, combinations, sizeof(*comb));
+                       comb->num_different_channels = 2;
+                       comb->radar_detect_widths = 0;
+               }
+
                goto out;
        }
 
+       combinations = kcalloc(n_combinations, sizeof(*combinations), GFP_KERNEL);
+       if (!combinations)
+               return -ENOMEM;
+
        /* there are multiple radios */
 
        radio = kcalloc(ah->num_radio, sizeof(*radio), GFP_KERNEL);
@@ -13518,7 +13531,7 @@ static int ath12k_mac_setup_iface_combinations(struct ath12k_hw *ah)
 
 out:
        wiphy->iface_combinations = combinations;
-       wiphy->n_iface_combinations = 1;
+       wiphy->n_iface_combinations = n_combinations;
 
        return 0;