diff --git a/drivers/acpi/irq.c b/drivers/acpi/irq.c index 15ce75b925457eb34573f50f90518420d6eae2ff..b6b8c47b258816ecee7a5f5a5313c347f38c28c3 100644 --- a/drivers/acpi/irq.c +++ b/drivers/acpi/irq.c @@ -13,6 +13,7 @@ enum acpi_irq_model_id acpi_irq_model; static struct fwnode_handle *(*acpi_get_gsi_domain_id)(u32 gsi); +static u32 (*acpi_gsi_to_irq_fallback)(u32 gsi); /** * acpi_gsi_to_irq() - Retrieve the linux irq number for a given GSI @@ -32,9 +33,12 @@ int acpi_gsi_to_irq(u32 gsi, unsigned int *irq) DOMAIN_BUS_ANY); *irq = irq_find_mapping(d, gsi); /* - * *irq == 0 means no mapping, that should - * be reported as a failure + * *irq == 0 means no mapping, that should be reported as a + * failure, unless there is an arch-specific fallback handler. */ + if (!*irq && acpi_gsi_to_irq_fallback) + *irq = acpi_gsi_to_irq_fallback(gsi); + return (*irq > 0) ? 0 : -EINVAL; } EXPORT_SYMBOL_GPL(acpi_gsi_to_irq); @@ -300,6 +304,16 @@ void __init acpi_set_irq_model(enum acpi_irq_model_id model, acpi_get_gsi_domain_id = fn; } +/** + * acpi_set_gsi_to_irq_fallback - Register a GSI transfer + * callback to fallback to arch specified implementation. + * @fn: arch-specific fallback handler + */ +void __init acpi_set_gsi_to_irq_fallback(u32 (*fn)(u32)) +{ + acpi_gsi_to_irq_fallback = fn; +} + /** * acpi_irq_create_hierarchy - Create a hierarchical IRQ domain with the default * GSI domain as its parent. diff --git a/include/linux/acpi.h b/include/linux/acpi.h index f4799d9384266acc5b6785007dba61d2ea0eb5c8..9f7f9a0d724fe6c11c8875222962812e7a0135ed 100644 --- a/include/linux/acpi.h +++ b/include/linux/acpi.h @@ -333,6 +333,7 @@ int acpi_isa_irq_to_gsi (unsigned isa_irq, u32 *gsi); void acpi_set_irq_model(enum acpi_irq_model_id model, struct fwnode_handle *(*)(u32)); +void acpi_set_gsi_to_irq_fallback(u32 (*)(u32)); struct irq_domain *acpi_irq_create_hierarchy(unsigned int flags, unsigned int size,