[PATCH v2 3/6] platform/x86/amd/pmc: Propagate SMU errors and validate S2D address

From: Mario Limonciello

Date: Tue Jul 21 2026 - 17:28:04 EST


amd_stb_s2d_init() discards the return value of several S2D SMU commands.
When the SMU refuses a command (e.g. "SMU cmd failed. err: 0xff") the
failure is only noticed indirectly - if at all - and reported as -EIO,
masking the real error.

More seriously, the S2D_PHYS_ADDR_LOW/HIGH return values are ignored, so
on failure phys_addr_low/hi are left uninitialised and the assembled
address is passed straight to devm_ioremap(). When the SMU leaves them at
zero this maps physical address 0 and trips the ioremap-on-RAM warning:

amd_pmc AMDI000B:00: SMU cmd failed. err: 0xff
ioremap on RAM at 0x0000000000000000 - 0x0000000000ffffff
WARNING: CPU: 13 PID: 4592 at arch/x86/mm/ioremap.c:...

Check the return value of each SMU command and propagate it, and reject a
zero physical address before calling devm_ioremap().

Reported-by: Francis De Brabandere <francisdb@xxxxxxxxx>
Closes: https://bugzilla.kernel.org/show_bug.cgi?id=221759
Tested-by: Francis De Brabandere <francisdb@xxxxxxxxx>
Fixes: 3d7d407dfb05 ("platform/x86: amd-pmc: Add support for AMD Spill to DRAM STB feature")
Cc: stable@xxxxxxxxxxxxxxx
Signed-off-by: Mario Limonciello <mario.limonciello@xxxxxxx>
---
drivers/platform/x86/amd/pmc/mp1_stb.c | 31 +++++++++++++++++---------
1 file changed, 20 insertions(+), 11 deletions(-)

diff --git a/drivers/platform/x86/amd/pmc/mp1_stb.c b/drivers/platform/x86/amd/pmc/mp1_stb.c
index 90b8a5cebfa82..1ec0e599df7f3 100644
--- a/drivers/platform/x86/amd/pmc/mp1_stb.c
+++ b/drivers/platform/x86/amd/pmc/mp1_stb.c
@@ -311,30 +311,39 @@ int amd_stb_s2d_init(struct amd_pmc_dev *dev)
/* Spill to DRAM feature uses separate SMU message port */
dev->msg_port = MSG_PORT_S2D;

- amd_pmc_send_cmd(dev, S2D_TELEMETRY_SIZE, &size, dev->stb_arg.s2d_msg_id, true);
+ ret = amd_pmc_send_cmd(dev, S2D_TELEMETRY_SIZE, &size, dev->stb_arg.s2d_msg_id, true);
+ if (ret)
+ goto out;
if (size != S2D_TELEMETRY_BYTES_MAX) {
ret = -EIO;
goto out;
}

- /* Get DRAM size */
- ret = amd_pmc_send_cmd(dev, S2D_DRAM_SIZE, &dev->dram_size, dev->stb_arg.s2d_msg_id, true);
- if (ret || !dev->dram_size)
+ /* Get DRAM size; fall back to the default if the query fails */
+ if (amd_pmc_send_cmd(dev, S2D_DRAM_SIZE, &dev->dram_size, dev->stb_arg.s2d_msg_id, true) ||
+ !dev->dram_size)
dev->dram_size = S2D_TELEMETRY_DRAMBYTES_MAX;

/* Get STB DRAM address */
- amd_pmc_send_cmd(dev, S2D_PHYS_ADDR_LOW, &phys_addr_low, dev->stb_arg.s2d_msg_id, true);
- amd_pmc_send_cmd(dev, S2D_PHYS_ADDR_HIGH, &phys_addr_hi, dev->stb_arg.s2d_msg_id, true);
+ ret = amd_pmc_send_cmd(dev, S2D_PHYS_ADDR_LOW, &phys_addr_low,
+ dev->stb_arg.s2d_msg_id, true);
+ if (ret)
+ goto out;
+ ret = amd_pmc_send_cmd(dev, S2D_PHYS_ADDR_HIGH, &phys_addr_hi,
+ dev->stb_arg.s2d_msg_id, true);
+ if (ret)
+ goto out;

stb_phys_addr = ((u64)phys_addr_hi << 32 | phys_addr_low);
-
- dev->stb_virt_addr = devm_ioremap(dev->dev, stb_phys_addr, dev->dram_size);
- if (!dev->stb_virt_addr) {
- ret = -ENOMEM;
+ if (!stb_phys_addr) {
+ dev_err(dev->dev, "S2D phys addr query returned invalid address\n");
+ ret = -ENXIO;
goto out;
}

- ret = 0;
+ dev->stb_virt_addr = devm_ioremap(dev->dev, stb_phys_addr, dev->dram_size);
+ if (!dev->stb_virt_addr)
+ ret = -ENOMEM;

out:
/* Restore the default message port for subsequent SMU operations */
--
2.43.0