wifi: ath12k: bring DFS support back for WCN7850

Due to the restrict in MAC80211 that DFS (Dynamic Frequency Selection)
can't be enabled on multiple channels, commit 176f3009ae ("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: 176f3009ae ("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>
This commit is contained in:
Baochen Qiang
2025-07-21 10:27:26 +08:00
committed by Jeff Johnson
parent 306facc029
commit c4825d540f

View 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;