[PATCH 1/4] ASoC: amd: ps: guard adata->sdw dereferences with NULL check in IRQ handler
From: Vijendar Mukunda
Date: Sat Nov 07 2026 - 12:55:16 EST
The ACP external IRQ handler is registered before sdw_amd_probe() assigns
adata->sdw, so a stray interrupt in the probe window could reach the
adata->sdw->pdev[i] dereference with adata->sdw still NULL.
The same window exists on the teardown side: after sdw_amd_exit() frees
the context but before adata->sdw is cleared by the caller.
Add NULL checks for adata->sdw in acp63_irq_handler() before dereferencing
->pdev[0] and ->pdev[1], and in handle_acp70_sdw_wake_event() for the same
reason. The interrupt-status register write that acknowledges the IRQ is
kept outside the guard so the hardware bit is always cleared regardless of
whether the SoundWire context is live.
Fixes: e1cb350610ce ("ASoC: amd: ps: handle SoundWire interrupts in acp pci driver")
Signed-off-by: Vijendar Mukunda <Vijendar.Mukunda@xxxxxxx>
---
sound/soc/amd/ps/pci-ps.c | 32 ++++++++++++++++++++------------
1 file changed, 20 insertions(+), 12 deletions(-)
diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c
index b604db4942dd..d0b66df10157 100644
--- a/sound/soc/amd/ps/pci-ps.c
+++ b/sound/soc/amd/ps/pci-ps.c
@@ -26,16 +26,20 @@ static void handle_acp70_sdw_wake_event(struct acp63_dev_data *adata)
struct amd_sdw_manager *amd_manager;
if (adata->acp70_sdw0_wake_event) {
- amd_manager = dev_get_drvdata(&adata->sdw->pdev[0]->dev);
- if (amd_manager)
- pm_request_resume(amd_manager->dev);
+ if (adata->sdw) {
+ amd_manager = dev_get_drvdata(&adata->sdw->pdev[0]->dev);
+ if (amd_manager)
+ pm_request_resume(amd_manager->dev);
+ }
adata->acp70_sdw0_wake_event = 0;
}
if (adata->acp70_sdw1_wake_event) {
- amd_manager = dev_get_drvdata(&adata->sdw->pdev[1]->dev);
- if (amd_manager)
- pm_request_resume(amd_manager->dev);
+ if (adata->sdw) {
+ amd_manager = dev_get_drvdata(&adata->sdw->pdev[1]->dev);
+ if (amd_manager)
+ pm_request_resume(amd_manager->dev);
+ }
adata->acp70_sdw1_wake_event = 0;
}
}
@@ -209,18 +213,22 @@ static irqreturn_t acp63_irq_handler(int irq, void *dev_id)
ext_intr_stat = readl(adata->acp63_base + ACP_EXTERNAL_INTR_STAT);
if (ext_intr_stat & ACP_SDW0_STAT) {
writel(ACP_SDW0_STAT, adata->acp63_base + ACP_EXTERNAL_INTR_STAT);
- amd_manager = dev_get_drvdata(&adata->sdw->pdev[0]->dev);
- if (amd_manager)
- schedule_work(&amd_manager->amd_sdw_irq_thread);
+ if (adata->sdw) {
+ amd_manager = dev_get_drvdata(&adata->sdw->pdev[0]->dev);
+ if (amd_manager)
+ schedule_work(&amd_manager->amd_sdw_irq_thread);
+ }
irq_flag = 1;
}
ext_intr_stat1 = readl(adata->acp63_base + ACP_EXTERNAL_INTR_STAT1);
if (ext_intr_stat1 & ACP_SDW1_STAT) {
writel(ACP_SDW1_STAT, adata->acp63_base + ACP_EXTERNAL_INTR_STAT1);
- amd_manager = dev_get_drvdata(&adata->sdw->pdev[1]->dev);
- if (amd_manager)
- schedule_work(&amd_manager->amd_sdw_irq_thread);
+ if (adata->sdw) {
+ amd_manager = dev_get_drvdata(&adata->sdw->pdev[1]->dev);
+ if (amd_manager)
+ schedule_work(&amd_manager->amd_sdw_irq_thread);
+ }
irq_flag = 1;
}
--
2.53.0