From: sashiko-bot@kernel.org
To: "Jiaxing Hu" <gahing@gahingwoo.com>
Cc: devicetree@vger.kernel.org, robh@kernel.org, conor+dt@kernel.org,
dri-devel@lists.freedesktop.org
Subject: Re: [RFC PATCH v3 4/6] accel/rocket: add RK3576 NPU (RKNN) support
Date: Fri, 31 Jul 2026 04:54:31 +0000 [thread overview]
Message-ID: <20260731045431.7E1051F000E9@smtp.kernel.org> (raw)
In-Reply-To: <20260731043507.1832277-5-gahing@gahingwoo.com>
Thank you for your contribution! Sashiko AI review found 4 potential issue(s) to consider:
New issues:
- [High] Missing teardown of `poll_timer` and `poll_work` causes use-after-free on module unload or device teardown.
- [High] Stale `poll_work` execution can prematurely complete and corrupt newly submitted jobs because pending work is not cancelled.
Pre-existing issues:
- [High] The shared IRQ handler accesses hardware registers without ensuring the device is active, causing potential crashes if the device is suspended.
- [High] Unbalanced `iommu_group_get()` leaks an IOMMU group reference on every job completion.
--
--- Patch [4]: [RFC PATCH v3 4/6] accel/rocket: add RK3576 NPU (RKNN) support ---
commit dd0a45989eab5a4ff6b90c355a58e175aad35c8f
Author: Jiaxing Hu <gahing@gahingwoo.com>
accel/rocket: add RK3576 NPU (RKNN) support
The RK3576 carries the same RKNN block as the RK3588, with two cores
instead of three and a few platform differences:
- the CBUF (convolution buffer) has its own clock domain, so the core
needs six clocks rather than four;
- the BIU reset moved into the power domain, leaving one reset here;
- the NPU spans two power domains, and a device with more than one is
skipped by the driver-core single-domain auto-attach, so the list has
to be attached explicitly;
- the DPU completion interrupt is armed exactly as on RK3588 but never
reaches the GIC. The completion is visible in INTERRUPT_RAW_STATUS,
so sample that from an hrtimer rather than wait for an interrupt that
does not come. The interrupt stays armed, so if it ever does arrive
the normal handler finalises the job first.
Select all of that from of_device_id match data so the RK3588 path keeps
its existing counts and behaviour unchanged.
> diff --git a/drivers/accel/rocket/rocket_drv.c b/drivers/accel/rocket/rocket_drv.c
> index 8bbbce594883e..7f7dfa3742fc8 100644
> --- a/drivers/accel/rocket/rocket_drv.c
> +++ b/drivers/accel/rocket/rocket_drv.c
[ ... ]
> @@ -260,7 +276,7 @@ static int rocket_device_runtime_suspend(struct device *dev)
> if (!rocket_job_is_idle(&rdev->cores[core]))
> return -EBUSY;
>
> - clk_bulk_disable_unprepare(ARRAY_SIZE(rdev->cores[core].clks), rdev->cores[core].clks);
> + clk_bulk_disable_unprepare(rdev->cores[core].soc->num_clks, rdev->cores[core].clks);
>
> return 0;
> }
[Severity: High]
This is a pre-existing issue, but can the shared IRQ handler crash if it runs
while the device is suspended?
The NPU driver registers its interrupt handler rocket_job_irq_handler() with
IRQF_SHARED. The hardirq handler unconditionally reads the
INTERRUPT_RAW_STATUS MMIO register without calling pm_runtime_get_if_active().
Additionally, rocket_device_runtime_suspend() disables hardware clocks here
without calling synchronize_irq().
If another device sharing the IRQ line triggers an interrupt while the NPU
is runtime-suspended, the handler will attempt to read powered-down hardware.
Should the suspend callback use synchronize_irq() and the IRQ handler verify
the device is active?
> diff --git a/drivers/accel/rocket/rocket_job.c b/drivers/accel/rocket/rocket_job.c
> index bb77b6bf0f231..e9103a93020cc 100644
> --- a/drivers/accel/rocket/rocket_job.c
> +++ b/drivers/accel/rocket/rocket_job.c
[ ... ]
> @@ -341,8 +358,42 @@ static struct dma_fence *rocket_job_run(struct drm_sched_job *sched_job)
> return ERR_PTR(ret);
> }
>
> +static void rocket_job_handle_irq(struct rocket_core *core);
> +
> +static enum hrtimer_restart rocket_poll_timer_fn(struct hrtimer *timer)
> +{
> + struct rocket_core *core = container_of(timer, struct rocket_core, poll_timer);
> + u32 raw;
> +
> + if (!atomic_read(&core->poll_active))
> + return HRTIMER_NORESTART;
> +
> + raw = rocket_pc_readl(core, INTERRUPT_RAW_STATUS);
> + if ((raw & (PC_INTERRUPT_RAW_STATUS_DPU_0 | PC_INTERRUPT_RAW_STATUS_DPU_1)) ||
> + ++core->poll_ticks >= RK3576_POLL_MAX_TICKS) {
> + atomic_set(&core->poll_active, 0);
> + schedule_work(&core->poll_work);
> + return HRTIMER_NORESTART;
> + }
> +
> + hrtimer_forward_now(timer, ns_to_ktime(RK3576_POLL_INTERVAL_NS));
> + return HRTIMER_RESTART;
> +}
> +
> +static void rocket_poll_work_fn(struct work_struct *work)
> +{
> + struct rocket_core *core = container_of(work, struct rocket_core, poll_work);
> +
> + rocket_job_handle_irq(core);
> +}
> +
> static void rocket_job_handle_irq(struct rocket_core *core)
> {
> + if (core->soc->poll_completion) {
> + atomic_set(&core->poll_active, 0);
> + hrtimer_cancel(&core->poll_timer);
> + }
> +
[Severity: High]
Can a stale poll_work execution corrupt the next job?
If a real hardware IRQ arrives after poll_timer queues poll_work, the real
IRQ handles the completion and cancels the timer here. However, poll_work
could remain pending in the workqueue.
The DRM scheduler could then immediately submit the next job. When the stale
poll_work executes, it calls rocket_job_handle_irq() which would incorrectly
mark the new job as finished, signal its completion fence early, detach its
IOMMU group, and halt the hardware.
Does the driver need a way to cancel the pending work or ignore it if it is
no longer relevant, both here and in rocket_reset()?
[Severity: High]
This is a pre-existing issue, but does this function leak an IOMMU group
reference on every job completion?
Further down in rocket_job_handle_irq(), the code calls:
iommu_detach_group(NULL, iommu_group_get(core->dev));
The iommu_group_get() function increments the kobject reference count, but
iommu_detach_group() does not consume it. Because there is no matching
iommu_group_put(), a reference is leaked every time a job finishes. Should
this use the existing core->iommu_group pointer instead?
> pm_runtime_mark_last_busy(core->dev);
>
> rocket_pc_writel(core, OPERATION_ENABLE, 0x0);
[ ... ]
> @@ -460,6 +511,10 @@ int rocket_job_init(struct rocket_core *core)
> int ret;
>
> INIT_WORK(&core->reset.work, rocket_reset_work);
> + INIT_WORK(&core->poll_work, rocket_poll_work_fn);
> + hrtimer_setup(&core->poll_timer, rocket_poll_timer_fn, CLOCK_MONOTONIC,
> + HRTIMER_MODE_REL);
> + atomic_set(&core->poll_active, 0);
[Severity: High]
Does this code leak the timer and work on module unload?
Since poll_timer and poll_work are initialized here, shouldn't they be
cancelled in rocket_job_fini() with hrtimer_cancel() and cancel_work_sync()?
Because the rocket_core struct is allocated with devm_kcalloc(), it is freed
shortly after driver removal. If the timer fires or the pending work executes
after the memory is freed, it could cause a use-after-free crash.
> spin_lock_init(&core->fence_lock);
> mutex_init(&core->job_lock);
>
--
Sashiko AI review · https://sashiko.dev/#/patchset/20260731043507.1832277-1-gahing@gahingwoo.com?part=4
next prev parent reply other threads:[~2026-07-31 4:54 UTC|newest]
Thread overview: 19+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-07-31 4:35 [RFC PATCH v3 0/6] accel/rocket: RK3576 NPU (RKNN) enablement Jiaxing Hu
2026-07-31 4:35 ` Jiaxing Hu
2026-07-31 4:35 ` [RFC PATCH v3 1/6] dt-bindings: npu: rockchip: add rockchip,rk3576-rknn-core Jiaxing Hu
2026-07-31 4:35 ` [RFC PATCH v3 1/6] dt-bindings: npu: rockchip: add rockchip, rk3576-rknn-core Jiaxing Hu
2026-07-31 4:35 ` [RFC PATCH v3 1/6] dt-bindings: npu: rockchip: add rockchip,rk3576-rknn-core Jiaxing Hu
2026-07-31 4:35 ` [RFC PATCH v3 2/6] pmdomain/rockchip: add optional per-domain power-on settle delay Jiaxing Hu
2026-07-31 4:35 ` Jiaxing Hu
2026-07-31 4:35 ` [RFC PATCH v3 3/6] pmdomain/rockchip: cycle optional power-domain resets on power-on Jiaxing Hu
2026-07-31 4:35 ` Jiaxing Hu
2026-07-31 4:50 ` sashiko-bot
2026-07-31 4:35 ` [RFC PATCH v3 4/6] accel/rocket: add RK3576 NPU (RKNN) support Jiaxing Hu
2026-07-31 4:35 ` Jiaxing Hu
2026-07-31 4:54 ` sashiko-bot [this message]
2026-07-31 4:35 ` [RFC PATCH v3 5/6] arm64: dts: rockchip: rk3576: add NPU (RKNN) nodes Jiaxing Hu
2026-07-31 4:35 ` Jiaxing Hu
2026-07-31 4:51 ` sashiko-bot
2026-07-31 4:35 ` [RFC PATCH v3 6/6] arm64: dts: rockchip: rk3576-rock-4d: enable NPU Jiaxing Hu
2026-07-31 4:35 ` Jiaxing Hu
2026-07-31 4:51 ` 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=20260731045431.7E1051F000E9@smtp.kernel.org \
--to=sashiko-bot@kernel.org \
--cc=conor+dt@kernel.org \
--cc=devicetree@vger.kernel.org \
--cc=dri-devel@lists.freedesktop.org \
--cc=gahing@gahingwoo.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.