]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
accel/amdxdna: Poll MPNPU_PWAITMODE after requesting firmware suspend
authorLizhi Hou <lizhi.hou@amd.com>
Tue, 2 Dec 2025 16:54:27 +0000 (08:54 -0800)
committerLizhi Hou <lizhi.hou@amd.com>
Wed, 3 Dec 2025 00:31:14 +0000 (16:31 -0800)
After issuing a firmware suspend request, the driver must ensure that the
suspend operation has completed before proceeding. Add polling of the
MPNPU_PWAITMODE register to confirm that the firmware has fully entered
the suspended state. This prevents race conditions where subsequent
operations assume the firmware is idle before it has actually completed
its suspend sequence.

Reviewed-by: Mario Limonciello (AMD) <superm1@kernel.org>
Reviewed-by: Maciej Falkowski <maciej.falkowski@linux.intel.com>
Signed-off-by: Lizhi Hou <lizhi.hou@amd.com>
Link: https://patch.msgid.link/20251202165427.507414-1-lizhi.hou@amd.com
drivers/accel/amdxdna/aie2_message.c
drivers/accel/amdxdna/aie2_pci.h
drivers/accel/amdxdna/aie2_psp.c
drivers/accel/amdxdna/npu1_regs.c
drivers/accel/amdxdna/npu2_regs.c
drivers/accel/amdxdna/npu4_regs.c
drivers/accel/amdxdna/npu5_regs.c
drivers/accel/amdxdna/npu6_regs.c

index d493bb1c33606fb094cc162c4b9d1eedd3f116bb..fee3b0627aba04409dee296a29b38b9c17f63b25 100644 (file)
@@ -59,8 +59,15 @@ static int aie2_send_mgmt_msg_wait(struct amdxdna_dev_hdl *ndev,
 int aie2_suspend_fw(struct amdxdna_dev_hdl *ndev)
 {
        DECLARE_AIE2_MSG(suspend, MSG_OP_SUSPEND);
+       int ret;
 
-       return aie2_send_mgmt_msg_wait(ndev, &msg);
+       ret = aie2_send_mgmt_msg_wait(ndev, &msg);
+       if (ret) {
+               XDNA_ERR(ndev->xdna, "Failed to suspend fw, ret %d", ret);
+               return ret;
+       }
+
+       return aie2_psp_waitmode_poll(ndev->psp_hdl);
 }
 
 int aie2_resume_fw(struct amdxdna_dev_hdl *ndev)
index a5f9c42155d178766e6b59bc22d1043d66fb4e92..cc9f933f80b2fbb40c8082ce5386ee5dc4e37a36 100644 (file)
@@ -70,6 +70,7 @@ enum psp_reg_idx {
        PSP_INTR_REG = PSP_NUM_IN_REGS,
        PSP_STATUS_REG,
        PSP_RESP_REG,
+       PSP_PWAITMODE_REG,
        PSP_MAX_REGS /* Keep this at the end */
 };
 
@@ -290,6 +291,7 @@ int aie2_pm_set_mode(struct amdxdna_dev_hdl *ndev, enum amdxdna_power_mode_type
 struct psp_device *aie2m_psp_create(struct drm_device *ddev, struct psp_config *conf);
 int aie2_psp_start(struct psp_device *psp);
 void aie2_psp_stop(struct psp_device *psp);
+int aie2_psp_waitmode_poll(struct psp_device *psp);
 
 /* aie2_error.c */
 int aie2_error_async_events_alloc(struct amdxdna_dev_hdl *ndev);
index f28a060a88109beba6837d5244123558a43aedc1..3a7130577e3e280deb883c73ad596c707d4c93d0 100644 (file)
@@ -76,6 +76,21 @@ static int psp_exec(struct psp_device *psp, u32 *reg_vals)
        return 0;
 }
 
+int aie2_psp_waitmode_poll(struct psp_device *psp)
+{
+       struct amdxdna_dev *xdna = to_xdna_dev(psp->ddev);
+       u32 mode_reg;
+       int ret;
+
+       ret = readx_poll_timeout(readl, PSP_REG(psp, PSP_PWAITMODE_REG), mode_reg,
+                                (mode_reg & 0x1) == 1,
+                                PSP_POLL_INTERVAL, PSP_POLL_TIMEOUT);
+       if (ret)
+               XDNA_ERR(xdna, "fw waitmode reg error, ret %d", ret);
+
+       return ret;
+}
+
 void aie2_psp_stop(struct psp_device *psp)
 {
        u32 reg_vals[PSP_NUM_IN_REGS] = { PSP_RELEASE_TMR, };
index ec407f3b48fc79c42a94214ac634ae91817f1d6d..ebc6e28022971d8db9903c3656dd1d29b8029edb 100644 (file)
@@ -13,6 +13,7 @@
 #include "amdxdna_pci_drv.h"
 
 /* Address definition from NPU1 docs */
+#define MPNPU_PWAITMODE                        0x3010034
 #define MPNPU_PUB_SEC_INTR             0x3010090
 #define MPNPU_PUB_PWRMGMT_INTR         0x3010094
 #define MPNPU_PUB_SCRATCH2             0x30100A0
@@ -92,6 +93,7 @@ static const struct amdxdna_dev_priv npu1_dev_priv = {
                DEFINE_BAR_OFFSET(PSP_INTR_REG,   NPU1_PSP, MPNPU_PUB_SEC_INTR),
                DEFINE_BAR_OFFSET(PSP_STATUS_REG, NPU1_PSP, MPNPU_PUB_SCRATCH2),
                DEFINE_BAR_OFFSET(PSP_RESP_REG,   NPU1_PSP, MPNPU_PUB_SCRATCH3),
+               DEFINE_BAR_OFFSET(PSP_PWAITMODE_REG, NPU1_PSP, MPNPU_PWAITMODE),
        },
        .smu_regs_off   = {
                DEFINE_BAR_OFFSET(SMU_CMD_REG,  NPU1_SMU, MPNPU_PUB_SCRATCH5),
index 86f87d0d135408334ad658952684d0e5915e424d..ad0743fb06d511e191f39363253fecfdee1e623b 100644 (file)
@@ -13,6 +13,7 @@
 #include "amdxdna_pci_drv.h"
 
 /* NPU Public Registers on MpNPUAxiXbar (refer to Diag npu_registers.h) */
+#define MPNPU_PWAITMODE                0x301003C
 #define MPNPU_PUB_SEC_INTR             0x3010060
 #define MPNPU_PUB_PWRMGMT_INTR         0x3010064
 #define MPNPU_PUB_SCRATCH0             0x301006C
@@ -85,6 +86,7 @@ static const struct amdxdna_dev_priv npu2_dev_priv = {
                DEFINE_BAR_OFFSET(PSP_INTR_REG,   NPU2_PSP, MP0_C2PMSG_73),
                DEFINE_BAR_OFFSET(PSP_STATUS_REG, NPU2_PSP, MP0_C2PMSG_123),
                DEFINE_BAR_OFFSET(PSP_RESP_REG,   NPU2_REG, MPNPU_PUB_SCRATCH3),
+               DEFINE_BAR_OFFSET(PSP_PWAITMODE_REG, NPU2_REG, MPNPU_PWAITMODE),
        },
        .smu_regs_off   = {
                DEFINE_BAR_OFFSET(SMU_CMD_REG,  NPU2_SMU, MP1_C2PMSG_0),
index 986a5f28ba2452a1137a4ce31e9f09fb986a94ba..4ca21db70478263202db164dbcb1bc7df12c968d 100644 (file)
@@ -13,6 +13,7 @@
 #include "amdxdna_pci_drv.h"
 
 /* NPU Public Registers on MpNPUAxiXbar (refer to Diag npu_registers.h) */
+#define MPNPU_PWAITMODE                0x301003C
 #define MPNPU_PUB_SEC_INTR             0x3010060
 #define MPNPU_PUB_PWRMGMT_INTR         0x3010064
 #define MPNPU_PUB_SCRATCH0             0x301006C
@@ -116,6 +117,7 @@ static const struct amdxdna_dev_priv npu4_dev_priv = {
                DEFINE_BAR_OFFSET(PSP_INTR_REG,   NPU4_PSP, MP0_C2PMSG_73),
                DEFINE_BAR_OFFSET(PSP_STATUS_REG, NPU4_PSP, MP0_C2PMSG_123),
                DEFINE_BAR_OFFSET(PSP_RESP_REG,   NPU4_REG, MPNPU_PUB_SCRATCH3),
+               DEFINE_BAR_OFFSET(PSP_PWAITMODE_REG, NPU4_REG, MPNPU_PWAITMODE),
        },
        .smu_regs_off   = {
                DEFINE_BAR_OFFSET(SMU_CMD_REG,  NPU4_SMU, MP1_C2PMSG_0),
index 75ad97f0b9370737929c8d6fa1494e1bb65ce892..131080652ef08bd3d85cce3524178f63c8c6b275 100644 (file)
@@ -13,6 +13,7 @@
 #include "amdxdna_pci_drv.h"
 
 /* NPU Public Registers on MpNPUAxiXbar (refer to Diag npu_registers.h) */
+#define MPNPU_PWAITMODE                0x301003C
 #define MPNPU_PUB_SEC_INTR             0x3010060
 #define MPNPU_PUB_PWRMGMT_INTR         0x3010064
 #define MPNPU_PUB_SCRATCH0             0x301006C
@@ -85,6 +86,7 @@ static const struct amdxdna_dev_priv npu5_dev_priv = {
                DEFINE_BAR_OFFSET(PSP_INTR_REG,   NPU5_PSP, MP0_C2PMSG_73),
                DEFINE_BAR_OFFSET(PSP_STATUS_REG, NPU5_PSP, MP0_C2PMSG_123),
                DEFINE_BAR_OFFSET(PSP_RESP_REG,   NPU5_REG, MPNPU_PUB_SCRATCH3),
+               DEFINE_BAR_OFFSET(PSP_PWAITMODE_REG, NPU5_REG, MPNPU_PWAITMODE),
        },
        .smu_regs_off   = {
                DEFINE_BAR_OFFSET(SMU_CMD_REG,  NPU5_SMU, MP1_C2PMSG_0),
index 758dc013fe13ba5ff3a924eaaae78c3aca823636..1f71285655b2ae83f4e1d9a572cd6b8d9244328f 100644 (file)
@@ -13,6 +13,7 @@
 #include "amdxdna_pci_drv.h"
 
 /* NPU Public Registers on MpNPUAxiXbar (refer to Diag npu_registers.h) */
+#define MPNPU_PWAITMODE                0x301003C
 #define MPNPU_PUB_SEC_INTR             0x3010060
 #define MPNPU_PUB_PWRMGMT_INTR         0x3010064
 #define MPNPU_PUB_SCRATCH0             0x301006C
@@ -85,6 +86,7 @@ static const struct amdxdna_dev_priv npu6_dev_priv = {
                DEFINE_BAR_OFFSET(PSP_INTR_REG,   NPU6_PSP, MP0_C2PMSG_73),
                DEFINE_BAR_OFFSET(PSP_STATUS_REG, NPU6_PSP, MP0_C2PMSG_123),
                DEFINE_BAR_OFFSET(PSP_RESP_REG,   NPU6_REG, MPNPU_PUB_SCRATCH3),
+               DEFINE_BAR_OFFSET(PSP_PWAITMODE_REG, NPU6_REG, MPNPU_PWAITMODE),
        },
        .smu_regs_off   = {
                DEFINE_BAR_OFFSET(SMU_CMD_REG,  NPU6_SMU, MP1_C2PMSG_0),