From: sashiko-bot@kernel.org
To: "Rishikesh Donadkar" <r-donadkar@ti.com>
Cc: devicetree@vger.kernel.org, robh@kernel.org, conor+dt@kernel.org
Subject: Re: [PATCH v13 14/17] media: ti: j721e-csi2rx: Change the drain architecture for multistream
Date: Wed, 20 May 2026 13:01:29 +0000 [thread overview]
Message-ID: <20260520130129.A2CB71F00893@smtp.kernel.org> (raw)
In-Reply-To: <20260520120022.539913-15-r-donadkar@ti.com>
Thank you for your contribution! Sashiko AI review found 6 potential issue(s) to consider:
- [High] Data race and waitqueue corruption due to `init_completion()` being called outside the lock after the `STOPPED` state is set in `ti_csi2rx_stop_dma()`.
- [High] `ti_csi2rx_dma_callback` unconditionally overwrites the `TI_CSI2RX_DMA_STOPPED` state, leading to endless draining and a 50ms timeout during streamoff.
- [High] Removal of the DMA restart logic causes a permanent stream stall if any DMA transaction fails to prepare or submit.
- [High] Pre-existing drain transactions can trigger a premature completion of the barrier wait in `ti_csi2rx_stop_dma`.
- [Medium] `ti_csi2rx_stop_dma` unconditionally blocks on `wait_for_completion_timeout`, causing a guaranteed 50ms delay on already-stopped streams or error paths.
- [Medium] The continuously draining architecture generates an excessively high interrupt rate during buffer starvation.
--
commit 3364f8fb9264e28b1fb58dc86804662c48056485
Author: Rishikesh Donadkar <r-donadkar@ti.com>
media: ti: j721e-csi2rx: Change the drain architecture for multistream
This patch introduces a continuous drain architecture for multistream
CSI2RX scenarios to prevent buffer starvation on one stream from blocking
the shared HW FIFO. It uses a 32KiB drain buffer and waits for a
completion barrier at the end of the stream.
> diff --git a/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c b/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c
> --- a/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c
> +++ b/drivers/media/platform/ti/j721e-csi2rx/j721e-csi2rx.c
[ ... ]
> @@ -608,9 +613,32 @@ static void ti_csi2rx_setup_shim(struct ti_csi2rx_ctx *ctx)
[ ... ]
> + if (list_empty(&dma->queue)) {
> + if (ti_csi2rx_drain_dma(ctx))
> + dev_warn(ctx->csi->dev, "DMA drain failed\n");
> + } else {
> + ti_csi2rx_dma_submit_pending(ctx);
> + }
> + spin_unlock_irqrestore(&dma->lock, flags);
> }
[Severity: Medium]
For high-bandwidth CSI-2 streams, a 32KiB buffer fills very quickly.
During user-space buffer starvation, this architecture continually loops
32KiB drain transactions.
Does this generate an excessively high interrupt rate (tens of thousands
per second) that could degrade overall system performance?
[ ... ]
> @@ -702,14 +720,24 @@ static void ti_csi2rx_dma_callback(void *param)
[ ... ]
> - if (list_empty(&dma->submitted))
> - dma->state = TI_CSI2RX_DMA_IDLE;
> -
> + if (list_empty(&dma->submitted)) {
> + dma->state = TI_CSI2RX_DMA_DRAINING;
> + if (ti_csi2rx_drain_dma(ctx))
> + dev_warn(ctx->csi->dev,
> + "DMA drain failed on one of the transactions\n");
> + }
> spin_unlock_irqrestore(&dma->lock, flags);
> }
[Severity: High]
If ti_csi2rx_stop_dma() concurrently sets the state to
TI_CSI2RX_DMA_STOPPED, does this blindly overwrite it?
If the state gets overwritten to TI_CSI2RX_DMA_DRAINING,
ti_csi2rx_drain_callback() might observe DRAINING instead of STOPPED,
triggering recursive drains and causing the streamoff operation to hit
its 50ms timeout.
[ ... ]
> @@ -754,6 +782,8 @@ static void ti_csi2rx_stop_dma(struct ti_csi2rx_ctx *ctx)
> dma->state = TI_CSI2RX_DMA_STOPPED;
> spin_unlock_irqrestore(&dma->lock, flags);
>
> + init_completion(&ctx->drain_complete);
[Severity: High]
If a concurrent drain DMA completes precisely after the lock is released
but before init_completion() is called, its callback will observe the
STOPPED state and call complete(&ctx->drain_complete).
Can this concurrent execution of complete() and init_completion() cause a
data race on the completion's waitqueue spinlock or lost completion events?
Should init_completion() be called before modifying the state?
[Severity: High]
Additionally, if the state was already TI_CSI2RX_DMA_DRAINING when
ti_csi2rx_stop_dma() is called, there may be a pre-existing drain
transaction currently running.
When this pre-existing drain finishes, its callback observes the new
STOPPED state and immediately calls complete(&ctx->drain_complete).
Does this wake up the wait_for_completion_timeout() below prematurely,
causing the driver to abort via dmaengine_terminate_sync() before the
actual barrier drain has finished clearing the hardware FIFO?
[ ... ]
> @@ -762,11 +792,19 @@ static void ti_csi2rx_stop_dma(struct ti_csi2rx_ctx *ctx)
[ ... ]
> ret = ti_csi2rx_drain_dma(ctx);
> - if (ret && ret != -ETIMEDOUT)
> + if (ret)
> dev_warn(ctx->csi->dev,
> "Failed to drain DMA. Next frame might be bogus\n");
> }
>
> + /* We wait for the drain to complete so that the stream stops
> + * cleanly, making sure the shared hardware FIFO is cleared of
> + * data from the current stream. No more data will be coming from
> + * the source after this.
> + */
> + wait_for_completion_timeout(&ctx->drain_complete,
> + msecs_to_jiffies(DRAIN_TIMEOUT_MS));
[Severity: Medium]
If the stream was already stopped (e.g., during error handling) or if
ti_csi2rx_drain_dma() failed to prepare a descriptor, no DMA transaction
is queued.
Since no callback will ever signal ctx->drain_complete in these paths, does
this cause the function to unnecessarily block for the full 50ms timeout
every time?
[ ... ]
> @@ -829,57 +867,14 @@ static void ti_csi2rx_buffer_queue(struct vb2_buffer *vb)
[ ... ]
> - /*
> - * Usually the DMA callback takes care of queueing the pending buffers.
> - * But if DMA has stalled due to lack of buffers, restart it now.
> - */
> - if (dma->state == TI_CSI2RX_DMA_IDLE) {
[ ... ]
> - } else {
> - list_add_tail(&buf->list, &dma->queue);
> - }
> + list_add_tail(&buf->list, &dma->queue);
> spin_unlock_irqrestore(&dma->lock, flags);
[Severity: High]
The previous architecture actively restarted the DMA engine if it was idle.
By removing this restart logic, the driver now relies entirely on an
unbroken chain of DMA callbacks.
If ti_csi2rx_drain_dma() fails to prepare or submit a descriptor (e.g., due
to memory pressure), the active DMA chain breaks and the DMA engine halts.
Without a way to kickstart the DMA here, do newly queued buffers just
accumulate in dma->queue, resulting in a silent, permanent stream deadlock?
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260520120022.539913-1-r-donadkar@ti.com?part=14
next prev parent reply other threads:[~2026-05-20 13:01 UTC|newest]
Thread overview: 35+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-05-20 12:00 [PATCH v13 00/17] media: cadence,ti: CSI2RX Multistream Support Rishikesh Donadkar
2026-05-20 12:00 ` [PATCH v13 01/17] media: ti: j721e-csi2rx: Remove word size alignment on frame width Rishikesh Donadkar
2026-05-20 12:27 ` sashiko-bot
2026-05-20 12:00 ` [PATCH v13 02/17] dt-bindings: media: ti,j721e-csi2rx-shim: Support 32 dma chans Rishikesh Donadkar
2026-05-20 12:00 ` [PATCH v13 03/17] media: ti: j721e-csi2rx: separate out device and context Rishikesh Donadkar
2026-05-20 12:37 ` sashiko-bot
2026-05-20 12:00 ` [PATCH v13 04/17] media: ti: j721e-csi2rx: prepare SHIM code for multiple contexts Rishikesh Donadkar
2026-05-20 12:00 ` [PATCH v13 05/17] media: ti: j721e-csi2rx: allocate DMA channel based on context index Rishikesh Donadkar
2026-05-20 12:32 ` sashiko-bot
2026-05-20 12:00 ` [PATCH v13 06/17] media: ti: j721e-csi2rx: add a subdev for the core device Rishikesh Donadkar
2026-05-20 12:28 ` Sakari Ailus
2026-05-20 12:49 ` sashiko-bot
2026-05-20 12:00 ` [PATCH v13 07/17] media: cadence: csi2rx: Move to .enable/disable_streams API Rishikesh Donadkar
2026-05-20 12:39 ` sashiko-bot
2026-05-20 12:00 ` [PATCH v13 08/17] media: ti: j721e-csi2rx: get number of contexts from device tree Rishikesh Donadkar
2026-05-20 12:45 ` sashiko-bot
2026-05-20 12:00 ` [PATCH v13 09/17] media: cadence: csi2rx: Add .get_frame_desc op Rishikesh Donadkar
2026-05-20 14:25 ` Jai Luthra
2026-05-20 12:00 ` [PATCH v13 10/17] media: ti: j721e-csi2rx: add support for processing virtual channels Rishikesh Donadkar
2026-05-20 12:44 ` sashiko-bot
2026-05-20 12:00 ` [PATCH v13 11/17] media: cadence: csi2rx: add multistream support Rishikesh Donadkar
2026-05-20 12:58 ` sashiko-bot
2026-05-20 12:00 ` [PATCH v13 12/17] media: ti: j721e-csi2rx: " Rishikesh Donadkar
2026-05-20 12:48 ` sashiko-bot
2026-05-20 12:00 ` [PATCH v13 13/17] media: ti: j721e-csi2rx: Submit all available buffers Rishikesh Donadkar
2026-05-20 12:59 ` sashiko-bot
2026-05-20 12:00 ` [PATCH v13 14/17] media: ti: j721e-csi2rx: Change the drain architecture for multistream Rishikesh Donadkar
2026-05-20 13:01 ` sashiko-bot [this message]
2026-05-20 12:00 ` [PATCH v13 15/17] media: cadence: csi2rx: Support runtime PM Rishikesh Donadkar
2026-05-20 13:00 ` sashiko-bot
2026-05-20 12:00 ` [PATCH v13 16/17] media: ti: j721e-csi2rx: Support runtime suspend Rishikesh Donadkar
2026-05-20 13:01 ` sashiko-bot
2026-05-20 12:00 ` [PATCH v13 17/17] media: ti: j721e-csi2rx: Support system suspend using pm_notifier Rishikesh Donadkar
2026-05-20 12:25 ` Sakari Ailus
2026-05-20 13:14 ` 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=20260520130129.A2CB71F00893@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=r-donadkar@ti.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 a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox