hc
2024-11-01 2f529f9b558ca1c1bd74be7437a84e4711743404
kernel/kernel/irq/manage.c
....@@ -10,6 +10,7 @@
1010
1111 #include <linux/irq.h>
1212 #include <linux/kthread.h>
13
+#include <linux/kconfig.h>
1314 #include <linux/module.h>
1415 #include <linux/random.h>
1516 #include <linux/interrupt.h>
....@@ -829,6 +830,50 @@
829830 }
830831 EXPORT_SYMBOL(irq_set_irq_wake);
831832
833
+#ifdef CONFIG_IRQ_PIPELINE
834
+
835
+/**
836
+ * irq_switch_oob - Control out-of-band setting for a registered IRQ descriptor
837
+ * @irq: interrupt to control
838
+ * @on: enable/disable pipelining
839
+ *
840
+ * Enable/disable out-of-band handling for an IRQ. At least one
841
+ * action must have been previously registered for such
842
+ * interrupt.
843
+ *
844
+ * The previously registered action(s) need(s) not bearing the
845
+ * IRQF_OOB flag for the IRQ to be switched to out-of-band
846
+ * handling. This call enables switching pre-installed IRQs from
847
+ * in-band to out-of-band handling.
848
+ *
849
+ * NOTE: This routine affects all action handlers sharing the
850
+ * IRQ.
851
+ */
852
+int irq_switch_oob(unsigned int irq, bool on)
853
+{
854
+ struct irq_desc *desc;
855
+ unsigned long flags;
856
+ int ret = 0;
857
+
858
+ desc = irq_get_desc_lock(irq, &flags, 0);
859
+ if (!desc)
860
+ return -EINVAL;
861
+
862
+ if (!desc->action)
863
+ ret = -EINVAL;
864
+ else if (on)
865
+ irq_settings_set_oob(desc);
866
+ else
867
+ irq_settings_clr_oob(desc);
868
+
869
+ irq_put_desc_unlock(desc, flags);
870
+
871
+ return ret;
872
+}
873
+EXPORT_SYMBOL_GPL(irq_switch_oob);
874
+
875
+#endif /* CONFIG_IRQ_PIPELINE */
876
+
832877 /*
833878 * Internal function that tells the architecture code whether a
834879 * particular irq has been exclusively allocated or is available
....@@ -845,7 +890,8 @@
845890
846891 if (irq_settings_can_request(desc)) {
847892 if (!desc->action ||
848
- irqflags & desc->action->flags & IRQF_SHARED)
893
+ ((irqflags & desc->action->flags & IRQF_SHARED) &&
894
+ !((irqflags ^ desc->action->flags) & IRQF_OOB)))
849895 canrequest = 1;
850896 }
851897 irq_put_desc_unlock(desc, flags);
....@@ -1419,6 +1465,21 @@
14191465
14201466 new->irq = irq;
14211467
1468
+ ret = -EINVAL;
1469
+ /*
1470
+ * Out-of-band interrupts can be shared but not threaded. We
1471
+ * silently ignore the OOB setting if interrupt pipelining is
1472
+ * disabled.
1473
+ */
1474
+ if (!irqs_pipelined())
1475
+ new->flags &= ~IRQF_OOB;
1476
+ else if (new->flags & IRQF_OOB) {
1477
+ if (new->thread_fn)
1478
+ goto out_mput;
1479
+ new->flags |= IRQF_NO_THREAD;
1480
+ new->flags &= ~IRQF_ONESHOT;
1481
+ }
1482
+
14221483 /*
14231484 * If the trigger type is not specified by the caller,
14241485 * then use the default for this interrupt.
....@@ -1432,10 +1493,8 @@
14321493 */
14331494 nested = irq_settings_is_nested_thread(desc);
14341495 if (nested) {
1435
- if (!new->thread_fn) {
1436
- ret = -EINVAL;
1496
+ if (!new->thread_fn)
14371497 goto out_mput;
1438
- }
14391498 /*
14401499 * Replace the primary handler which was provided from
14411500 * the driver for non nested interrupt handling by the
....@@ -1519,7 +1578,7 @@
15191578 * the same type (level, edge, polarity). So both flag
15201579 * fields must have IRQF_SHARED set and the bits which
15211580 * set the trigger type must match. Also all must
1522
- * agree on ONESHOT.
1581
+ * agree on ONESHOT and OOB.
15231582 * Interrupt lines used for NMIs cannot be shared.
15241583 */
15251584 unsigned int oldtype;
....@@ -1544,7 +1603,7 @@
15441603
15451604 if (!((old->flags & new->flags) & IRQF_SHARED) ||
15461605 (oldtype != (new->flags & IRQF_TRIGGER_MASK)) ||
1547
- ((old->flags ^ new->flags) & IRQF_ONESHOT))
1606
+ ((old->flags ^ new->flags) & (IRQF_OOB|IRQF_ONESHOT)))
15481607 goto mismatch;
15491608
15501609 /* All handlers must agree on per-cpuness */
....@@ -1661,6 +1720,9 @@
16611720
16621721 if (new->flags & IRQF_ONESHOT)
16631722 desc->istate |= IRQS_ONESHOT;
1723
+
1724
+ if (new->flags & IRQF_OOB)
1725
+ irq_settings_set_oob(desc);
16641726
16651727 /* Exclude IRQ from balancing if requested */
16661728 if (new->flags & IRQF_NOBALANCING) {
....@@ -1809,6 +1871,8 @@
18091871 irq_settings_clr_disable_unlazy(desc);
18101872 /* Only shutdown. Deactivate after synchronize_hardirq() */
18111873 irq_shutdown(desc);
1874
+ /* Turn off OOB handling (after shutdown). */
1875
+ irq_settings_clr_oob(desc);
18121876 }
18131877
18141878 #ifdef CONFIG_SMP
....@@ -1845,14 +1909,15 @@
18451909
18461910 #ifdef CONFIG_DEBUG_SHIRQ
18471911 /*
1848
- * It's a shared IRQ -- the driver ought to be prepared for an IRQ
1849
- * event to happen even now it's being freed, so let's make sure that
1850
- * is so by doing an extra call to the handler ....
1912
+ * It's a shared IRQ (with in-band handler) -- the driver
1913
+ * ought to be prepared for an IRQ event to happen even now
1914
+ * it's being freed, so let's make sure that is so by doing an
1915
+ * extra call to the handler ....
18511916 *
18521917 * ( We do this after actually deregistering it, to make sure that a
18531918 * 'real' IRQ doesn't run in parallel with our fake. )
18541919 */
1855
- if (action->flags & IRQF_SHARED) {
1920
+ if ((action->flags & (IRQF_SHARED|IRQF_OOB)) == IRQF_SHARED) {
18561921 local_irq_save(flags);
18571922 action->handler(irq, dev_id);
18581923 local_irq_restore(flags);
....@@ -2473,7 +2538,7 @@
24732538 * __request_percpu_irq - allocate a percpu interrupt line
24742539 * @irq: Interrupt line to allocate
24752540 * @handler: Function to be called when the IRQ occurs.
2476
- * @flags: Interrupt type flags (IRQF_TIMER only)
2541
+ * @flags: Interrupt type flags (IRQF_TIMER and/or IRQF_OOB only)
24772542 * @devname: An ascii name for the claiming device
24782543 * @dev_id: A percpu cookie passed back to the handler function
24792544 *
....@@ -2502,7 +2567,7 @@
25022567 !irq_settings_is_per_cpu_devid(desc))
25032568 return -EINVAL;
25042569
2505
- if (flags && flags != IRQF_TIMER)
2570
+ if (flags & ~(IRQF_TIMER|IRQF_OOB))
25062571 return -EINVAL;
25072572
25082573 action = kzalloc(sizeof(struct irqaction), GFP_KERNEL);