genirq: Use irq_resolve_mapping() to implement __handle_domain_irq() and co
authorMarc Zyngier <maz@kernel.org>
Tue, 4 May 2021 13:24:37 +0000 (14:24 +0100)
committerMarc Zyngier <maz@kernel.org>
Thu, 10 Jun 2021 12:09:18 +0000 (13:09 +0100)
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>
include/linux/irqdesc.h
kernel/irq/irqdesc.c

index df465125078552b097e38ccf26e9e4b0249e6970..cdd1cf8207f6217ca9320795c2fa8730c6a27174 100644 (file)
@@ -158,6 +158,7 @@ static inline void generic_handle_irq_desc(struct irq_desc *desc)
        desc->handle_irq(desc);
 }
 
+int handle_irq_desc(struct irq_desc *desc);
 int generic_handle_irq(unsigned int irq);
 
 #ifdef CONFIG_HANDLE_DOMAIN_IRQ
index 4a617d7312a4785454f001a0f2cc381cc58936d6..684c5b7b783239ba31eee2cfb8d2f225837ff124 100644 (file)
@@ -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;