]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
wifi: ath12k: Add lock to protect the hardware state
authorKarthikeyan Periyasamy <quic_periyasa@quicinc.com>
Fri, 3 May 2024 10:34:37 +0000 (13:34 +0300)
committerKalle Valo <quic_kvalo@quicinc.com>
Fri, 3 May 2024 13:12:14 +0000 (16:12 +0300)
Currently, hardware state is not protected across the reconfigure
operations. However, in single wiphy models, multiple radio/links is
exposed as a MAC hardware (ieee80211_hw) through the driver hardware
abstraction (ath12k_hw) layer. In such scenario, we need to protect
hardware state across the multiple radio/link at the driver hardware
abstraction (ath12k_hw) layer. Therefore, introduce a new mutex in
the ath12k_hw layer.

Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.0.1-00029-QCAHKSWPL_SILICONZ-1

Signed-off-by: Karthikeyan Periyasamy <quic_periyasa@quicinc.com>
Acked-by: Jeff Johnson <quic_jjohnson@quicinc.com>
Signed-off-by: Kalle Valo <quic_kvalo@quicinc.com>
Link: https://msgid.link/20240425090307.3233434-4-quic_periyasa@quicinc.com
drivers/net/wireless/ath/ath12k/core.c
drivers/net/wireless/ath/ath12k/core.h
drivers/net/wireless/ath/ath12k/mac.c

index a685cfd6fd92f9aaabf96144fc8baae4369347e4..e9aabdb9341c3891d01b933b605f73fdbecbf8dd 100644 (file)
@@ -1048,6 +1048,8 @@ static void ath12k_core_post_reconfigure_recovery(struct ath12k_base *ab)
                if (!ah || ah->state == ATH12K_HW_STATE_OFF)
                        continue;
 
+               mutex_lock(&ah->hw_mutex);
+
                switch (ah->state) {
                case ATH12K_HW_STATE_ON:
                        ah->state = ATH12K_HW_STATE_RESTARTING;
@@ -1078,6 +1080,8 @@ static void ath12k_core_post_reconfigure_recovery(struct ath12k_base *ab)
                                    "device is wedged, will not restart hw %d\n", i);
                        break;
                }
+
+               mutex_unlock(&ah->hw_mutex);
        }
 
        complete(&ab->driver_recovery);
index c4eb8b25398c05b8750513889f4a30d7903b3441..d833361948b7306da61697e98f20b35cb388948e 100644 (file)
@@ -636,11 +636,17 @@ struct ath12k {
 struct ath12k_hw {
        struct ieee80211_hw *hw;
        struct ath12k_base *ab;
+
+       /* Protect the write operation of the hardware state ath12k_hw::state
+        * between hardware start<=>reconfigure<=>stop transitions.
+        */
+       struct mutex hw_mutex;
        enum ath12k_hw_state state;
        bool regd_updated;
        bool use_6ghz_regd;
        u8 num_radio;
 
+       /* Keep last */
        struct ath12k radio[] __aligned(sizeof(void *));
 };
 
index 0cb2e0435cc06524353035e356599b94f8971dfe..4f07ac8c0287c233bf4d0887a9fdc34a44290219 100644 (file)
@@ -5615,10 +5615,13 @@ static void ath12k_mac_wait_reconfigure(struct ath12k_base *ab)
 
 static int ath12k_mac_start(struct ath12k *ar)
 {
+       struct ath12k_hw *ah = ar->ah;
        struct ath12k_base *ab = ar->ab;
        struct ath12k_pdev *pdev = ar->pdev;
        int ret;
 
+       lockdep_assert_held(&ah->hw_mutex);
+
        mutex_lock(&ar->conf_mutex);
 
        ret = ath12k_wmi_pdev_set_param(ar, WMI_PDEV_PARAM_PMF_QOS,
@@ -5733,6 +5736,8 @@ static int ath12k_mac_op_start(struct ieee80211_hw *hw)
 
        ath12k_drain_tx(ah);
 
+       guard(mutex)(&ah->hw_mutex);
+
        switch (ah->state) {
        case ATH12K_HW_STATE_OFF:
                ah->state = ATH12K_HW_STATE_ON;
@@ -5831,9 +5836,12 @@ int ath12k_mac_rfkill_enable_radio(struct ath12k *ar, bool enable)
 
 static void ath12k_mac_stop(struct ath12k *ar)
 {
+       struct ath12k_hw *ah = ar->ah;
        struct htt_ppdu_stats_info *ppdu_stats, *tmp;
        int ret;
 
+       lockdep_assert_held(&ah->hw_mutex);
+
        mutex_lock(&ar->conf_mutex);
        ret = ath12k_mac_config_mon_status_default(ar, false);
        if (ret && (ret != -EOPNOTSUPP))
@@ -5869,10 +5877,14 @@ static void ath12k_mac_op_stop(struct ieee80211_hw *hw)
 
        ath12k_drain_tx(ah);
 
+       mutex_lock(&ah->hw_mutex);
+
        ah->state = ATH12K_HW_STATE_OFF;
 
        for_each_ar(ah, ar, i)
                ath12k_mac_stop(ar);
+
+       mutex_unlock(&ah->hw_mutex);
 }
 
 static u8
@@ -7931,6 +7943,8 @@ ath12k_mac_op_reconfig_complete(struct ieee80211_hw *hw,
        if (reconfig_type != IEEE80211_RECONFIG_TYPE_RESTART)
                return;
 
+       guard(mutex)(&ah->hw_mutex);
+
        if (ah->state != ATH12K_HW_STATE_RESTARTED)
                return;
 
@@ -8933,6 +8947,8 @@ static struct ath12k_hw *ath12k_mac_hw_allocate(struct ath12k_base *ab,
        ah->ab = ab;
        ah->num_radio = num_pdev_map;
 
+       mutex_init(&ah->hw_mutex);
+
        for (i = 0; i < num_pdev_map; i++) {
                ab = pdev_map[i].ab;
                pdev_idx = pdev_map[i].pdev_idx;