[PATCH v1 21/27] drm/panthor: Request AW to yield GPU access on idle
From: Karunika Choo
Date: Tue Sep 22 2026 - 17:01:43 EST
v15 GPU introduces a YIELD_IDLE command/interrupt to signal an access
window to relinquish GPU access as soon as it is idle. With FW v2, the
GPU is immediately yielded when it detects the GPU is idle and the
YIELD_IDLE interrupt is raised.
For latency and CPU scheduling reasons, we want to avoid constantly
yielding the GPU the moment it goes idle when there is only a singular
access window requesting access. As such, we only send YIELD_IDLE when:
- The GPU is granted to an access window and there are other access
windows requesting GPU access.
- A new GPU_REQUEST was received and the currently active access window
was the singular requesting AW.
Signed-off-by: Karunika Choo <karunika.choo@xxxxxxx>
---
.../panthor/arbitration/panthor_arbitration.h | 1 +
.../arbitration/panthor_arbitration_drv.c | 10 ++++++++++
.../arbitration/panthor_arbitration_sched.c | 16 +++++++++++++++-
3 files changed, 26 insertions(+), 1 deletion(-)
diff --git a/drivers/gpu/drm/panthor/arbitration/panthor_arbitration.h b/drivers/gpu/drm/panthor/arbitration/panthor_arbitration.h
index 53d64abb50379..c0e93f940fccb 100644
--- a/drivers/gpu/drm/panthor/arbitration/panthor_arbitration.h
+++ b/drivers/gpu/drm/panthor/arbitration/panthor_arbitration.h
@@ -75,6 +75,7 @@ int panthor_arbitration_on_grant(struct panthor_arbitration *adev, u8 aw_id);
int panthor_arbitration_on_stop(struct panthor_arbitration *adev, u8 aw_id);
int panthor_arbitration_on_close(struct panthor_arbitration *adev, u8 aw_id);
+int panthor_arbitration_notify_yield_idle(struct panthor_arbitration *adev, u8 aw_id);
int panthor_arbitration_notify_err(struct panthor_arbitration *adev, u8 aw_id);
#endif
diff --git a/drivers/gpu/drm/panthor/arbitration/panthor_arbitration_drv.c b/drivers/gpu/drm/panthor/arbitration/panthor_arbitration_drv.c
index 3cdf03f3f4879..058fe39cbc002 100644
--- a/drivers/gpu/drm/panthor/arbitration/panthor_arbitration_drv.c
+++ b/drivers/gpu/drm/panthor/arbitration/panthor_arbitration_drv.c
@@ -298,6 +298,16 @@ int panthor_arbitration_on_close(struct panthor_arbitration *adev, u8 aw_id)
return panthor_partition_control_close_window(adev->pc[idx]);
}
+int panthor_arbitration_notify_yield_idle(struct panthor_arbitration *adev, u8 aw_id)
+{
+ int idx = to_assigned_sched_idx(adev, aw_id);
+
+ if (idx < 0)
+ return idx;
+
+ return panthor_partition_control_yield_idle(adev->pc[idx]);
+}
+
int panthor_arbitration_notify_err(struct panthor_arbitration *adev, u8 aw_id)
{
int idx = to_assigned_sched_idx(adev, aw_id);
diff --git a/drivers/gpu/drm/panthor/arbitration/panthor_arbitration_sched.c b/drivers/gpu/drm/panthor/arbitration/panthor_arbitration_sched.c
index df0785a80442c..df58fcc56e375 100644
--- a/drivers/gpu/drm/panthor/arbitration/panthor_arbitration_sched.c
+++ b/drivers/gpu/drm/panthor/arbitration/panthor_arbitration_sched.c
@@ -347,6 +347,10 @@ static int arb_sched_next_locked(struct panthor_arbitration_sched *sched)
arb_sched_grant_locked(sched);
+ if (sched->phase == ARB_SCHED_PHASE_GRANTED &&
+ !kfifo_is_empty(&sched->queue))
+ panthor_arbitration_notify_yield_idle(to_adev(sched), aw_id);
+
wake_up_all(&sched->waitqueue);
return 0;
@@ -475,8 +479,18 @@ int panthor_arbitration_sched_on_request(struct panthor_arbitration_sched *sched
* Grant timer for the current AW has previously expired, request it to
* yield the GPU.
*/
- if (sched->grant_previously_expired)
+ if (sched->grant_previously_expired) {
arb_sched_request_stop_locked(sched);
+ return 0;
+ }
+
+ /*
+ * GPU was previously granted to a lone requesting AW, YIELD_IDLE was
+ * not sent to it. Send YIELD_IDLE to it now that multiple AWs are
+ * requesting for the GPU.
+ */
+ if (sched->phase == ARB_SCHED_PHASE_GRANTED && kfifo_len(&sched->queue) == 1)
+ panthor_arbitration_notify_yield_idle(to_adev(sched), sched->active_aw_id);
return 0;
}
--
2.43.0