Skip to content

Commit 21d01db

Browse files
Wen Gongharshimogalapalli
authored andcommitted
wifi: ath11k: update channel list in worker when wait flag is set
commit 02aae8e upstream. 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 when wait flag is set, wait_for_completion_timeout() will be called during 11d/hw scan. 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. Tested-on: WCN6855 hw2.0 PCI WLAN.HSP.1.1-03125-QCAHSPSWPL_V1_V2_SILICONZ_LITE-3 Signed-off-by: Wen Gong <[email protected]> Co-developed-by: Kang Yang <[email protected]> Signed-off-by: Kang Yang <[email protected]> Reviewed-by: Aditya Kumar Singh <[email protected]> Link: https://patch.msgid.link/[email protected] Signed-off-by: Jeff Johnson <[email protected]> Signed-off-by: Harshit Mogalapalli <[email protected]> Signed-off-by: Greg Kroah-Hartman <[email protected]> (cherry picked from commit fa4abd439f275fb01c016930c1b5448b8aa6f481) Signed-off-by: Harshit Mogalapalli <[email protected]>
1 parent 21779ca commit 21d01db

File tree

6 files changed

+81
-28
lines changed

6 files changed

+81
-28
lines changed

drivers/net/wireless/ath/ath11k/core.c

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1972,6 +1972,7 @@ void ath11k_core_halt(struct ath11k *ar)
19721972
ath11k_mac_scan_finish(ar);
19731973
ath11k_mac_peer_cleanup_all(ar);
19741974
cancel_delayed_work_sync(&ar->scan.timeout);
1975+
cancel_work_sync(&ar->channel_update_work);
19751976
cancel_work_sync(&ar->regd_update_work);
19761977
cancel_work_sync(&ab->update_11d_work);
19771978

drivers/net/wireless/ath/ath11k/core.h

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -691,7 +691,7 @@ struct ath11k {
691691
struct mutex conf_mutex;
692692
/* protects the radio specific data like debug stats, ppdu_stats_info stats,
693693
* vdev_stop_status info, scan data, ath11k_sta info, ath11k_vif info,
694-
* channel context data, survey info, test mode data.
694+
* channel context data, survey info, test mode data, channel_update_queue.
695695
*/
696696
spinlock_t data_lock;
697697

@@ -749,6 +749,9 @@ struct ath11k {
749749
struct completion bss_survey_done;
750750

751751
struct work_struct regd_update_work;
752+
struct work_struct channel_update_work;
753+
/* protected with data_lock */
754+
struct list_head channel_update_queue;
752755

753756
struct work_struct wmi_mgmt_tx_work;
754757
struct sk_buff_head wmi_mgmt_tx_queue;

drivers/net/wireless/ath/ath11k/mac.c

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6367,6 +6367,7 @@ static void ath11k_mac_op_stop(struct ieee80211_hw *hw, bool suspend)
63676367
{
63686368
struct ath11k *ar = hw->priv;
63696369
struct htt_ppdu_stats_info *ppdu_stats, *tmp;
6370+
struct scan_chan_list_params *params;
63706371
int ret;
63716372

63726373
ath11k_mac_drain_tx(ar);
@@ -6382,6 +6383,7 @@ static void ath11k_mac_op_stop(struct ieee80211_hw *hw, bool suspend)
63826383
mutex_unlock(&ar->conf_mutex);
63836384

63846385
cancel_delayed_work_sync(&ar->scan.timeout);
6386+
cancel_work_sync(&ar->channel_update_work);
63856387
cancel_work_sync(&ar->regd_update_work);
63866388
cancel_work_sync(&ar->ab->update_11d_work);
63876389

@@ -6391,10 +6393,19 @@ static void ath11k_mac_op_stop(struct ieee80211_hw *hw, bool suspend)
63916393
}
63926394

63936395
spin_lock_bh(&ar->data_lock);
6396+
63946397
list_for_each_entry_safe(ppdu_stats, tmp, &ar->ppdu_stats_info, list) {
63956398
list_del(&ppdu_stats->list);
63966399
kfree(ppdu_stats);
63976400
}
6401+
6402+
while ((params = list_first_entry_or_null(&ar->channel_update_queue,
6403+
struct scan_chan_list_params,
6404+
list))) {
6405+
list_del(&params->list);
6406+
kfree(params);
6407+
}
6408+
63986409
spin_unlock_bh(&ar->data_lock);
63996410

64006411
rcu_assign_pointer(ar->ab->pdevs_active[ar->pdev_idx], NULL);
@@ -10194,6 +10205,7 @@ static const struct wiphy_iftype_ext_capab ath11k_iftypes_ext_capa[] = {
1019410205

1019510206
static void __ath11k_mac_unregister(struct ath11k *ar)
1019610207
{
10208+
cancel_work_sync(&ar->channel_update_work);
1019710209
cancel_work_sync(&ar->regd_update_work);
1019810210

1019910211
ieee80211_unregister_hw(ar->hw);
@@ -10593,6 +10605,8 @@ int ath11k_mac_allocate(struct ath11k_base *ab)
1059310605
init_completion(&ar->thermal.wmi_sync);
1059410606

1059510607
INIT_DELAYED_WORK(&ar->scan.timeout, ath11k_scan_timeout_work);
10608+
INIT_WORK(&ar->channel_update_work, ath11k_regd_update_chan_list_work);
10609+
INIT_LIST_HEAD(&ar->channel_update_queue);
1059610610
INIT_WORK(&ar->regd_update_work, ath11k_regd_update_work);
1059710611

1059810612
INIT_WORK(&ar->wmi_mgmt_tx_work, ath11k_mgmt_over_wmi_tx_work);

drivers/net/wireless/ath/ath11k/reg.c

Lines changed: 59 additions & 26 deletions
Original file line numberDiff line numberDiff line change
@@ -124,32 +124,7 @@ int ath11k_reg_update_chan_list(struct ath11k *ar, bool wait)
124124
struct channel_param *ch;
125125
enum nl80211_band band;
126126
int num_channels = 0;
127-
int i, ret, left;
128-
129-
if (wait && ar->state_11d != ATH11K_11D_IDLE) {
130-
left = wait_for_completion_timeout(&ar->completed_11d_scan,
131-
ATH11K_SCAN_TIMEOUT_HZ);
132-
if (!left) {
133-
ath11k_dbg(ar->ab, ATH11K_DBG_REG,
134-
"failed to receive 11d scan complete: timed out\n");
135-
ar->state_11d = ATH11K_11D_IDLE;
136-
}
137-
ath11k_dbg(ar->ab, ATH11K_DBG_REG,
138-
"11d scan wait left time %d\n", left);
139-
}
140-
141-
if (wait &&
142-
(ar->scan.state == ATH11K_SCAN_STARTING ||
143-
ar->scan.state == ATH11K_SCAN_RUNNING)) {
144-
left = wait_for_completion_timeout(&ar->scan.completed,
145-
ATH11K_SCAN_TIMEOUT_HZ);
146-
if (!left)
147-
ath11k_dbg(ar->ab, ATH11K_DBG_REG,
148-
"failed to receive hw scan complete: timed out\n");
149-
150-
ath11k_dbg(ar->ab, ATH11K_DBG_REG,
151-
"hw scan wait left time %d\n", left);
152-
}
127+
int i, ret = 0;
153128

154129
if (ar->state == ATH11K_STATE_RESTARTING)
155130
return 0;
@@ -231,6 +206,16 @@ int ath11k_reg_update_chan_list(struct ath11k *ar, bool wait)
231206
}
232207
}
233208

209+
if (wait) {
210+
spin_lock_bh(&ar->data_lock);
211+
list_add_tail(&params->list, &ar->channel_update_queue);
212+
spin_unlock_bh(&ar->data_lock);
213+
214+
queue_work(ar->ab->workqueue, &ar->channel_update_work);
215+
216+
return 0;
217+
}
218+
234219
ret = ath11k_wmi_send_scan_chan_list_cmd(ar, params);
235220
kfree(params);
236221

@@ -811,6 +796,54 @@ ath11k_reg_build_regd(struct ath11k_base *ab,
811796
return new_regd;
812797
}
813798

799+
void ath11k_regd_update_chan_list_work(struct work_struct *work)
800+
{
801+
struct ath11k *ar = container_of(work, struct ath11k,
802+
channel_update_work);
803+
struct scan_chan_list_params *params;
804+
struct list_head local_update_list;
805+
int left;
806+
807+
INIT_LIST_HEAD(&local_update_list);
808+
809+
spin_lock_bh(&ar->data_lock);
810+
list_splice_tail_init(&ar->channel_update_queue, &local_update_list);
811+
spin_unlock_bh(&ar->data_lock);
812+
813+
while ((params = list_first_entry_or_null(&local_update_list,
814+
struct scan_chan_list_params,
815+
list))) {
816+
if (ar->state_11d != ATH11K_11D_IDLE) {
817+
left = wait_for_completion_timeout(&ar->completed_11d_scan,
818+
ATH11K_SCAN_TIMEOUT_HZ);
819+
if (!left) {
820+
ath11k_dbg(ar->ab, ATH11K_DBG_REG,
821+
"failed to receive 11d scan complete: timed out\n");
822+
ar->state_11d = ATH11K_11D_IDLE;
823+
}
824+
825+
ath11k_dbg(ar->ab, ATH11K_DBG_REG,
826+
"reg 11d scan wait left time %d\n", left);
827+
}
828+
829+
if ((ar->scan.state == ATH11K_SCAN_STARTING ||
830+
ar->scan.state == ATH11K_SCAN_RUNNING)) {
831+
left = wait_for_completion_timeout(&ar->scan.completed,
832+
ATH11K_SCAN_TIMEOUT_HZ);
833+
if (!left)
834+
ath11k_dbg(ar->ab, ATH11K_DBG_REG,
835+
"failed to receive hw scan complete: timed out\n");
836+
837+
ath11k_dbg(ar->ab, ATH11K_DBG_REG,
838+
"reg hw scan wait left time %d\n", left);
839+
}
840+
841+
ath11k_wmi_send_scan_chan_list_cmd(ar, params);
842+
list_del(&params->list);
843+
kfree(params);
844+
}
845+
}
846+
814847
static bool ath11k_reg_is_world_alpha(char *alpha)
815848
{
816849
if (alpha[0] == '0' && alpha[1] == '0')

drivers/net/wireless/ath/ath11k/reg.h

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
/* SPDX-License-Identifier: BSD-3-Clause-Clear */
22
/*
33
* Copyright (c) 2019 The Linux Foundation. All rights reserved.
4-
* Copyright (c) 2022-2024 Qualcomm Innovation Center, Inc. All rights reserved.
4+
* Copyright (c) 2022-2025 Qualcomm Innovation Center, Inc. All rights reserved.
55
*/
66

77
#ifndef ATH11K_REG_H
@@ -33,6 +33,7 @@ void ath11k_reg_init(struct ath11k *ar);
3333
void ath11k_reg_reset_info(struct cur_regulatory_info *reg_info);
3434
void ath11k_reg_free(struct ath11k_base *ab);
3535
void ath11k_regd_update_work(struct work_struct *work);
36+
void ath11k_regd_update_chan_list_work(struct work_struct *work);
3637
struct ieee80211_regdomain *
3738
ath11k_reg_build_regd(struct ath11k_base *ab,
3839
struct cur_regulatory_info *reg_info, bool intersect,

drivers/net/wireless/ath/ath11k/wmi.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3817,6 +3817,7 @@ struct wmi_stop_scan_cmd {
38173817
};
38183818

38193819
struct scan_chan_list_params {
3820+
struct list_head list;
38203821
u32 pdev_id;
38213822
u16 nallchans;
38223823
struct channel_param ch_param[];

0 commit comments

Comments
 (0)