Skip to content

Commit 4d185fd

Browse files
vlsunilPaul Walmsley
authored andcommitted
ACPI: RISC-V: Add support to update gsi range
Some RISC-V interrupt controllers like RPMI based system MSI interrupt controllers do not have MADT entry defined. These interrupt controllers exist only in the namespace. ACPI spec defines _GSB method to get the GSI base of the interrupt controller, However, there is no such standard method to get the GSI range. To support such interrupt controllers, set the GSI range of such interrupt controllers to non-overlapping range and provide API for interrupt controller driver to update it with proper value. Signed-off-by: Sunil V L <sunilvl@ventanamicro.com> Signed-off-by: Anup Patel <apatel@ventanamicro.com> Acked-by: Jassi Brar <jassisinghbrar@gmail.com> Link: https://lore.kernel.org/r/20250818040920.272664-19-apatel@ventanamicro.com Signed-off-by: Paul Walmsley <pjw@kernel.org>
1 parent 694b2ef commit 4d185fd

2 files changed

Lines changed: 41 additions & 2 deletions

File tree

  • arch/riscv/include/asm
  • drivers/acpi/riscv

arch/riscv/include/asm/irq.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -42,6 +42,7 @@ unsigned long acpi_rintc_ext_parent_to_hartid(unsigned int plic_id, unsigned int
4242
unsigned int acpi_rintc_get_plic_nr_contexts(unsigned int plic_id);
4343
unsigned int acpi_rintc_get_plic_context(unsigned int plic_id, unsigned int ctxt_idx);
4444
int __init acpi_rintc_get_imsic_mmio_info(u32 index, struct resource *res);
45+
int riscv_acpi_update_gsi_range(u32 gsi_base, u32 nr_irqs);
4546

4647
#else
4748
static inline int riscv_acpi_get_gsi_info(struct fwnode_handle *fwnode, u32 *gsi_base,
@@ -76,6 +77,10 @@ static inline int __init acpi_rintc_get_imsic_mmio_info(u32 index, struct resour
7677
return 0;
7778
}
7879

80+
static inline int riscv_acpi_update_gsi_range(u32 gsi_base, u32 nr_irqs)
81+
{
82+
return -ENODEV;
83+
}
7984
#endif /* CONFIG_ACPI */
8085

8186
#endif /* _ASM_RISCV_IRQ_H */

drivers/acpi/riscv/irq.c

Lines changed: 36 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,13 +10,16 @@
1010

1111
#include "init.h"
1212

13+
#define RISCV_ACPI_INTC_FLAG_PENDING BIT(0)
14+
1315
struct riscv_ext_intc_list {
1416
acpi_handle handle;
1517
u32 gsi_base;
1618
u32 nr_irqs;
1719
u32 nr_idcs;
1820
u32 id;
1921
u32 type;
22+
u32 flag;
2023
struct list_head list;
2124
};
2225

@@ -69,6 +72,22 @@ static acpi_status riscv_acpi_update_gsi_handle(u32 gsi_base, acpi_handle handle
6972
return AE_NOT_FOUND;
7073
}
7174

75+
int riscv_acpi_update_gsi_range(u32 gsi_base, u32 nr_irqs)
76+
{
77+
struct riscv_ext_intc_list *ext_intc_element;
78+
79+
list_for_each_entry(ext_intc_element, &ext_intc_list, list) {
80+
if (gsi_base == ext_intc_element->gsi_base &&
81+
(ext_intc_element->flag & RISCV_ACPI_INTC_FLAG_PENDING)) {
82+
ext_intc_element->nr_irqs = nr_irqs;
83+
ext_intc_element->flag &= ~RISCV_ACPI_INTC_FLAG_PENDING;
84+
return 0;
85+
}
86+
}
87+
88+
return -ENODEV;
89+
}
90+
7291
int riscv_acpi_get_gsi_info(struct fwnode_handle *fwnode, u32 *gsi_base,
7392
u32 *id, u32 *nr_irqs, u32 *nr_idcs)
7493
{
@@ -115,21 +134,36 @@ struct fwnode_handle *riscv_acpi_get_gsi_domain_id(u32 gsi)
115134
static int __init riscv_acpi_register_ext_intc(u32 gsi_base, u32 nr_irqs, u32 nr_idcs,
116135
u32 id, u32 type)
117136
{
118-
struct riscv_ext_intc_list *ext_intc_element, *node;
137+
struct riscv_ext_intc_list *ext_intc_element, *node, *prev;
119138

120139
ext_intc_element = kzalloc(sizeof(*ext_intc_element), GFP_KERNEL);
121140
if (!ext_intc_element)
122141
return -ENOMEM;
123142

124143
ext_intc_element->gsi_base = gsi_base;
125-
ext_intc_element->nr_irqs = nr_irqs;
144+
145+
/* If nr_irqs is zero, indicate it in flag and set to max range possible */
146+
if (nr_irqs) {
147+
ext_intc_element->nr_irqs = nr_irqs;
148+
} else {
149+
ext_intc_element->flag |= RISCV_ACPI_INTC_FLAG_PENDING;
150+
ext_intc_element->nr_irqs = U32_MAX - ext_intc_element->gsi_base;
151+
}
152+
126153
ext_intc_element->nr_idcs = nr_idcs;
127154
ext_intc_element->id = id;
128155
list_for_each_entry(node, &ext_intc_list, list) {
129156
if (node->gsi_base < ext_intc_element->gsi_base)
130157
break;
131158
}
132159

160+
/* Adjust the previous node's GSI range if that has pending registration */
161+
prev = list_prev_entry(node, list);
162+
if (!list_entry_is_head(prev, &ext_intc_list, list)) {
163+
if (prev->flag & RISCV_ACPI_INTC_FLAG_PENDING)
164+
prev->nr_irqs = ext_intc_element->gsi_base - prev->gsi_base;
165+
}
166+
133167
list_add_tail(&ext_intc_element->list, &node->list);
134168
return 0;
135169
}

0 commit comments

Comments
 (0)