diff options
author | Marc Zyngier <marc.zyngier@arm.com> | 2016-04-11 04:57:51 -0400 |
---|---|---|
committer | Thomas Gleixner <tglx@linutronix.de> | 2016-05-02 07:42:50 -0400 |
commit | 651e8b54abdeeaa36f5f54ffa05c18707a3cc1d0 (patch) | |
tree | 61c85560b32b720e5f1ec99b1c8980ea02d346bd /kernel/irq | |
parent | 7cec18a3906b52e855c9386650c0226bbe594a4c (diff) |
irqdomain: Allow domain matching on irq_fwspec
When iterating over the irq domain list, we try to match a domain
either by calling a match() function or by comparing a number
of fields passed as parameters.
Both approaches are a bit restrictive:
- match() is DT specific and only takes a device node
- the fallback case only deals with the fwnode_handle
It would be useful if we had a per-domain function that would
actually perform the matching check on the whole of the
irq_fwspec structure. This would allow for a domain to triage
matching attempts that need to extend beyond the fwnode.
Let's introduce irq_find_matching_fwspec(), which takes a full
blown irq_fwspec structure, and call into a select() function
implemented by the irqdomain. irq_find_matching_fwnode() is
made a wrapper around irq_find_matching_fwspec in order to
preserve compatibility.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
Cc: Mark Rutland <mark.rutland@arm.com>
Cc: devicetree@vger.kernel.org
Cc: Jason Cooper <jason@lakedaemon.net>
Cc: Will Deacon <will.deacon@arm.com>
Cc: Rob Herring <robh+dt@kernel.org>
Link: http://lkml.kernel.org/r/1460365075-7316-2-git-send-email-marc.zyngier@arm.com
Signed-off-by: Thomas Gleixner <tglx@linutronix.de>
Diffstat (limited to 'kernel/irq')
-rw-r--r-- | kernel/irq/irqdomain.c | 19 |
1 files changed, 10 insertions, 9 deletions
diff --git a/kernel/irq/irqdomain.c b/kernel/irq/irqdomain.c index 3a519a01118b..503c5b9dd030 100644 --- a/kernel/irq/irqdomain.c +++ b/kernel/irq/irqdomain.c | |||
@@ -243,14 +243,15 @@ struct irq_domain *irq_domain_add_legacy(struct device_node *of_node, | |||
243 | EXPORT_SYMBOL_GPL(irq_domain_add_legacy); | 243 | EXPORT_SYMBOL_GPL(irq_domain_add_legacy); |
244 | 244 | ||
245 | /** | 245 | /** |
246 | * irq_find_matching_fwnode() - Locates a domain for a given fwnode | 246 | * irq_find_matching_fwspec() - Locates a domain for a given fwspec |
247 | * @fwnode: FW descriptor of the interrupt controller | 247 | * @fwspec: FW specifier for an interrupt |
248 | * @bus_token: domain-specific data | 248 | * @bus_token: domain-specific data |
249 | */ | 249 | */ |
250 | struct irq_domain *irq_find_matching_fwnode(struct fwnode_handle *fwnode, | 250 | struct irq_domain *irq_find_matching_fwspec(struct irq_fwspec *fwspec, |
251 | enum irq_domain_bus_token bus_token) | 251 | enum irq_domain_bus_token bus_token) |
252 | { | 252 | { |
253 | struct irq_domain *h, *found = NULL; | 253 | struct irq_domain *h, *found = NULL; |
254 | struct fwnode_handle *fwnode = fwspec->fwnode; | ||
254 | int rc; | 255 | int rc; |
255 | 256 | ||
256 | /* We might want to match the legacy controller last since | 257 | /* We might want to match the legacy controller last since |
@@ -264,7 +265,9 @@ struct irq_domain *irq_find_matching_fwnode(struct fwnode_handle *fwnode, | |||
264 | */ | 265 | */ |
265 | mutex_lock(&irq_domain_mutex); | 266 | mutex_lock(&irq_domain_mutex); |
266 | list_for_each_entry(h, &irq_domain_list, link) { | 267 | list_for_each_entry(h, &irq_domain_list, link) { |
267 | if (h->ops->match) | 268 | if (h->ops->select && fwspec->param_count) |
269 | rc = h->ops->select(h, fwspec, bus_token); | ||
270 | else if (h->ops->match) | ||
268 | rc = h->ops->match(h, to_of_node(fwnode), bus_token); | 271 | rc = h->ops->match(h, to_of_node(fwnode), bus_token); |
269 | else | 272 | else |
270 | rc = ((fwnode != NULL) && (h->fwnode == fwnode) && | 273 | rc = ((fwnode != NULL) && (h->fwnode == fwnode) && |
@@ -279,7 +282,7 @@ struct irq_domain *irq_find_matching_fwnode(struct fwnode_handle *fwnode, | |||
279 | mutex_unlock(&irq_domain_mutex); | 282 | mutex_unlock(&irq_domain_mutex); |
280 | return found; | 283 | return found; |
281 | } | 284 | } |
282 | EXPORT_SYMBOL_GPL(irq_find_matching_fwnode); | 285 | EXPORT_SYMBOL_GPL(irq_find_matching_fwspec); |
283 | 286 | ||
284 | /** | 287 | /** |
285 | * irq_set_default_host() - Set a "default" irq domain | 288 | * irq_set_default_host() - Set a "default" irq domain |
@@ -574,11 +577,9 @@ unsigned int irq_create_fwspec_mapping(struct irq_fwspec *fwspec) | |||
574 | int virq; | 577 | int virq; |
575 | 578 | ||
576 | if (fwspec->fwnode) { | 579 | if (fwspec->fwnode) { |
577 | domain = irq_find_matching_fwnode(fwspec->fwnode, | 580 | domain = irq_find_matching_fwspec(fwspec, DOMAIN_BUS_WIRED); |
578 | DOMAIN_BUS_WIRED); | ||
579 | if (!domain) | 581 | if (!domain) |
580 | domain = irq_find_matching_fwnode(fwspec->fwnode, | 582 | domain = irq_find_matching_fwspec(fwspec, DOMAIN_BUS_ANY); |
581 | DOMAIN_BUS_ANY); | ||
582 | } else { | 583 | } else { |
583 | domain = irq_default_domain; | 584 | domain = irq_default_domain; |
584 | } | 585 | } |