From f5755c23ed8a4603194f6425828a2760f814e117 Mon Sep 17 00:00:00 2001 From: Aditya Kumar Singh Date: Tue, 8 Apr 2025 11:36:37 +0530 Subject: [PATCH] wifi: ath12k: reset MLO global memory during recovery When operating with multiple devices grouped together, the firmware stores data related to the state machine of each partner device in the MLO global memory region. If the firmware crashes, it updates the state to 'crashed'. During recovery, this memory is shared with the firmware again, and upon detecting the 'crashed' state, it reasserts. This leads to a loop of firmware asserts and it never recovers. Hence to fix this issue, once all devices in the group have been asserted and powered down, reset the MLO global memory region. Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.3.1-00173-QCAHKSWPL_SILICONZ-1 Tested-on: QCN9274 hw2.0 PCI WLAN.WBE.1.4.1-00199-QCAHKSWPL_SILICONZ-1 Tested-on: WCN7850 hw2.0 PCI WLAN.HMT.1.0.c5-00481-QCAHMTSWPL_V1.0_V2.0_SILICONZ-3 Signed-off-by: Aditya Kumar Singh Reviewed-by: Vasanthakumar Thiagarajan Link: https://patch.msgid.link/20250408-fix_reboot_issues_with_hw_grouping-v4-9-95e7bf048595@oss.qualcomm.com Signed-off-by: Jeff Johnson --- drivers/net/wireless/ath/ath12k/core.c | 3 +++ drivers/net/wireless/ath/ath12k/qmi.c | 22 ++++++++++++++++++++++ drivers/net/wireless/ath/ath12k/qmi.h | 2 ++ 3 files changed, 27 insertions(+) diff --git a/drivers/net/wireless/ath/ath12k/core.c b/drivers/net/wireless/ath/ath12k/core.c index 55db189d82346..9b23329f1bf2a 100644 --- a/drivers/net/wireless/ath/ath12k/core.c +++ b/drivers/net/wireless/ath/ath12k/core.c @@ -1657,6 +1657,9 @@ static void ath12k_core_reset(struct work_struct *work) return; } + /* Prepare MLO global memory region for power up */ + ath12k_qmi_reset_mlo_mem(ag); + for (i = 0; i < ag->num_devices; i++) { ab = ag->ab[i]; if (!ab) diff --git a/drivers/net/wireless/ath/ath12k/qmi.c b/drivers/net/wireless/ath/ath12k/qmi.c index 7df6c6eebed68..c867130f1ddc8 100644 --- a/drivers/net/wireless/ath/ath12k/qmi.c +++ b/drivers/net/wireless/ath/ath12k/qmi.c @@ -2439,6 +2439,28 @@ out: return ret; } +void ath12k_qmi_reset_mlo_mem(struct ath12k_hw_group *ag) +{ + struct target_mem_chunk *mlo_chunk; + int i; + + lockdep_assert_held(&ag->mutex); + + if (!ag->mlo_mem.init_done || ag->num_started) + return; + + for (i = 0; i < ARRAY_SIZE(ag->mlo_mem.chunk); i++) { + mlo_chunk = &ag->mlo_mem.chunk[i]; + + if (mlo_chunk->v.addr) + /* TODO: Mode 0 recovery is the default mode hence resetting the + * whole memory region for now. Once Mode 1 support is added, this + * needs to be handled properly + */ + memset(mlo_chunk->v.addr, 0, mlo_chunk->size); + } +} + static void ath12k_qmi_free_mlo_mem_chunk(struct ath12k_base *ab, struct target_mem_chunk *chunk, int idx) diff --git a/drivers/net/wireless/ath/ath12k/qmi.h b/drivers/net/wireless/ath/ath12k/qmi.h index 7c44ced22c6f6..96e6c3daecfea 100644 --- a/drivers/net/wireless/ath/ath12k/qmi.h +++ b/drivers/net/wireless/ath/ath12k/qmi.h @@ -42,6 +42,7 @@ #define ATH12K_BOARD_ID_DEFAULT 0xFF struct ath12k_base; +struct ath12k_hw_group; enum ath12k_qmi_file_type { ATH12K_QMI_FILE_TYPE_BDF_GOLDEN = 0, @@ -622,5 +623,6 @@ void ath12k_qmi_deinit_service(struct ath12k_base *ab); int ath12k_qmi_init_service(struct ath12k_base *ab); void ath12k_qmi_free_resource(struct ath12k_base *ab); void ath12k_qmi_trigger_host_cap(struct ath12k_base *ab); +void ath12k_qmi_reset_mlo_mem(struct ath12k_hw_group *ag); #endif -- 2.50.1