* [PATCH 1/2] drivers/acpi: Move RISC-V interrupt controllers autodep to ACPI IRQ code
2026-05-05 8:48 [PATCH 0/2] irqchip: Arm GICv5 IWB ACPI IRQ probe deferral Lorenzo Pieralisi
@ 2026-05-05 8:48 ` Lorenzo Pieralisi
2026-05-05 8:48 ` [PATCH 2/2] irqchip/gic-v5: Add IWB to ACPI probe dependency control Lorenzo Pieralisi
1 sibling, 0 replies; 4+ messages in thread
From: Lorenzo Pieralisi @ 2026-05-05 8:48 UTC (permalink / raw)
To: Rafael J. Wysocki, Len Brown, Sunil V L, Marc Zyngier,
Thomas Gleixner, Huacai Chen, Anup Patel, Hanjun Guo,
Sudeep Holla, Catalin Marinas, Will Deacon
Cc: linux-riscv, linux-kernel, linux-acpi, linux-arm-kernel,
loongarch, Lorenzo Pieralisi
RISC-V implements arch code to detect probe dependencies for devices and
the interrupt controller the devices GSIs are routed to.
The code itself is arch agnostic apart from an arch specific helper
function required to retrieve the acpi_handle of the interrupt controller
that manages the device GSI interrupt.
In order to enable IRQ probe dependencies detection on other
architectures, move RISC-V IRQ probe dependency detection code to
generic ACPI IRQ code.
RISC-V IRQ code detecting IRQ probe dependency has some limitations/latent
bugs:
- riscv_acpi_irq_get_dep() would force the loop in
riscv_acpi_add_irq_dep() to stop at the first IRQ index that does not
map to an interrupt controller handle (missing some possible
dependencies)
- riscv_acpi_add_prt_dep() does not validate acpi_get_handle() output
- riscv_acpi_add_prt_dep() logic to handle memory allocation failure is
forcing the loop to continue on the same PRT entry
Fix the above limitations along with the code move.
Allow interrupt controller drivers to register an arch specific
function to determine the acpi_handle for a specific GSI number to use
the mechanism if needed by the respective interrupt controller drivers.
Signed-off-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
Cc: Huacai Chen <chenhuacai@kernel.org>
Cc: Thomas Gleixner <tglx@kernel.org>
Cc: Anup Patel <anup@brainfault.org>
Cc: "Rafael J. Wysocki" <rafael@kernel.org>
Cc: Sunil V L <sunilvl@ventanamicro.com>
Cc: Marc Zyngier <maz@kernel.org>
---
arch/riscv/include/asm/acpi.h | 1 +
drivers/acpi/irq.c | 172 +++++++++++++++++++++++++++++++++++-
drivers/acpi/riscv/irq.c | 141 +----------------------------
drivers/irqchip/irq-gic-v3.c | 2 +-
drivers/irqchip/irq-gic-v5.c | 2 +-
drivers/irqchip/irq-gic.c | 2 +-
drivers/irqchip/irq-loongarch-cpu.c | 2 +-
drivers/irqchip/irq-riscv-intc.c | 3 +-
include/linux/acpi.h | 5 +-
9 files changed, 181 insertions(+), 149 deletions(-)
diff --git a/arch/riscv/include/asm/acpi.h b/arch/riscv/include/asm/acpi.h
index 26ab37c171bc..f598520ac903 100644
--- a/arch/riscv/include/asm/acpi.h
+++ b/arch/riscv/include/asm/acpi.h
@@ -67,6 +67,7 @@ int acpi_get_riscv_isa(struct acpi_table_header *table,
void acpi_get_cbo_block_size(struct acpi_table_header *table, u32 *cbom_size,
u32 *cboz_size, u32 *cbop_size);
+acpi_handle acpi_get_riscv_gsi_handle(u32 gsi);
#else
static inline void acpi_init_rintc_map(void) { }
static inline struct acpi_madt_rintc *acpi_cpu_get_madt_rintc(int cpu)
diff --git a/drivers/acpi/irq.c b/drivers/acpi/irq.c
index d1595156c86a..e4293458bf61 100644
--- a/drivers/acpi/irq.c
+++ b/drivers/acpi/irq.c
@@ -13,6 +13,7 @@
enum acpi_irq_model_id acpi_irq_model;
static acpi_gsi_domain_disp_fn acpi_get_gsi_domain_id;
+static acpi_gsi_handle_disp_fn acpi_get_gsi_handle;
static u32 (*acpi_gsi_to_irq_fallback)(u32 gsi);
/**
@@ -321,15 +322,19 @@ const struct cpumask *acpi_irq_get_affinity(acpi_handle handle,
/**
* acpi_set_irq_model - Setup the GSI irqdomain information
- * @model: the value assigned to acpi_irq_model
- * @fn: a dispatcher function that will return the domain fwnode
- * for a given GSI
+ * @model: the value assigned to acpi_irq_model
+ * @fn: a dispatcher function that will return the domain fwnode
+ * for a given GSI
+ * @gsi_dep_fn: a function to retrieve the acpi_handle a GSI interrupt is
+ * dependent on
+ *
*/
void __init acpi_set_irq_model(enum acpi_irq_model_id model,
- acpi_gsi_domain_disp_fn fn)
+ acpi_gsi_domain_disp_fn fn, acpi_gsi_handle_disp_fn gsi_dep_fn)
{
acpi_irq_model = model;
acpi_get_gsi_domain_id = fn;
+ acpi_get_gsi_handle = gsi_dep_fn;
}
/*
@@ -385,3 +390,162 @@ struct irq_domain *acpi_irq_create_hierarchy(unsigned int flags,
host_data);
}
EXPORT_SYMBOL_GPL(acpi_irq_create_hierarchy);
+
+struct acpi_irq_dep_ctx {
+ int rc;
+ unsigned int index;
+ acpi_handle handle;
+};
+
+static acpi_status acpi_irq_get_parent(struct acpi_resource *ares, void *context)
+{
+ struct acpi_irq_dep_ctx *ctx = context;
+ struct acpi_resource_irq *irq;
+ struct acpi_resource_extended_irq *eirq;
+
+ switch (ares->type) {
+ case ACPI_RESOURCE_TYPE_IRQ:
+ irq = &ares->data.irq;
+ if (ctx->index >= irq->interrupt_count) {
+ ctx->index -= irq->interrupt_count;
+ return AE_OK;
+ }
+ ctx->handle = acpi_get_gsi_handle(irq->interrupts[ctx->index]);
+ ctx->rc = 0;
+ return AE_CTRL_TERMINATE;
+ case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
+ eirq = &ares->data.extended_irq;
+ if (eirq->producer_consumer == ACPI_PRODUCER)
+ return AE_OK;
+
+ if (ctx->index >= eirq->interrupt_count) {
+ ctx->index -= eirq->interrupt_count;
+ return AE_OK;
+ }
+
+ /* Support GSIs only */
+ if (eirq->resource_source.string_length)
+ return AE_OK;
+
+ ctx->handle = acpi_get_gsi_handle(eirq->interrupts[ctx->index]);
+ ctx->rc = 0;
+ return AE_CTRL_TERMINATE;
+ }
+
+ return AE_OK;
+}
+
+static int acpi_irq_get_dep(acpi_handle handle, unsigned int index, acpi_handle *gsi_handle)
+{
+ struct acpi_irq_dep_ctx ctx = {-EINVAL, index, NULL};
+
+ if (!gsi_handle)
+ return -EINVAL;
+
+ acpi_walk_resources(handle, METHOD_NAME__CRS, acpi_irq_get_parent, &ctx);
+ *gsi_handle = ctx.handle;
+
+ return ctx.rc;
+}
+
+static bool acpi_prt_entry_valid(void *prt_entry)
+{
+ struct acpi_pci_routing_table *entry = prt_entry;
+
+ return entry && entry->length > 0;
+}
+
+static void *acpi_prt_next_entry(void *prt_entry)
+{
+ struct acpi_pci_routing_table *entry = prt_entry;
+
+ return prt_entry + entry->length;
+}
+
+static u32 acpi_add_prt_dep(acpi_handle handle)
+{
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ struct acpi_pci_routing_table *entry;
+ struct acpi_handle_list dep_devices;
+ acpi_handle gsi_handle;
+ acpi_handle link_handle;
+ acpi_status status;
+ u32 count = 0;
+
+ status = acpi_get_irq_routing_table(handle, &buffer);
+ if (ACPI_FAILURE(status)) {
+ acpi_handle_err(handle, "failed to get IRQ routing table\n");
+ kfree(buffer.pointer);
+ return 0;
+ }
+
+ entry = buffer.pointer;
+ for (; acpi_prt_entry_valid(entry); entry = acpi_prt_next_entry(entry)) {
+ if (entry->source[0]) {
+ status = acpi_get_handle(handle, entry->source, &link_handle);
+ if (ACPI_FAILURE(status))
+ continue;
+ dep_devices.count = 1;
+ dep_devices.handles = kcalloc(1, sizeof(*dep_devices.handles), GFP_KERNEL);
+ if (!dep_devices.handles) {
+ acpi_handle_err(handle, "failed to allocate memory\n");
+ continue;
+ }
+
+ dep_devices.handles[0] = link_handle;
+ count += acpi_scan_add_dep(handle, &dep_devices);
+ } else {
+ gsi_handle = acpi_get_gsi_handle(entry->source_index);
+ if (!gsi_handle)
+ continue;
+ dep_devices.count = 1;
+ dep_devices.handles = kcalloc(1, sizeof(*dep_devices.handles), GFP_KERNEL);
+ if (!dep_devices.handles) {
+ acpi_handle_err(handle, "failed to allocate memory\n");
+ continue;
+ }
+
+ dep_devices.handles[0] = gsi_handle;
+ count += acpi_scan_add_dep(handle, &dep_devices);
+ }
+ }
+
+ kfree(buffer.pointer);
+ return count;
+}
+
+static u32 acpi_add_irq_dep(acpi_handle handle)
+{
+ struct acpi_handle_list dep_devices;
+ acpi_handle gsi_handle;
+ u32 count = 0;
+ int i;
+
+ for (i = 0; !acpi_irq_get_dep(handle, i, &gsi_handle); i++) {
+ if (!gsi_handle)
+ continue;
+
+ dep_devices.count = 1;
+ dep_devices.handles = kcalloc(1, sizeof(*dep_devices.handles), GFP_KERNEL);
+ if (!dep_devices.handles) {
+ acpi_handle_err(handle, "failed to allocate memory\n");
+ continue;
+ }
+
+ dep_devices.handles[0] = gsi_handle;
+ count += acpi_scan_add_dep(handle, &dep_devices);
+ }
+
+ return count;
+}
+
+u32 acpi_irq_add_auto_dep(acpi_handle handle)
+{
+ if (!acpi_get_gsi_handle)
+ return 0;
+
+ if (acpi_has_method(handle, "_PRT"))
+ return acpi_add_prt_dep(handle);
+
+ return acpi_add_irq_dep(handle);
+}
diff --git a/drivers/acpi/riscv/irq.c b/drivers/acpi/riscv/irq.c
index 9b88d0993e88..da2c42e0ebfd 100644
--- a/drivers/acpi/riscv/irq.c
+++ b/drivers/acpi/riscv/irq.c
@@ -23,12 +23,6 @@ struct riscv_ext_intc_list {
struct list_head list;
};
-struct acpi_irq_dep_ctx {
- int rc;
- unsigned int index;
- acpi_handle handle;
-};
-
LIST_HEAD(ext_intc_list);
static int irqchip_cmp_func(const void *in0, const void *in1)
@@ -254,7 +248,7 @@ void __init riscv_acpi_init_gsi_mapping(void)
acpi_get_devices("RSCV0006", riscv_acpi_create_gsi_map_smsi, NULL, NULL);
}
-static acpi_handle riscv_acpi_get_gsi_handle(u32 gsi)
+acpi_handle acpi_get_riscv_gsi_handle(u32 gsi)
{
struct riscv_ext_intc_list *ext_intc_element;
struct list_head *i;
@@ -269,138 +263,7 @@ static acpi_handle riscv_acpi_get_gsi_handle(u32 gsi)
return NULL;
}
-static acpi_status riscv_acpi_irq_get_parent(struct acpi_resource *ares, void *context)
-{
- struct acpi_irq_dep_ctx *ctx = context;
- struct acpi_resource_irq *irq;
- struct acpi_resource_extended_irq *eirq;
-
- switch (ares->type) {
- case ACPI_RESOURCE_TYPE_IRQ:
- irq = &ares->data.irq;
- if (ctx->index >= irq->interrupt_count) {
- ctx->index -= irq->interrupt_count;
- return AE_OK;
- }
- ctx->handle = riscv_acpi_get_gsi_handle(irq->interrupts[ctx->index]);
- return AE_CTRL_TERMINATE;
- case ACPI_RESOURCE_TYPE_EXTENDED_IRQ:
- eirq = &ares->data.extended_irq;
- if (eirq->producer_consumer == ACPI_PRODUCER)
- return AE_OK;
-
- if (ctx->index >= eirq->interrupt_count) {
- ctx->index -= eirq->interrupt_count;
- return AE_OK;
- }
-
- /* Support GSIs only */
- if (eirq->resource_source.string_length)
- return AE_OK;
-
- ctx->handle = riscv_acpi_get_gsi_handle(eirq->interrupts[ctx->index]);
- return AE_CTRL_TERMINATE;
- }
-
- return AE_OK;
-}
-
-static int riscv_acpi_irq_get_dep(acpi_handle handle, unsigned int index, acpi_handle *gsi_handle)
-{
- struct acpi_irq_dep_ctx ctx = {-EINVAL, index, NULL};
-
- if (!gsi_handle)
- return 0;
-
- acpi_walk_resources(handle, METHOD_NAME__CRS, riscv_acpi_irq_get_parent, &ctx);
- *gsi_handle = ctx.handle;
- if (*gsi_handle)
- return 1;
-
- return 0;
-}
-
-static u32 riscv_acpi_add_prt_dep(acpi_handle handle)
-{
- struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
- struct acpi_pci_routing_table *entry;
- struct acpi_handle_list dep_devices;
- acpi_handle gsi_handle;
- acpi_handle link_handle;
- acpi_status status;
- u32 count = 0;
-
- status = acpi_get_irq_routing_table(handle, &buffer);
- if (ACPI_FAILURE(status)) {
- acpi_handle_err(handle, "failed to get IRQ routing table\n");
- kfree(buffer.pointer);
- return 0;
- }
-
- entry = buffer.pointer;
- while (entry && (entry->length > 0)) {
- if (entry->source[0]) {
- acpi_get_handle(handle, entry->source, &link_handle);
- dep_devices.count = 1;
- dep_devices.handles = kzalloc_objs(*dep_devices.handles,
- 1);
- if (!dep_devices.handles) {
- acpi_handle_err(handle, "failed to allocate memory\n");
- continue;
- }
-
- dep_devices.handles[0] = link_handle;
- count += acpi_scan_add_dep(handle, &dep_devices);
- } else {
- gsi_handle = riscv_acpi_get_gsi_handle(entry->source_index);
- dep_devices.count = 1;
- dep_devices.handles = kzalloc_objs(*dep_devices.handles,
- 1);
- if (!dep_devices.handles) {
- acpi_handle_err(handle, "failed to allocate memory\n");
- continue;
- }
-
- dep_devices.handles[0] = gsi_handle;
- count += acpi_scan_add_dep(handle, &dep_devices);
- }
-
- entry = (struct acpi_pci_routing_table *)
- ((unsigned long)entry + entry->length);
- }
-
- kfree(buffer.pointer);
- return count;
-}
-
-static u32 riscv_acpi_add_irq_dep(acpi_handle handle)
-{
- struct acpi_handle_list dep_devices;
- acpi_handle gsi_handle;
- u32 count = 0;
- int i;
-
- for (i = 0;
- riscv_acpi_irq_get_dep(handle, i, &gsi_handle);
- i++) {
- dep_devices.count = 1;
- dep_devices.handles = kzalloc_objs(*dep_devices.handles, 1);
- if (!dep_devices.handles) {
- acpi_handle_err(handle, "failed to allocate memory\n");
- continue;
- }
-
- dep_devices.handles[0] = gsi_handle;
- count += acpi_scan_add_dep(handle, &dep_devices);
- }
-
- return count;
-}
-
u32 arch_acpi_add_auto_dep(acpi_handle handle)
{
- if (acpi_has_method(handle, "_PRT"))
- return riscv_acpi_add_prt_dep(handle);
-
- return riscv_acpi_add_irq_dep(handle);
+ return acpi_irq_add_auto_dep(handle);
}
diff --git a/drivers/irqchip/irq-gic-v3.c b/drivers/irqchip/irq-gic-v3.c
index 99444a1b2ffa..2673954d4577 100644
--- a/drivers/irqchip/irq-gic-v3.c
+++ b/drivers/irqchip/irq-gic-v3.c
@@ -2588,7 +2588,7 @@ gic_acpi_init(union acpi_subtable_headers *header, const unsigned long end)
if (err)
goto out_fwhandle_free;
- acpi_set_irq_model(ACPI_IRQ_MODEL_GIC, gic_v3_get_gsi_domain_id);
+ acpi_set_irq_model(ACPI_IRQ_MODEL_GIC, gic_v3_get_gsi_domain_id, NULL);
if (static_branch_likely(&supports_deactivate_key))
gic_acpi_setup_kvm_info();
diff --git a/drivers/irqchip/irq-gic-v5.c b/drivers/irqchip/irq-gic-v5.c
index 6b0903be8ebf..03cc2830b260 100644
--- a/drivers/irqchip/irq-gic-v5.c
+++ b/drivers/irqchip/irq-gic-v5.c
@@ -1242,7 +1242,7 @@ static int __init gic_acpi_init(union acpi_subtable_headers *header, const unsig
if (ret)
goto out_irs;
- acpi_set_irq_model(ACPI_IRQ_MODEL_GIC_V5, gic_v5_get_gsi_domain_id);
+ acpi_set_irq_model(ACPI_IRQ_MODEL_GIC_V5, gic_v5_get_gsi_domain_id, NULL);
return 0;
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index ec70c84e9f91..f6bc29f515fb 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -1690,7 +1690,7 @@ static int __init gic_v2_acpi_init(union acpi_subtable_headers *header,
return ret;
}
- acpi_set_irq_model(ACPI_IRQ_MODEL_GIC, gic_v2_get_gsi_domain_id);
+ acpi_set_irq_model(ACPI_IRQ_MODEL_GIC, gic_v2_get_gsi_domain_id, NULL);
if (IS_ENABLED(CONFIG_ARM_GIC_V2M))
gicv2m_init(NULL, gic_data[0].domain);
diff --git a/drivers/irqchip/irq-loongarch-cpu.c b/drivers/irqchip/irq-loongarch-cpu.c
index 950bc087e388..84ce24889488 100644
--- a/drivers/irqchip/irq-loongarch-cpu.c
+++ b/drivers/irqchip/irq-loongarch-cpu.c
@@ -168,7 +168,7 @@ static int __init cpuintc_acpi_init(union acpi_subtable_headers *header,
panic("Failed to add irqdomain for LoongArch CPU");
set_handle_irq(&handle_cpu_irq);
- acpi_set_irq_model(ACPI_IRQ_MODEL_LPIC, lpic_get_gsi_domain_id);
+ acpi_set_irq_model(ACPI_IRQ_MODEL_LPIC, lpic_get_gsi_domain_id, NULL);
acpi_set_gsi_to_irq_fallback(lpic_gsi_to_irq);
ret = acpi_cascade_irqdomain_init();
diff --git a/drivers/irqchip/irq-riscv-intc.c b/drivers/irqchip/irq-riscv-intc.c
index 84418dbd5a27..0595144116e2 100644
--- a/drivers/irqchip/irq-riscv-intc.c
+++ b/drivers/irqchip/irq-riscv-intc.c
@@ -384,7 +384,8 @@ static int __init riscv_intc_acpi_init(union acpi_subtable_headers *header,
if (rc)
irq_domain_free_fwnode(fn);
else
- acpi_set_irq_model(ACPI_IRQ_MODEL_RINTC, riscv_acpi_get_gsi_domain_id);
+ acpi_set_irq_model(ACPI_IRQ_MODEL_RINTC, riscv_acpi_get_gsi_domain_id,
+ acpi_get_riscv_gsi_handle);
return rc;
}
diff --git a/include/linux/acpi.h b/include/linux/acpi.h
index 67effb91fa98..468fc6a54651 100644
--- a/include/linux/acpi.h
+++ b/include/linux/acpi.h
@@ -360,9 +360,10 @@ int acpi_gsi_to_irq (u32 gsi, unsigned int *irq);
int acpi_isa_irq_to_gsi (unsigned isa_irq, u32 *gsi);
typedef struct fwnode_handle *(*acpi_gsi_domain_disp_fn)(u32);
+typedef acpi_handle (*acpi_gsi_handle_disp_fn)(u32);
void acpi_set_irq_model(enum acpi_irq_model_id model,
- acpi_gsi_domain_disp_fn fn);
+ acpi_gsi_domain_disp_fn fn, acpi_gsi_handle_disp_fn gsi_dep_fn);
acpi_gsi_domain_disp_fn acpi_get_gsi_dispatcher(void);
void acpi_set_gsi_to_irq_fallback(u32 (*)(u32));
@@ -372,6 +373,8 @@ struct irq_domain *acpi_irq_create_hierarchy(unsigned int flags,
const struct irq_domain_ops *ops,
void *host_data);
+u32 acpi_irq_add_auto_dep(acpi_handle handle);
+
#ifdef CONFIG_X86_IO_APIC
extern int acpi_get_override_irq(u32 gsi, int *trigger, int *polarity);
#else
--
2.54.0
^ permalink raw reply related [flat|nested] 4+ messages in thread* [PATCH 2/2] irqchip/gic-v5: Add IWB to ACPI probe dependency control
2026-05-05 8:48 [PATCH 0/2] irqchip: Arm GICv5 IWB ACPI IRQ probe deferral Lorenzo Pieralisi
2026-05-05 8:48 ` [PATCH 1/2] drivers/acpi: Move RISC-V interrupt controllers autodep to ACPI IRQ code Lorenzo Pieralisi
@ 2026-05-05 8:48 ` Lorenzo Pieralisi
2026-05-05 19:58 ` Thomas Gleixner
1 sibling, 1 reply; 4+ messages in thread
From: Lorenzo Pieralisi @ 2026-05-05 8:48 UTC (permalink / raw)
To: Rafael J. Wysocki, Len Brown, Sunil V L, Marc Zyngier,
Thomas Gleixner, Huacai Chen, Anup Patel, Hanjun Guo,
Sudeep Holla, Catalin Marinas, Will Deacon
Cc: linux-riscv, linux-kernel, linux-acpi, linux-arm-kernel,
loongarch, Lorenzo Pieralisi
On Arm GICv5 systems, wired IRQs routed to an IWB may require resolving
probe dependencies to make sure drivers for devices whose IRQs are routed
to an IWB are probed after the IWB interrupt controller driver for the IWB
they are routed to has probed.
Implement an ACPI hook to retrieve an acpi_handle for a specific GSI (if
any, on GICv5 systems only the IWB is represented in firmware with an
ACPI device object), hook it into ACPI IRQ core (updating
acpi_set_irq_model()) and add the IWB to the list of devices whose
dependencies can be detected (and cleared) in ACPI core to guarantee that
probe dependencies for the IWB are satisfied.
Signed-off-by: Lorenzo Pieralisi <lpieralisi@kernel.org>
Cc: Thomas Gleixner <tglx@kernel.org>
Cc: Hanjun Guo <guohanjun@huawei.com>
Cc: Sudeep Holla <sudeep.holla@kernel.org>
Cc: "Rafael J. Wysocki" <rafael@kernel.org>
Cc: Marc Zyngier <maz@kernel.org>
---
drivers/acpi/arm64/iort.c | 22 +++++++++++++++++++---
drivers/acpi/scan.c | 1 +
drivers/irqchip/irq-gic-v5-iwb.c | 5 +++++
drivers/irqchip/irq-gic-v5.c | 13 +++++++++++--
include/linux/acpi_iort.h | 3 ++-
5 files changed, 38 insertions(+), 6 deletions(-)
diff --git a/drivers/acpi/arm64/iort.c b/drivers/acpi/arm64/iort.c
index af7a9b2fd5bc..34412cd697d8 100644
--- a/drivers/acpi/arm64/iort.c
+++ b/drivers/acpi/arm64/iort.c
@@ -789,11 +789,9 @@ struct irq_domain *iort_get_device_domain(struct device *dev, u32 id,
return irq_find_matching_fwnode(handle, bus_token);
}
-struct fwnode_handle *iort_iwb_handle(u32 iwb_id)
+acpi_handle iort_iwb_handle(u32 iwb_id)
{
- struct fwnode_handle *fwnode;
struct acpi_iort_node *node;
- struct acpi_device *device;
struct acpi_iort_iwb *iwb;
acpi_status status;
acpi_handle handle;
@@ -808,6 +806,19 @@ struct fwnode_handle *iort_iwb_handle(u32 iwb_id)
if (ACPI_FAILURE(status))
return NULL;
+ return handle;
+}
+
+struct fwnode_handle *iort_iwb_handle_fwnode(u32 iwb_id)
+{
+ struct fwnode_handle *fwnode;
+ struct acpi_device *device;
+ acpi_handle handle;
+
+ handle = iort_iwb_handle(iwb_id);
+ if (!handle)
+ return NULL;
+
device = acpi_get_acpi_dev(handle);
if (!device)
return NULL;
@@ -2090,6 +2101,11 @@ static void __init iort_init_platform_devices(void)
}
}
+u32 arch_acpi_add_auto_dep(acpi_handle handle)
+{
+ return acpi_irq_add_auto_dep(handle);
+}
+
void __init acpi_iort_init(void)
{
acpi_status status;
diff --git a/drivers/acpi/scan.c b/drivers/acpi/scan.c
index 530547cda8b2..ba15da9058dc 100644
--- a/drivers/acpi/scan.c
+++ b/drivers/acpi/scan.c
@@ -856,6 +856,7 @@ static const char * const acpi_ignore_dep_ids[] = {
/* List of HIDs for which we honor deps of matching ACPI devs, when checking _DEP lists. */
static const char * const acpi_honor_dep_ids[] = {
+ "ARMH0003", /* ARM GICv5 IWB */
"INT3472", /* Camera sensor PMIC / clk and regulator info */
"INTC1059", /* IVSC (TGL) driver must be loaded to allow i2c access to camera sensors */
"INTC1095", /* IVSC (ADL) driver must be loaded to allow i2c access to camera sensors */
diff --git a/drivers/irqchip/irq-gic-v5-iwb.c b/drivers/irqchip/irq-gic-v5-iwb.c
index 9103feb70ce8..a02cb9537b15 100644
--- a/drivers/irqchip/irq-gic-v5-iwb.c
+++ b/drivers/irqchip/irq-gic-v5-iwb.c
@@ -269,6 +269,11 @@ static int gicv5_iwb_device_probe(struct platform_device *pdev)
if (IS_ERR(iwb_node))
return PTR_ERR(iwb_node);
+#ifdef CONFIG_ACPI
+ if (has_acpi_companion(&pdev->dev))
+ acpi_dev_clear_dependencies(ACPI_COMPANION(&pdev->dev));
+#endif
+
return 0;
}
diff --git a/drivers/irqchip/irq-gic-v5.c b/drivers/irqchip/irq-gic-v5.c
index 03cc2830b260..26cfaea1af41 100644
--- a/drivers/irqchip/irq-gic-v5.c
+++ b/drivers/irqchip/irq-gic-v5.c
@@ -1217,11 +1217,19 @@ static struct fwnode_handle *gsi_domain_handle;
static struct fwnode_handle *gic_v5_get_gsi_domain_id(u32 gsi)
{
if (FIELD_GET(GICV5_GSI_IC_TYPE, gsi) == GICV5_GSI_IWB_TYPE)
- return iort_iwb_handle(FIELD_GET(GICV5_GSI_IWB_FRAME_ID, gsi));
+ return iort_iwb_handle_fwnode(FIELD_GET(GICV5_GSI_IWB_FRAME_ID, gsi));
return gsi_domain_handle;
}
+static acpi_handle gic_v5_get_gsi_handle(u32 gsi)
+{
+ if (FIELD_GET(GICV5_GSI_IC_TYPE, gsi) == GICV5_GSI_IWB_TYPE)
+ return iort_iwb_handle(FIELD_GET(GICV5_GSI_IWB_FRAME_ID, gsi));
+
+ return NULL;
+}
+
static int __init gic_acpi_init(union acpi_subtable_headers *header, const unsigned long end)
{
struct acpi_madt_gicv5_irs *irs = (struct acpi_madt_gicv5_irs *)header;
@@ -1242,7 +1250,8 @@ static int __init gic_acpi_init(union acpi_subtable_headers *header, const unsig
if (ret)
goto out_irs;
- acpi_set_irq_model(ACPI_IRQ_MODEL_GIC_V5, gic_v5_get_gsi_domain_id, NULL);
+ acpi_set_irq_model(ACPI_IRQ_MODEL_GIC_V5, gic_v5_get_gsi_domain_id,
+ gic_v5_get_gsi_handle);
return 0;
diff --git a/include/linux/acpi_iort.h b/include/linux/acpi_iort.h
index 17bb3374f4ca..931eaa7bbf6a 100644
--- a/include/linux/acpi_iort.h
+++ b/include/linux/acpi_iort.h
@@ -27,7 +27,8 @@ int iort_register_domain_token(int trans_id, phys_addr_t base,
struct fwnode_handle *fw_node);
void iort_deregister_domain_token(int trans_id);
struct fwnode_handle *iort_find_domain_token(int trans_id);
-struct fwnode_handle *iort_iwb_handle(u32 iwb_id);
+acpi_handle iort_iwb_handle(u32 iwb_id);
+struct fwnode_handle *iort_iwb_handle_fwnode(u32 iwb_id);
#ifdef CONFIG_ACPI_IORT
u32 iort_msi_map_id(struct device *dev, u32 id);
--
2.54.0
^ permalink raw reply related [flat|nested] 4+ messages in thread