|
@@ -14,6 +14,7 @@
|
|
|
#include <linux/kernel_stat.h>
|
|
|
#include <linux/radix-tree.h>
|
|
|
#include <linux/bitmap.h>
|
|
|
+#include <linux/irqdomain.h>
|
|
|
|
|
|
#include "internals.h"
|
|
|
|
|
@@ -336,6 +337,47 @@ int generic_handle_irq(unsigned int irq)
|
|
|
}
|
|
|
EXPORT_SYMBOL_GPL(generic_handle_irq);
|
|
|
|
|
|
+#ifdef CONFIG_HANDLE_DOMAIN_IRQ
|
|
|
+/**
|
|
|
+ * __handle_domain_irq - Invoke the handler for a HW irq belonging to a domain
|
|
|
+ * @domain: The domain where to perform the lookup
|
|
|
+ * @hwirq: The HW irq number to convert to a logical one
|
|
|
+ * @lookup: Whether to perform the domain lookup or not
|
|
|
+ * @regs: Register file coming from the low-level handling code
|
|
|
+ *
|
|
|
+ * Returns: 0 on success, or -EINVAL if conversion has failed
|
|
|
+ */
|
|
|
+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;
|
|
|
+ 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;
|
|
|
+ } else {
|
|
|
+ generic_handle_irq(irq);
|
|
|
+ }
|
|
|
+
|
|
|
+ irq_exit();
|
|
|
+ set_irq_regs(old_regs);
|
|
|
+ return ret;
|
|
|
+}
|
|
|
+#endif
|
|
|
+
|
|
|
/* Dynamic interrupt handling */
|
|
|
|
|
|
/**
|