]> git.proxmox.com Git - mirror_ubuntu-kernels.git/commitdiff
ACPI: irq: Allow acpi_gsi_to_irq() to have an arch-specific fallback
authorMarc Zyngier <maz@kernel.org>
Wed, 20 Jul 2022 10:51:22 +0000 (18:51 +0800)
committerMarc Zyngier <maz@kernel.org>
Wed, 20 Jul 2022 11:05:17 +0000 (12:05 +0100)
It appears that the generic version of acpi_gsi_to_irq() doesn't
fallback to establishing a mapping if there is no pre-existing
one while the x86 version does.

While arm64 seems unaffected by it, LoongArch is relying on the x86
behaviour. In an effort to prevent new architectures from reinventing
the proverbial wheel, provide an optional callback that the arch code
can set to restore the x86 behaviour.

Hopefully we can eventually get rid of this in the future once
the expected behaviour has been clarified.

Reported-by: Jianmin Lv <lvjianmin@loongson.cn>
Signed-off-by: Marc Zyngier <maz@kernel.org>
Signed-off-by: Jianmin Lv <lvjianmin@loongson.cn>
Tested-by: Hanjun Guo <guohanjun@huawei.com>
Reviewed-by: Hanjun Guo <guohanjun@huawei.com>
Link: https://lore.kernel.org/r/1658314292-35346-4-git-send-email-lvjianmin@loongson.cn
drivers/acpi/irq.c
include/linux/acpi.h

index f0de7687949737d1c9f460ee372a2e30b0850e44..dabe45eba055d1f28721138e832ad422650bcf81 100644 (file)
@@ -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);
@@ -301,6 +305,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.
index 957e23f727eaddc997e9d8db90d177dd548f1254..e2b60d53ca6015dd8e3b61d04307c6d9165e0b79 100644 (file)
@@ -357,6 +357,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,