wifi: ath12k: switch to using wiphy_lock() and remove ar->conf_mutex

Switch from using driver specific ar->conf_mutex to wiphy->mtx. The benefits are:

* one lock less and simplified locking

* possibility to use wiphy_work_queue() without other locks

Most of the mac80211 ops are called within wiphy_lock(), most notable exception
being tx op. This can be checked with lockdep_assert_wiphy() from
net/mac80211/driver-ops.[ch] and I veried that by manually going through all
the ops in ath12k_ops which had lockdep_assert_wiphy().

The conversion was simple:

* All conf_mutex lock() and unlock() calls which
  already were called under wiphy_lock() I replaced with
  lockdep_assert_wiphy().

* The rest of conf_mutex calls I replaced with wiphy_lock() and wiphy_unlock().

* All lockdep_asset_held(conf_mutex) calls I replaced with
  lockdep_assert_wiphy().

One exception was in ath12k_core_post_reconfigure_recovery() where the wiphy
lock needs to be taken before hw_mutex to avoid a lockdep warning.

Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3

Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
Link: https://patch.msgid.link/20241007165932.78081-4-kvalo@kernel.org
Signed-off-by: Jeff Johnson <quic_jjohnson@quicinc.com>
This commit is contained in:
Kalle Valo 2024-10-07 19:59:29 +03:00 committed by Jeff Johnson
parent 58550cdda9
commit b8c67509b9
7 changed files with 142 additions and 210 deletions

View File

@ -1004,7 +1004,7 @@ void ath12k_core_halt(struct ath12k *ar)
{
struct ath12k_base *ab = ar->ab;
lockdep_assert_held(&ar->conf_mutex);
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
ar->num_created_vdevs = 0;
ar->allocated_vdev_map = 0;
@ -1078,6 +1078,7 @@ static void ath12k_core_post_reconfigure_recovery(struct ath12k_base *ab)
if (!ah || ah->state == ATH12K_HW_STATE_OFF)
continue;
wiphy_lock(ah->hw->wiphy);
mutex_lock(&ah->hw_mutex);
switch (ah->state) {
@ -1086,10 +1087,7 @@ static void ath12k_core_post_reconfigure_recovery(struct ath12k_base *ab)
for (j = 0; j < ah->num_radio; j++) {
ar = &ah->radio[j];
mutex_lock(&ar->conf_mutex);
ath12k_core_halt(ar);
mutex_unlock(&ar->conf_mutex);
}
break;
@ -1110,6 +1108,7 @@ static void ath12k_core_post_reconfigure_recovery(struct ath12k_base *ab)
}
mutex_unlock(&ah->hw_mutex);
wiphy_unlock(ah->hw->wiphy);
}
complete(&ab->driver_recovery);

View File

@ -562,10 +562,7 @@ struct ath12k {
u32 num_stations;
u32 max_num_stations;
bool monitor_present;
/* To synchronize concurrent synchronous mac80211 callback operations,
* concurrent debugfs configuration and concurrent FW statistics events.
*/
struct mutex conf_mutex;
/* protects the radio specific data like debug stats, ppdu_stats_info stats,
* vdev_stop_status info, scan data, ath12k_sta info, ath12k_vif info,
* channel context data, survey info, test mode data.

View File

@ -15,14 +15,14 @@ static ssize_t ath12k_write_simulate_radar(struct file *file,
struct ath12k *ar = file->private_data;
int ret;
mutex_lock(&ar->conf_mutex);
wiphy_lock(ath12k_ar_to_hw(ar)->wiphy);
ret = ath12k_wmi_simulate_radar(ar);
if (ret)
goto exit;
ret = count;
exit:
mutex_unlock(&ar->conf_mutex);
wiphy_unlock(ath12k_ar_to_hw(ar)->wiphy);
return ret;
}

View File

@ -2750,9 +2750,9 @@ static ssize_t ath12k_read_htt_stats_type(struct file *file,
char buf[32];
size_t len;
mutex_lock(&ar->conf_mutex);
wiphy_lock(ath12k_ar_to_hw(ar)->wiphy);
type = ar->debug.htt_stats.type;
mutex_unlock(&ar->conf_mutex);
wiphy_unlock(ath12k_ar_to_hw(ar)->wiphy);
len = scnprintf(buf, sizeof(buf), "%u\n", type);
@ -2785,7 +2785,7 @@ static ssize_t ath12k_write_htt_stats_type(struct file *file,
type >= ATH12K_DBG_HTT_NUM_EXT_STATS)
return -EINVAL;
mutex_lock(&ar->conf_mutex);
wiphy_lock(ath12k_ar_to_hw(ar)->wiphy);
ar->debug.htt_stats.type = type;
ar->debug.htt_stats.cfg_param[0] = cfg_param[0];
@ -2793,7 +2793,7 @@ static ssize_t ath12k_write_htt_stats_type(struct file *file,
ar->debug.htt_stats.cfg_param[2] = cfg_param[2];
ar->debug.htt_stats.cfg_param[3] = cfg_param[3];
mutex_unlock(&ar->conf_mutex);
wiphy_unlock(ath12k_ar_to_hw(ar)->wiphy);
return count;
}
@ -2814,7 +2814,7 @@ static int ath12k_debugfs_htt_stats_req(struct ath12k *ar)
int ret, pdev_id;
struct htt_ext_stats_cfg_params cfg_params = { 0 };
lockdep_assert_held(&ar->conf_mutex);
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
init_completion(&stats_req->htt_stats_rcvd);
@ -2864,7 +2864,7 @@ static int ath12k_open_htt_stats(struct inode *inode,
if (type == ATH12K_DBG_HTT_EXT_STATS_RESET)
return -EPERM;
mutex_lock(&ar->conf_mutex);
wiphy_lock(ath12k_ar_to_hw(ar)->wiphy);
if (ah->state != ATH12K_HW_STATE_ON) {
ret = -ENETDOWN;
@ -2899,14 +2899,14 @@ static int ath12k_open_htt_stats(struct inode *inode,
file->private_data = stats_req;
mutex_unlock(&ar->conf_mutex);
wiphy_unlock(ath12k_ar_to_hw(ar)->wiphy);
return 0;
out:
kfree(stats_req);
ar->debug.htt_stats.stats_req = NULL;
err_unlock:
mutex_unlock(&ar->conf_mutex);
wiphy_unlock(ath12k_ar_to_hw(ar)->wiphy);
return ret;
}
@ -2916,10 +2916,10 @@ static int ath12k_release_htt_stats(struct inode *inode,
{
struct ath12k *ar = inode->i_private;
mutex_lock(&ar->conf_mutex);
wiphy_lock(ath12k_ar_to_hw(ar)->wiphy);
kfree(file->private_data);
ar->debug.htt_stats.stats_req = NULL;
mutex_unlock(&ar->conf_mutex);
wiphy_unlock(ath12k_ar_to_hw(ar)->wiphy);
return 0;
}
@ -2963,7 +2963,7 @@ static ssize_t ath12k_write_htt_stats_reset(struct file *file,
type == ATH12K_DBG_HTT_EXT_STATS_RESET)
return -E2BIG;
mutex_lock(&ar->conf_mutex);
wiphy_lock(ath12k_ar_to_hw(ar)->wiphy);
cfg_params.cfg0 = HTT_STAT_DEFAULT_RESET_START_OFFSET;
param_pos = (type >> 5) + 1;
@ -2989,12 +2989,12 @@ static ssize_t ath12k_write_htt_stats_reset(struct file *file,
0ULL);
if (ret) {
ath12k_warn(ar->ab, "failed to send htt stats request: %d\n", ret);
mutex_unlock(&ar->conf_mutex);
wiphy_unlock(ath12k_ar_to_hw(ar)->wiphy);
return ret;
}
ar->debug.htt_stats.reset = type;
mutex_unlock(&ar->conf_mutex);
wiphy_unlock(ath12k_ar_to_hw(ar)->wiphy);
return count;
}

File diff suppressed because it is too large Load Diff

View File

@ -1,7 +1,7 @@
// SPDX-License-Identifier: BSD-3-Clause-Clear
/*
* Copyright (c) 2018-2021 The Linux Foundation. All rights reserved.
* Copyright (c) 2021-2022 Qualcomm Innovation Center, Inc. All rights reserved.
* Copyright (c) 2021-2022, 2024 Qualcomm Innovation Center, Inc. All rights reserved.
*/
#include "core.h"
@ -186,7 +186,7 @@ void ath12k_peer_cleanup(struct ath12k *ar, u32 vdev_id)
struct ath12k_peer *peer, *tmp;
struct ath12k_base *ab = ar->ab;
lockdep_assert_held(&ar->conf_mutex);
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
spin_lock_bh(&ab->base_lock);
list_for_each_entry_safe(peer, tmp, &ab->peers, list) {
@ -235,7 +235,7 @@ int ath12k_peer_delete(struct ath12k *ar, u32 vdev_id, u8 *addr)
{
int ret;
lockdep_assert_held(&ar->conf_mutex);
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
reinit_completion(&ar->peer_delete_done);
@ -268,7 +268,7 @@ int ath12k_peer_create(struct ath12k *ar, struct ath12k_vif *arvif,
struct ath12k_peer *peer;
int ret;
lockdep_assert_held(&ar->conf_mutex);
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
if (ar->num_peers > (ar->max_num_peers - 1)) {
ath12k_warn(ar->ab,

View File

@ -132,7 +132,7 @@ static int ath12k_wow_cleanup(struct ath12k *ar)
struct ath12k_vif *arvif;
int ret;
lockdep_assert_held(&ar->conf_mutex);
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
list_for_each_entry(arvif, &ar->arvifs, list) {
ret = ath12k_wow_vif_cleanup(arvif);
@ -476,7 +476,7 @@ static int ath12k_wow_set_wakeups(struct ath12k *ar,
struct ath12k_vif *arvif;
int ret;
lockdep_assert_held(&ar->conf_mutex);
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
list_for_each_entry(arvif, &ar->arvifs, list) {
if (ath12k_wow_is_p2p_vdev(arvif))
@ -535,7 +535,7 @@ static int ath12k_wow_nlo_cleanup(struct ath12k *ar)
struct ath12k_vif *arvif;
int ret;
lockdep_assert_held(&ar->conf_mutex);
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
list_for_each_entry(arvif, &ar->arvifs, list) {
if (ath12k_wow_is_p2p_vdev(arvif))
@ -558,7 +558,7 @@ static int ath12k_wow_set_hw_filter(struct ath12k *ar)
struct ath12k_vif *arvif;
int ret;
lockdep_assert_held(&ar->conf_mutex);
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
list_for_each_entry(arvif, &ar->arvifs, list) {
if (arvif->vdev_type != WMI_VDEV_TYPE_STA)
@ -584,7 +584,7 @@ static int ath12k_wow_clear_hw_filter(struct ath12k *ar)
struct ath12k_vif *arvif;
int ret;
lockdep_assert_held(&ar->conf_mutex);
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
list_for_each_entry(arvif, &ar->arvifs, list) {
if (arvif->vdev_type != WMI_VDEV_TYPE_STA)
@ -735,7 +735,7 @@ static int ath12k_wow_arp_ns_offload(struct ath12k *ar, bool enable)
struct ath12k_vif *arvif;
int ret;
lockdep_assert_held(&ar->conf_mutex);
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
offload = kmalloc(sizeof(*offload), GFP_KERNEL);
if (!offload)
@ -769,7 +769,7 @@ static int ath12k_gtk_rekey_offload(struct ath12k *ar, bool enable)
struct ath12k_vif *arvif;
int ret;
lockdep_assert_held(&ar->conf_mutex);
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
list_for_each_entry(arvif, &ar->arvifs, list) {
if (arvif->vdev_type != WMI_VDEV_TYPE_STA ||
@ -827,7 +827,7 @@ static int ath12k_wow_set_keepalive(struct ath12k *ar,
struct ath12k_vif *arvif;
int ret;
lockdep_assert_held(&ar->conf_mutex);
lockdep_assert_wiphy(ath12k_ar_to_hw(ar)->wiphy);
list_for_each_entry(arvif, &ar->arvifs, list) {
ret = ath12k_mac_vif_set_keepalive(arvif, method, interval);
@ -845,7 +845,7 @@ int ath12k_wow_op_suspend(struct ieee80211_hw *hw,
struct ath12k *ar = ath12k_ah_to_ar(ah, 0);
int ret;
mutex_lock(&ar->conf_mutex);
lockdep_assert_wiphy(hw->wiphy);
ret = ath12k_wow_cleanup(ar);
if (ret) {
@ -913,7 +913,6 @@ int ath12k_wow_op_suspend(struct ieee80211_hw *hw,
ath12k_wow_cleanup(ar);
exit:
mutex_unlock(&ar->conf_mutex);
return ret ? 1 : 0;
}
@ -922,9 +921,9 @@ void ath12k_wow_op_set_wakeup(struct ieee80211_hw *hw, bool enabled)
struct ath12k_hw *ah = ath12k_hw_to_ah(hw);
struct ath12k *ar = ath12k_ah_to_ar(ah, 0);
mutex_lock(&ar->conf_mutex);
lockdep_assert_wiphy(hw->wiphy);
device_set_wakeup_enable(ar->ab->dev, enabled);
mutex_unlock(&ar->conf_mutex);
}
int ath12k_wow_op_resume(struct ieee80211_hw *hw)
@ -933,7 +932,7 @@ int ath12k_wow_op_resume(struct ieee80211_hw *hw)
struct ath12k *ar = ath12k_ah_to_ar(ah, 0);
int ret;
mutex_lock(&ar->conf_mutex);
lockdep_assert_wiphy(hw->wiphy);
ret = ath12k_hif_resume(ar->ab);
if (ret) {
@ -995,7 +994,6 @@ int ath12k_wow_op_resume(struct ieee80211_hw *hw)
}
}
mutex_unlock(&ar->conf_mutex);
return ret;
}