[PATCH net] pds_core: fix cmd_regs access racing BAR unmap on reset
From: Nikhil P. Rao <hidden>
Date: 2026-07-29 05:53:23
Subsystem:
amd pds core driver, networking drivers, the rest · Maintainers:
Brett Creeley, Andrew Lunn, "David S. Miller", Eric Dumazet, Jakub Kicinski, Paolo Abeni, Linus Torvalds
pdsc_reset_prepare() and pdsc_reset_done()'s pdsc_map_bars() error path
clear/iounmap cmd_regs without devcmd_lock, and pdsc_firmware_update()'s
download loop derefs cmd_regs after dropping and retaking the lock
without re-checking. An FLR concurrent with a devlink flash can unmap
cmd_regs under an in-flight devcmd, causing a NULL deref or a write to
unmapped MMIO.
Take devcmd_lock across the BAR unmap/remap. Only the PF maps cmd_regs
and runs devcmd, so guard the locking to the PF.
pdsc_unmap_bars() also clears info_regs, which has its own readers under
config_lock (and a lockless debugfs reader); that teardown race is
pre-existing and handled separately.
Fixes: e96094c1d11c ("pds_core: Clear BARs on reset")
Reported-by: sashiko-bot <sashiko-bot@kernel.org>
Closes: https://sashiko.dev/#/patchset/20260708212222.296202-1-nikhil.rao%40amd.com?part=3
Assisted-by: Claude:claude-opus-4.8
Signed-off-by: Nikhil P. Rao <redacted>
---
drivers/net/ethernet/amd/pds_core/fw.c | 6 ++++++
drivers/net/ethernet/amd/pds_core/main.c | 10 +++++++++-
2 files changed, 15 insertions(+), 1 deletion(-)
diff --git a/drivers/net/ethernet/amd/pds_core/fw.c b/drivers/net/ethernet/amd/pds_core/fw.c
index fa626719e68d..cd7616ed9ef3 100644
--- a/drivers/net/ethernet/amd/pds_core/fw.c
+++ b/drivers/net/ethernet/amd/pds_core/fw.c@@ -134,6 +134,12 @@ int pdsc_firmware_update(struct pdsc *pdsc, const struct firmware *fw, copy_sz = min_t(unsigned int, buf_sz, fw->size - offset); mutex_lock(&pdsc->devcmd_lock); + if (!pdsc->cmd_regs) { + mutex_unlock(&pdsc->devcmd_lock); + err = -ENXIO; + NL_SET_ERR_MSG_MOD(extack, "Device reset during flash"); + goto err_out; + } memcpy_toio(&pdsc->cmd_regs->data, fw->data + offset, copy_sz); err = pdsc_devcmd_fw_download_locked(pdsc, data_addr, offset, copy_sz);
diff --git a/drivers/net/ethernet/amd/pds_core/main.c b/drivers/net/ethernet/amd/pds_core/main.c
index 8d94a4d70395..08af92b47d7d 100644
--- a/drivers/net/ethernet/amd/pds_core/main.c
+++ b/drivers/net/ethernet/amd/pds_core/main.c@@ -501,7 +501,13 @@ static void pdsc_reset_prepare(struct pci_dev *pdev) pdsc_auxbus_dev_del(pdsc, pdsc, &pdsc->padev); } - pdsc_unmap_bars(pdsc); + if (!pdev->is_virtfn) { + mutex_lock(&pdsc->devcmd_lock); + pdsc_unmap_bars(pdsc); + mutex_unlock(&pdsc->devcmd_lock); + } else { + pdsc_unmap_bars(pdsc); + } pci_release_regions(pdev); if (pci_is_enabled(pdev)) pci_disable_device(pdev);
@@ -530,7 +536,9 @@ static void pdsc_reset_done(struct pci_dev *pdev) return; } + mutex_lock(&pdsc->devcmd_lock); err = pdsc_map_bars(pdsc); + mutex_unlock(&pdsc->devcmd_lock); if (err) return; }
--
2.43.0