From: sashiko-bot@kernel.org
To: "Harendra Gautam" <harendra.gautam@oss.qualcomm.com>
Cc: devicetree@vger.kernel.org, robh@kernel.org, conor+dt@kernel.org
Subject: Re: [PATCH 12/13] ASoC: qcom: Add QAIF IRQ handling, suspend/resume and platform register
Date: Fri, 05 Jun 2026 11:13:46 +0000 [thread overview]
Message-ID: <20260605111347.0951E1F00893@smtp.kernel.org> (raw)
In-Reply-To: <20260605103739.3557573-13-harendra.gautam@oss.qualcomm.com>
Thank you for your contribution! Sashiko AI review found 10 potential issue(s) to consider:
New issues:
- [Critical] The IRQ handler accesses memory-mapped registers without ensuring that the required device clocks are enabled.
- [Critical] `qaif_platform_pcmops_resume` unconditionally attempts to write to hardware registers via `regcache_sync` while clocks are disabled.
- [High] Hardcoded DT parsing of the 'iommus' property makes the driver brittle and violates standard bindings.
- [High] Masking the interrupt clear register write leaves unhandled bits set, causing an infinite IRQ storm.
- [High] The DMA clocks are not properly balanced during system suspend/resume if multiple streams are open.
- [High] `snd_pcm_stop()` is called from the IRQ handler without holding the required ALSA stream lock.
- [High] Unprotected double-read of `substream[stream_dma_idx]` can lead to dereferencing a NULL pointer in the IRQ handler.
- [Medium] Clock enables are leaked if `regcache_sync()` fails during system resume.
Pre-existing issues:
- [High] The DMA memory is mapped to userspace with a different device pointer than the one used to allocate it.
- [High] Concurrent `.open` and `.close` operations lack locking, leading to data races on `qaif_init_ref_cnt`.
--
commit 79f7f868b0ea8024295676f54c8ca826ce51828f
Author: Harendra Gautam <harendra.gautam@oss.qualcomm.com>
ASoC: qcom: Add QAIF IRQ handling, suspend/resume and platform register
Complete the QAIF PCM platform support by registering the component,
requesting the QAIF interrupt, and handling DMA interrupt events.
> diff --git a/sound/soc/qcom/qaif-platform.c b/sound/soc/qcom/qaif-platform.c
> index beebec55222a5..8cf4d68f72b1c 100644
> --- a/sound/soc/qcom/qaif-platform.c
> +++ b/sound/soc/qcom/qaif-platform.c
> @@ -847,3 +847,323 @@ static int qaif_platform_pcmops_mmap(struct snd_soc_component *component,
>
> return snd_pcm_lib_default_mmap(substream, vma);
> }
[Severity: High]
This is a pre-existing issue, but does qaif_platform_cdc_dma_mmap map the
DMA buffer using the correct device pointer?
The buffer appears to be allocated using dma_alloc_coherent() with the
component device pointer, but qaif_platform_cdc_dma_mmap() maps it using:
return dma_mmap_coherent(substream->pcm->card->dev, vma, ...);
Could passing a different device pointer for mapping violate the DMA API
and cause IOMMU faults on platforms where only the component device is
attached to the SMMU domain?
> +
> +static irqreturn_t qaif_process_dma_irq(struct qaif_drv_data *drvdata,
[ ... ]
> + mask = GENMASK(num_dma-1, 0);
> + rv = regmap_read(drvdata->audio_qaif_map, stat_reg_addr, ®);
> + if (rv) {
> + dev_err(regmap_get_device(drvdata->audio_qaif_map),
> + "error reading stat reg 0x%x: %d\n", stat_reg_addr, rv);
> + return IRQ_NONE;
> + }
> +
> + regmap_write(drvdata->audio_qaif_map, clr_reg_addr, reg & mask);
[Severity: High]
If the hardware asserts bits outside of the computed mask, will those bits
remain uncleared?
Because the IRQ is level-triggered (IRQF_TRIGGER_HIGH), could failing to
clear all asserted bits cause the interrupt controller to immediately
re-invoke the handler, leading to an interrupt storm and CPU lockup?
> +
> + for (dma_idx = 0; dma_idx < num_dma; dma_idx++) {
> + stream_dma_idx = dma_idx + stream_offset;
> + if ((reg & BIT(dma_idx)) && substream[stream_dma_idx]) {
> + stream = substream[stream_dma_idx];
[Severity: High]
Is there a risk of a null pointer dereference here due to a time-of-check
to time-of-use race?
If a concurrent close operation locklessly nullifies the substream array
entry between checking substream[stream_dma_idx] and assigning it to stream:
CPU1 (close)
drvdata->aif_substream[data->stream_dma_idx] = NULL;
CPU2 (qaif_process_dma_irq)
if ((reg & BIT(dma_idx)) && substream[stream_dma_idx]) {
stream = substream[stream_dma_idx];
Would the handler then pass a NULL stream pointer to snd_pcm_stop()?
Should this use READ_ONCE() or be protected by a lock?
> + switch (irq) {
> + case QAIF_IRQ_PERIOD:
> + snd_pcm_period_elapsed(stream);
> + ret = IRQ_HANDLED;
> + break;
> +
> + case QAIF_IRQ_OVERFLOW:
> + case QAIF_IRQ_UNDERFLOW:
> + dev_warn_ratelimited(regmap_get_device(drvdata->audio_qaif_map),
> + "QAIF DMA xRun\n");
> + ret = IRQ_HANDLED;
> + break;
> +
> + case QAIF_IRQ_ERROR:
> + snd_pcm_stop(stream, SNDRV_PCM_STATE_DISCONNECTED);
[Severity: High]
Can this call to snd_pcm_stop() corrupt the PCM state?
The ALSA core API snd_pcm_stop() manipulates the substream's runtime state
and expects the caller to hold the PCM stream lock. Could calling it
locklessly from this interrupt handler introduce a data race with
concurrent userspace or ALSA core operations?
Would using the IRQ-safe snd_pcm_stop_xrun() or manually acquiring the lock
be more appropriate here?
[ ... ]
> +static irqreturn_t asoc_platform_qaif_irq(int irq, void *data)
> +{
> + struct qaif_drv_data *drvdata = data;
> + const struct qaif_variant *v = drvdata->variant;
> + u32 summary_irq_status;
> + int rv, client;
> + irqreturn_t ret = IRQ_NONE;
> +
> + rv = regmap_read(drvdata->audio_qaif_map,
> + QAIF_SUMMARY_IRQSTAT_REG(v), &summary_irq_status);
[Severity: Critical]
Is it possible for this MMIO read to trigger a synchronous external abort?
If an interrupt fires (e.g. spurious or shared line activity) while no PCM
streams are active (qaif_init_ref_cnt == 0), the hardware clocks might be
physically disabled.
Since the handler unconditionally executes regmap_read() on
QAIF_SUMMARY_IRQSTAT_REG, could this unclocked access cause a bus stall
and kernel panic?
[ ... ]
> +static int qaif_platform_pcmops_suspend(struct snd_soc_component *component)
> +{
> + struct qaif_drv_data *drvdata = snd_soc_component_get_drvdata(component);
> + struct regmap *map;
> +
> + map = drvdata->audio_qaif_map;
> +
> + regcache_cache_only(map, true);
> + regcache_mark_dirty(map);
> + if (drvdata->qaif_init_ref_cnt > 0) {
> + clk_disable(drvdata->aud_dma_clk);
> + clk_disable(drvdata->aud_dma_mem_clk);
> + }
[Severity: High]
Does this leave the hardware clocks running if multiple streams are active?
If clk_prepare_enable() is called for every new stream, the clock's
reference count is incremented N times for N active streams.
However, qaif_platform_pcmops_suspend() only calls clk_disable() once if
qaif_init_ref_cnt > 0. If more than one stream was active, wouldn't the
enable count remain at N - 1, keeping the physical hardware clocks running
throughout system suspend?
> + return 0;
> +}
> +
> +static int qaif_platform_pcmops_resume(struct snd_soc_component *component)
> +{
> + struct qaif_drv_data *drvdata = snd_soc_component_get_drvdata(component);
> + struct regmap *map = drvdata->audio_qaif_map;
> + int ret;
> +
> + if (drvdata->qaif_init_ref_cnt > 0) {
> + ret = clk_enable(drvdata->aud_dma_clk);
> + if (ret)
> + return ret;
> + ret = clk_enable(drvdata->aud_dma_mem_clk);
> + if (ret) {
> + clk_disable(drvdata->aud_dma_clk);
> + return ret;
> + }
> + }
> + regcache_cache_only(map, false);
> + return regcache_sync(map);
[Severity: Critical]
Can this regcache_sync() call cause an unclocked access exception?
If no streams were active before suspend (qaif_init_ref_cnt == 0), the
driver skips enabling the clocks.
Because the system suspend callback executed regcache_mark_dirty(map), this
unconditional regcache_sync() attempt will write to the hardware registers.
Could writing to the MMIO registers of a clock-gated IP block cause an
SError and system crash?
[Severity: Medium]
Does this leak the clock enables if regcache_sync() fails?
If regcache_sync(map) returns an error, it fails to call clk_disable() on
the previously enabled aud_dma_clk and aud_dma_mem_clk.
Could transient regmap failures during successive suspend/resume cycles
continuously increment the clock reference counts and prevent the clocks
from ever being turned off?
[ ... ]
> +static const struct snd_soc_component_driver qaif_component_driver = {
> + .name = DRV_NAME,
> + .open = qaif_platform_pcmops_open,
[Severity: High]
This is a pre-existing issue, but are concurrent calls to
qaif_platform_pcmops_open() and qaif_platform_pcmops_close() safe?
The global drvdata->qaif_init_ref_cnt is modified locklessly in these
functions. Since a single component can expose multiple DAIs and
independent PCMs, could concurrent open and close calls for different PCMs
race on the read-modify-write operations and corrupt the counter?
Could this lead to premature clock disablement during active playback?
[ ... ]
> +static int qaif_parse_smmu_sid(struct platform_device *pdev,
> + struct qaif_drv_data *drvdata)
> +{
> + struct device_node *np = pdev->dev.of_node;
> + int ret;
> + u32 sid;
> +
> + ret = of_property_read_u32_index(np, "iommus", 1, &sid);
[Severity: High]
Does hardcoding the DT parsing of the "iommus" property break probe on
platforms with different IOMMU bindings?
By bypassing standard OF parsing APIs (like of_parse_phandle_with_args)
and fetching the SMMU SID at index 1 directly, this assumes a specific
layout.
What happens on platforms where #iommu-cells = <2> (where index 1 might be
the ID and index 2 the mask, or index 0 is phandle), or on platforms
without an IOMMU? Will this return a fatal error and completely prevent
audio initialization?
> + if (ret) {
> + dev_err(&pdev->dev, "failed to read SMMU SID from iommus property: %d\n", ret);
> + return ret;
> + }
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260605103739.3557573-1-harendra.gautam@oss.qualcomm.com?part=12
next prev parent reply other threads:[~2026-06-05 11:13 UTC|newest]
Thread overview: 40+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-06-05 10:37 [PATCH 0/13] ASoC: qcom: Add QAIF driver for Shikra audio platform Harendra Gautam
2026-06-05 10:37 ` [PATCH 1/13] dt-bindings: sound: Add Qualcomm QAIF DAI ID header Harendra Gautam
2026-06-05 10:42 ` Krzysztof Kozlowski
2026-06-05 10:37 ` [PATCH 2/13] dt-bindings: sound: Add Qualcomm QAIF binding Harendra Gautam
2026-06-05 10:46 ` Krzysztof Kozlowski
2026-06-05 10:51 ` Krzysztof Kozlowski
2026-06-24 7:02 ` Harendra Gautam
2026-06-05 11:27 ` Rob Herring (Arm)
2026-06-23 12:30 ` Harendra Gautam
2026-06-05 11:45 ` sashiko-bot
2026-06-09 9:57 ` Konrad Dybcio
2026-06-23 12:26 ` Harendra Gautam
2026-06-23 15:48 ` Konrad Dybcio
2026-06-24 6:59 ` Harendra Gautam
2026-06-16 19:59 ` Srinivas Kandagatla
2026-06-23 12:17 ` Harendra Gautam
2026-06-05 10:37 ` [PATCH 3/13] MAINTAINERS: Add Qualcomm QAIF driver entry Harendra Gautam
2026-06-05 10:52 ` Krzysztof Kozlowski
2026-06-05 10:37 ` [PATCH 4/13] ASoC: qcom: Add QAIF hardware register map Harendra Gautam
2026-06-05 10:37 ` [PATCH 5/13] ASoC: qcom: Add QAIF shared data structures and variant interface Harendra Gautam
2026-06-05 10:51 ` sashiko-bot
2026-06-16 20:28 ` Srinivas Kandagatla
[not found] ` <CAC-tS8BvfQOLhwicBJ986UqTTZGmiYDbg5MVA54ScUsYLb-dog@mail.gmail.com>
2026-06-23 8:11 ` Harendra Gautam
2026-06-05 10:37 ` [PATCH 6/13] ASoC: qcom: Add QAIF CIF (CDC DMA) DAI ops Harendra Gautam
2026-06-05 10:37 ` [PATCH 7/13] ASoC: qcom: Add QAIF AIF " Harendra Gautam
2026-06-05 10:52 ` sashiko-bot
2026-06-05 10:37 ` [PATCH 8/13] ASoC: qcom: Add generic of_xlate_dai_name helper to common Harendra Gautam
2026-06-05 10:48 ` sashiko-bot
2026-06-05 10:37 ` [PATCH 9/13] ASoC: qcom: lpass-cpu: Use asoc_qcom_of_xlate_dai_name helper Harendra Gautam
2026-06-05 10:51 ` sashiko-bot
2026-06-05 10:37 ` [PATCH 10/13] ASoC: qcom: Add QAIF regmap, DT parsing and platform init Harendra Gautam
2026-06-05 11:02 ` Krzysztof Kozlowski
2026-06-05 11:15 ` sashiko-bot
2026-06-05 10:37 ` [PATCH 11/13] ASoC: qcom: Add QAIF PCM operations Harendra Gautam
2026-06-05 11:02 ` sashiko-bot
2026-06-05 10:37 ` [PATCH 12/13] ASoC: qcom: Add QAIF IRQ handling, suspend/resume and platform register Harendra Gautam
2026-06-05 11:13 ` sashiko-bot [this message]
2026-06-05 10:37 ` [PATCH 13/13] ASoC: qcom: Add Shikra QAIF support Harendra Gautam
2026-06-05 10:58 ` Krzysztof Kozlowski
2026-06-05 11:02 ` sashiko-bot
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=20260605111347.0951E1F00893@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=harendra.gautam@oss.qualcomm.com \
--cc=robh@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.