* [PATCH v4 0/2] wifi: ath11k: fix data out of sync for channel list for reg update
@ 2024-12-13 9:39 Kang Yang
2024-12-13 9:39 ` [PATCH v4 1/2] wifi: ath11k: move update channel list from update reg worker to reg notifier Kang Yang
2024-12-13 9:39 ` [PATCH v4 2/2] wifi: ath11k: move update channel list to worker when wait flag is set Kang Yang
0 siblings, 2 replies; 5+ messages in thread
From: Kang Yang @ 2024-12-13 9:39 UTC (permalink / raw)
To: ath11k; +Cc: linux-wireless, quic_kangyang
Currently there are two threads to updating/fetch data of channel
list, and there are no synchronization for the data, it leads data out
of sync for channel list when doing reg update.
So change the call flow to make sure the fetch data running after the
update data finished, then data of channel list become synchronization.
Note: This patch-set is an old patch-set in public review written by
Wen Gong. Just continue sending it for him.
Link: https://lore.kernel.org/linux-wireless/20230329091235.19500-1-quic_wgong@quicinc.com/
v4:
1. rewrite commit message in patch#1, #2.
2. use list_splice_tail_init() to move list entry.
3. use data_lock instead of adding a new lock.
v3:
1. rebase on tag ath-202411251703.
2. add KASAN BUG report in patch #1.
v2:
1. rewrite commit message for patch #1 and #2.
2. use a local list without the spinlock held for patch #2.
Wen Gong (2):
wifi: ath11k: move update channel list from update reg worker to reg
notifier
wifi: ath11k: move update channel list to worker when wait flag is set
drivers/net/wireless/ath/ath11k/core.c | 1 +
drivers/net/wireless/ath/ath11k/core.h | 4 +-
drivers/net/wireless/ath/ath11k/mac.c | 14 ++++
drivers/net/wireless/ath/ath11k/reg.c | 107 +++++++++++++++++--------
drivers/net/wireless/ath/ath11k/reg.h | 1 +
drivers/net/wireless/ath/ath11k/wmi.h | 1 +
6 files changed, 93 insertions(+), 35 deletions(-)
base-commit: 175616a7658cd5d53389d1f9c1ce22debd4595a5
--
2.34.1
^ permalink raw reply [flat|nested] 5+ messages in thread
* [PATCH v4 1/2] wifi: ath11k: move update channel list from update reg worker to reg notifier
2024-12-13 9:39 [PATCH v4 0/2] wifi: ath11k: fix data out of sync for channel list for reg update Kang Yang
@ 2024-12-13 9:39 ` Kang Yang
2024-12-17 14:46 ` Kalle Valo
2024-12-13 9:39 ` [PATCH v4 2/2] wifi: ath11k: move update channel list to worker when wait flag is set Kang Yang
1 sibling, 1 reply; 5+ messages in thread
From: Kang Yang @ 2024-12-13 9:39 UTC (permalink / raw)
To: ath11k; +Cc: linux-wireless, quic_kangyang
From: Wen Gong <quic_wgong@quicinc.com>
Currently when ath11k gets new channel list, it will mainly do two things
in ath11k_regd_update():
1. update channel list to cfg80211 by reg_work.
2. update cfg80211's channel list to firmware by
ath11k_reg_update_chan_list().
Flow:
ath11k_regd_update
->regulatory_set_wiphy_regd
-> schedule_work(®_work)
->reg_work->reg_process_self_managed_hint
->handle_band_custom(update to cfg80211)
-> ath11k_reg_update_chan_list(update to firmware)
But ath11k_reg_update_chan_list() is immediately called after reg_work
is queued. They are running in different threads. At this time,
ath11k_reg_update_chan_list() may use a wrong channel list because
handle_band_custom() may not be finished.
This may result in out-of-bounds write errors:
BUG: KASAN: slab-out-of-bounds in ath11k_reg_update_chan_list
Call Trace:
ath11k_reg_update_chan_list+0xbfe/0xfe0 [ath11k]
kfree+0x109/0x3a0
ath11k_regd_update+0x1cf/0x350 [ath11k]
ath11k_regd_update_work+0x14/0x20 [ath11k]
process_one_work+0xe35/0x14c0
So should make sure ath11k_reg_update_chan_list() is called after
handle_band_custom() is finished.
reg_process_self_managed_hint() will call reg_call_notifier() after
handle_band_custom(). This function will call ath11k_reg_notifier(), so
move ath11k_reg_update_chan_list() to ath11k_reg_notifier(). Then
ath11k can update correct channel list to firmware.
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@quicinc.com>
Signed-off-by: Kang Yang <quic_kangyang@quicinc.com>
---
drivers/net/wireless/ath/ath11k/reg.c | 20 ++++++++++++++------
1 file changed, 14 insertions(+), 6 deletions(-)
diff --git a/drivers/net/wireless/ath/ath11k/reg.c b/drivers/net/wireless/ath/ath11k/reg.c
index b0f289784dd3..cb2cf9b63d18 100644
--- a/drivers/net/wireless/ath/ath11k/reg.c
+++ b/drivers/net/wireless/ath/ath11k/reg.c
@@ -55,6 +55,19 @@ 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) {
+ ath11k_dbg(ar->ab, ATH11K_DBG_REG,
+ "driver initiated regd update\n");
+ if (ar->state != ATH11K_STATE_ON)
+ return;
+
+ 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
@@ -293,12 +306,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);
@@ -977,6 +984,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.34.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* [PATCH v4 2/2] wifi: ath11k: move update channel list to worker when wait flag is set
2024-12-13 9:39 [PATCH v4 0/2] wifi: ath11k: fix data out of sync for channel list for reg update Kang Yang
2024-12-13 9:39 ` [PATCH v4 1/2] wifi: ath11k: move update channel list from update reg worker to reg notifier Kang Yang
@ 2024-12-13 9:39 ` Kang Yang
2024-12-17 14:53 ` Kalle Valo
1 sibling, 1 reply; 5+ messages in thread
From: Kang Yang @ 2024-12-13 9:39 UTC (permalink / raw)
To: ath11k; +Cc: linux-wireless, quic_kangyang
From: Wen Gong <quic_wgong@quicinc.com>
With previous patch "wifi: ath11k: move update channel list from update
reg worker to reg notifier", ath11k_reg_update_chan_list() will be
called during reg_process_self_managed_hint().
reg_process_self_managed_hint() will hold rtnl_lock all the time.
But ath11k_reg_update_chan_list() may increase the occupation time of
rtnl_lock, because wait flag is set and wait_for_completion_timeout()
will be called when 11d/hw scan is running.
Should minimize the occupation time of rtnl_lock as much as possible.
Move update channel list operation to a new worker, so that
wait_for_completion_timeout() won't be called and will not increase the
occupation time of rtnl_lock.
Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3
Signed-off-by: Wen Gong <quic_wgong@quicinc.com>
Co-developed-by: Kang Yang <quic_kangyang@quicinc.com>
Signed-off-by: Kang Yang <quic_kangyang@quicinc.com>
---
drivers/net/wireless/ath/ath11k/core.c | 1 +
drivers/net/wireless/ath/ath11k/core.h | 4 +-
drivers/net/wireless/ath/ath11k/mac.c | 14 +++++
drivers/net/wireless/ath/ath11k/reg.c | 87 +++++++++++++++++---------
drivers/net/wireless/ath/ath11k/reg.h | 1 +
drivers/net/wireless/ath/ath11k/wmi.h | 1 +
6 files changed, 79 insertions(+), 29 deletions(-)
diff --git a/drivers/net/wireless/ath/ath11k/core.c b/drivers/net/wireless/ath/ath11k/core.c
index c576bbba52bf..e4db3cdecf29 100644
--- a/drivers/net/wireless/ath/ath11k/core.c
+++ b/drivers/net/wireless/ath/ath11k/core.c
@@ -2056,6 +2056,7 @@ void ath11k_core_halt(struct ath11k *ar)
ath11k_mac_scan_finish(ar);
ath11k_mac_peer_cleanup_all(ar);
cancel_delayed_work_sync(&ar->scan.timeout);
+ cancel_work_sync(&ar->channel_update_work);
cancel_work_sync(&ar->regd_update_work);
cancel_work_sync(&ab->update_11d_work);
diff --git a/drivers/net/wireless/ath/ath11k/core.h b/drivers/net/wireless/ath/ath11k/core.h
index a9dc7fe7765a..49c02cca501d 100644
--- a/drivers/net/wireless/ath/ath11k/core.h
+++ b/drivers/net/wireless/ath/ath11k/core.h
@@ -685,7 +685,7 @@ struct ath11k {
struct mutex conf_mutex;
/* protects the radio specific data like debug stats, ppdu_stats_info stats,
* vdev_stop_status info, scan data, ath11k_sta info, ath11k_vif info,
- * channel context data, survey info, test mode data.
+ * channel context data, survey info, test mode data, channel_update_queue.
*/
spinlock_t data_lock;
@@ -743,6 +743,8 @@ struct ath11k {
struct completion bss_survey_done;
struct work_struct regd_update_work;
+ struct work_struct channel_update_work;
+ struct list_head channel_update_queue;
struct work_struct wmi_mgmt_tx_work;
struct sk_buff_head wmi_mgmt_tx_queue;
diff --git a/drivers/net/wireless/ath/ath11k/mac.c b/drivers/net/wireless/ath/ath11k/mac.c
index 31ae9b384a29..ec59ac829f79 100644
--- a/drivers/net/wireless/ath/ath11k/mac.c
+++ b/drivers/net/wireless/ath/ath11k/mac.c
@@ -6288,6 +6288,7 @@ static void ath11k_mac_op_stop(struct ieee80211_hw *hw, bool suspend)
{
struct ath11k *ar = hw->priv;
struct htt_ppdu_stats_info *ppdu_stats, *tmp;
+ struct scan_chan_list_params *params;
int ret;
ath11k_mac_drain_tx(ar);
@@ -6303,6 +6304,7 @@ static void ath11k_mac_op_stop(struct ieee80211_hw *hw, bool suspend)
mutex_unlock(&ar->conf_mutex);
cancel_delayed_work_sync(&ar->scan.timeout);
+ cancel_work_sync(&ar->channel_update_work);
cancel_work_sync(&ar->regd_update_work);
cancel_work_sync(&ar->ab->update_11d_work);
@@ -6312,10 +6314,19 @@ static void ath11k_mac_op_stop(struct ieee80211_hw *hw, bool suspend)
}
spin_lock_bh(&ar->data_lock);
+
list_for_each_entry_safe(ppdu_stats, tmp, &ar->ppdu_stats_info, list) {
list_del(&ppdu_stats->list);
kfree(ppdu_stats);
}
+
+ while ((params = list_first_entry_or_null(&ar->channel_update_queue,
+ struct scan_chan_list_params,
+ list))) {
+ list_del(¶ms->list);
+ kfree(params);
+ }
+
spin_unlock_bh(&ar->data_lock);
rcu_assign_pointer(ar->ab->pdevs_active[ar->pdev_idx], NULL);
@@ -10018,6 +10029,7 @@ static const struct wiphy_iftype_ext_capab ath11k_iftypes_ext_capa[] = {
static void __ath11k_mac_unregister(struct ath11k *ar)
{
+ cancel_work_sync(&ar->channel_update_work);
cancel_work_sync(&ar->regd_update_work);
ieee80211_unregister_hw(ar->hw);
@@ -10417,6 +10429,8 @@ int ath11k_mac_allocate(struct ath11k_base *ab)
init_completion(&ar->thermal.wmi_sync);
INIT_DELAYED_WORK(&ar->scan.timeout, ath11k_scan_timeout_work);
+ INIT_WORK(&ar->channel_update_work, ath11k_regd_update_chan_list_work);
+ INIT_LIST_HEAD(&ar->channel_update_queue);
INIT_WORK(&ar->regd_update_work, ath11k_regd_update_work);
INIT_WORK(&ar->wmi_mgmt_tx_work, ath11k_mgmt_over_wmi_tx_work);
diff --git a/drivers/net/wireless/ath/ath11k/reg.c b/drivers/net/wireless/ath/ath11k/reg.c
index cb2cf9b63d18..9f27860fd93e 100644
--- a/drivers/net/wireless/ath/ath11k/reg.c
+++ b/drivers/net/wireless/ath/ath11k/reg.c
@@ -124,32 +124,7 @@ int ath11k_reg_update_chan_list(struct ath11k *ar, bool wait)
struct channel_param *ch;
enum nl80211_band band;
int num_channels = 0;
- int i, ret, left;
-
- if (wait && ar->state_11d != ATH11K_11D_IDLE) {
- left = wait_for_completion_timeout(&ar->completed_11d_scan,
- ATH11K_SCAN_TIMEOUT_HZ);
- if (!left) {
- ath11k_dbg(ar->ab, ATH11K_DBG_REG,
- "failed to receive 11d scan complete: timed out\n");
- ar->state_11d = ATH11K_11D_IDLE;
- }
- ath11k_dbg(ar->ab, ATH11K_DBG_REG,
- "11d scan wait left time %d\n", left);
- }
-
- if (wait &&
- (ar->scan.state == ATH11K_SCAN_STARTING ||
- ar->scan.state == ATH11K_SCAN_RUNNING)) {
- left = wait_for_completion_timeout(&ar->scan.completed,
- ATH11K_SCAN_TIMEOUT_HZ);
- if (!left)
- ath11k_dbg(ar->ab, ATH11K_DBG_REG,
- "failed to receive hw scan complete: timed out\n");
-
- ath11k_dbg(ar->ab, ATH11K_DBG_REG,
- "hw scan wait left time %d\n", left);
- }
+ int i, ret = 0;
if (ar->state == ATH11K_STATE_RESTARTING)
return 0;
@@ -231,8 +206,16 @@ int ath11k_reg_update_chan_list(struct ath11k *ar, bool wait)
}
}
- ret = ath11k_wmi_send_scan_chan_list_cmd(ar, params);
- kfree(params);
+ if (wait) {
+ spin_lock_bh(&ar->data_lock);
+ list_add_tail(¶ms->list, &ar->channel_update_queue);
+ spin_unlock_bh(&ar->data_lock);
+
+ queue_work(ar->ab->workqueue, &ar->channel_update_work);
+ } else {
+ ret = ath11k_wmi_send_scan_chan_list_cmd(ar, params);
+ kfree(params);
+ }
return ret;
}
@@ -811,6 +794,54 @@ ath11k_reg_build_regd(struct ath11k_base *ab,
return new_regd;
}
+void ath11k_regd_update_chan_list_work(struct work_struct *work)
+{
+ struct ath11k *ar = container_of(work, struct ath11k,
+ channel_update_work);
+ struct scan_chan_list_params *params;
+ struct list_head local_update_list;
+ int left;
+
+ INIT_LIST_HEAD(&local_update_list);
+
+ spin_lock_bh(&ar->data_lock);
+ list_splice_tail_init(&ar->channel_update_queue, &local_update_list);
+ spin_unlock_bh(&ar->data_lock);
+
+ while ((params = list_first_entry_or_null(&local_update_list,
+ struct scan_chan_list_params,
+ list))) {
+ if (ar->state_11d != ATH11K_11D_IDLE) {
+ left = wait_for_completion_timeout(&ar->completed_11d_scan,
+ ATH11K_SCAN_TIMEOUT_HZ);
+ if (!left) {
+ ath11k_dbg(ar->ab, ATH11K_DBG_REG,
+ "failed to receive 11d scan complete: timed out\n");
+ ar->state_11d = ATH11K_11D_IDLE;
+ }
+
+ ath11k_dbg(ar->ab, ATH11K_DBG_REG,
+ "reg 11d scan wait left time %d\n", left);
+ }
+
+ if ((ar->scan.state == ATH11K_SCAN_STARTING ||
+ ar->scan.state == ATH11K_SCAN_RUNNING)) {
+ left = wait_for_completion_timeout(&ar->scan.completed,
+ ATH11K_SCAN_TIMEOUT_HZ);
+ if (!left)
+ ath11k_dbg(ar->ab, ATH11K_DBG_REG,
+ "failed to receive hw scan complete: timed out\n");
+
+ ath11k_dbg(ar->ab, ATH11K_DBG_REG,
+ "reg hw scan wait left time %d\n", left);
+ }
+
+ ath11k_wmi_send_scan_chan_list_cmd(ar, params);
+ list_del(¶ms->list);
+ kfree(params);
+ }
+}
+
static bool ath11k_reg_is_world_alpha(char *alpha)
{
if (alpha[0] == '0' && alpha[1] == '0')
diff --git a/drivers/net/wireless/ath/ath11k/reg.h b/drivers/net/wireless/ath/ath11k/reg.h
index 263ea9061948..0d5e10bb5730 100644
--- a/drivers/net/wireless/ath/ath11k/reg.h
+++ b/drivers/net/wireless/ath/ath11k/reg.h
@@ -33,6 +33,7 @@ void ath11k_reg_init(struct ath11k *ar);
void ath11k_reg_reset_info(struct cur_regulatory_info *reg_info);
void ath11k_reg_free(struct ath11k_base *ab);
void ath11k_regd_update_work(struct work_struct *work);
+void ath11k_regd_update_chan_list_work(struct work_struct *work);
struct ieee80211_regdomain *
ath11k_reg_build_regd(struct ath11k_base *ab,
struct cur_regulatory_info *reg_info, bool intersect,
diff --git a/drivers/net/wireless/ath/ath11k/wmi.h b/drivers/net/wireless/ath/ath11k/wmi.h
index 8982b909c821..30b4b0c17682 100644
--- a/drivers/net/wireless/ath/ath11k/wmi.h
+++ b/drivers/net/wireless/ath/ath11k/wmi.h
@@ -3817,6 +3817,7 @@ struct wmi_stop_scan_cmd {
};
struct scan_chan_list_params {
+ struct list_head list;
u32 pdev_id;
u16 nallchans;
struct channel_param ch_param[];
--
2.34.1
^ permalink raw reply related [flat|nested] 5+ messages in thread
* Re: [PATCH v4 1/2] wifi: ath11k: move update channel list from update reg worker to reg notifier
2024-12-13 9:39 ` [PATCH v4 1/2] wifi: ath11k: move update channel list from update reg worker to reg notifier Kang Yang
@ 2024-12-17 14:46 ` Kalle Valo
0 siblings, 0 replies; 5+ messages in thread
From: Kalle Valo @ 2024-12-17 14:46 UTC (permalink / raw)
To: Kang Yang; +Cc: ath11k, linux-wireless
Kang Yang <quic_kangyang@quicinc.com> writes:
> From: Wen Gong <quic_wgong@quicinc.com>
>
> Currently when ath11k gets new channel list, it will mainly do two things
> in ath11k_regd_update():
> 1. update channel list to cfg80211 by reg_work.
> 2. update cfg80211's channel list to firmware by
> ath11k_reg_update_chan_list().
>
> Flow:
> ath11k_regd_update
> ->regulatory_set_wiphy_regd
> -> schedule_work(®_work)
> ->reg_work->reg_process_self_managed_hint
> ->handle_band_custom(update to cfg80211)
> -> ath11k_reg_update_chan_list(update to firmware)
>
> But ath11k_reg_update_chan_list() is immediately called after reg_work
> is queued. They are running in different threads. At this time,
> ath11k_reg_update_chan_list() may use a wrong channel list because
> handle_band_custom() may not be finished.
> This may result in out-of-bounds write errors:
> BUG: KASAN: slab-out-of-bounds in ath11k_reg_update_chan_list
> Call Trace:
> ath11k_reg_update_chan_list+0xbfe/0xfe0 [ath11k]
> kfree+0x109/0x3a0
> ath11k_regd_update+0x1cf/0x350 [ath11k]
> ath11k_regd_update_work+0x14/0x20 [ath11k]
> process_one_work+0xe35/0x14c0
>
> So should make sure ath11k_reg_update_chan_list() is called after
> handle_band_custom() is finished.
>
> reg_process_self_managed_hint() will call reg_call_notifier() after
> handle_band_custom(). This function will call ath11k_reg_notifier(), so
> move ath11k_reg_update_chan_list() to ath11k_reg_notifier(). Then
> ath11k can update correct channel list to firmware.
>
> 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@quicinc.com>
> Signed-off-by: Kang Yang <quic_kangyang@quicinc.com>
I think the commit message should be completely rewritten, the idea here
is not to list functions and their call orders.
--
https://patchwork.kernel.org/project/linux-wireless/list/
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
^ permalink raw reply [flat|nested] 5+ messages in thread
* Re: [PATCH v4 2/2] wifi: ath11k: move update channel list to worker when wait flag is set
2024-12-13 9:39 ` [PATCH v4 2/2] wifi: ath11k: move update channel list to worker when wait flag is set Kang Yang
@ 2024-12-17 14:53 ` Kalle Valo
0 siblings, 0 replies; 5+ messages in thread
From: Kalle Valo @ 2024-12-17 14:53 UTC (permalink / raw)
To: Kang Yang; +Cc: ath11k, linux-wireless
Kang Yang <quic_kangyang@quicinc.com> writes:
> From: Wen Gong <quic_wgong@quicinc.com>
>
> With previous patch "wifi: ath11k: move update channel list from update
> reg worker to reg notifier", ath11k_reg_update_chan_list() will be
> called during reg_process_self_managed_hint().
>
> reg_process_self_managed_hint() will hold rtnl_lock all the time.
> But ath11k_reg_update_chan_list() may increase the occupation time of
> rtnl_lock, because wait flag is set and wait_for_completion_timeout()
> will be called when 11d/hw scan is running.
>
> Should minimize the occupation time of rtnl_lock as much as possible.
>
> Move update channel list operation to a new worker, so that
> wait_for_completion_timeout() won't be called and will not increase the
> occupation time of rtnl_lock.
Maybe the last two paragraphs could be merged (and edited) like this:
We should minimize the occupation time of rtnl_lock as much as possible
to avoid interfering with rest of the system. So move the update channel
list operation to a new worker, so that wait_for_completion_timeout()
won't be called and will not increase the occupation time of rtnl_lock.
> --- a/drivers/net/wireless/ath/ath11k/core.h
> +++ b/drivers/net/wireless/ath/ath11k/core.h
> @@ -685,7 +685,7 @@ struct ath11k {
> struct mutex conf_mutex;
> /* protects the radio specific data like debug stats, ppdu_stats_info stats,
> * vdev_stop_status info, scan data, ath11k_sta info, ath11k_vif info,
> - * channel context data, survey info, test mode data.
> + * channel context data, survey info, test mode data, channel_update_queue.
> */
> spinlock_t data_lock;
Usually is best to add a comment the data you are protecting, in this
case the new fields in struct ath11k.
> @@ -743,6 +743,8 @@ struct ath11k {
> struct completion bss_survey_done;
>
> struct work_struct regd_update_work;
> + struct work_struct channel_update_work;
> + struct list_head channel_update_queue;
So here add '/* protected with data_lock */' or similar before channel_update_queue.
> @@ -231,8 +206,16 @@ int ath11k_reg_update_chan_list(struct ath11k *ar, bool wait)
> }
> }
>
> - ret = ath11k_wmi_send_scan_chan_list_cmd(ar, params);
> - kfree(params);
> + if (wait) {
> + spin_lock_bh(&ar->data_lock);
> + list_add_tail(¶ms->list, &ar->channel_update_queue);
> + spin_unlock_bh(&ar->data_lock);
> +
> + queue_work(ar->ab->workqueue, &ar->channel_update_work);
> + } else {
> + ret = ath11k_wmi_send_scan_chan_list_cmd(ar, params);
> + kfree(params);
> + }
You can avoid the else branch like this:
if (wait) {
spin_lock_bh(&ar->data_lock);
list_add_tail(¶ms->list, &ar->channel_update_queue);
spin_unlock_bh(&ar->data_lock);
queue_work(ar->ab->workqueue, &ar->channel_update_work);
return 0;
}
ret = ath11k_wmi_send_scan_chan_list_cmd(ar, params);
kfree(params);
--
https://patchwork.kernel.org/project/linux-wireless/list/
https://wireless.wiki.kernel.org/en/developers/documentation/submittingpatches
^ permalink raw reply [flat|nested] 5+ messages in thread
end of thread, other threads:[~2024-12-17 14:53 UTC | newest]
Thread overview: 5+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-12-13 9:39 [PATCH v4 0/2] wifi: ath11k: fix data out of sync for channel list for reg update Kang Yang
2024-12-13 9:39 ` [PATCH v4 1/2] wifi: ath11k: move update channel list from update reg worker to reg notifier Kang Yang
2024-12-17 14:46 ` Kalle Valo
2024-12-13 9:39 ` [PATCH v4 2/2] wifi: ath11k: move update channel list to worker when wait flag is set Kang Yang
2024-12-17 14:53 ` Kalle Valo
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).