From: sashiko-bot@kernel.org
To: "Syed Saba Kareem" <syed.sabakareem@amd.com>
Cc: bpf@vger.kernel.org, media-ci@linuxtv.org,
dri-devel@lists.freedesktop.org
Subject: Re: [PATCH v2 4/5] soundwire: amd: Add BRA/BPT firmware download support
Date: Tue, 29 Sep 2026 12:07:40 +0000 [thread overview]
Message-ID: <20260929120740.B29B21F000FF@smtp.kernel.org> (raw)
In-Reply-To: <20260929115052.247086-5-syed.sabakareem@amd.com>
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
- [Critical] soundwire: amd: deconfiguring wedged BRA descriptor redirects active DMA to physical address 0
- [High] soundwire: amd: master port 0 aliasing silences concurrent audio streams during BPT
- [High] soundwire: amd: global acp_bra_wedged flag breaks independent SoundWire controllers
- [Medium] soundwire: amd: integer overflow in total_len causes heap buffer overflow
--
commit 10078bc80a59ffcc131913ae41fbb4706ce8f69f
Author: Syed Saba Kareem <Syed.SabaKareem@amd.com>
Subject: soundwire: amd: Add BRA/BPT firmware download support
This commit adds Bulk Register Access (BRA) and Bulk Payload Transport
(BPT) support for AMD SoundWire platforms. It uses the SoundWire stream
framework for programming the DP0 port and relies on the ACP BRA DMA
engine for transferring large firmware segments.
> diff --git a/drivers/soundwire/amd_manager.c b/drivers/soundwire/amd_manager.c
> index a3316efdf8ac2..f5b4096c83ac3 100644
> --- a/drivers/soundwire/amd_manager.c
> +++ b/drivers/soundwire/amd_manager.c
> [ ... ]
> @@ -713,6 +764,13 @@ static int amd_sdw_port_params(struct sdw_bus *bus, struct sdw_port_params *p_pa
> struct amd_sdw_manager *amd_manager = to_amd_sdw(bus);
> u32 frame_fmt_reg, dpn_frame_fmt;
>
> + /*
> + * BPT uses dedicated ACP BRA descriptor registers; ignore DP0 ops only.
> + * Allow DPn audio port ops to proceed even while BPT is active.
> + */
> + if (READ_ONCE(bus->bpt_stream) && p_params->num == 0)
> + return 0;
> +
[Severity: High]
By checking p_params->num == 0 when bus->bpt_stream is active, won't this
skip hardware programming for any concurrent audio stream using CPU DAI 0
(which also maps to master port 0)? Because the callback cannot distinguish
between the concurrent audio stream's port 0 and the BPT stream's port 0,
does this leave the audio stream unconfigured in the hardware?
> [ ... ]
> @@ -764,6 +843,13 @@ static int amd_sdw_transport_params(struct sdw_bus *bus,
> u32 frame_fmt_reg, sample_int_reg, hctrl_dp0_reg;
> u32 offset_reg, lane_ctrl_ch_en_reg;
>
> + /*
> + * BPT uses dedicated ACP BRA descriptor registers; ignore DP0 ops only.
> + * Allow DPn audio port ops to proceed even while BPT is active.
> + */
> + if (READ_ONCE(bus->bpt_stream) && params->port_num == 0)
> + return 0;
> +
[Severity: High]
Similarly, does skipping the transport parameters leave concurrent audio
streams on port 0 in a broken hardware state?
> [ ... ]
> @@ -887,6 +953,1062 @@ static int amd_sdw_port_enable(struct sdw_bus *bus,
> +/*
> + * Latched when a BRA transfer leaves the ACP DMA engine wedged: it failed to
> + * confirm it stopped and may still be bus-mastering through the ACP-global ATU
> + * PTEs. Once set, amd_sdw_bra_configure_pte() refuses to reprogram those shared
> + * PTEs, so a still-active engine on one manager instance cannot be redirected
> + * into another instance's buffer. Written and read only under acp_bra_lock and
> + * never cleared: recovering the engine requires a device reset / driver reload.
> + */
> +static bool acp_bra_wedged;
> +
> +static u32 amd_sdw_bra_configure_pte(struct amd_sdw_manager *amd_manager,
> + dma_addr_t dma_addr, size_t size)
> +{
> [ ... ]
> +
> + if (acp_bra_wedged) {
> + dev_err(amd_manager->dev,
> + "BRA engine previously wedged; refusing to reprogram shared ATU PTEs\n");
> + return 0;
> + }
[Severity: High]
Since acp_bra_wedged is declared as a static module-level global variable,
won't a failure in one SoundWire controller permanently disable firmware
downloads on all other independent controllers in the system? Should this
state be scoped to the shared ACP hardware context (for example, inside
acp_dev_data or sdw_amd_res) so that physically distinct ACP PCI devices
like an APU and a discrete GPU do not share this wedged state?
> [ ... ]
> +static void amd_sdw_deconfig_bra_descriptor(struct amd_sdw_manager *amd_manager)
> +{
> [ ... ]
> + writel(0, amd_manager->mmio + ACP_SW_BRA_BASE_ADDRESS);
> + writel(0, amd_manager->mmio + ACP_SW_BRA_TRANSFER_SIZE);
> +}
> [ ... ]
> +static int amd_sdw_bra_transfer(struct amd_sdw_manager *amd_manager,
> + struct sdw_slave *slave, u32 reg_addr,
> + u32 acp_base_addr, size_t len, bool write,
> + bool *dma_unsafe)
> +{
> [ ... ]
> + ret = amd_sdw_execute_bra_transfer(amd_manager, slave, dma_unsafe);
> + amd_sdw_deconfig_bra_descriptor(amd_manager);
> +
> + return ret;
> +}
[Severity: Critical]
If amd_sdw_execute_bra_transfer() sets dma_unsafe to true, this signals
that the DMA engine failed to quiesce and is still actively bus-mastering.
Because amd_sdw_deconfig_bra_descriptor() is called unconditionally, it
writes 0 to ACP_SW_BRA_BASE_ADDRESS. Won't altering the base address
mid-flight redirect the ongoing DMA writes to physical address 0x0,
bypassing the ATU safe leak buffer and causing memory corruption?
> [ ... ]
> +static int amd_sdw_bpt_send_async(struct sdw_bus *bus,
> + struct sdw_slave *slave,
> + struct sdw_bpt_msg *msg)
> +{
> + struct amd_sdw_manager *amd_manager = to_amd_sdw(bus);
> + size_t total_len = 0;
> + int i;
> +
> + for (i = 0; i < msg->sections; i++)
> + total_len += msg->sec[i].len;
> +
> [ ... ]
> +static int amd_sdw_bpt_wait(struct sdw_bus *bus,
> + struct sdw_slave *slave,
> + struct sdw_bpt_msg *msg)
> +{
> [ ... ]
> + size_t total_len = 0;
> + int ret = 0;
> + int i;
> + bool dma_unsafe = false;
> +
> + for (i = 0; i < msg->sections; i++)
> + total_len += msg->sec[i].len;
[Severity: Medium]
Could total_len (a 32-bit size_t on 32-bit architectures) integer-overflow
here? If a multi-section firmware payload specifies lengths that sum past
4GB, total_len would wrap to a small value, bypassing the
SDW_BPT_MSG_MAX_BYTES validation limit.
> [ ... ]
> + /* For writes, copy all section data into the DMA buffer */
> + if (is_write) {
> + for (i = 0; i < msg->sections; i++) {
> + memcpy(dma_buf + offset, msg->sec[i].buf, msg->sec[i].len);
> + offset += msg->sec[i].len;
> + }
> + }
[Severity: Medium]
If the validation is bypassed due to the wrap-around, dma_buf is allocated
with the wrapped, small total_len. Will this memcpy() using the original,
un-wrapped msg->sec[i].len cause a heap buffer overflow?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260929115052.247086-2-syed.sabakareem@amd.com?part=4
next prev parent reply other threads:[~2026-09-29 12:07 UTC|newest]
Thread overview: 3+ messages / expand[flat|nested] mbox.gz Atom feed top
[not found] <20260929115052.247086-1-syed.sabakareem@amd.com>
2026-09-29 11:50 ` [PATCH v2 4/5] soundwire: amd: Add BRA/BPT firmware download support Syed Saba Kareem
2026-09-29 12:07 ` sashiko-bot [this message]
2026-09-29 11:50 ` [PATCH v2 5/5] soundwire: amd: honor peripheral BRA block alignment Syed Saba Kareem
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=20260929120740.B29B21F000FF@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=bpf@vger.kernel.org \
--cc=dri-devel@lists.freedesktop.org \
--cc=media-ci@linuxtv.org \
--cc=sashiko-reviews@lists.linux.dev \
--cc=syed.sabakareem@amd.com \
/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