Currently, in irq_find_host(), irq_domain_ops.match() uses struct device_node pointer to match a particular irq_domain. This will not be able to support ACPI where reference to GICv2m is in the MADT table (i.e the MSI frame).
This patch modifies irq_domain_ops.match(), to allow various types of irq_domain reference. It also introduces enum irq_domain_ref_types.
Along with the new reference type, it also introduces a new function, irq_find_domain(), which can be used to find a particular irqdomain using different reference types.
Signed-off-by: Suravee Suthikulpanit Suravee.Suthikulpanit@amd.com --- include/linux/irqdomain.h | 15 +++++++++++++-- kernel/irq/irqdomain.c | 31 ++++++++++++++++++++++++------- 2 files changed, 37 insertions(+), 9 deletions(-)
diff --git a/include/linux/irqdomain.h b/include/linux/irqdomain.h index 39fbcd8..a91af80 100644 --- a/include/linux/irqdomain.h +++ b/include/linux/irqdomain.h @@ -45,6 +45,11 @@ struct irq_data; /* Number of irqs reserved for a legacy isa controller */ #define NUM_ISA_INTERRUPTS 16
+enum irq_domain_ref_type { + IRQ_DOMAIN_REF_OF_DEV_NODE = 0, + IRQ_DOMAIN_REF_ACPI_MSI_FRAME, +}; + /** * struct irq_domain_ops - Methods for irq_domain objects * @match: Match an interrupt controller device node to a host, returns @@ -61,7 +66,7 @@ struct irq_data; * to setup the irq_desc when returning from map(). */ struct irq_domain_ops { - int (*match)(struct irq_domain *d, struct device_node *node); + int (*match)(struct irq_domain *d, enum irq_domain_ref_type type, void *data); int (*map)(struct irq_domain *d, unsigned int virq, irq_hw_number_t hw); void (*unmap)(struct irq_domain *d, unsigned int virq); int (*xlate)(struct irq_domain *d, struct device_node *node, @@ -117,7 +122,11 @@ struct irq_domain { unsigned int flags;
/* Optional data */ - struct device_node *of_node; + enum irq_domain_ref_type type; + union { + struct device_node *of_node; + void *acpi_ref; + }; struct irq_domain_chip_generic *gc; #ifdef CONFIG_IRQ_DOMAIN_HIERARCHY struct irq_domain *parent; @@ -165,6 +174,8 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node, void *host_data); extern struct irq_domain *irq_find_host(struct device_node *node); extern void irq_set_default_host(struct irq_domain *host); +extern struct irq_domain *irq_find_domain(enum irq_domain_ref_type type, + void *ref);
/** * irq_domain_add_linear() - Allocate and register a linear revmap irq_domain. diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index cc4ef7c..31536d1 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c @@ -187,10 +187,11 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node, EXPORT_SYMBOL_GPL(irq_domain_add_legacy);
/** - * irq_find_host() - Locates a domain for a given device node - * @node: device-tree node of the interrupt controller + * irq_find_domain() - Locates a domain for a given a refence pointer + * @type: specify irq domain reference pointer type to be match + * @ref: pointer to the reference data structure to be matched */ -struct irq_domain *irq_find_host(struct device_node *node) +struct irq_domain *irq_find_domain(enum irq_domain_ref_type type, void *ref) { struct irq_domain *h, *found = NULL; int rc; @@ -202,10 +203,16 @@ struct irq_domain *irq_find_host(struct device_node *node) */ mutex_lock(&irq_domain_mutex); list_for_each_entry(h, &irq_domain_list, link) { - if (h->ops->match) - rc = h->ops->match(h, node); - else - rc = (h->of_node != NULL) && (h->of_node == node); + if (h->ops->match) { + rc = h->ops->match(h, type, ref); + } else if (type == IRQ_DOMAIN_REF_OF_DEV_NODE || + type == IRQ_DOMAIN_REF_ACPI_MSI_FRAME) { + /* Here, we just need to compare reference pointer */ + rc = (h->of_node != NULL) && (h->of_node == ref); + } else { + /* For non-DT and non-ACPI reference, must specify match */ + BUG(); + }
if (rc) { found = h; @@ -215,6 +222,16 @@ struct irq_domain *irq_find_host(struct device_node *node) mutex_unlock(&irq_domain_mutex); return found; } +EXPORT_SYMBOL_GPL(irq_find_domain); + +/** + * irq_find_host() - Locates a domain for a given device node + * @node: device-tree node of the interrupt controller + */ +struct irq_domain *irq_find_host(struct device_node *node) +{ + return irq_find_domain(IRQ_DOMAIN_REF_OF_DEV_NODE, node); +} EXPORT_SYMBOL_GPL(irq_find_host);
/**