From: Karunika Choo <karunika.choo@arm.com>
To: dri-devel@lists.freedesktop.org
Cc: nd@arm.com, Boris Brezillon <boris.brezillon@collabora.com>,
Steven Price <steven.price@arm.com>,
Liviu Dudau <liviu.dudau@arm.com>,
linux-kernel@vger.kernel.org,
Maarten Lankhorst <maarten.lankhorst@linux.intel.com>,
Maxime Ripard <mripard@kernel.org>,
Thomas Zimmermann <tzimmermann@suse.de>,
David Airlie <airlied@gmail.com>, Simona Vetter <simona@ffwll.ch>
Subject: [PATCH v1 20/27] drm/panthor: Handle partition control INVALID_COMMAND interrupt
Date: Tue, 22 Sep 2026 21:45:14 +0100 [thread overview]
Message-ID: <20260922204535.2850094-21-karunika.choo@arm.com> (raw)
In-Reply-To: <20260922204535.2850094-1-karunika.choo@arm.com>
Partition control commands have specific partition state requirements
to be valid. We cannot afford to wait for the states to complete
transitions before sending these commands as it would work against the
arbitration scheduler's goal of handling phase transitions as fast as
possible (i.e. in IRQ context).
Fortunately, the hardware raises INVALID_COMMAND interrupts in cases
where the partition state requirements are not met. In such cases, retry
commands when the partition state permits, and request scheduler
recovery when an open-window command encounters an inconsistent
assignment.
Signed-off-by: Karunika Choo <karunika.choo@arm.com>
---
.../panthor/arbitration/panthor_arbitration.h | 2 +
.../arbitration/panthor_arbitration_drv.c | 12 ++
.../arbitration/panthor_arbitration_sched.c | 10 ++
.../arbitration/panthor_arbitration_sched.h | 4 +
.../arbitration/panthor_partition_control.c | 108 ++++++++++++++++--
5 files changed, 125 insertions(+), 11 deletions(-)
diff --git a/drivers/gpu/drm/panthor/arbitration/panthor_arbitration.h b/drivers/gpu/drm/panthor/arbitration/panthor_arbitration.h
index e1d569158ac6c..53d64abb50379 100644
--- a/drivers/gpu/drm/panthor/arbitration/panthor_arbitration.h
+++ b/drivers/gpu/drm/panthor/arbitration/panthor_arbitration.h
@@ -75,4 +75,6 @@ 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_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 f44cd45ea342e..3cdf03f3f4879 100644
--- a/drivers/gpu/drm/panthor/arbitration/panthor_arbitration_drv.c
+++ b/drivers/gpu/drm/panthor/arbitration/panthor_arbitration_drv.c
@@ -298,6 +298,18 @@ 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_err(struct panthor_arbitration *adev, u8 aw_id)
+{
+ int idx = to_assigned_sched_idx(adev, aw_id);
+
+ if (idx < 0)
+ return idx;
+
+ panthor_arbitration_sched_reset(adev->sched[idx], aw_id);
+
+ return 0;
+}
+
static int panthor_arbitration_probe(struct platform_device *pdev)
{
struct panthor_arbitration *adev;
diff --git a/drivers/gpu/drm/panthor/arbitration/panthor_arbitration_sched.c b/drivers/gpu/drm/panthor/arbitration/panthor_arbitration_sched.c
index 9e26b8f92b69a..df0785a80442c 100644
--- a/drivers/gpu/drm/panthor/arbitration/panthor_arbitration_sched.c
+++ b/drivers/gpu/drm/panthor/arbitration/panthor_arbitration_sched.c
@@ -729,3 +729,13 @@ void panthor_arbitration_sched_disable_clear(struct panthor_arbitration_sched *s
sched->disabled &= ~BIT(reason);
}
+
+void panthor_arbitration_sched_reset(struct panthor_arbitration_sched *sched, u8 aw_id)
+{
+ guard(spinlock_irqsave)(&sched->lock);
+
+ if (aw_id != sched->active_aw_id)
+ return;
+
+ arb_sched_queue_work(sched, &sched->reset_work);
+}
diff --git a/drivers/gpu/drm/panthor/arbitration/panthor_arbitration_sched.h b/drivers/gpu/drm/panthor/arbitration/panthor_arbitration_sched.h
index 803a405964a4e..ba43cc19f0eff 100644
--- a/drivers/gpu/drm/panthor/arbitration/panthor_arbitration_sched.h
+++ b/drivers/gpu/drm/panthor/arbitration/panthor_arbitration_sched.h
@@ -6,6 +6,8 @@
#include <linux/types.h>
+#include "panthor_arbitration.h"
+
struct panthor_arbitration;
struct panthor_arbitration_sched;
@@ -35,6 +37,8 @@ void panthor_arbitration_sched_disable_set(struct panthor_arbitration_sched *sch
void panthor_arbitration_sched_disable_clear(struct panthor_arbitration_sched *sched,
enum panthor_arb_sched_disable_reason reason);
+void panthor_arbitration_sched_reset(struct panthor_arbitration_sched *sched, u8 aw_id);
+
int panthor_arbitration_sched_on_request(struct panthor_arbitration_sched *sched, u8 aw_id);
int panthor_arbitration_sched_on_idle(struct panthor_arbitration_sched *sched, u8 aw_id);
int panthor_arbitration_sched_on_stopped(struct panthor_arbitration_sched *sched, u8 aw_id);
diff --git a/drivers/gpu/drm/panthor/arbitration/panthor_partition_control.c b/drivers/gpu/drm/panthor/arbitration/panthor_partition_control.c
index 95c26015cb637..446f77fc67891 100644
--- a/drivers/gpu/drm/panthor/arbitration/panthor_partition_control.c
+++ b/drivers/gpu/drm/panthor/arbitration/panthor_partition_control.c
@@ -28,6 +28,7 @@
#define AM_PART_COMMAND 0x100
#define AM_PART_SET_COMMAND(x) FIELD_PREP(GENMASK(7, 0), x)
+#define AM_PART_GET_COMMAND(x) FIELD_GET(GENMASK(7, 0), x)
#define PART_CMD_YIELD_IDLE 0x10
#define PART_CMD_YIELD_NOW 0x11
#define PART_CMD_CLOSE_WINDOW 0x20
@@ -40,6 +41,15 @@
#define PART_REG_POLL_SLEEP_US 10
#define PART_STATE_TRANSITION_TIMEOUT_US 5000000
+/** struct panthor_partition_cmd - Partition command data */
+struct panthor_partition_cmd {
+ /** @cmd: AM_PARTITION_COMMAND value */
+ u32 cmd;
+
+ /** @aw_id: AW ID the command was sent for */
+ int aw_id;
+};
+
/**
* struct panthor_partition_control - Partition control data
*/
@@ -64,6 +74,9 @@ struct panthor_partition_control {
/** @closing: synchronous closing of the partition */
bool closing;
+
+ /** @last_cmd: Last sent command */
+ struct panthor_partition_cmd last_cmd;
};
static void partition_irq_suspend(struct panthor_partition_control *pc)
@@ -101,18 +114,45 @@ static int partition_state_wait(struct panthor_partition_control *pc, u32 state)
false, pc);
}
+static inline void
+partition_command_write_untracked(struct panthor_partition_control *pc, u32 cmd)
+{
+ gpu_write(pc->iomem, AM_PART_COMMAND, cmd);
+}
+
+static void partition_command_write(struct panthor_partition_control *pc,
+ u32 cmd, int aw_id)
+{
+ lockdep_assert_held(&pc->lock);
+
+ partition_command_write_untracked(pc, cmd);
+
+ pc->last_cmd.cmd = cmd;
+ pc->last_cmd.aw_id = aw_id;
+}
+
static int yield_now(struct panthor_partition_control *pc)
{
- gpu_write(pc->iomem, AM_PART_COMMAND,
- AM_PART_SET_COMMAND(PART_CMD_YIELD_NOW));
+ guard(spinlock_irqsave)(&pc->lock);
+
+ partition_command_write(pc, AM_PART_SET_COMMAND(PART_CMD_YIELD_NOW),
+ pc->current_aw);
return 0;
}
static int yield_idle(struct panthor_partition_control *pc)
{
- gpu_write(pc->iomem, AM_PART_COMMAND,
- AM_PART_SET_COMMAND(PART_CMD_YIELD_IDLE));
+ guard(spinlock_irqsave)(&pc->lock);
+
+ /*
+ * This is a notification to yield the GPU once FW is idle. It is not
+ * a command that must succeed. Nothing of note is lost if the command
+ * fails apart from some minor scheduling optimisation losses. We can
+ * skip tracking this command.
+ */
+ partition_command_write_untracked(
+ pc, AM_PART_SET_COMMAND(PART_CMD_YIELD_IDLE));
return 0;
}
@@ -127,8 +167,8 @@ static int window_close(struct panthor_partition_control *pc)
pc->closing = true;
- gpu_write(pc->iomem, AM_PART_COMMAND,
- AM_PART_SET_COMMAND(PART_CMD_CLOSE_WINDOW));
+ partition_command_write(pc, AM_PART_SET_COMMAND(PART_CMD_CLOSE_WINDOW),
+ pc->current_aw);
return 0;
}
@@ -153,8 +193,8 @@ static int window_open(struct panthor_partition_control *pc, u8 aw_id)
guard(spinlock_irqsave)(&pc->lock);
- gpu_write(pc->iomem, AM_PART_COMMAND,
- AM_PART_SET_COMMAND(PART_CMD_OPEN_WINDOW) | AM_PART_SET_WINDOW(aw_id));
+ partition_command_write(pc, (AM_PART_SET_COMMAND(PART_CMD_OPEN_WINDOW) |
+ AM_PART_SET_WINDOW(aw_id)), aw_id);
pc->current_aw = aw_id;
@@ -166,6 +206,8 @@ static void partition_handle_reset_done(struct panthor_partition_control *pc)
bool notify_stopped = false;
int aw_id;
+ gpu_write(pc->iomem, AM_PART_IRQ_CLEAR, PART_RESET_DONE);
+
scoped_guard(spinlock_irqsave, &pc->lock) {
aw_id = pc->current_aw;
pc->current_aw = -1;
@@ -181,6 +223,52 @@ static void partition_handle_reset_done(struct panthor_partition_control *pc)
panthor_arbitration_on_stopped(dev_get_drvdata(pc->dev), aw_id);
}
+static void partition_handle_invalid_cmd(struct panthor_partition_control *pc)
+{
+ bool on_err = false;
+ int aw_id;
+
+ gpu_write(pc->iomem, AM_PART_IRQ_CLEAR, PART_INVALID_COMMAND);
+
+ scoped_guard(spinlock_irqsave, &pc->lock) {
+ if (!pc->last_cmd.cmd)
+ return;
+
+ if (pc->last_cmd.aw_id < 0)
+ return;
+
+ if (pc->last_cmd.aw_id != pc->current_aw)
+ return;
+
+ switch (AM_PART_GET_COMMAND(pc->last_cmd.cmd)) {
+ case PART_CMD_YIELD_NOW:
+ case PART_CMD_CLOSE_WINDOW:
+ if (partition_state_get(pc) == PART_STATE_WINDOW_OPEN) {
+ partition_command_write_untracked(pc, pc->last_cmd.cmd);
+ return;
+ }
+ break;
+ case PART_CMD_OPEN_WINDOW:
+ if (partition_state_get(pc) == PART_STATE_RESET) {
+ partition_command_write_untracked(pc, pc->last_cmd.cmd);
+ return;
+ } else if (partition_aw_get(pc) == pc->last_cmd.aw_id) {
+ return;
+ }
+
+ on_err = true;
+ aw_id = pc->last_cmd.aw_id;
+
+ break;
+ default:
+ return;
+ }
+ }
+
+ if (on_err)
+ panthor_arbitration_notify_err(dev_get_drvdata(pc->dev), aw_id);
+}
+
static irqreturn_t partition_irq_raw_handler(int irq, void *data)
{
struct panthor_partition_control *pc = data;
@@ -194,9 +282,7 @@ static irqreturn_t partition_irq_raw_handler(int irq, void *data)
partition_handle_reset_done(pc);
if (status & PART_INVALID_COMMAND)
- dev_warn(pc->dev, "%s: Invalid command", pc->name);
-
- gpu_write(pc->iomem, AM_PART_IRQ_CLEAR, status);
+ partition_handle_invalid_cmd(pc);
return IRQ_HANDLED;
}
--
2.43.0
next prev parent reply other threads:[~2026-09-22 20:48 UTC|newest]
Thread overview: 42+ 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-10-28 15:51 ` Liviu Dudau
2026-09-22 20:44 ` [PATCH v1 02/27] drm/panthor: Move register access helpers out of panthor_device.h Karunika Choo
2026-10-28 15:52 ` Liviu Dudau
2026-09-22 20:44 ` [PATCH v1 03/27] drm/panthor: Parse and store GPU_ID fields Karunika Choo
2026-10-28 15:57 ` Liviu Dudau
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 23:23 ` Deborah Brouwer
2026-10-28 15:58 ` Liviu Dudau
2026-09-22 20:44 ` [PATCH v1 05/27] drm/panthor: Move register base offsets to the HW description Karunika Choo
2026-10-28 16:03 ` Liviu Dudau
2026-09-22 20:45 ` [PATCH v1 06/27] drm/panthor: Derive MMU AS register addresses from base and stride Karunika Choo
2026-10-28 16:06 ` Liviu Dudau
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-10-28 13:21 ` Liviu Dudau
2026-10-28 16:20 ` Liviu Dudau
2026-09-22 20:45 ` [PATCH v1 09/27] drm/panthor: Skip devfreq when no OPP table is present Karunika Choo
2026-10-28 16:26 ` Liviu Dudau
2026-09-22 20:45 ` [PATCH v1 10/27] dt-bindings: gpu: panthor: Document panthor-system bindings Karunika Choo
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:45 ` [PATCH v1 12/27] dt-bindings: gpu: panthor: Document panthor-arbitration bindings Karunika Choo
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:45 ` [PATCH v1 14/27] drm/panthor: Add AM message helpers Karunika Choo
2026-09-22 20:45 ` [PATCH v1 15/27] drm/panthor: Add AM_RESOURCE_GROUP support Karunika Choo
2026-09-22 20:45 ` [PATCH v1 16/27] drm/panthor: Add arbitration scheduler Karunika Choo
2026-09-22 20:45 ` [PATCH v1 17/27] drm/panthor: Route arbitration events Karunika Choo
2026-09-22 20:45 ` [PATCH v1 18/27] dt-bindings: gpu: panthor: Document AW assignment DT property Karunika Choo
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 ` Karunika Choo [this message]
2026-09-22 20:45 ` [PATCH v1 21/27] drm/panthor: Request AW to yield GPU access on idle Karunika Choo
2026-09-22 20:45 ` [PATCH v1 22/27] drm/panthor: Add access-window support Karunika Choo
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 20:45 ` [PATCH v1 25/27] drm/panthor: Tolerate access-window loss during HW waits Karunika Choo
2026-09-22 20:45 ` [PATCH v1 26/27] drm/panthor: Prevent missed post-yield cleanup due to reset Karunika Choo
2026-09-22 20:45 ` [PATCH v1 27/27] drm/panthor: Release GPU access immediately for out-of-band grants Karunika Choo
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=20260922204535.2850094-21-karunika.choo@arm.com \
--to=karunika.choo@arm.com \
--cc=airlied@gmail.com \
--cc=boris.brezillon@collabora.com \
--cc=dri-devel@lists.freedesktop.org \
--cc=linux-kernel@vger.kernel.org \
--cc=liviu.dudau@arm.com \
--cc=maarten.lankhorst@linux.intel.com \
--cc=mripard@kernel.org \
--cc=nd@arm.com \
--cc=simona@ffwll.ch \
--cc=steven.price@arm.com \
--cc=tzimmermann@suse.de \
/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
all inboxes | Powered by JetHome®