[PATCH v3 05/13] irqchip/gic-v3-its: Compute the wait target under the ITS lock
Fuad Tabba
fuad.tabba at linux.dev
Mon Nov 2 05:01:25 PST 2026
its_wait_for_range_completion() converts the posted command pointer into
a queue offset against its->cmd_base, after the caller has dropped
its->lock. That's fine while cmd_base never changes, but the protected
KVM takeover in a later patch switches cmd_base to a copy of the queue
under the lock, and a wait racing with it would compute its target
against the wrong base.
Compute the offset in its_post_commands(), under the lock, and pass it
to the wait instead of the pointer.
No functional change intended.
Signed-off-by: Fuad Tabba <fuad.tabba at linux.dev>
---
drivers/irqchip/irq-gic-v3-its.c | 17 ++++++++---------
1 file changed, 8 insertions(+), 9 deletions(-)
diff --git a/drivers/irqchip/irq-gic-v3-its.c b/drivers/irqchip/irq-gic-v3-its.c
index 8cc1bd8e7835b..f06da58cccf3d 100644
--- a/drivers/irqchip/irq-gic-v3-its.c
+++ b/drivers/irqchip/irq-gic-v3-its.c
@@ -1144,13 +1144,13 @@ static struct its_cmd_block *its_allocate_entry(struct its_node *its)
return cmd;
}
-static struct its_cmd_block *its_post_commands(struct its_node *its)
+static u64 its_post_commands(struct its_node *its)
{
u64 wr = its_cmd_ptr_to_offset(its, its->cmd_write);
writel_relaxed(wr, its->base + GITS_CWRITER);
- return its->cmd_write;
+ return wr;
}
static void its_flush_cmd(struct its_node *its, struct its_cmd_block *cmd)
@@ -1167,13 +1167,12 @@ static void its_flush_cmd(struct its_node *its, struct its_cmd_block *cmd)
static int its_wait_for_range_completion(struct its_node *its,
u64 prev_idx,
- struct its_cmd_block *to)
+ u64 to_idx)
{
- u64 rd_idx, to_idx, linear_idx;
+ u64 rd_idx, linear_idx;
u32 count = 1000000; /* 1s! */
/* Linearize to_idx if the command set has wrapped around */
- to_idx = its_cmd_ptr_to_offset(its, to);
if (to_idx < prev_idx)
to_idx += ITS_CMD_QUEUE_SZ;
@@ -1216,10 +1215,10 @@ void name(struct its_node *its, \
buildtype builder, \
struct its_cmd_desc *desc) \
{ \
- struct its_cmd_block *cmd, *sync_cmd, *next_cmd; \
+ struct its_cmd_block *cmd, *sync_cmd; \
synctype *sync_obj; \
unsigned long flags; \
- u64 rd_idx; \
+ u64 rd_idx, wr_idx; \
\
raw_spin_lock_irqsave(&its->lock, flags); \
\
@@ -1242,10 +1241,10 @@ void name(struct its_node *its, \
\
post: \
rd_idx = readl_relaxed(its->base + GITS_CREADR); \
- next_cmd = its_post_commands(its); \
+ wr_idx = its_post_commands(its); \
raw_spin_unlock_irqrestore(&its->lock, flags); \
\
- if (its_wait_for_range_completion(its, rd_idx, next_cmd)) \
+ if (its_wait_for_range_completion(its, rd_idx, wr_idx)) \
pr_err_ratelimited("ITS cmd %ps failed\n", builder); \
}
--
2.47.3
More information about the linux-arm-kernel
mailing list