[PATCH] acpi/riscv: use a dedicated insertion point in riscv_acpi_register_ext_intc()
Maoyi Xie
maoyixie.tju at gmail.com
Mon May 25 00:44:15 PDT 2026
riscv_acpi_register_ext_intc() inserts into ext_intc_list, which
is sorted with the largest gsi_base first. It walks the list
until it finds the first entry with a smaller gsi_base, then
inserts the new entry before that entry. After the loop it also
caps the predecessor's nr_irqs if that predecessor was registered
as PENDING.
The current code uses the loop cursor for both jobs:
list_for_each_entry(node, &ext_intc_list, list) {
if (node->gsi_base < ext_intc_element->gsi_base)
break;
}
prev = list_prev_entry(node, list);
if (!list_entry_is_head(prev, &ext_intc_list, list)) {
...
}
list_add_tail(&ext_intc_element->list, &node->list);
If the loop falls through (no entry has a smaller gsi_base),
node ends up past the end of the list. `&node->list` resolves
to `&ext_intc_list` via container_of() offset cancellation. So
list_prev_entry() lands on the last real entry, and
list_add_tail() inserts at the tail. The code works today.
It is fragile though. Any future change that reads another field
of node will hit memory before the ext_intc_list global.
Track the insertion point with a dedicated list_head pointer.
Initialise pos to `&ext_intc_list`. Set it to `&node->list` on
early break. Use pos->prev for the PENDING adjustment, and pos
for list_add_tail(). The cursor is no longer touched after the
loop. Behaviour is unchanged.
Same shape as the Koschel cleanups from 2022 (e.g. 99d8ae4ec8a
tracing, 2966a9918df clockevents, dc1acd5c946 dlm).
Signed-off-by: Maoyi Xie <maoyixie.tju at gmail.com>
---
drivers/acpi/riscv/irq.c | 15 ++++++++++-----
1 file changed, 10 insertions(+), 5 deletions(-)
diff --git a/drivers/acpi/riscv/irq.c b/drivers/acpi/riscv/irq.c
index 9b88d0993e88..49582cf4f4e2 100644
--- a/drivers/acpi/riscv/irq.c
+++ b/drivers/acpi/riscv/irq.c
@@ -134,7 +134,8 @@ struct fwnode_handle *riscv_acpi_get_gsi_domain_id(u32 gsi)
static int __init riscv_acpi_register_ext_intc(u32 gsi_base, u32 nr_irqs, u32 nr_idcs,
u32 id, u32 type)
{
- struct riscv_ext_intc_list *ext_intc_element, *node, *prev;
+ struct riscv_ext_intc_list *ext_intc_element, *node;
+ struct list_head *pos = &ext_intc_list;
ext_intc_element = kzalloc_obj(*ext_intc_element);
if (!ext_intc_element)
@@ -153,18 +154,22 @@ static int __init riscv_acpi_register_ext_intc(u32 gsi_base, u32 nr_irqs, u32 nr
ext_intc_element->nr_idcs = nr_idcs;
ext_intc_element->id = id;
list_for_each_entry(node, &ext_intc_list, list) {
- if (node->gsi_base < ext_intc_element->gsi_base)
+ if (node->gsi_base < ext_intc_element->gsi_base) {
+ pos = &node->list;
break;
+ }
}
/* Adjust the previous node's GSI range if that has pending registration */
- prev = list_prev_entry(node, list);
- if (!list_entry_is_head(prev, &ext_intc_list, list)) {
+ if (pos->prev != &ext_intc_list) {
+ struct riscv_ext_intc_list *prev =
+ list_entry(pos->prev, struct riscv_ext_intc_list, list);
+
if (prev->flag & RISCV_ACPI_INTC_FLAG_PENDING)
prev->nr_irqs = ext_intc_element->gsi_base - prev->gsi_base;
}
- list_add_tail(&ext_intc_element->list, &node->list);
+ list_add_tail(&ext_intc_element->list, pos);
return 0;
}
--
2.34.1
More information about the linux-riscv
mailing list