From: sashiko-bot@kernel.org
To: "Cody Kang" <codykang.hk@gmail.com>
Cc: vkoul@kernel.org, dri-devel@lists.freedesktop.org,
conor+dt@kernel.org, devicetree@vger.kernel.org,
olteanv@gmail.com, linux-phy@lists.infradead.org,
neil.armstrong@linaro.org, robh@kernel.org
Subject: Re: [PATCH v2 10/17] drm/spacemit: add Saturn DPU KMS pipeline
Date: Sun, 09 Aug 2026 13:35:28 +0000 [thread overview]
Message-ID: <20260809133529.9A5571F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260809-k3-display-v2-10-327d7910bf71@gmail.com>
Thank you for your contribution! Sashiko AI review found 9 potential issue(s) to consider:
- [Critical] Early return in atomic_disable due to drm_dev_enter skips hardware teardown and timer cancellation.
- [Critical] Permanent physical memory leak due to unbalanced page pinning in spacemit_dmmu_map.
- [High] Sleeping functions called from atomic context in CRTC atomic_enable and atomic_disable callbacks.
- [High] Plane atomic_update callback invokes sleeping GEM helpers.
- [High] Interrupt storm due to unhandled IRQ during device bind.
- [High] Race condition between IRQ synchronization and clock gating.
- [High] Memory leak of DRM device on component unbind.
- [High] Unconditional interrupt enable via spin_unlock_irq in atomic context.
- [High] Ignored return value of get_cl_rdma_buf leads to Use-After-Free of command list registers.
--
--- Patch [10]: [PATCH v2 10/17] drm/spacemit: add Saturn DPU KMS pipeline ---
commit f9572a94b08eefdd84a13496054fbc00b42837b7
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; atomic commit builds the cmdlist batches, maps the
framebuffer through the DMMU and arms the cfg-ready handshake, with
vblank events driven from the DPU interrupt.
> diff --git a/drivers/gpu/drm/spacemit/spacemit_crtc.c b/drivers/gpu/drm/spacemit/spacemit_crtc.c
> --- /dev/null
> +++ b/drivers/gpu/drm/spacemit/spacemit_crtc.c
[ ... ]
> @@ -96,25 +96,25 @@ static void spacemit_crtc_atomic_enable(struct drm_crtc *crtc,
> struct drm_atomic_commit *old_state)
> {
[ ... ]
> if (unlikely(a_crtc->first_modeset)) {
> ret = reset_control_bulk_assert(ARRAY_SIZE(priv->pipe_resets),
> priv->pipe_resets);
> if (ret)
> dev_warn(a_crtc->dev,
> "failed to assert resets: %d\n", ret);
> usleep_range(10000, 20000);
> a_crtc->first_modeset = false;
> }
>
> if (!a_crtc->clocks_on) {
> dpu_pm_resume(a_crtc->dev);
> a_crtc->clocks_on = true;
>
> /*
> * The DPU must settle after reset deassert or CFG_RDY races
> * the flush.
> */
> usleep_range(10000, 20000);
> }
[Severity: High]
Could the usleep_range() calls cause system instability?
The DRM subsystem requires CRTC atomic_enable and atomic_disable callbacks to
execute in atomic context, where sleeping is strictly forbidden.
Because usleep_range() sleeps, calling it directly here violates the atomic
context constraints.
[ ... ]
> @@ -131,23 +129,20 @@ static void spacemit_crtc_atomic_disable(struct drm_crtc *crtc,
> struct drm_atomic_commit *old_state)
> {
> struct spacemit_crtc *a_crtc = to_spacemit_crtc(crtc);
> struct drm_device *drm = a_crtc->crtc.dev;
> int idx;
>
> if (!drm_dev_enter(drm, &idx))
> return;
[Severity: Critical]
Does checking drm_dev_enter() here inadvertently skip hardware teardown
during unbind?
During driver unbind, spacemit_drm_master_unbind() calls drm_dev_unregister(),
which sets the unplugged flag. It then calls drm_atomic_helper_shutdown(),
which invokes spacemit_crtc_atomic_disable().
Because the device is already marked unplugged, drm_dev_enter() evaluates to
false. This causes an immediate return, bypassing the timer cancellation
(which leaves a pending timer pointing to freed memory) and the VBLANK event
signaling (which can stall the teardown commit).
[ ... ]
> /*
> * MMIO on a clock-gated DPU stalls the bus, so an in-flight handler
> * 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]
Is it safe to call synchronize_irq() in atomic context?
This function can sleep, which violates the requirement that atomic_disable
callbacks execute in atomic context without sleeping.
> /*
> * 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]
Might this sequence allow a new interrupt to slip in?
If synchronize_irq() completes, it only guarantees that in-flight handlers
have finished. Because a_crtc->clocks_on is still true when it returns, a
newly triggered interrupt could immediately enter the ISR.
Meanwhile, this thread continues, setting a_crtc->clocks_on to false and
calling dpu_pm_suspend() to gate the clocks. If the racing ISR attempts
MMIO reads on the clock-gated hardware, it could stall the system bus.
Additionally, does dpu_pm_suspend() sleep in this atomic context? It
invokes usleep_range() internally, which would violate the atomic_disable
constraints.
> 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]
Will this unconditionally re-enable local interrupts?
Because spacemit_crtc_atomic_disable() executes in atomic context, the caller
might have already disabled interrupts. Calling spin_unlock_irq() re-enables
them unconditionally.
Would it be better to use spin_unlock_irqrestore() to preserve the original
CPU interrupt state?
[ ... ]
> @@ -467,20 +465,19 @@ 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))
> return PTR_ERR(kms);
[Severity: High]
Will this leak the DRM device structure on component unbind?
The KMS structure is allocated with devm_drm_dev_alloc() inside
spacemit_drm_master_bind(). The devm_* lifecycle is tied to the platform
device's probe and remove cycle, not the component bind and unbind cycle.
When spacemit_drm_master_unbind() is called, the DRM device is unregistered
but never freed because the platform device is not removed. A subsequent
re-bind would allocate a new instance, permanently leaking the old one along
with all drmm_* managed allocations.
[ ... ]
> enable_irq(priv->irq_online);
>
> ret = drm_dev_register(drm, 0);
[Severity: High]
Could enabling the IRQ here lead to an interrupt storm?
At this point during bind, the hardware might not be fully reset and
a_crtc->clocks_on is still false. If a bootloader left the display pipeline
active, the hardware will continuously assert the interrupt.
When the ISR fires, it sees !a_crtc->clocks_on and immediately returns
IRQ_NONE without clearing the hardware interrupt status. This causes the
interrupt to fire repeatedly, potentially hanging the system.
> diff --git a/drivers/gpu/drm/spacemit/spacemit_planes.c b/drivers/gpu/drm/spacemit/spacemit_planes.c
> --- /dev/null
> +++ b/drivers/gpu/drm/spacemit/spacemit_planes.c
[ ... ]
> @@ -170,25 +170,24 @@ static void spacemit_plane_atomic_update(struct drm_plane *plane,
> struct drm_atomic_commit *state)
> {
[ ... ]
> hwdev->get_cl_rdma_buf(a_crtc);
[Severity: High]
What happens if hwdev->get_cl_rdma_buf() fails here?
If the return value is ignored and it fails to allocate, a_crtc->cl_rdma could
remain uninitialized or retain a dangling pointer from a previous iteration.
Later, free_cmdlist_regs(a_crtc->cl_rdma) frees the pointer but does not set
it to NULL. If a subsequent plane update fails its allocation, it would
double-free the old pointer.
> hwdev->plane_update_hw_channel(plane);
>
> /* Solid-fill layers have no RDMA and no page table */
> if (rdma_id < hwdev->rdma_nums && spacemit_pstate->mmu_tbl.va) {
> u8 tbu_id = rdma_id * 2;
>
> ret = spacemit_dmmu_map(plane->state->fb,
> &spacemit_pstate->mmu_tbl, tbu_id,
> a_crtc->cl_rdma, plane);
[Severity: High]
Does this path invoke sleeping functions from atomic context?
The spacemit_plane_atomic_update() callback executes in atomic context.
However, it calls spacemit_dmmu_map(), which subsequently calls
drm_gem_shmem_get_pages_sgt().
The drm_gem_shmem_get_pages_sgt() helper acquires the pages_lock mutex and
can block for disk I/O or GFP_KERNEL allocations, which is unsafe in
atomic context. Should this mapping be deferred to the prepare_fb phase?
[Severity: Critical]
Is there a missing unpin for the pages acquired inside the mapping function?
Calling drm_gem_shmem_get_pages_sgt() retrieves the scatter-gather table
and implicitly pins the backing physical pages by incrementing the object's
pages_use_count.
Since this occurs on every plane atomic update, and there appears to be no
matching drm_gem_shmem_put_pages() call during cleanup, the pages_use_count
will continually inflate. This prevents the GEM SHMEM core from releasing the
physical pages when the framebuffer is destroyed, leading to a permanent
memory leak.
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260809-k3-display-v2-0-327d7910bf71@gmail.com?part=10
next prev parent reply other threads:[~2026-08-09 13:35 UTC|newest]
Thread overview: 27+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-08-09 13:14 [PATCH v2 00/17] drm/spacemit: add SpacemiT K3 display support Cody Kang via B4 Relay
2026-08-09 13:14 ` [PATCH v2 01/17] dt-bindings: display: spacemit: add K3 Saturn DPU controller Cody Kang via B4 Relay
2026-08-09 13:14 ` [PATCH v2 02/17] dt-bindings: phy: add SpacemiT K3 Innosilicon DP PHY Cody Kang via B4 Relay
2026-08-09 13:14 ` [PATCH v2 03/17] dt-bindings: display: spacemit: add K3 Innosilicon DP/eDP controller Cody Kang via B4 Relay
2026-08-09 13:25 ` sashiko-bot
2026-08-09 13:14 ` [PATCH v2 04/17] dt-bindings: soc: spacemit: allow eDP/DP PHY PLL pixel clocks on K3 APMU Cody Kang via B4 Relay
2026-08-09 20:57 ` Rob Herring (Arm)
2026-08-09 13:14 ` [PATCH v2 05/17] phy: spacemit: add Innosilicon DP TX PHY driver Cody Kang via B4 Relay
2026-08-09 13:26 ` sashiko-bot
2026-08-09 13:14 ` [PATCH v2 06/17] clk: spacemit: k3: parent eDP/DP pixel clock to the PHY PLL Cody Kang via B4 Relay
2026-08-09 13:14 ` [PATCH v2 07/17] drm/spacemit: add Saturn DPU register model Cody Kang via B4 Relay
2026-08-09 13:14 ` [PATCH v2 08/17] drm/spacemit: add Saturn DPU core types, cmdlist and display MMU Cody Kang via B4 Relay
2026-08-09 13:32 ` sashiko-bot
2026-08-09 13:14 ` [PATCH v2 09/17] drm/spacemit: add Saturn DPU hardware backend Cody Kang via B4 Relay
2026-08-09 13:31 ` sashiko-bot
2026-08-09 13:14 ` [PATCH v2 10/17] drm/spacemit: add Saturn DPU KMS pipeline Cody Kang via B4 Relay
2026-08-09 13:35 ` sashiko-bot [this message]
2026-08-09 13:14 ` [PATCH v2 11/17] drm/spacemit: add Saturn DPU DRM device driver Cody Kang via B4 Relay
2026-08-09 13:35 ` sashiko-bot
2026-08-09 13:14 ` [PATCH v2 12/17] drm/spacemit: add Innosilicon DP/eDP controller bridge driver Cody Kang via B4 Relay
2026-08-09 13:36 ` sashiko-bot
2026-08-09 13:14 ` [PATCH v2 13/17] MAINTAINERS: add SpacemiT K3 display driver entry Cody Kang via B4 Relay
2026-08-09 13:14 ` [PATCH v2 14/17] riscv: dts: spacemit: k3: add display nodes Cody Kang via B4 Relay
2026-08-09 13:14 ` [PATCH v2 15/17] riscv: dts: spacemit: k3-pico-itx: enable the DisplayPort output Cody Kang via B4 Relay
2026-08-09 13:30 ` sashiko-bot
2026-08-09 13:14 ` [PATCH v2 16/17] riscv: dts: spacemit: k3-com260-ifx: " Cody Kang via B4 Relay
2026-08-09 13:14 ` [PATCH v2 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=20260809133529.9A5571F000E9@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=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-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