Re: [PATCH v4 01/18] drm/panthor: Disable reset work before unplug

From: Adrian Larumbe

Date: Wed Sep 09 2026 - 21:13:36 EST


Reviewed-by: Adrián Larumbe <adrian.larumbe@xxxxxxxxxxxxx>

On 26.08.2026 16:56, Boris Brezillon wrote:
> Unplug is supposed to be the end of the road, so we need to make sure
> reset works won't execute while we're cleaning up everything as part
> of the unplug, otherwise it would mess up the internal state.
>
> In order to be able to call disable_work_sync() in the unplug
> path, we need to defer the unplug triggered by the reset logic,
> otherwise we would deadlock.
>
> Fixes: 5fe909cae118 ("drm/panthor: Add the device logical block")
> Signed-off-by: Boris Brezillon <boris.brezillon@xxxxxxxxxxxxx>
> ---
> drivers/gpu/drm/panthor/panthor_device.c | 21 ++++++++++++++++++++-
> drivers/gpu/drm/panthor/panthor_device.h | 3 +++
> 2 files changed, 23 insertions(+), 1 deletion(-)
>
> diff --git a/drivers/gpu/drm/panthor/panthor_device.c b/drivers/gpu/drm/panthor/panthor_device.c
> index 0b25abebb803..7c55d0c45cfd 100644
> --- a/drivers/gpu/drm/panthor/panthor_device.c
> +++ b/drivers/gpu/drm/panthor/panthor_device.c
> @@ -79,6 +79,9 @@ void panthor_device_unplug(struct panthor_device *ptdev)
> return;
> }
>
> + /* Make sure we're not interrupted by resets while we're unplugging. */
> + disable_work_sync(&ptdev->reset.work);
> +
> drm_WARN_ON(&ptdev->base, pm_runtime_get_sync(ptdev->base.dev) < 0);
>
> /* Call drm_dev_unplug() so any access to HW blocks happening after
> @@ -91,6 +94,13 @@ void panthor_device_unplug(struct panthor_device *ptdev)
> */
> mutex_unlock(&ptdev->unplug.lock);
>
> + /* Unplug triggered by a device removal might race with the deferred
> + * one queued by the reset work. The function covers this concurrent
> + * unplug situation, but if we can disable the work before its
> + * execution, that's still better.
> + */
> + disable_work(&ptdev->unplug.work);
> +
> /* Now, try to cleanly shutdown the GPU before the device resources
> * get reclaimed.
> */
> @@ -114,6 +124,13 @@ void panthor_device_unplug(struct panthor_device *ptdev)
> complete_all(&ptdev->unplug.done);
> }
>
> +static void panthor_device_unplug_work(struct work_struct *work)
> +{
> + struct panthor_device *ptdev = container_of(work, struct panthor_device, unplug.work);
> +
> + panthor_device_unplug(ptdev);
> +}
> +
> static void panthor_device_reset_cleanup(struct drm_device *ddev, void *data)
> {
> struct panthor_device *ptdev = container_of(ddev, struct panthor_device, base);
> @@ -148,8 +165,9 @@ static void panthor_device_reset_work(struct work_struct *work)
> drm_dev_exit(cookie);
>
> if (ret) {
> - panthor_device_unplug(ptdev);
> + disable_work(&ptdev->reset.work);
> drm_err(&ptdev->base, "Failed to boot MCU after reset, making device unusable.");
> + queue_work(ptdev->reset.wq, &ptdev->unplug.work);
> }
> }
>
> @@ -206,6 +224,7 @@ int panthor_device_init(struct panthor_device *ptdev)
> */
> *dummy_page_virt = 1;
>
> + INIT_WORK(&ptdev->unplug.work, panthor_device_unplug_work);
> INIT_WORK(&ptdev->reset.work, panthor_device_reset_work);
> disable_work(&ptdev->reset.work);
> ptdev->reset.wq = alloc_ordered_workqueue("panthor-reset-wq", 0);
> diff --git a/drivers/gpu/drm/panthor/panthor_device.h b/drivers/gpu/drm/panthor/panthor_device.h
> index b55a3f9edd41..6529e01e838d 100644
> --- a/drivers/gpu/drm/panthor/panthor_device.h
> +++ b/drivers/gpu/drm/panthor/panthor_device.h
> @@ -268,6 +268,9 @@ struct panthor_device {
> * operation is done.
> */
> struct completion done;
> +
> + /** @work: Unplug work. */
> + struct work_struct work;
> } unplug;
>
> /** @reset: Reset related fields. */
>
> --
> 2.55.0

Adrian Larumbe