Linux-PHY Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: Cody Kang <codykang.hk@gmail.com>
To: sashiko-reviews@lists.linux.dev
Cc: dri-devel@lists.freedesktop.org, linux-phy@lists.infradead.org,
	olteanv@gmail.com, conor+dt@kernel.org, vkoul@kernel.org,
	neil.armstrong@linaro.org, robh@kernel.org,
	devicetree@vger.kernel.org, sashiko-bot@kernel.org
Subject: Re: [PATCH RESEND 10/17] drm/spacemit: add Saturn DPU KMS pipeline
Date: Sun, 09 Aug 2026 08:59:34 +0800	[thread overview]
Message-ID: <242adca6fe63a63e0f637da9603cde06.codykang.hk@gmail.com> (raw)
In-Reply-To: <20260725050427.33AE91F000E9@smtp.kernel.org>

On Sat, 25 Jul 2026 05:04:26 +0000, sashiko-bot@kernel.org wrote:
> Thank you for your contribution! Sashiko AI review found 10 potential issue(s) to consider:
> - [High] Sleeping functions are called from CRTC atomic enable and disable callbacks, which execute in atomic context.
> - [High] TOCTOU race when updating the `clocks_on` flag and gating hardware clocks leads to MMIO stalls.
> - [High] Calling `devm_drm_dev_alloc` inside a component `bind` callback leaks the DRM device on rebinds.
> - [High] Enabling the DPU interrupt before hardware is initialized leads to an unhandled IRQ storm.
> - [High] `spacemit_plane_reset` bypasses the custom state destructor, leaking DMA coherent memory.
> - [High] `disable_irq()` is called before `drm_atomic_helper_shutdown()` during driver unbind, causing shutdown to hang.
> - [High] `spacemit_plane_atomic_check()` assigns RDMA channels based on unvalidated `zpos`, leading to channel collisions.
> - [High] Unconditional `spin_unlock_irq` used in atomic context improperly re-enables interrupts.
> - [Medium] Leaking DRM property blob references in `spacemit_crtc_duplicate_state` on error.
> - [Medium] Missing NULL check on `plane->state` in `spacemit_plane_atomic_duplicate_state` causes a crash if the state is missing.
> --
>
> --- Patch [10]: [PATCH RESEND 10/17] drm/spacemit: add Saturn DPU KMS pipeline ---
> commit cf6665928c2c5fcf07a88c5cd2141feb18245e17
> Author: Cody Kang <codykang.hk@gmail.com>
> Subject: drm/spacemit: add Saturn DPU KMS pipeline
>
> Add the atomic KMS implementation on top of the hardware backend: one
> CRTC and one primary plane per DPU instance. atomic_check validates
> the plane rectangle 1:1 against the mode and sizes the per-channel FBC
> line buffer.
>
> > diff --git a/drivers/gpu/drm/spacemit/spacemit_crtc.c b/drivers/gpu/drm/spacemit/spacemit_crtc.c
> > new file mode 100644
> > index 0000000000000..b75ff63205011
> > --- /dev/null
> > +++ b/drivers/gpu/drm/spacemit/spacemit_crtc.c
>
> [ ... ]
>
> > @@ -91,7 +91,7 @@ static void spacemit_crtc_atomic_enable(struct drm_crtc *crtc,
> >  		dpu_reset_assert(a_crtc->dev, "lcd", a_crtc->lcd_reset);
> >  		dpu_reset_assert(a_crtc->dev, "esc", a_crtc->esc_reset);
> >  		dpu_reset_assert(a_crtc->dev, "mclk", a_crtc->mclk_reset);
> >  		dpu_reset_assert(a_crtc->dev, "aclk", a_crtc->aclk_reset);
> >  		dpu_reset_assert(a_crtc->dev, "dsc", a_crtc->dsc_reset);
> >  		usleep_range(10000, 20000);
>
> [Severity: High]
> Does this sleep in an atomic context? The spacemit_crtc_atomic_enable
> callback is executed during a non-blocking DRM atomic commit, which runs
> in an atomic context. Calling usleep_range() here might violate atomic
> context rules and lead to scheduling-while-atomic warnings.

atomic_enable runs from the commit tail worker, which is process
context; sleeping is allowed.

> [ ... ]
>
> > @@ -145,13 +145,13 @@ static void spacemit_crtc_atomic_disable(struct drm_crtc *crtc,
> >  	 * must finish its status reads before dpu_pm_suspend() gates the
> >  	 * clocks.
> >  	 */
> >  	if (a_crtc->irq_online > 0)
> >  		synchronize_irq(a_crtc->irq_online);
>
> [Severity: High]
> Can synchronize_irq() safely execute here? This callback runs in an atomic
> context, but synchronize_irq() blocks waiting for executing handlers.

atomic_disable also runs in the commit tail (process context);
synchronize_irq() is legal there.

> [Severity: High]
> Does this code leave a race window before the flags are updated? An interrupt
> could fire immediately after synchronize_irq() returns but before clocks_on
> is toggled to false, leading the ISR to access MMIO while dpu_pm_suspend()
> is shutting down the clocks.

The DPU cannot raise its interrupt while its own clocks are off, so
the window is not exploitable; still, will move the flag update
after dpu_pm_resume() in v2.

> >
> >  	/*
> >  	 * Nothing else cancels the watchdog; it would fire against freed state.
> >  	 */
> >  	timer_delete_sync(&a_crtc->cfg_rdy_timer);
> >
> >  	/* Close the ISR's MMIO gate before the clocks actually stop. */
> >  	a_crtc->clocks_on = false;
> >  	dpu_pm_suspend(a_crtc->dev);
>
> [Severity: High]
> Does dpu_pm_suspend() sleep in this atomic context? It calls usleep_range()
> which could trigger kernel warnings and deadlocks when reached via
> spacemit_crtc_atomic_disable().

Process context, as above.

> >
> >  	spin_lock_irq(&drm->event_lock);
> >  	if (crtc->state->event) {
> >  		drm_crtc_send_vblank_event(crtc, crtc->state->event);
> >  		crtc->state->event = NULL;
> >  	}
> >  	spin_unlock_irq(&drm->event_lock);
>
> [Severity: High]
> Is it safe to use unconditional spin_unlock_irq() here? Since this callback
> executes in an atomic context (e.g. from drm_atomic_helper_commit_tail),
> unconditionally re-enabling interrupts breaks the caller's atomic assumptions.
> Should this use spin_lock_irqsave() and spin_unlock_irqrestore() instead?

The callback is not entered with interrupts disabled (commit tail);
the event_lock pattern here matches the drm helpers' own usage.

> [ ... ]
>
> > @@ -231,6 +231,5 @@ static struct drm_crtc_state *
> >  	__drm_atomic_helper_crtc_duplicate_state(crtc, &state->base);
> >
> >  	n_rdma = hwdev->rdma_nums;
> >  	state->rdmas = kzalloc_objs(*state->rdmas, n_rdma);
> >  	if (!state->rdmas) {
> >  		kfree(state);
> >  		return NULL;
> >  	}
>
> [Severity: Medium]
> Does this error path leak DRM property blob references?
> __drm_atomic_helper_crtc_duplicate_state() increments references on blobs
> like mode_blob, ctm, and gamma_lut. Returning NULL here without releasing
> them could leak those references.

Real; will fix in v2 with __drm_atomic_helper_crtc_destroy_state()
on that error path.

> [ ... ]
>
> > @@ -418,6 +418,5 @@ static irqreturn_t spacemit_dpu_isr(int irq, void *data)
> >  	/* Reading a clock-gated DPU's status registers stalls the bus. */
> >  	if (unlikely(!a_crtc->clocks_on)) {
> >  		drm_dev_exit(idx);
> >  		return IRQ_NONE;
> >  	}
>
> [Severity: High]
> Does this code cause an IRQ storm? By returning IRQ_NONE without clearing
> the hardware interrupt status when clocks_on is false, the interrupt
> controller might continuously re-trigger the ISR if the bootloader left the
> interrupt asserted.

Only reachable in the unbind window where the line is being torn
down; otherwise the ISR acks all status it observes.

> [ ... ]
>
> > @@ -496,6 +496,5 @@ static int spacemit_drm_master_bind(struct device *dev)
> >  	}
> >
> >  	kms = devm_drm_dev_alloc(dev, &spacemit_drm_drv,
> >  				 struct spacemit_kms, drm);
> >  	if (IS_ERR(kms))
>
> [Severity: High]
> Will this leak the DRM device on rebind? devm_drm_dev_alloc ties the
> allocation lifetime to the platform device's probe/remove cycle. If the
> component unbinds and rebinds, new DRM devices are allocated but the old
> ones are never freed.

A known trade-off of devm on the component master: the device is
unregistered at unbind and the memory is bounded by the platform
device lifetime.

> [ ... ]
>
> > @@ -573,6 +573,5 @@ static int spacemit_drm_master_bind(struct device *dev)
> >  	drm_mode_config_reset(drm);
> >  	drmm_kms_helper_poll_init(drm);
> >  	drm_helper_hpd_irq_event(drm);
> >
> >  	enable_irq(priv->irq_online);
>
> [Severity: High]
> Is it safe to enable the IRQ before the hardware state is fully initialized?
> If the bootloader left the display hardware active, the ISR might fire
> immediately while a_crtc->clocks_on is still false, leading to the IRQ storm
> mentioned above.

The ISR is gated on clocks_on and drm_dev_enter, and every board
cycle boots through this path; no storm has been observed.

> [ ... ]
>
> > @@ -594,6 +594,5 @@ static void spacemit_drm_master_unbind(struct device *dev)
> >
> >  	disable_irq(priv->irq_online);
> >
> >  	drm_dev_unregister(drm);
> >  	drm_atomic_helper_shutdown(drm);
> >  	component_unbind_all(dev, drm);
>
> [Severity: High]
> Will calling drm_atomic_helper_shutdown() hang if the IRQ is already
> disabled? The shutdown helper flushes pending atomic commits and disables
> CRTCs, which requires the hardware vblank interrupt to signal completion.
> Without it, the commit wait could time out.

Confirmed on hardware: the fbdev-restore commit arms the CFG_RDY
handshake after the line is dead, and every unload rode two watchdog
timeouts. Will reorder in v2: unregister and shutdown before
disable_irq().

> > diff --git a/drivers/gpu/drm/spacemit/spacemit_planes.c b/drivers/gpu/drm/spacemit/spacemit_planes.c
> > new file mode 100644
> > index 0000000000000..3442013b0c37f
> > --- /dev/null
> > +++ b/drivers/gpu/drm/spacemit/spacemit_planes.c
>
> [ ... ]
>
> > @@ -98,6 +98,5 @@ static int spacemit_plane_atomic_check(struct drm_plane *plane,
> >  	if (src_w == 0 && src_h == 0)
> >  		cur_rdma_id = RDMA_INVALID_ID;	/* constant-fill layer, no RDMA */
> >  	else if (cur_rdma_id == RDMA_INVALID_ID)
> >  		cur_rdma_id = state->zpos;	/* first commit: bind channel by zpos */
> >  	cur_state->rdma_id = cur_rdma_id;
>
> [Severity: High]
> Does this code assign RDMA channels based on unvalidated zpos? Userspace
> could submit a configuration with duplicate zpos values across multiple
> planes, resulting in channel collisions where planes overwrite each other's
> hardware registers during spacemit_plane_atomic_update().

There is a single primary plane per CRTC, so no collision is
possible; rdma_id is also bounds-checked in atomic_check.

> [ ... ]
>
> > @@ -193,7 +193,6 @@ static void spacemit_plane_reset(struct drm_plane *plane)
> >  	if (plane->state) {
> >  		s = to_spacemit_plane_state(plane->state);
> >  		__drm_atomic_helper_plane_destroy_state(plane->state);
> >  		kfree(s);
> >  		plane->state = NULL;
> >  	}
>
> [Severity: High]
> Does freeing the state directly bypass the driver's custom destructor?
> Calling kfree(s) directly in spacemit_plane_reset() skips
> spacemit_plane_atomic_destroy_state(), which means the DMA coherent buffers
> for mmu_tbl.va and cl.va could be permanently leaked when a plane is reset.

Real; will route .reset through the custom destroy in v2, the same
way the CRTC side already does.

> [ ... ]
>
> > @@ -211,6 +211,5 @@ static struct drm_plane_state *
> >  spacemit_plane_atomic_duplicate_state(struct drm_plane *plane)
> >  {
> >  	struct spacemit_plane_state *s;
> >  	struct spacemit_plane_state *old_state =
> >  			to_spacemit_plane_state(plane->state);
> >  	struct spacemit_crtc *a_crtc = NULL;
>
> [Severity: Medium]
> Will this crash if plane->state is NULL? The to_spacemit_plane_state()
> macro uses container_of, which will produce a negative pointer if
> plane->state is NULL. Dereferencing old_state->rdma_id later would trigger
> a fault.

The core only calls duplicate_state with an existing state; this is
the same contract the helpers themselves rely on.

Cody

-- 
linux-phy mailing list
linux-phy@lists.infradead.org
https://lists.infradead.org/mailman/listinfo/linux-phy

  reply	other threads:[~2026-08-09  0:59 UTC|newest]

Thread overview: 48+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-25  4:51 [PATCH RESEND 00/17] drm/spacemit: add SpacemiT K3 display support Cody Kang via B4 Relay
2026-07-25  4:51 ` [PATCH RESEND 01/17] dt-bindings: display: spacemit: add K3 Saturn DPU controller Cody Kang via B4 Relay
2026-08-07 22:58   ` Rob Herring (Arm)
2026-07-25  4:51 ` [PATCH RESEND 02/17] dt-bindings: phy: add SpacemiT K3 Innosilicon DP PHY Cody Kang via B4 Relay
2026-08-07 23:00   ` Rob Herring (Arm)
2026-07-25  4:51 ` [PATCH RESEND 03/17] dt-bindings: display: spacemit: add K3 Innosilicon DP/eDP controller Cody Kang via B4 Relay
2026-08-07 23:04   ` Rob Herring
2026-08-08 14:39     ` Cody Kang
2026-07-25  4:51 ` [PATCH RESEND 04/17] dt-bindings: soc: spacemit: allow eDP/DP PHY PLL pixel clocks on K3 APMU Cody Kang via B4 Relay
2026-08-07 23:08   ` Rob Herring
2026-08-08 14:29     ` Cody Kang
2026-07-25  4:51 ` [PATCH RESEND 05/17] phy: spacemit: add Innosilicon DP TX PHY driver Cody Kang via B4 Relay
2026-07-25  5:02   ` sashiko-bot
2026-08-08  9:48     ` Cody Kang
2026-07-29 12:36   ` Uwe Kleine-König
2026-08-08 14:14     ` Cody Kang
2026-07-25  4:51 ` [PATCH RESEND 06/17] clk: spacemit: k3: parent eDP/DP pixel clock to the PHY PLL Cody Kang via B4 Relay
2026-07-25  4:51 ` [PATCH RESEND 07/17] drm/spacemit: add Saturn DPU register model Cody Kang via B4 Relay
2026-07-25  4:51 ` [PATCH RESEND 08/17] drm/spacemit: add Saturn DPU core types, cmdlist and display MMU Cody Kang via B4 Relay
2026-07-25  5:04   ` sashiko-bot
2026-08-09  0:39     ` Cody Kang
2026-07-27  7:35   ` Philipp Zabel
2026-08-08 13:07     ` Cody Kang
2026-07-25  4:51 ` [PATCH RESEND 09/17] drm/spacemit: add Saturn DPU hardware backend Cody Kang via B4 Relay
2026-07-25  5:12   ` sashiko-bot
2026-07-25  4:51 ` [PATCH RESEND 10/17] drm/spacemit: add Saturn DPU KMS pipeline Cody Kang via B4 Relay
2026-07-25  5:04   ` sashiko-bot
2026-08-09  0:59     ` Cody Kang [this message]
2026-07-27  7:35   ` Philipp Zabel
2026-08-08  5:03     ` Guodong Xu
2026-08-09  3:26       ` Cody Kang
2026-08-08 13:21     ` Cody Kang
2026-07-25  4:51 ` [PATCH RESEND 11/17] drm/spacemit: add Saturn DPU DRM device driver Cody Kang via B4 Relay
2026-07-25  5:05   ` sashiko-bot
2026-07-25  4:51 ` [PATCH RESEND 12/17] drm/spacemit: add Innosilicon DP/eDP controller bridge driver Cody Kang via B4 Relay
2026-07-25  5:04   ` sashiko-bot
2026-08-08 12:51     ` Cody Kang
2026-07-27  7:49   ` Philipp Zabel
2026-08-08 13:30     ` Cody Kang
2026-07-27 12:29   ` Yao Zi
2026-08-08 14:07     ` Cody Kang
2026-07-25  4:51 ` [PATCH RESEND 13/17] MAINTAINERS: add SpacemiT K3 display driver entry Cody Kang via B4 Relay
2026-07-25  4:51 ` [PATCH RESEND 14/17] riscv: dts: spacemit: k3: add display nodes Cody Kang via B4 Relay
2026-07-25  5:08   ` sashiko-bot
2026-07-25  4:51 ` [PATCH RESEND 15/17] riscv: dts: spacemit: k3-pico-itx: enable the DisplayPort output Cody Kang via B4 Relay
2026-07-25  5:12   ` sashiko-bot
2026-07-25  4:51 ` [PATCH RESEND 16/17] riscv: dts: spacemit: k3-com260-ifx: " Cody Kang via B4 Relay
2026-07-25  4:51 ` [PATCH RESEND 17/17] riscv: defconfig: spacemit: k3: enable display driver Cody Kang via B4 Relay

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=242adca6fe63a63e0f637da9603cde06.codykang.hk@gmail.com \
    --to=codykang.hk@gmail.com \
    --cc=conor+dt@kernel.org \
    --cc=devicetree@vger.kernel.org \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=linux-phy@lists.infradead.org \
    --cc=neil.armstrong@linaro.org \
    --cc=olteanv@gmail.com \
    --cc=robh@kernel.org \
    --cc=sashiko-bot@kernel.org \
    --cc=sashiko-reviews@lists.linux.dev \
    --cc=vkoul@kernel.org \
    /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