dri-devel Archive on lore.kernel.org
 help / color / mirror / Atom feed
From: sashiko-bot@kernel.org
To: "Karunika Choo" <karunika.choo@arm.com>
Cc: dri-devel@lists.freedesktop.org
Subject: Re: [PATCH v1 16/27] drm/panthor: Add arbitration scheduler
Date: Tue, 22 Sep 2026 21:00:21 +0000	[thread overview]
Message-ID: <20260922210022.394441F00893@smtp.kernel.org> (raw)
In-Reply-To: <20260922204535.2850094-17-karunika.choo@arm.com>

Thank you for your contribution! Sashiko AI review found 6 potential issue(s) to consider:
- [High] workqueue: infinite loop in reset_work on hardware unresponsiveness
- [High] timers: use-after-free due to timer re-arming by reset_work during teardown
- [High] timers: use-after-free due to missing IRQ teardown in remove error path
- [Medium] pm: incomplete error rollback in panthor_arbitration_sched_suspend()
- [Medium] probe: missing NULL check for devm_kasprintf() return
- [Medium] time: truncation of 64-bit module parameters in msecs_to_jiffies()
--

commit 48cf2a79eb3e38b7bf9c8fdb322edaecd8d1e020
Author: Karunika Choo <karunika.choo@arm.com>

drm/panthor: Add arbitration scheduler

Add a per-partition arbitration scheduler that queues access-window GPU
requests, grants the active window, asks it to stop when its lease
expires, and force-closes it if it does not yield in time.

Track grant, stop and close deadlines with hrtimers so scheduler
progress remains bounded. Use scheduler reset work to recover from
unrecoverable arbitration errors and stale timeout state.

> diff --git a/drivers/gpu/drm/panthor/arbitration/panthor_arbitration_drv.c b/drivers/gpu/drm/panthor/arbitration/panthor_arbitration_drv.c
> index a1068a2c78f1a..2d0c8d95f1abd 100644
> --- a/drivers/gpu/drm/panthor/arbitration/panthor_arbitration_drv.c
> +++ b/drivers/gpu/drm/panthor/arbitration/panthor_arbitration_drv.c
> @@ -56,6 +57,13 @@ static int panthor_arbitration_runtime_suspend(struct device *dev)
>  	struct panthor_arbitration *adev = dev_get_drvdata(dev);
>  	int ret = 0;
>  
> +	if (adev->tearing_down)
> +		return 0;
> +
> +	ret = panthor_arbitration_sched_suspend(adev);
> +	if (ret)
> +		return ret;
> +

[Severity: Medium]
Does returning early here leave the state partially broken?

In panthor_arbitration_sched_suspend(), if panthor_arbitration_sched_stop()
fails for scheduler N, the loop returns an error. Schedulers 0 to N-1 keep
the ARB_SCHED_DISABLE_PM flag. Propagating the error to the PM core here
means it considers the device active and won't call the resume path, which
permanently disables the successful schedulers from scheduling new access
windows.

>  	ret = panthor_resource_group_suspend(adev);
>  	if (ret)
>  		return ret;

[ ... ]

> @@ -151,15 +185,20 @@ static void panthor_arbitration_remove(struct platform_device *pdev)
>  		dev_warn(adev->dev, "failed to resume during remove: %d", ret);
>  
>  	of_platform_depopulate(adev->dev);
> -	panthor_resource_group_cancel_work(adev);
>  
>  	if (ret >= 0) {
> +		adev->tearing_down = true;
> +
> +		panthor_arbitration_sched_term(adev);
> +		panthor_resource_group_cancel_work(adev);
>  		panthor_resource_group_term(adev);
>  		panthor_partition_control_term(adev);
> -		pm_runtime_put_noidle(adev->dev);
> +		pm_runtime_put_sync_suspend(adev->dev);
> +	} else {
> +		panthor_arbitration_sched_cancel(adev);
> +		panthor_resource_group_cancel_work(adev);
> +		pm_runtime_set_suspended(adev->dev);
>  	}

[Severity: High]
Does this error path leave hardware interrupts registered and active?

If pm_runtime_resume_and_get() fails, the error path is taken, but it misses
calling panthor_partition_control_term() or panthor_resource_group_term().

A late shared interrupt could trigger the handler and invoke
panthor_arbitration_sched_on_idle(). Because the scheduler's phase is not
reset in panthor_arbitration_sched_cancel(), it can proceed to
arb_sched_close_locked() which re-arms the timer on a soon-to-be-freed
object, leading to a use-after-free.

> -
> -	pm_runtime_set_suspended(adev->dev);
>  }
>  
>  static const struct dev_pm_ops panthor_arbitration_pm_ops = {
> diff --git a/drivers/gpu/drm/panthor/arbitration/panthor_arbitration_sched.c b/drivers/gpu/drm/panthor/arbitration/panthor_arbitration_sched.c
> new file mode 100644
> index 0000000000000..41f06af92ce0c
> --- /dev/null
> +++ b/drivers/gpu/drm/panthor/arbitration/panthor_arbitration_sched.c

[ ... ]

> +/* This method is not IRQ safe as it sleeps. */
> +static int arb_sched_wait_phase(struct panthor_arbitration_sched *sched,
> +				enum arbitration_sched_phase phase,
> +				u64 timeout_ms)
> +{
> +	if (!wait_event_timeout(
> +		    sched->waitqueue, arb_sched_phase_reached(sched, phase),
> +		    msecs_to_jiffies(timeout_ms))) {

[Severity: Medium]
Will this truncate the 64-bit timeout values?

The module parameters request_timeout and yield_timeout are defined as u64.
In arb_sched_wait_phase(), their sum is passed to msecs_to_jiffies(), which
takes an unsigned int. If userspace sets excessively large timeouts, the
value could truncate silently, resulting in an unexpectedly short or zero
timeout.

> +
> +		if (!arb_sched_phase_reached(sched, phase))
> +			return -ETIMEDOUT;
> +	}

[ ... ]

> +static int __arb_sched_close_locked(struct panthor_arbitration_sched *sched)
> +{
> +	int ret;
> +
> +	lockdep_assert_held(&sched->lock);
> +
> +	ret = panthor_arbitration_on_close(to_adev(sched), sched->active_aw_id);
> +	if (ret < 0) {
> +		dev_err(sched->dev, "%s: Failed to close AW%u", sched->name,
> +			sched->active_aw_id);
> +
> +		arb_sched_queue_work(sched, &sched->reset_work);
> +	}

[Severity: High]
Can this cause an infinite loop in the workqueue?

If the hardware becomes unresponsive and panthor_arbitration_on_close()
persistently returns an error, __arb_sched_close_locked() queues reset_work. 

The reset_work executes arb_sched_force_close_locked(), which recursively
attempts __arb_sched_close_locked(). This fails again and re-queues
reset_work ad infinitum.

> +
> +	return ret;
> +}
> +
> +static void arb_sched_close_locked(struct panthor_arbitration_sched *sched)
> +{
> +	int ret;
> +
> +	lockdep_assert_held(&sched->lock);
> +
> +	ret = __arb_sched_close_locked(sched);
> +	if (!ret) {
> +		sched->close_timer.epoch = sched->epoch;
> +		hrtimer_start(&sched->close_timer.timer,
> +			      ms_to_ktime(yield_timeout), HRTIMER_MODE_REL);
> +	} else if (ret > 0) {

[Severity: High]
Is it safe to unconditionally re-arm the timer here?

During panthor_arbitration_sched_stop(), all timers are cancelled and
flush_workqueue() is called. If a reset_work is pending, it executes and
calls arb_sched_close_locked(), which re-arms the close_timer unconditionally.

Without checking if a teardown is in progress (such as checking for
ARB_SCHED_DISABLE_TERM), this can lead to a use-after-free when the re-armed
hrtimer expires and its callback executes on a freed object.

[ ... ]

> +static int arbitration_sched_init(struct panthor_arbitration *adev, int i)
> +{
> +	struct device *dev = adev->dev;
> +	struct panthor_arbitration_sched *sched;
> +
> +	sched = devm_kzalloc(dev, sizeof(*sched), GFP_KERNEL);
> +	if (!sched)
> +		return -ENOMEM;
> +
> +	sched->name = devm_kasprintf(dev, GFP_KERNEL, "sched%d", i);
> +	sched->dev = dev;
> +
> +	sched->wq = devm_alloc_ordered_workqueue(dev, "%s-wq", 0, sched->name);

[Severity: Medium]
Could devm_kasprintf() return NULL here?

If memory allocation fails, sched->name will be NULL. It is immediately
passed to devm_alloc_ordered_workqueue() which will dereference it for
string formatting, leading to a kernel crash.

> +	if (!sched->wq)
> +		return -ENOMEM;

[ ... ]

> +int panthor_arbitration_sched_suspend(struct panthor_arbitration *adev)
> +{
> +	for (int i = 0; i < AM_ARB_MAX_PC_COUNT; i++) {
> +		struct panthor_arbitration_sched *sched = adev->sched[i];
> +		int ret;
> +
> +		if (!sched)
> +			continue;
> +
> +		panthor_arbitration_sched_disable_set(sched, ARB_SCHED_DISABLE_PM);
> +		ret = panthor_arbitration_sched_stop(sched);
> +		if (ret) {
> +			panthor_arbitration_sched_disable_clear(
> +				sched, ARB_SCHED_DISABLE_PM);
> +			return ret;
> +		}

[Severity: Medium]
Does this properly roll back the state of previously processed schedulers?

If panthor_arbitration_sched_stop() fails for scheduler N, the loop returns
an error. Schedulers 0 to N-1 will remain permanently disabled because
ARB_SCHED_DISABLE_PM is not cleared for them.

> +	}
> +
> +	return 0;
> +}

[ ... ]

> +int panthor_arbitration_sched_stop(struct panthor_arbitration_sched *sched)
> +{
> +	int ret;
> +
> +	arb_sched_request_stop(sched);
> +
> +	/*
> +	 * Provisionally waiting for up to 2x yield_timeout, but path may
> +	 * include time taken for panthor_arbitration_on_grant() to complete
> +	 * if sched_request_stop() is called while in the GRANTING state.
> +	 *
> +	 * Realistically, if granting takes more than yield_timeout, HW is in
> +	 * bad state either way. Best continue and stop the scheduler.
> +	 */
> +	ret = arb_sched_wait_phase(sched, ARB_SCHED_PHASE_IDLE,
> +				   request_timeout + yield_timeout);
> +	if (ret)
> +		arb_sched_force_close(sched);
> +
> +	/* Should no longer have any further activity. Cancel timer. */
> +	hrtimer_cancel(&sched->grant_timer.timer);
> +	hrtimer_cancel(&sched->stop_timer.timer);
> +	hrtimer_cancel(&sched->close_timer.timer);
> +	flush_workqueue(sched->wq);

[Severity: High]
Will this hang indefinitely if reset_work is trapped in a re-queuing loop?

As noted earlier, if the hardware becomes unresponsive,
__arb_sched_close_locked() queues reset_work which recursively fails and
re-queues itself. This unthrottled infinite loop will block
flush_workqueue() indefinitely during system suspend or driver removal.

> +
> +	scoped_guard(spinlock_irqsave, &sched->lock)
> +		if (sched->phase == ARB_SCHED_PHASE_IDLE)
> +			return 0;
> +
> +	return ret;
> +}

-- 
Sashiko AI review · https://sashiko.dev/#/patchset/20260922204535.2850094-1-karunika.choo@arm.com?part=16

  reply	other threads:[~2026-09-22 21:00 UTC|newest]

Thread overview: 54+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-09-22 20:44 [PATCH v1 00/27] drm/panthor: Add Mali v15 virtualization support Karunika Choo
2026-09-22 20:44 ` [PATCH v1 01/27] drm/panthor: Ignore -EOPNOTSUPP for shader-present nvmem lookup Karunika Choo
2026-09-22 20:44 ` [PATCH v1 02/27] drm/panthor: Move register access helpers out of panthor_device.h Karunika Choo
2026-09-22 20:54   ` sashiko-bot
2026-09-22 20:44 ` [PATCH v1 03/27] drm/panthor: Parse and store GPU_ID fields Karunika Choo
2026-09-22 20:56   ` sashiko-bot
2026-09-22 20:44 ` [PATCH v1 04/27] drm/panthor: Add 64-bit GPU_ID decoding for v15 GPUs Karunika Choo
2026-09-22 21:01   ` sashiko-bot
2026-09-22 23:23   ` Deborah Brouwer
2026-09-22 20:44 ` [PATCH v1 05/27] drm/panthor: Move register base offsets to the HW description Karunika Choo
2026-09-22 20:45 ` [PATCH v1 06/27] drm/panthor: Derive MMU AS register addresses from base and stride Karunika Choo
2026-09-22 21:00   ` sashiko-bot
2026-09-22 20:45 ` [PATCH v1 07/27] dt-bindings: gpu: mali-valhall-csf: Add Mali Gen5 AM compatible Karunika Choo
2026-09-28 10:02   ` Krzysztof Kozlowski
2026-09-22 20:45 ` [PATCH v1 08/27] drm/panthor: Add Mali v15 hardware support Karunika Choo
2026-09-22 20:58   ` sashiko-bot
2026-09-22 20:45 ` [PATCH v1 09/27] drm/panthor: Skip devfreq when no OPP table is present Karunika Choo
2026-09-22 20:45 ` [PATCH v1 10/27] dt-bindings: gpu: panthor: Document panthor-system bindings Karunika Choo
2026-09-22 20:56   ` sashiko-bot
2026-09-28 10:05   ` Krzysztof Kozlowski
2026-09-22 20:45 ` [PATCH v1 11/27] drm/panthor: Add AM_SYSTEM platform driver Karunika Choo
2026-09-22 20:59   ` sashiko-bot
2026-09-22 20:45 ` [PATCH v1 12/27] dt-bindings: gpu: panthor: Document panthor-arbitration bindings Karunika Choo
2026-09-22 20:59   ` sashiko-bot
2026-09-28 10:06   ` Krzysztof Kozlowski
2026-09-22 20:45 ` [PATCH v1 13/27] drm/panthor: Add AM_PARTITION_CONTROL support Karunika Choo
2026-09-22 20:57   ` sashiko-bot
2026-09-22 20:45 ` [PATCH v1 14/27] drm/panthor: Add AM message helpers Karunika Choo
2026-09-22 20:58   ` sashiko-bot
2026-09-22 20:45 ` [PATCH v1 15/27] drm/panthor: Add AM_RESOURCE_GROUP support Karunika Choo
2026-09-22 20:56   ` sashiko-bot
2026-09-22 20:45 ` [PATCH v1 16/27] drm/panthor: Add arbitration scheduler Karunika Choo
2026-09-22 21:00   ` sashiko-bot [this message]
2026-09-22 20:45 ` [PATCH v1 17/27] drm/panthor: Route arbitration events Karunika Choo
2026-09-22 21:04   ` sashiko-bot
2026-09-22 20:45 ` [PATCH v1 18/27] dt-bindings: gpu: panthor: Document AW assignment DT property Karunika Choo
2026-09-22 20:57   ` sashiko-bot
2026-09-28 10:06   ` Krzysztof Kozlowski
2026-09-22 20:45 ` [PATCH v1 19/27] drm/panthor: Add AW assignment tracking Karunika Choo
2026-09-22 20:45 ` [PATCH v1 20/27] drm/panthor: Handle partition control INVALID_COMMAND interrupt Karunika Choo
2026-09-22 21:04   ` sashiko-bot
2026-09-22 20:45 ` [PATCH v1 21/27] drm/panthor: Request AW to yield GPU access on idle Karunika Choo
2026-09-22 21:07   ` sashiko-bot
2026-09-22 20:45 ` [PATCH v1 22/27] drm/panthor: Add access-window support Karunika Choo
2026-09-22 21:05   ` sashiko-bot
2026-09-22 20:45 ` [PATCH v1 23/27] drm/panthor: Synchronize HW component PM transitions Karunika Choo
2026-09-22 20:45 ` [PATCH v1 24/27] drm/panthor: Route HW component PM through access windows Karunika Choo
2026-09-22 21:06   ` sashiko-bot
2026-09-22 20:45 ` [PATCH v1 25/27] drm/panthor: Tolerate access-window loss during HW waits Karunika Choo
2026-09-22 21:14   ` sashiko-bot
2026-09-22 20:45 ` [PATCH v1 26/27] drm/panthor: Prevent missed post-yield cleanup due to reset Karunika Choo
2026-09-22 21:12   ` sashiko-bot
2026-09-22 20:45 ` [PATCH v1 27/27] drm/panthor: Release GPU access immediately for out-of-band grants Karunika Choo
2026-09-22 21:06   ` 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=20260922210022.394441F00893@smtp.kernel.org \
    --to=sashiko-bot@kernel.org \
    --cc=dri-devel@lists.freedesktop.org \
    --cc=karunika.choo@arm.com \
    --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