[PATCH ath-next] wifi: ath12k: handle regulatory hints during mac registration

Aditya Kumar Singh posted 1 patch 4 months ago
There is a newer version of this series
drivers/net/wireless/ath/ath12k/core.c |  4 ++++
drivers/net/wireless/ath/ath12k/core.h |  1 +
drivers/net/wireless/ath/ath12k/mac.c  | 15 +++++++++++++++
drivers/net/wireless/ath/ath12k/reg.c  | 12 ++++++++++++
drivers/net/wireless/ath/ath12k/reg.h  |  2 ++
drivers/net/wireless/ath/ath12k/wmi.c  | 13 ++++++++++++-
6 files changed, 46 insertions(+), 1 deletion(-)
[PATCH ath-next] wifi: ath12k: handle regulatory hints during mac registration
Posted by Aditya Kumar Singh 4 months ago
If a regulatory notification is there in the system while the hardware is
being registered, it attempts to set the new regulatory country. However,
ath12k currently boots with a default country derived from the BDF. If this
default country differs from the one provided in the notification, a race
condition can occur while updating the regulatory information back to
userspace. This potentially leads to driver having the incorrect regulatory
applied.

For example, suppose the regulatory domain for France (FR) is already
applied, and then the driver is loaded with a BDF that has the United
States (US) country programmed. When the driver finishes loading, the
regulatory domain shown in phyX still reflects the US regulatory settings.
This is incorrect, as the driver had already received a notification for
FR during hardware registration, but failed to process it properly due to
the race condition.

The race condition exists during driver initialization and hardware
registration:
- On driver load, the firmware sends BDF-based country regulatory rules,
  which are stored in default_regd via ath12k_reg_handle_chan_list().

- During hardware registration, a regulatory notification is triggered
  through:
    ath12k_mac_hw_register()
      -> ieee80211_register_hw()
        -> wiphy_register()
          -> wiphy_regulatory_register()
            -> reg_call_notifier()

  This sends a country code to the firmware, which responds with updated
  regulatory rules.

- After registration, ath12k_mac_hw_register() calls ath12k_regd_update(),
  which copies default_regd and passes it to the upper layers.

The race occurs between the firmware's response and the execution of
ath12k_regd_update(). If the firmware's new rules are processed before the
update call, the correct values are used. Otherwise, outdated boot-time
country settings are exposed to userspace.

To resolve this issue, introduce a completion mechanism within the hardware
group (ah). Trigger this completion whenever a regulatory change is
requested from the firmware. Then, in ath12k_regd_update(), wait for the
firmware to complete its regulatory processing before proceeding with the
update.

This ensures that during driver load, the default country is processed
first. However, before ath12k_regd_update() is called, the new regulatory
notification will have already been received by the driver. As a result, it
will wait for the firmware's regulatory processing to complete, and only
the final, correct regulatory domain will be updated to userspace.

Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.4.1-00199-QCAHKSWPL_SILICONZ-1

Signed-off-by: Aditya Kumar Singh <aditya.kumar.singh@oss.qualcomm.com>
---
 drivers/net/wireless/ath/ath12k/core.c |  4 ++++
 drivers/net/wireless/ath/ath12k/core.h |  1 +
 drivers/net/wireless/ath/ath12k/mac.c  | 15 +++++++++++++++
 drivers/net/wireless/ath/ath12k/reg.c  | 12 ++++++++++++
 drivers/net/wireless/ath/ath12k/reg.h  |  2 ++
 drivers/net/wireless/ath/ath12k/wmi.c  | 13 ++++++++++++-
 6 files changed, 46 insertions(+), 1 deletion(-)

diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c
index ebc0560d40e3419130e4caf01c9b91bd9affb3bd..9c18a706dc3ae3b8c5b95d8575e778c8a9c898ba 100644
--- a/drivers/net/wireless/ath/ath12k/core.c
+++ b/drivers/net/wireless/ath/ath12k/core.c
@@ -1470,6 +1470,7 @@ static void ath12k_core_pre_reconfigure_recovery(struct ath12k_base *ab)
 			complete(&ar->vdev_setup_done);
 			complete(&ar->vdev_delete_done);
 			complete(&ar->bss_survey_done);
+			complete(&ar->regd_update_completed);
 
 			wake_up(&ar->dp.tx_empty_waitq);
 			idr_for_each(&ar->txmgmt_idr,
@@ -1509,6 +1510,9 @@ static void ath12k_update_11d(struct work_struct *work)
 		ar = pdev->ar;
 
 		memcpy(&ar->alpha2, &arg.alpha2, 2);
+
+		reinit_completion(&ar->regd_update_completed);
+
 		ret = ath12k_wmi_send_set_current_country_cmd(ar, &arg);
 		if (ret)
 			ath12k_warn(ar->ab,
diff --git a/drivers/net/wireless/ath/ath12k/core.h b/drivers/net/wireless/ath/ath12k/core.h
index 941db6e49d6eaeb03783f7714d433259d887820b..329f3e490a713b179413f73a4024448aedc363fd 100644
--- a/drivers/net/wireless/ath/ath12k/core.h
+++ b/drivers/net/wireless/ath/ath12k/core.h
@@ -804,6 +804,7 @@ struct ath12k {
 	enum ath12k_11d_state state_11d;
 	u8 alpha2[REG_ALPHA2_LEN];
 	bool regdom_set_by_user;
+	struct completion regd_update_completed;
 
 	struct completion fw_stats_complete;
 
diff --git a/drivers/net/wireless/ath/ath12k/mac.c b/drivers/net/wireless/ath/ath12k/mac.c
index 88b59f3ff87af8b48cb3fafcd364fd9ced4ff197..ef2e8398cbe8723c020aff03da5db7fa7fb2245e 100644
--- a/drivers/net/wireless/ath/ath12k/mac.c
+++ b/drivers/net/wireless/ath/ath12k/mac.c
@@ -10900,6 +10900,7 @@ ath12k_mac_op_reconfig_complete(struct ieee80211_hw *hw,
 			struct wmi_set_current_country_arg arg = {};
 
 			memcpy(&arg.alpha2, ar->alpha2, 2);
+			reinit_completion(&ar->regd_update_completed);
 			ath12k_wmi_send_set_current_country_cmd(ar, &arg);
 		}
 
@@ -12116,6 +12117,16 @@ static int ath12k_mac_hw_register(struct ath12k_hw *ah)
 		goto err_cleanup_if_combs;
 	}
 
+	/* Boot-time regulatory updates have already been processed.
+	 * Mark them as complete now, because after registration,
+	 * cfg80211 will notify us again if there are any pending hints.
+	 * We need to wait for those hints to be processed, so it's
+	 * important to mark the boot-time updates as complete before
+	 * proceeding with registration.
+	 */
+	for_each_ar(ah, ar, i)
+		complete(&ar->regd_update_completed);
+
 	ret = ieee80211_register_hw(hw);
 	if (ret) {
 		ath12k_err(ab, "ieee80211 registration failed: %d\n", ret);
@@ -12143,6 +12154,9 @@ static int ath12k_mac_hw_register(struct ath12k_hw *ah)
 
 			memcpy(&current_cc.alpha2, ab->new_alpha2, 2);
 			memcpy(&ar->alpha2, ab->new_alpha2, 2);
+
+			reinit_completion(&ar->regd_update_completed);
+
 			ret = ath12k_wmi_send_set_current_country_cmd(ar, &current_cc);
 			if (ret)
 				ath12k_warn(ar->ab,
@@ -12215,6 +12229,7 @@ static void ath12k_mac_setup(struct ath12k *ar)
 	init_completion(&ar->scan.on_channel);
 	init_completion(&ar->mlo_setup_done);
 	init_completion(&ar->completed_11d_scan);
+	init_completion(&ar->regd_update_completed);
 
 	INIT_DELAYED_WORK(&ar->scan.timeout, ath12k_scan_timeout_work);
 	wiphy_work_init(&ar->scan.vdev_clean_wk, ath12k_scan_vdev_clean_work);
diff --git a/drivers/net/wireless/ath/ath12k/reg.c b/drivers/net/wireless/ath/ath12k/reg.c
index 2598b39d5d7ee9b24ad8ed5d6de1bc5bbc6554e0..079dcb6d83df4eb487fb0dbf4088fb8cacca8f6e 100644
--- a/drivers/net/wireless/ath/ath12k/reg.c
+++ b/drivers/net/wireless/ath/ath12k/reg.c
@@ -102,6 +102,8 @@ ath12k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
 
 	/* Send the reg change request to all the radios */
 	for_each_ar(ah, ar, i) {
+		reinit_completion(&ar->regd_update_completed);
+
 		if (ar->ab->hw_params->current_cc_support) {
 			memcpy(&current_arg.alpha2, request->alpha2, 2);
 			memcpy(&ar->alpha2, &current_arg.alpha2, 2);
@@ -272,9 +274,19 @@ int ath12k_regd_update(struct ath12k *ar, bool init)
 	struct ieee80211_regdomain *regd, *regd_copy = NULL;
 	int ret, regd_len, pdev_id;
 	struct ath12k_base *ab;
+	long time_left;
 
 	ab = ar->ab;
 
+	time_left = wait_for_completion_timeout(&ar->regd_update_completed,
+						ATH12K_REG_UPDATE_TIMEOUT_HZ);
+	if (time_left == 0) {
+		ath12k_warn(ab, "Timeout while waiting for regulatory update");
+		/* Even though timeout has occurred, still continue since at least boot
+		 * time data would be there to process
+		 */
+	}
+
 	supported_bands = ar->pdev->cap.supported_bands;
 	reg_cap = &ab->hal_reg_cap[ar->pdev_idx];
 
diff --git a/drivers/net/wireless/ath/ath12k/reg.h b/drivers/net/wireless/ath/ath12k/reg.h
index 8af8e9ba462e90db3eb137885d0acd4b1cb2286e..fb508302c7f0f1fea2588ad4cf9d813da574d06b 100644
--- a/drivers/net/wireless/ath/ath12k/reg.h
+++ b/drivers/net/wireless/ath/ath12k/reg.h
@@ -13,6 +13,8 @@
 struct ath12k_base;
 struct ath12k;
 
+#define ATH12K_REG_UPDATE_TIMEOUT_HZ	(3 * HZ)
+
 #define ATH12K_2GHZ_MAX_FREQUENCY	2495
 #define ATH12K_5GHZ_MAX_FREQUENCY	5920
 
diff --git a/drivers/net/wireless/ath/ath12k/wmi.c b/drivers/net/wireless/ath/ath12k/wmi.c
index 60e2444fe08cefa39ae218d07eb9736d2a0c982b..047d7a0f0e7423759f7cf05dff4aafbd3b9697d7 100644
--- a/drivers/net/wireless/ath/ath12k/wmi.c
+++ b/drivers/net/wireless/ath/ath12k/wmi.c
@@ -6143,6 +6143,7 @@ static void ath12k_wmi_htc_tx_complete(struct ath12k_base *ab,
 static int ath12k_reg_chan_list_event(struct ath12k_base *ab, struct sk_buff *skb)
 {
 	struct ath12k_reg_info *reg_info;
+	struct ath12k *ar;
 	u8 pdev_idx;
 	int ret;
 
@@ -6198,7 +6199,7 @@ static int ath12k_reg_chan_list_event(struct ath12k_base *ab, struct sk_buff *sk
 	kfree(reg_info);
 
 	if (ret == ATH12K_REG_STATUS_VALID)
-		return ret;
+		goto out;
 
 fallback:
 	/* Fallback to older reg (by sending previous country setting
@@ -6212,6 +6213,16 @@ static int ath12k_reg_chan_list_event(struct ath12k_base *ab, struct sk_buff *sk
 	WARN_ON(1);
 
 out:
+	ar = ab->pdevs[pdev_idx].ar;
+
+	/* During the boot-time update, 'ar' might not be allocated,
+	 * so the completion cannot be marked at that point.
+	 * This boot-time update is handled in ath12k_mac_hw_register()
+	 * before registering the hardware.
+	 */
+	if (ar)
+		complete(&ar->regd_update_completed);
+
 	return ret;
 }
 

---
base-commit: 8270f43193a0d097659eca55e701fd6818708945
change-id: 20250522-handle_user_regd_update_hints_during_insmod-42c71ee7f386
Re: [PATCH ath-next] wifi: ath12k: handle regulatory hints during mac registration
Posted by kernel test robot 3 months, 4 weeks ago
Hi Aditya,

kernel test robot noticed the following build warnings:

[auto build test WARNING on 8270f43193a0d097659eca55e701fd6818708945]

url:    https://github.com/intel-lab-lkp/linux/commits/Aditya-Kumar-Singh/wifi-ath12k-handle-regulatory-hints-during-mac-registration/20250613-012106
base:   8270f43193a0d097659eca55e701fd6818708945
patch link:    https://lore.kernel.org/r/20250612-handle_user_regd_update_hints_during_insmod-v1-1-576bd0f6dbe0%40oss.qualcomm.com
patch subject: [PATCH ath-next] wifi: ath12k: handle regulatory hints during mac registration
config: um-allmodconfig (https://download.01.org/0day-ci/archive/20250613/202506131836.KoxnhWuQ-lkp@intel.com/config)
compiler: clang version 19.1.7 (https://github.com/llvm/llvm-project cd708029e0b2869e80abe31ddb175f7c35361f90)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20250613/202506131836.KoxnhWuQ-lkp@intel.com/reproduce)

If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202506131836.KoxnhWuQ-lkp@intel.com/

All warnings (new ones prefixed by >>):

   In file included from drivers/net/wireless/ath/ath12k/wmi.c:6:
   In file included from include/linux/skbuff.h:17:
   In file included from include/linux/bvec.h:10:
   In file included from include/linux/highmem.h:12:
   In file included from include/linux/hardirq.h:11:
   In file included from arch/um/include/asm/hardirq.h:5:
   In file included from include/asm-generic/hardirq.h:17:
   In file included from include/linux/irq.h:20:
   In file included from include/linux/io.h:12:
   In file included from arch/um/include/asm/io.h:24:
   include/asm-generic/io.h:1175:55: warning: performing pointer arithmetic on a null pointer has undefined behavior [-Wnull-pointer-arithmetic]
    1175 |         return (port > MMIO_UPPER_LIMIT) ? NULL : PCI_IOBASE + port;
         |                                                   ~~~~~~~~~~ ^
>> drivers/net/wireless/ath/ath12k/wmi.c:6169:13: warning: variable 'pdev_idx' is used uninitialized whenever 'if' condition is true [-Wsometimes-uninitialized]
    6169 |         } else if (ret == ATH12K_REG_STATUS_DROP) {
         |                    ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/net/wireless/ath/ath12k/wmi.c:6216:17: note: uninitialized use occurs here
    6216 |         ar = ab->pdevs[pdev_idx].ar;
         |                        ^~~~~~~~
   drivers/net/wireless/ath/ath12k/wmi.c:6169:9: note: remove the 'if' if its condition is always false
    6169 |         } else if (ret == ATH12K_REG_STATUS_DROP) {
         |                ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    6170 |                 /* reg info is valid but we will not store it and
         |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    6171 |                  * not going to create new regd for it
         |                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    6172 |                  */
         |                  ~~
    6173 |                 ret = ATH12K_REG_STATUS_VALID;
         |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    6174 |                 goto mem_free;
         |                 ~~~~~~~~~~~~~~
    6175 |         }
         |         ~
   drivers/net/wireless/ath/ath12k/wmi.c:6163:6: warning: variable 'pdev_idx' is used uninitialized whenever 'if' condition is true [-Wsometimes-uninitialized]
    6163 |         if (ret == ATH12K_REG_STATUS_FALLBACK) {
         |             ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
   drivers/net/wireless/ath/ath12k/wmi.c:6216:17: note: uninitialized use occurs here
    6216 |         ar = ab->pdevs[pdev_idx].ar;
         |                        ^~~~~~~~
   drivers/net/wireless/ath/ath12k/wmi.c:6163:2: note: remove the 'if' if its condition is always false
    6163 |         if (ret == ATH12K_REG_STATUS_FALLBACK) {
         |         ^~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    6164 |                 ath12k_warn(ab, "failed to validate reg info %d\n", ret);
         |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    6165 |                 /* firmware has successfully switches to new regd but host can not
         |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    6166 |                  * continue, so free reginfo and fallback to old regd
         |                  ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    6167 |                  */
         |                  ~~
    6168 |                 goto mem_free;
         |                 ~~~~~~~~~~~~~~
    6169 |         } else if (ret == ATH12K_REG_STATUS_DROP) {
         |         ~~~~~~
   drivers/net/wireless/ath/ath12k/wmi.c:6157:6: warning: variable 'pdev_idx' is used uninitialized whenever 'if' condition is true [-Wsometimes-uninitialized]
    6157 |         if (ret) {
         |             ^~~
   drivers/net/wireless/ath/ath12k/wmi.c:6216:17: note: uninitialized use occurs here
    6216 |         ar = ab->pdevs[pdev_idx].ar;
         |                        ^~~~~~~~
   drivers/net/wireless/ath/ath12k/wmi.c:6157:2: note: remove the 'if' if its condition is always false
    6157 |         if (ret) {
         |         ^~~~~~~~~~
    6158 |                 ath12k_warn(ab, "failed to extract regulatory info from received event\n");
         |                 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
    6159 |                 goto mem_free;
         |                 ~~~~~~~~~~~~~~
    6160 |         }
         |         ~
   drivers/net/wireless/ath/ath12k/wmi.c:6151:6: warning: variable 'pdev_idx' is used uninitialized whenever 'if' condition is true [-Wsometimes-uninitialized]
    6151 |         if (!reg_info) {
         |             ^~~~~~~~~
   drivers/net/wireless/ath/ath12k/wmi.c:6216:17: note: uninitialized use occurs here
    6216 |         ar = ab->pdevs[pdev_idx].ar;
         |                        ^~~~~~~~
   drivers/net/wireless/ath/ath12k/wmi.c:6151:2: note: remove the 'if' if its condition is always false
    6151 |         if (!reg_info) {
         |         ^~~~~~~~~~~~~~~~
    6152 |                 ret = -ENOMEM;
         |                 ~~~~~~~~~~~~~~
    6153 |                 goto fallback;
         |                 ~~~~~~~~~~~~~~
    6154 |         }
         |         ~
   drivers/net/wireless/ath/ath12k/wmi.c:6147:13: note: initialize the variable 'pdev_idx' to silence this warning
    6147 |         u8 pdev_idx;
         |                    ^
         |                     = '\0'
   5 warnings generated.


vim +6169 drivers/net/wireless/ath/ath12k/wmi.c

d889913205cf7e Kalle Valo         2022-11-28  6142  
d889913205cf7e Kalle Valo         2022-11-28  6143  static int ath12k_reg_chan_list_event(struct ath12k_base *ab, struct sk_buff *skb)
d889913205cf7e Kalle Valo         2022-11-28  6144  {
9e8e55c5832d4f Baochen Qiang      2025-04-18  6145  	struct ath12k_reg_info *reg_info;
e05f9e5c56466b Aditya Kumar Singh 2025-06-12  6146  	struct ath12k *ar;
eaa027a1d83f87 Baochen Qiang      2025-04-18  6147  	u8 pdev_idx;
9e8e55c5832d4f Baochen Qiang      2025-04-18  6148  	int ret;
d889913205cf7e Kalle Valo         2022-11-28  6149  
d889913205cf7e Kalle Valo         2022-11-28  6150  	reg_info = kzalloc(sizeof(*reg_info), GFP_ATOMIC);
d889913205cf7e Kalle Valo         2022-11-28  6151  	if (!reg_info) {
d889913205cf7e Kalle Valo         2022-11-28  6152  		ret = -ENOMEM;
d889913205cf7e Kalle Valo         2022-11-28  6153  		goto fallback;
d889913205cf7e Kalle Valo         2022-11-28  6154  	}
d889913205cf7e Kalle Valo         2022-11-28  6155  
d889913205cf7e Kalle Valo         2022-11-28  6156  	ret = ath12k_pull_reg_chan_list_ext_update_ev(ab, skb, reg_info);
d889913205cf7e Kalle Valo         2022-11-28  6157  	if (ret) {
d889913205cf7e Kalle Valo         2022-11-28  6158  		ath12k_warn(ab, "failed to extract regulatory info from received event\n");
75639b74351553 Baochen Qiang      2025-04-18  6159  		goto mem_free;
75639b74351553 Baochen Qiang      2025-04-18  6160  	}
75639b74351553 Baochen Qiang      2025-04-18  6161  
75639b74351553 Baochen Qiang      2025-04-18  6162  	ret = ath12k_reg_validate_reg_info(ab, reg_info);
75639b74351553 Baochen Qiang      2025-04-18  6163  	if (ret == ATH12K_REG_STATUS_FALLBACK) {
75639b74351553 Baochen Qiang      2025-04-18  6164  		ath12k_warn(ab, "failed to validate reg info %d\n", ret);
75639b74351553 Baochen Qiang      2025-04-18  6165  		/* firmware has successfully switches to new regd but host can not
75639b74351553 Baochen Qiang      2025-04-18  6166  		 * continue, so free reginfo and fallback to old regd
75639b74351553 Baochen Qiang      2025-04-18  6167  		 */
75639b74351553 Baochen Qiang      2025-04-18  6168  		goto mem_free;
75639b74351553 Baochen Qiang      2025-04-18 @6169  	} else if (ret == ATH12K_REG_STATUS_DROP) {
75639b74351553 Baochen Qiang      2025-04-18  6170  		/* reg info is valid but we will not store it and
75639b74351553 Baochen Qiang      2025-04-18  6171  		 * not going to create new regd for it
75639b74351553 Baochen Qiang      2025-04-18  6172  		 */
75639b74351553 Baochen Qiang      2025-04-18  6173  		ret = ATH12K_REG_STATUS_VALID;
75639b74351553 Baochen Qiang      2025-04-18  6174  		goto mem_free;
d889913205cf7e Kalle Valo         2022-11-28  6175  	}
d889913205cf7e Kalle Valo         2022-11-28  6176  
eaa027a1d83f87 Baochen Qiang      2025-04-18  6177  	/* free old reg_info if it exist */
eaa027a1d83f87 Baochen Qiang      2025-04-18  6178  	pdev_idx = reg_info->phy_id;
eaa027a1d83f87 Baochen Qiang      2025-04-18  6179  	if (ab->reg_info[pdev_idx]) {
eaa027a1d83f87 Baochen Qiang      2025-04-18  6180  		ath12k_reg_reset_reg_info(ab->reg_info[pdev_idx]);
eaa027a1d83f87 Baochen Qiang      2025-04-18  6181  		kfree(ab->reg_info[pdev_idx]);
eaa027a1d83f87 Baochen Qiang      2025-04-18  6182  	}
eaa027a1d83f87 Baochen Qiang      2025-04-18  6183  	/* reg_info is valid, we store it for later use
eaa027a1d83f87 Baochen Qiang      2025-04-18  6184  	 * even below regd build failed
eaa027a1d83f87 Baochen Qiang      2025-04-18  6185  	 */
eaa027a1d83f87 Baochen Qiang      2025-04-18  6186  	ab->reg_info[pdev_idx] = reg_info;
eaa027a1d83f87 Baochen Qiang      2025-04-18  6187  
fafa6ff0823b79 Baochen Qiang      2025-04-18  6188  	ret = ath12k_reg_handle_chan_list(ab, reg_info, WMI_VDEV_TYPE_UNSPEC,
fafa6ff0823b79 Baochen Qiang      2025-04-18  6189  					  IEEE80211_REG_UNSET_AP);
9e8e55c5832d4f Baochen Qiang      2025-04-18  6190  	if (ret) {
9e8e55c5832d4f Baochen Qiang      2025-04-18  6191  		ath12k_warn(ab, "failed to handle chan list %d\n", ret);
d889913205cf7e Kalle Valo         2022-11-28  6192  		goto fallback;
d889913205cf7e Kalle Valo         2022-11-28  6193  	}
d889913205cf7e Kalle Valo         2022-11-28  6194  
75639b74351553 Baochen Qiang      2025-04-18  6195  	goto out;
75639b74351553 Baochen Qiang      2025-04-18  6196  
75639b74351553 Baochen Qiang      2025-04-18  6197  mem_free:
75639b74351553 Baochen Qiang      2025-04-18  6198  	ath12k_reg_reset_reg_info(reg_info);
75639b74351553 Baochen Qiang      2025-04-18  6199  	kfree(reg_info);
75639b74351553 Baochen Qiang      2025-04-18  6200  
75639b74351553 Baochen Qiang      2025-04-18  6201  	if (ret == ATH12K_REG_STATUS_VALID)
e05f9e5c56466b Aditya Kumar Singh 2025-06-12  6202  		goto out;
d889913205cf7e Kalle Valo         2022-11-28  6203  
d889913205cf7e Kalle Valo         2022-11-28  6204  fallback:
d889913205cf7e Kalle Valo         2022-11-28  6205  	/* Fallback to older reg (by sending previous country setting
d889913205cf7e Kalle Valo         2022-11-28  6206  	 * again if fw has succeeded and we failed to process here.
d889913205cf7e Kalle Valo         2022-11-28  6207  	 * The Regdomain should be uniform across driver and fw. Since the
d889913205cf7e Kalle Valo         2022-11-28  6208  	 * FW has processed the command and sent a success status, we expect
d889913205cf7e Kalle Valo         2022-11-28  6209  	 * this function to succeed as well. If it doesn't, CTRY needs to be
d889913205cf7e Kalle Valo         2022-11-28  6210  	 * reverted at the fw and the old SCAN_CHAN_LIST cmd needs to be sent.
d889913205cf7e Kalle Valo         2022-11-28  6211  	 */
d889913205cf7e Kalle Valo         2022-11-28  6212  	/* TODO: This is rare, but still should also be handled */
d889913205cf7e Kalle Valo         2022-11-28  6213  	WARN_ON(1);
9e8e55c5832d4f Baochen Qiang      2025-04-18  6214  
75639b74351553 Baochen Qiang      2025-04-18  6215  out:
e05f9e5c56466b Aditya Kumar Singh 2025-06-12  6216  	ar = ab->pdevs[pdev_idx].ar;
e05f9e5c56466b Aditya Kumar Singh 2025-06-12  6217  
e05f9e5c56466b Aditya Kumar Singh 2025-06-12  6218  	/* During the boot-time update, 'ar' might not be allocated,
e05f9e5c56466b Aditya Kumar Singh 2025-06-12  6219  	 * so the completion cannot be marked at that point.
e05f9e5c56466b Aditya Kumar Singh 2025-06-12  6220  	 * This boot-time update is handled in ath12k_mac_hw_register()
e05f9e5c56466b Aditya Kumar Singh 2025-06-12  6221  	 * before registering the hardware.
e05f9e5c56466b Aditya Kumar Singh 2025-06-12  6222  	 */
e05f9e5c56466b Aditya Kumar Singh 2025-06-12  6223  	if (ar)
e05f9e5c56466b Aditya Kumar Singh 2025-06-12  6224  		complete(&ar->regd_update_completed);
e05f9e5c56466b Aditya Kumar Singh 2025-06-12  6225  
d889913205cf7e Kalle Valo         2022-11-28  6226  	return ret;
d889913205cf7e Kalle Valo         2022-11-28  6227  }
d889913205cf7e Kalle Valo         2022-11-28  6228  

-- 
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki