From: sashiko-bot@kernel.org
To: "Corey Smith" <corsmith@gmail.com>
Cc: linux-sound@vger.kernel.org
Subject: Re: [PATCH 10/11] ASoC: amd: ps: harden the ACP interrupt path for ACP6x
Date: Wed, 28 Oct 2026 02:21:02 +0000 [thread overview]
Message-ID: <sashiko-outbox-187339@kernel.org> (raw)
In-Reply-To: <20261028020552.35278-11-corsmith@gmail.com>
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] ASoC: amd: ps: unacknowledged DMA IRQ and NULL sdw_data in acp63_irq_handler()
- [High] ASoC: amd: ps: NULL sdw->pdev[i] dereference in acp63_irq_handler()
--
commit 00d5bef454b30567a1333bcc6ac7ae59904adf98
Author: Corey Smith <corsmith@gmail.com>
ASoC: amd: ps: harden the ACP interrupt path for ACP6x
This commit adds NULL checks for adata->sdw, adata->pdm_dev, and
adata->sdw_dma_dev in acp63_irq_handler(), and extends
check_and_handle_sdw_dma_irq() to handle ACP6X_PCI_REV and ACP6XR_PCI_REV.
> diff --git a/sound/soc/amd/ps/pci-ps.c b/sound/soc/amd/ps/pci-ps.c
> index 235cb1ef25f14..b06b399060288 100644
> --- a/sound/soc/amd/ps/pci-ps.c
> +++ b/sound/soc/amd/ps/pci-ps.c
[ ... ]
> @@ -209,18 +213,28 @@ 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);
> + /*
> + * The handler may run before the SoundWire manager devices
> + * have been created (shared IRQ lines can fire as soon as
> + * they are registered, and the ACP interrupts are enabled by
> + * acp_hw_init() before create_acp63_platform_devs() runs).
> + */
> + 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;
> }
[Severity: High]
Can adata->sdw->pdev[0] or adata->sdw->pdev[1] still be NULL here when
adata->sdw is non-NULL?
In drivers/soundwire/amd_init.c:sdw_amd_probe_controller(), ctx->pdev[index]
is only registered for links enabled in link_mask:
for (index = 0; index < count; index++) {
if (!(link_mask & BIT(index)))
continue;
...
ctx->pdev[index] = platform_device_register_full(&pdevinfo[index]);
On single-link platforms where only one link is set in link_mask (for example,
link_mask == BIT(0) where adata->sdw->pdev[1] remains NULL), if a pending or
spurious ACP_SDW1_STAT or ACP_SDW0_STAT bit is set in ACP_EXTERNAL_INTR_STAT1
or ACP_EXTERNAL_INTR_STAT, acp63_irq_handler() will pass the adata->sdw check
and pass &adata->sdw->pdev[i]->dev to dev_get_drvdata(), dereferencing a NULL
pdev[i] pointer in hard IRQ context.
Note that handle_acp70_sdw_wake_event() in sound/soc/amd/ps/pci-ps.c (called
from acp63_irq_handler() -> check_and_handle_acp70_sdw_wake_irq()) also
dereferences adata->sdw->pdev[0] and adata->sdw->pdev[1] without checking
adata->sdw or adata->sdw->pdev[i] first, whereas
handle_acp63_sdw_pme_event() in sound/soc/amd/ps/ps-common.c checks both
adata->sdw and adata->sdw->pdev[i]. Should both acp63_irq_handler() and
handle_acp70_sdw_wake_event() check adata->sdw->pdev[i] before calling
dev_get_drvdata()?
> @@ -237,16 +251,22 @@ static irqreturn_t acp63_irq_handler(int irq, void *dev_id)
> wake_irq_flag = check_and_handle_acp70_sdw_wake_irq(adata);
>
> if (ext_intr_stat & BIT(PDM_DMA_STAT)) {
> - ps_pdm_data = dev_get_drvdata(&adata->pdm_dev->dev);
> writel(BIT(PDM_DMA_STAT), adata->acp63_base + ACP_EXTERNAL_INTR_STAT);
> - if (ps_pdm_data->capture_stream)
> - snd_pcm_period_elapsed(ps_pdm_data->capture_stream);
> + if (adata->pdm_dev) {
> + ps_pdm_data = dev_get_drvdata(&adata->pdm_dev->dev);
> + if (ps_pdm_data && ps_pdm_data->capture_stream)
> + snd_pcm_period_elapsed(ps_pdm_data->capture_stream);
> + }
> irq_flag = 1;
> }
>
> - sdw_dma_irq_flag = check_and_handle_sdw_dma_irq(adata, ext_intr_stat, ext_intr_stat1);
> - if (sdw_dma_irq_flag)
> - return IRQ_WAKE_THREAD;
> + /* The SoundWire DMA device may not exist yet during probe */
> + if (adata->sdw_dma_dev) {
> + sdw_dma_irq_flag = check_and_handle_sdw_dma_irq(adata, ext_intr_stat,
> + ext_intr_stat1);
> + if (sdw_dma_irq_flag)
> + return IRQ_WAKE_THREAD;
> + }
[Severity: High]
Does skipping check_and_handle_sdw_dma_irq() when adata->sdw_dma_dev is NULL
leave pending SoundWire DMA interrupt bits uncleared, and can waking the IRQ
thread as soon as adata->sdw_dma_dev is non-NULL dereference a NULL sdw_data?
Unlike the ACP_SDW0_STAT, ACP_SDW1_STAT, and BIT(PDM_DMA_STAT) branches above,
which clear their status bits in ACP_EXTERNAL_INTR_STAT /
ACP_EXTERNAL_INTR_STAT1 before checking the device pointers, the writel()
calls that clear the SoundWire DMA interrupt status bits are inside
check_and_handle_sdw_dma_irq():
if (ext_intr_stat & ACP63_SDW_DMA_IRQ_MASK) {
for (index = ACP_AUDIO2_RX_THRESHOLD; index <= ACP_AUDIO0_TX_THRESHOLD; index++) {
if (ext_intr_stat & BIT(index)) {
writel(BIT(index), adata->acp63_base + ACP_EXTERNAL_INTR_STAT);
If a SoundWire DMA interrupt bit is pending while adata->sdw_dma_dev is NULL
(during snd_acp63_probe() before create_acp63_platform_devs(), or on a
PDM-only configuration), skipping check_and_handle_sdw_dma_irq() leaves the
hardware status bit asserted and returns IRQ_NONE on a shared level-triggered
PCI interrupt line, causing an unhandled interrupt storm.
Furthermore, in sound/soc/amd/ps/pci-ps.c:create_acp63_platform_devs():
adata->sdw_dma_dev = platform_device_register_full(&pdevinfo);
adata->sdw_dma_dev becomes non-NULL before the amd_ps_sdw_dma driver
(acp63_sdw_platform_probe() in sound/soc/amd/ps/ps-sdw-dma.c, which may be in
a separate module) binds to the device and sets drvdata (or holds an ERR_PTR
if registration fails). Because this patch also adds ACP6X_PCI_REV and
ACP6XR_PCI_REV to check_and_handle_sdw_dma_irq(), an interrupt in that window
returns IRQ_WAKE_THREAD and runs acp63_irq_thread() ->
acp63_sdw_dma_irq_thread() (or acp70_sdw_dma_irq_thread()) in
sound/soc/amd/ps/ps-common.c:
sdw_data = dev_get_drvdata(&adata->sdw_dma_dev->dev);
for (stream_id = 0; stream_id < ACP63_SDW0_DMA_MAX_STREAMS; stream_id++) {
if (adata->acp63_sdw0_dma_intr_stat[stream_id]) {
if (sdw_data->acp63_sdw0_dma_stream[stream_id])
snd_pcm_period_elapsed(sdw_data->acp63_sdw0_dma_stream[stream_id]);
which dereferences sdw_data without checking if it is NULL.
Should check_and_handle_sdw_dma_irq() always run to clear the hardware status
bits, and should acp63_sdw_dma_irq_thread() / acp70_sdw_dma_irq_thread() (or
acp63_irq_handler() before returning IRQ_WAKE_THREAD) verify that
adata->sdw_dma_dev and dev_get_drvdata(&adata->sdw_dma_dev->dev) are valid?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20261028020552.35278-1-corsmith@gmail.com?part=10
next prev parent reply other threads:[~2026-10-28 2:21 UTC|newest]
Thread overview: 17+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-28 2:05 [PATCH 0/11] ASoC/soundwire: AMD ACP6x (Rembrandt) SoundWire speaker support Corey Smith
2026-10-28 2:05 ` [PATCH 1/11] soundwire: amd: add ACP6x PCI revision ids Corey Smith
2026-10-28 2:05 ` [PATCH 2/11] soundwire: amd: support ACP6x SoundWire managers Corey Smith
2026-10-28 2:05 ` [PATCH 3/11] ASoC: amd: ps: add ACP6x PCI revision ids Corey Smith
2026-10-28 2:15 ` sashiko-bot
2026-10-28 2:05 ` [PATCH 4/11] ASoC: amd: ps: support ACP6x in the SoundWire DMA driver Corey Smith
2026-10-28 2:05 ` [PATCH 5/11] ASoC: amd: acp: add ACP6x (Rembrandt) SoundWire machine table Corey Smith
2026-10-28 2:05 ` [PATCH 6/11] ASoC: amd: acp-config: route HP Dragonfly Pro ONE through the ACP6x SDW stack Corey Smith
2026-10-28 2:05 ` [PATCH 7/11] ASoC: amd: ps: probe the ACP6x SoundWire stack Corey Smith
2026-10-28 2:20 ` sashiko-bot
2026-10-28 2:05 ` [PATCH 8/11] ASoC: amd: acp: add ACP6x SoundWire quirks and machine support Corey Smith
2026-10-28 2:22 ` sashiko-bot
2026-10-28 2:05 ` [PATCH 9/11] soundwire: amd: accept the legacy mipi-sdw-master-list property Corey Smith
2026-10-28 2:05 ` [PATCH 10/11] ASoC: amd: ps: harden the ACP interrupt path for ACP6x Corey Smith
2026-10-28 2:21 ` sashiko-bot [this message]
2026-10-28 2:05 ` [PATCH 11/11] soundwire: amd: provide defaults for the bus clock properties Corey Smith
2026-10-29 6:58 ` [PATCH 0/11] ASoC/soundwire: AMD ACP6x (Rembrandt) SoundWire speaker support Mukunda,Vijendar
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=sashiko-outbox-187339@kernel.org \
--to=sashiko-bot@kernel.org \
--cc=corsmith@gmail.com \
--cc=linux-sound@vger.kernel.org \
--cc=sashiko-reviews@lists.linux.dev \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox