]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
wifi: ath12k: fix handling of 6 GHz rules
authorAditya Kumar Singh <aditya.kumar.singh@oss.qualcomm.com>
Thu, 23 Jan 2025 16:21:38 +0000 (21:51 +0530)
committerJeff Johnson <jeff.johnson@oss.qualcomm.com>
Fri, 24 Jan 2025 18:32:44 +0000 (10:32 -0800)
In the US country code, to avoid including 6 GHz rules in the 5 GHz rules
list, the number of 5 GHz rules is set to a default constant value of 4
(REG_US_5G_NUM_REG_RULES). However, if there are more than 4 valid 5 GHz
rules, the current logic will bypass the legitimate 6 GHz rules.

For example, if there are 5 valid 5 GHz rules and 1 valid 6 GHz rule, the
current logic will only consider 4 of the 5 GHz rules, treating the last
valid rule as a 6 GHz rule. Consequently, the actual 6 GHz rule is never
processed, leading to the eventual disabling of 6 GHz channels.

To fix this issue, instead of hardcoding the value to 4, use a helper
function to determine the number of 6 GHz rules present in the 5 GHz rules
list and ignore only those rules.

Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00173-QCAHKSWPL_SILICONZ-1

Cc: stable@vger.kernel.org
Fixes: d889913205cf ("wifi: ath12k: driver for Qualcomm Wi-Fi 7 devices")
Signed-off-by: Aditya Kumar Singh <aditya.kumar.singh@oss.qualcomm.com>
Link: https://patch.msgid.link/20250123-fix_6ghz_rules_handling-v1-1-d734bfa58ff4@oss.qualcomm.com
Signed-off-by: Jeff Johnson <jeff.johnson@oss.qualcomm.com>
drivers/net/wireless/ath/ath12k/wmi.c
drivers/net/wireless/ath/ath12k/wmi.h

index dced2aa9ba1a3efd5fbb5b35fa3fb4dbf2b71e77..d953742b67e149944eaed0bcf5c41594f01a7916 100644 (file)
@@ -4681,6 +4681,22 @@ static struct ath12k_reg_rule
        return reg_rule_ptr;
 }
 
+static u8 ath12k_wmi_ignore_num_extra_rules(struct ath12k_wmi_reg_rule_ext_params *rule,
+                                           u32 num_reg_rules)
+{
+       u8 num_invalid_5ghz_rules = 0;
+       u32 count, start_freq;
+
+       for (count = 0; count < num_reg_rules; count++) {
+               start_freq = le32_get_bits(rule[count].freq_info, REG_RULE_START_FREQ);
+
+               if (start_freq >= ATH12K_MIN_6G_FREQ)
+                       num_invalid_5ghz_rules++;
+       }
+
+       return num_invalid_5ghz_rules;
+}
+
 static int ath12k_pull_reg_chan_list_ext_update_ev(struct ath12k_base *ab,
                                                   struct sk_buff *skb,
                                                   struct ath12k_reg_info *reg_info)
@@ -4691,6 +4707,7 @@ static int ath12k_pull_reg_chan_list_ext_update_ev(struct ath12k_base *ab,
        u32 num_2g_reg_rules, num_5g_reg_rules;
        u32 num_6g_reg_rules_ap[WMI_REG_CURRENT_MAX_AP_TYPE];
        u32 num_6g_reg_rules_cl[WMI_REG_CURRENT_MAX_AP_TYPE][WMI_REG_MAX_CLIENT_TYPE];
+       u8 num_invalid_5ghz_ext_rules;
        u32 total_reg_rules = 0;
        int ret, i, j;
 
@@ -4784,20 +4801,6 @@ static int ath12k_pull_reg_chan_list_ext_update_ev(struct ath12k_base *ab,
 
        memcpy(reg_info->alpha2, &ev->alpha2, REG_ALPHA2_LEN);
 
-       /* FIXME: Currently FW includes 6G reg rule also in 5G rule
-        * list for country US.
-        * Having same 6G reg rule in 5G and 6G rules list causes
-        * intersect check to be true, and same rules will be shown
-        * multiple times in iw cmd. So added hack below to avoid
-        * parsing 6G rule from 5G reg rule list, and this can be
-        * removed later, after FW updates to remove 6G reg rule
-        * from 5G rules list.
-        */
-       if (memcmp(reg_info->alpha2, "US", 2) == 0) {
-               reg_info->num_5g_reg_rules = REG_US_5G_NUM_REG_RULES;
-               num_5g_reg_rules = reg_info->num_5g_reg_rules;
-       }
-
        reg_info->dfs_region = le32_to_cpu(ev->dfs_region);
        reg_info->phybitmap = le32_to_cpu(ev->phybitmap);
        reg_info->num_phy = le32_to_cpu(ev->num_phy);
@@ -4900,8 +4903,29 @@ static int ath12k_pull_reg_chan_list_ext_update_ev(struct ath12k_base *ab,
                }
        }
 
+       ext_wmi_reg_rule += num_2g_reg_rules;
+
+       /* Firmware might include 6 GHz reg rule in 5 GHz rule list
+        * for few countries along with separate 6 GHz rule.
+        * Having same 6 GHz reg rule in 5 GHz and 6 GHz rules list
+        * causes intersect check to be true, and same rules will be
+        * shown multiple times in iw cmd.
+        * Hence, avoid parsing 6 GHz rule from 5 GHz reg rule list
+        */
+       num_invalid_5ghz_ext_rules = ath12k_wmi_ignore_num_extra_rules(ext_wmi_reg_rule,
+                                                                      num_5g_reg_rules);
+
+       if (num_invalid_5ghz_ext_rules) {
+               ath12k_dbg(ab, ATH12K_DBG_WMI,
+                          "CC: %s 5 GHz reg rules number %d from fw, %d number of invalid 5 GHz rules",
+                          reg_info->alpha2, reg_info->num_5g_reg_rules,
+                          num_invalid_5ghz_ext_rules);
+
+               num_5g_reg_rules = num_5g_reg_rules - num_invalid_5ghz_ext_rules;
+               reg_info->num_5g_reg_rules = num_5g_reg_rules;
+       }
+
        if (num_5g_reg_rules) {
-               ext_wmi_reg_rule += num_2g_reg_rules;
                reg_info->reg_rules_5g_ptr =
                        create_ext_reg_rules_from_wmi(num_5g_reg_rules,
                                                      ext_wmi_reg_rule);
@@ -4913,7 +4937,12 @@ static int ath12k_pull_reg_chan_list_ext_update_ev(struct ath12k_base *ab,
                }
        }
 
-       ext_wmi_reg_rule += num_5g_reg_rules;
+       /* We have adjusted the number of 5 GHz reg rules above. But still those
+        * many rules needs to be adjusted in ext_wmi_reg_rule.
+        *
+        * NOTE: num_invalid_5ghz_ext_rules will be 0 for rest other cases.
+        */
+       ext_wmi_reg_rule += (num_5g_reg_rules + num_invalid_5ghz_ext_rules);
 
        for (i = 0; i < WMI_REG_CURRENT_MAX_AP_TYPE; i++) {
                reg_info->reg_rules_6g_ap_ptr[i] =
index 6f55dbdf629dbe154fe81d6463e3a5d1ca506dcb..b16615b116ae71eff34f46bde59336e6108d7642 100644 (file)
@@ -3943,7 +3943,6 @@ struct ath12k_wmi_eht_rate_set_params {
 #define MAX_REG_RULES 10
 #define REG_ALPHA2_LEN 2
 #define MAX_6G_REG_RULES 5
-#define REG_US_5G_NUM_REG_RULES 4
 
 enum wmi_start_event_param {
        WMI_VDEV_START_RESP_EVENT = 0,