Search Linux Wireless

[PATCH 1/2] wifi: ath11k: move update channel list from update reg worker to reg notifier

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Currently ath11k call regulatory_set_wiphy_regd() in ath11k_regd_update()
to notify the reg domain change to cfg80211, and then ath11k update the
channel list to firmware by ath11k_reg_update_chan_list() immediately in
ath11k_regd_update(), they are running in two threads, it leads the channel
list data out of sync caused by muti-threads without synchronization.
cfg80211 calculate the flags of ieee80211_channel asynchronously in its
reg_work, it is calculated by the callstack below and ath11k get the
flags of ieee80211_channel in another thread without synchronization
for the channel list data.

callstack:
handle_channel_custom()
handle_band_custom()
reg_process_self_managed_hint()
reg_process_self_managed_hints()
reg_todo()

ath11k_reg_update_chan_list() need to use the flags calculated by the
reg_work, they are two thread and have no synchronization for the flags,
then ath11k_reg_update_chan_list() maybe get the wrong flags value before
the calculation finished.

The correct flow is ath11k_reg_update_chan_list() should be called after
the flags finished calculation by reg_work. reg_call_notifier() with
initiator type NL80211_REGDOM_SET_BY_DRIVER will be called by
reg_process_self_managed_hint() after the calculation finished.

So change to update channel list in ath11k_reg_notifier() for initiator
type NL80211_REGDOM_SET_BY_DRIVER, then the calculation of flags of
ieee80211_channel has already finished and ath11k_reg_update_chan_list()
will use the correct value of flags.

Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3

Fixes: f45cb6b29cd3 ("wifi: ath11k: avoid deadlock during regulatory update in ath11k_regd_update()")
Signed-off-by: Wen Gong <quic_wgong@xxxxxxxxxxx>
---
 drivers/net/wireless/ath/ath11k/reg.c | 18 ++++++++++++------
 1 file changed, 12 insertions(+), 6 deletions(-)

diff --git a/drivers/net/wireless/ath/ath11k/reg.c b/drivers/net/wireless/ath/ath11k/reg.c
index 6fae4e61ede7..f50740219202 100644
--- a/drivers/net/wireless/ath/ath11k/reg.c
+++ b/drivers/net/wireless/ath/ath11k/reg.c
@@ -55,6 +55,17 @@ ath11k_reg_notifier(struct wiphy *wiphy, struct regulatory_request *request)
 	ath11k_dbg(ar->ab, ATH11K_DBG_REG,
 		   "Regulatory Notification received for %s\n", wiphy_name(wiphy));
 
+	if ((request->initiator == NL80211_REGDOM_SET_BY_DRIVER) &&
+	    (ar->state == ATH11K_STATE_ON)) {
+		ath11k_dbg(ar->ab, ATH11K_DBG_REG,
+			   "dynamically updated by driver\n");
+		ret = ath11k_reg_update_chan_list(ar, true);
+		if (ret)
+			ath11k_warn(ar->ab, "failed to update channel list: %d\n", ret);
+
+		return;
+	}
+
 	/* Currently supporting only General User Hints. Cell base user
 	 * hints to be handled later.
 	 * Hints from other sources like Core, Beacons are not expected for
@@ -294,12 +305,6 @@ int ath11k_regd_update(struct ath11k *ar)
 	if (ret)
 		goto err;
 
-	if (ar->state == ATH11K_STATE_ON) {
-		ret = ath11k_reg_update_chan_list(ar, true);
-		if (ret)
-			goto err;
-	}
-
 	return 0;
 err:
 	ath11k_warn(ab, "failed to perform regd update : %d\n", ret);
@@ -743,6 +748,7 @@ void ath11k_regd_update_work(struct work_struct *work)
 void ath11k_reg_init(struct ath11k *ar)
 {
 	ar->hw->wiphy->regulatory_flags = REGULATORY_WIPHY_SELF_MANAGED;
+	ar->hw->wiphy->flags |= WIPHY_FLAG_NOTIFY_REGDOM_BY_DRIVER;
 	ar->hw->wiphy->reg_notifier = ath11k_reg_notifier;
 }
 
-- 
2.31.1




[Index of Archives]     [Linux Host AP]     [ATH6KL]     [Linux Wireless Personal Area Network]     [Linux Bluetooth]     [Wireless Regulations]     [Linux Netdev]     [Kernel Newbies]     [Linux Kernel]     [IDE]     [Git]     [Netfilter]     [Bugtraq]     [Yosemite Hiking]     [MIPS Linux]     [ARM Linux]     [Linux RAID]

  Powered by Linux