]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
wifi: ath12k: Refactor the hardware recovery procedure
authorKarthikeyan Periyasamy <quic_periyasa@quicinc.com>
Fri, 3 May 2024 10:34:36 +0000 (13:34 +0300)
committerKalle Valo <quic_kvalo@quicinc.com>
Fri, 3 May 2024 13:12:13 +0000 (16:12 +0300)
Currently, in multi-wiphy models, the recovery handler access mac80211
HW from the radio/link structure. This will be incorrect for single wiphy
model, as they will hold multiple link/radio structures. To fix this,
access mac80211 HW based on the number of hardware in the SoC/chip. This
approach makes the recovery handler compatible with both multi wiphy and
single wiphy models.

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-2-quic_periyasa@quicinc.com
drivers/net/wireless/ath/ath12k/core.c
drivers/net/wireless/ath/ath12k/mac.c

index 6663f4e1792de1f778d7f849a1a1594931e9e505..ae14614c3568a5bdace0d486e14c66d1bd9142f6 100644 (file)
@@ -994,9 +994,8 @@ void ath12k_core_halt(struct ath12k *ar)
 static void ath12k_core_pre_reconfigure_recovery(struct ath12k_base *ab)
 {
        struct ath12k *ar;
-       struct ath12k_pdev *pdev;
        struct ath12k_hw *ah;
-       int i;
+       int i, j;
 
        spin_lock_bh(&ab->base_lock);
        ab->stats.fw_crash_counter++;
@@ -1006,35 +1005,34 @@ static void ath12k_core_pre_reconfigure_recovery(struct ath12k_base *ab)
                set_bit(ATH12K_FLAG_CRASH_FLUSH, &ab->dev_flags);
 
        for (i = 0; i < ab->num_hw; i++) {
-               if (!ab->ah[i])
+               ah = ab->ah[i];
+               if (!ah)
                        continue;
 
-               ah = ab->ah[i];
                ieee80211_stop_queues(ah->hw);
-       }
 
-       for (i = 0; i < ab->num_radios; i++) {
-               pdev = &ab->pdevs[i];
-               ar = pdev->ar;
-               if (!ar || ar->state == ATH12K_STATE_OFF)
-                       continue;
+               for (j = 0; j < ah->num_radio; j++) {
+                       ar = &ah->radio[j];
+                       if (ar->state == ATH12K_STATE_OFF)
+                               continue;
 
-               ath12k_mac_drain_tx(ar);
-               complete(&ar->scan.started);
-               complete(&ar->scan.completed);
-               complete(&ar->scan.on_channel);
-               complete(&ar->peer_assoc_done);
-               complete(&ar->peer_delete_done);
-               complete(&ar->install_key_done);
-               complete(&ar->vdev_setup_done);
-               complete(&ar->vdev_delete_done);
-               complete(&ar->bss_survey_done);
-
-               wake_up(&ar->dp.tx_empty_waitq);
-               idr_for_each(&ar->txmgmt_idr,
-                            ath12k_mac_tx_mgmt_pending_free, ar);
-               idr_destroy(&ar->txmgmt_idr);
-               wake_up(&ar->txmgmt_empty_waitq);
+                       ath12k_mac_drain_tx(ar);
+                       complete(&ar->scan.started);
+                       complete(&ar->scan.completed);
+                       complete(&ar->scan.on_channel);
+                       complete(&ar->peer_assoc_done);
+                       complete(&ar->peer_delete_done);
+                       complete(&ar->install_key_done);
+                       complete(&ar->vdev_setup_done);
+                       complete(&ar->vdev_delete_done);
+                       complete(&ar->bss_survey_done);
+
+                       wake_up(&ar->dp.tx_empty_waitq);
+                       idr_for_each(&ar->txmgmt_idr,
+                                    ath12k_mac_tx_mgmt_pending_free, ar);
+                       idr_destroy(&ar->txmgmt_idr);
+                       wake_up(&ar->txmgmt_empty_waitq);
+               }
        }
 
        wake_up(&ab->wmi_ab.tx_credits_wq);
@@ -1043,41 +1041,52 @@ static void ath12k_core_pre_reconfigure_recovery(struct ath12k_base *ab)
 
 static void ath12k_core_post_reconfigure_recovery(struct ath12k_base *ab)
 {
+       struct ath12k_hw *ah;
        struct ath12k *ar;
-       struct ath12k_pdev *pdev;
-       int i;
+       int i, j;
+       u8 restart_count;
 
-       for (i = 0; i < ab->num_radios; i++) {
-               pdev = &ab->pdevs[i];
-               ar = pdev->ar;
-               if (!ar || ar->state == ATH12K_STATE_OFF)
+       for (i = 0; i < ab->num_hw; i++) {
+               ah = ab->ah[i];
+               if (!ah)
                        continue;
 
-               mutex_lock(&ar->conf_mutex);
-
-               switch (ar->state) {
-               case ATH12K_STATE_ON:
-                       ar->state = ATH12K_STATE_RESTARTING;
-                       ath12k_core_halt(ar);
-                       ieee80211_restart_hw(ath12k_ar_to_hw(ar));
-                       break;
-               case ATH12K_STATE_OFF:
-                       ath12k_warn(ab,
-                                   "cannot restart radio %d that hasn't been started\n",
-                                   i);
-                       break;
-               case ATH12K_STATE_RESTARTING:
-                       break;
-               case ATH12K_STATE_RESTARTED:
-                       ar->state = ATH12K_STATE_WEDGED;
-                       fallthrough;
-               case ATH12K_STATE_WEDGED:
-                       ath12k_warn(ab,
-                                   "device is wedged, will not restart radio %d\n", i);
-                       break;
+               for (j = 0, restart_count = 0; j < ah->num_radio; j++) {
+                       ar = &ah->radio[j];
+                       if (ar->state == ATH12K_STATE_OFF)
+                               continue;
+
+                       mutex_lock(&ar->conf_mutex);
+
+                       switch (ar->state) {
+                       case ATH12K_STATE_ON:
+                               ar->state = ATH12K_STATE_RESTARTING;
+                               ath12k_core_halt(ar);
+                               restart_count++;
+                               break;
+                       case ATH12K_STATE_OFF:
+                               ath12k_warn(ab,
+                                           "cannot restart radio %d that hasn't been started\n",
+                                           j);
+                               break;
+                       case ATH12K_STATE_RESTARTING:
+                               break;
+                       case ATH12K_STATE_RESTARTED:
+                               ar->state = ATH12K_STATE_WEDGED;
+                               fallthrough;
+                       case ATH12K_STATE_WEDGED:
+                               ath12k_warn(ab,
+                                           "device is wedged, will not restart radio %d\n", j);
+                               break;
+                       }
+                       mutex_unlock(&ar->conf_mutex);
                }
-               mutex_unlock(&ar->conf_mutex);
+
+               /* Restart after all the link/radio got restart */
+               if (restart_count == ah->num_radio)
+                       ieee80211_restart_hw(ah->hw);
        }
+
        complete(&ab->driver_recovery);
 }
 
index 805cb084484a4f6acfccc4faab6c54592b504d8d..6d19b6003aea2cffe8828cad18b4a37eea416c91 100644 (file)
@@ -7920,26 +7920,33 @@ ath12k_mac_op_reconfig_complete(struct ieee80211_hw *hw,
        struct ath12k *ar;
        struct ath12k_base *ab;
        struct ath12k_vif *arvif;
-       int recovery_count;
+       int recovery_count, i;
 
        if (reconfig_type != IEEE80211_RECONFIG_TYPE_RESTART)
                return;
 
-       ar = ath12k_ah_to_ar(ah, 0);
-       ab = ar->ab;
+       for_each_ar(ah, ar, i) {
+               mutex_lock(&ar->conf_mutex);
 
-       mutex_lock(&ar->conf_mutex);
+               if (ar->state != ATH12K_STATE_RESTARTED) {
+                       mutex_unlock(&ar->conf_mutex);
+                       continue;
+               }
+
+               ab = ar->ab;
 
-       if (ar->state == ATH12K_STATE_RESTARTED) {
                ath12k_warn(ar->ab, "pdev %d successfully recovered\n",
                            ar->pdev->pdev_id);
+
                ar->state = ATH12K_STATE_ON;
                ieee80211_wake_queues(hw);
 
                if (ab->is_reset) {
                        recovery_count = atomic_inc_return(&ab->recovery_count);
+
                        ath12k_dbg(ab, ATH12K_DBG_BOOT, "recovery count %d\n",
                                   recovery_count);
+
                        /* When there are multiple radios in an SOC,
                         * the recovery has to be done for each radio
                         */
@@ -7958,6 +7965,7 @@ ath12k_mac_op_reconfig_complete(struct ieee80211_hw *hw,
                                   arvif->key_cipher,
                                   arvif->is_up,
                                   arvif->vdev_type);
+
                        /* After trigger disconnect, then upper layer will
                         * trigger connect again, then the PN number of
                         * upper layer will be reset to keep up with AP
@@ -7967,13 +7975,14 @@ ath12k_mac_op_reconfig_complete(struct ieee80211_hw *hw,
                            arvif->vdev_type == WMI_VDEV_TYPE_STA &&
                            arvif->vdev_subtype == WMI_VDEV_SUBTYPE_NONE) {
                                ieee80211_hw_restart_disconnect(arvif->vif);
+
                                ath12k_dbg(ab, ATH12K_DBG_BOOT,
                                           "restart disconnect\n");
                        }
                }
-       }
 
-       mutex_unlock(&ar->conf_mutex);
+               mutex_unlock(&ar->conf_mutex);
+       }
 }
 
 static void