|
@@ -396,6 +396,57 @@ err:
|
|
}
|
|
}
|
|
EXPORT_SYMBOL_GPL(__irq_alloc_descs);
|
|
EXPORT_SYMBOL_GPL(__irq_alloc_descs);
|
|
|
|
|
|
|
|
+#ifdef CONFIG_GENERIC_IRQ_LEGACY_ALLOC_HWIRQ
|
|
|
|
+/**
|
|
|
|
+ * irq_alloc_hwirqs - Allocate an irq descriptor and initialize the hardware
|
|
|
|
+ * @cnt: number of interrupts to allocate
|
|
|
|
+ * @node: node on which to allocate
|
|
|
|
+ *
|
|
|
|
+ * Returns an interrupt number > 0 or 0, if the allocation fails.
|
|
|
|
+ */
|
|
|
|
+unsigned int irq_alloc_hwirqs(int cnt, int node)
|
|
|
|
+{
|
|
|
|
+ int i, irq = __irq_alloc_descs(-1, 0, cnt, node, NULL);
|
|
|
|
+
|
|
|
|
+ if (irq < 0)
|
|
|
|
+ return 0;
|
|
|
|
+
|
|
|
|
+ for (i = irq; cnt > 0; i++, cnt--) {
|
|
|
|
+ if (arch_setup_hwirq(i, node))
|
|
|
|
+ goto err;
|
|
|
|
+ irq_clear_status_flags(i, _IRQ_NOREQUEST);
|
|
|
|
+ }
|
|
|
|
+ return irq;
|
|
|
|
+
|
|
|
|
+err:
|
|
|
|
+ for (i--; i >= irq; i--) {
|
|
|
|
+ irq_set_status_flags(i, _IRQ_NOREQUEST | _IRQ_NOPROBE);
|
|
|
|
+ arch_teardown_hwirq(i);
|
|
|
|
+ }
|
|
|
|
+ irq_free_descs(irq, cnt);
|
|
|
|
+ return 0;
|
|
|
|
+}
|
|
|
|
+EXPORT_SYMBOL_GPL(irq_alloc_hwirqs);
|
|
|
|
+
|
|
|
|
+/**
|
|
|
|
+ * irq_free_hwirqs - Free irq descriptor and cleanup the hardware
|
|
|
|
+ * @from: Free from irq number
|
|
|
|
+ * @cnt: number of interrupts to free
|
|
|
|
+ *
|
|
|
|
+ */
|
|
|
|
+void irq_free_hwirqs(unsigned int from, int cnt)
|
|
|
|
+{
|
|
|
|
+ int i;
|
|
|
|
+
|
|
|
|
+ for (i = from; cnt > 0; i++, cnt--) {
|
|
|
|
+ irq_set_status_flags(i, _IRQ_NOREQUEST | _IRQ_NOPROBE);
|
|
|
|
+ arch_teardown_hwirq(i);
|
|
|
|
+ }
|
|
|
|
+ irq_free_descs(from, cnt);
|
|
|
|
+}
|
|
|
|
+EXPORT_SYMBOL_GPL(irq_free_hwirqs);
|
|
|
|
+#endif
|
|
|
|
+
|
|
/**
|
|
/**
|
|
* irq_reserve_irqs - mark irqs allocated
|
|
* irq_reserve_irqs - mark irqs allocated
|
|
* @from: mark from irq number
|
|
* @from: mark from irq number
|