summaryrefslogtreecommitdiff
path: root/kernel/irq
diff options
context:
space:
mode:
authorMarc Zyngier <maz@kernel.org>2021-05-04 16:24:37 +0300
committerMarc Zyngier <maz@kernel.org>2021-06-10 15:09:18 +0300
commita3016b26ee6ee13d5647d701404a7912d4eaea9e (patch)
treee8b7c6162b1c65353879fd87de817885ef1cabcd /kernel/irq
parentd22558dd0a6c888b1829f9d3a0a627e330e27585 (diff)
downloadlinux-a3016b26ee6ee13d5647d701404a7912d4eaea9e.tar.xz
genirq: Use irq_resolve_mapping() to implement __handle_domain_irq() and co
In order to start reaping the benefits of irq_resolve_mapping(), start using it in __handle_domain_irq() and handle_domain_nmi(). This involves splitting generic_handle_irq() to be able to directly provide the irq_desc. Signed-off-by: Marc Zyngier <maz@kernel.org>
Diffstat (limited to 'kernel/irq')
-rw-r--r--kernel/irq/irqdesc.c60
1 files changed, 35 insertions, 25 deletions
diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c
index 4a617d7312a4..684c5b7b7832 100644
--- a/kernel/irq/irqdesc.c
+++ b/kernel/irq/irqdesc.c
@@ -632,14 +632,8 @@ void irq_init_desc(unsigned int irq)
#endif /* !CONFIG_SPARSE_IRQ */
-/**
- * generic_handle_irq - Invoke the handler for a particular irq
- * @irq: The irq number to handle
- *
- */
-int generic_handle_irq(unsigned int irq)
+int handle_irq_desc(struct irq_desc *desc)
{
- struct irq_desc *desc = irq_to_desc(irq);
struct irq_data *data;
if (!desc)
@@ -652,6 +646,17 @@ int generic_handle_irq(unsigned int irq)
generic_handle_irq_desc(desc);
return 0;
}
+EXPORT_SYMBOL_GPL(handle_irq_desc);
+
+/**
+ * generic_handle_irq - Invoke the handler for a particular irq
+ * @irq: The irq number to handle
+ *
+ */
+int generic_handle_irq(unsigned int irq)
+{
+ return handle_irq_desc(irq_to_desc(irq));
+}
EXPORT_SYMBOL_GPL(generic_handle_irq);
#ifdef CONFIG_HANDLE_DOMAIN_IRQ
@@ -668,27 +673,32 @@ int __handle_domain_irq(struct irq_domain *domain, unsigned int hwirq,
bool lookup, struct pt_regs *regs)
{
struct pt_regs *old_regs = set_irq_regs(regs);
- unsigned int irq = hwirq;
+ struct irq_desc *desc;
int ret = 0;
irq_enter();
-#ifdef CONFIG_IRQ_DOMAIN
- if (lookup)
- irq = irq_find_mapping(domain, hwirq);
-#endif
-
- /*
- * Some hardware gives randomly wrong interrupts. Rather
- * than crashing, do something sensible.
- */
- if (unlikely(!irq || irq >= nr_irqs)) {
- ack_bad_irq(irq);
- ret = -EINVAL;
+ if (likely(IS_ENABLED(CONFIG_IRQ_DOMAIN) && lookup)) {
+ /* The irqdomain code provides boundary checks */
+ desc = irq_resolve_mapping(domain, hwirq);
} else {
- generic_handle_irq(irq);
+ /*
+ * Some hardware gives randomly wrong interrupts. Rather
+ * than crashing, do something sensible.
+ */
+ if (unlikely(!hwirq || hwirq >= nr_irqs)) {
+ ack_bad_irq(hwirq);
+ desc = NULL;
+ } else {
+ desc = irq_to_desc(hwirq);
+ }
}
+ if (likely(desc))
+ handle_irq_desc(desc);
+ else
+ ret = -EINVAL;
+
irq_exit();
set_irq_regs(old_regs);
return ret;
@@ -709,7 +719,7 @@ int handle_domain_nmi(struct irq_domain *domain, unsigned int hwirq,
struct pt_regs *regs)
{
struct pt_regs *old_regs = set_irq_regs(regs);
- unsigned int irq;
+ struct irq_desc *desc;
int ret = 0;
/*
@@ -717,14 +727,14 @@ int handle_domain_nmi(struct irq_domain *domain, unsigned int hwirq,
*/
WARN_ON(!in_nmi());
- irq = irq_find_mapping(domain, hwirq);
+ desc = irq_resolve_mapping(domain, hwirq);
/*
* ack_bad_irq is not NMI-safe, just report
* an invalid interrupt.
*/
- if (likely(irq))
- generic_handle_irq(irq);
+ if (likely(desc))
+ handle_irq_desc(desc);
else
ret = -EINVAL;