.. | .. |
---|
10 | 10 | |
---|
11 | 11 | #include <linux/irq.h> |
---|
12 | 12 | #include <linux/kthread.h> |
---|
| 13 | +#include <linux/kconfig.h> |
---|
13 | 14 | #include <linux/module.h> |
---|
14 | 15 | #include <linux/random.h> |
---|
15 | 16 | #include <linux/interrupt.h> |
---|
.. | .. |
---|
829 | 830 | } |
---|
830 | 831 | EXPORT_SYMBOL(irq_set_irq_wake); |
---|
831 | 832 | |
---|
| 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 | + |
---|
832 | 877 | /* |
---|
833 | 878 | * Internal function that tells the architecture code whether a |
---|
834 | 879 | * particular irq has been exclusively allocated or is available |
---|
.. | .. |
---|
845 | 890 | |
---|
846 | 891 | if (irq_settings_can_request(desc)) { |
---|
847 | 892 | if (!desc->action || |
---|
848 | | - irqflags & desc->action->flags & IRQF_SHARED) |
---|
| 893 | + ((irqflags & desc->action->flags & IRQF_SHARED) && |
---|
| 894 | + !((irqflags ^ desc->action->flags) & IRQF_OOB))) |
---|
849 | 895 | canrequest = 1; |
---|
850 | 896 | } |
---|
851 | 897 | irq_put_desc_unlock(desc, flags); |
---|
.. | .. |
---|
1419 | 1465 | |
---|
1420 | 1466 | new->irq = irq; |
---|
1421 | 1467 | |
---|
| 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 | + |
---|
1422 | 1483 | /* |
---|
1423 | 1484 | * If the trigger type is not specified by the caller, |
---|
1424 | 1485 | * then use the default for this interrupt. |
---|
.. | .. |
---|
1432 | 1493 | */ |
---|
1433 | 1494 | nested = irq_settings_is_nested_thread(desc); |
---|
1434 | 1495 | if (nested) { |
---|
1435 | | - if (!new->thread_fn) { |
---|
1436 | | - ret = -EINVAL; |
---|
| 1496 | + if (!new->thread_fn) |
---|
1437 | 1497 | goto out_mput; |
---|
1438 | | - } |
---|
1439 | 1498 | /* |
---|
1440 | 1499 | * Replace the primary handler which was provided from |
---|
1441 | 1500 | * the driver for non nested interrupt handling by the |
---|
.. | .. |
---|
1519 | 1578 | * the same type (level, edge, polarity). So both flag |
---|
1520 | 1579 | * fields must have IRQF_SHARED set and the bits which |
---|
1521 | 1580 | * set the trigger type must match. Also all must |
---|
1522 | | - * agree on ONESHOT. |
---|
| 1581 | + * agree on ONESHOT and OOB. |
---|
1523 | 1582 | * Interrupt lines used for NMIs cannot be shared. |
---|
1524 | 1583 | */ |
---|
1525 | 1584 | unsigned int oldtype; |
---|
.. | .. |
---|
1544 | 1603 | |
---|
1545 | 1604 | if (!((old->flags & new->flags) & IRQF_SHARED) || |
---|
1546 | 1605 | (oldtype != (new->flags & IRQF_TRIGGER_MASK)) || |
---|
1547 | | - ((old->flags ^ new->flags) & IRQF_ONESHOT)) |
---|
| 1606 | + ((old->flags ^ new->flags) & (IRQF_OOB|IRQF_ONESHOT))) |
---|
1548 | 1607 | goto mismatch; |
---|
1549 | 1608 | |
---|
1550 | 1609 | /* All handlers must agree on per-cpuness */ |
---|
.. | .. |
---|
1661 | 1720 | |
---|
1662 | 1721 | if (new->flags & IRQF_ONESHOT) |
---|
1663 | 1722 | desc->istate |= IRQS_ONESHOT; |
---|
| 1723 | + |
---|
| 1724 | + if (new->flags & IRQF_OOB) |
---|
| 1725 | + irq_settings_set_oob(desc); |
---|
1664 | 1726 | |
---|
1665 | 1727 | /* Exclude IRQ from balancing if requested */ |
---|
1666 | 1728 | if (new->flags & IRQF_NOBALANCING) { |
---|
.. | .. |
---|
1809 | 1871 | irq_settings_clr_disable_unlazy(desc); |
---|
1810 | 1872 | /* Only shutdown. Deactivate after synchronize_hardirq() */ |
---|
1811 | 1873 | irq_shutdown(desc); |
---|
| 1874 | + /* Turn off OOB handling (after shutdown). */ |
---|
| 1875 | + irq_settings_clr_oob(desc); |
---|
1812 | 1876 | } |
---|
1813 | 1877 | |
---|
1814 | 1878 | #ifdef CONFIG_SMP |
---|
.. | .. |
---|
1845 | 1909 | |
---|
1846 | 1910 | #ifdef CONFIG_DEBUG_SHIRQ |
---|
1847 | 1911 | /* |
---|
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 .... |
---|
1851 | 1916 | * |
---|
1852 | 1917 | * ( We do this after actually deregistering it, to make sure that a |
---|
1853 | 1918 | * 'real' IRQ doesn't run in parallel with our fake. ) |
---|
1854 | 1919 | */ |
---|
1855 | | - if (action->flags & IRQF_SHARED) { |
---|
| 1920 | + if ((action->flags & (IRQF_SHARED|IRQF_OOB)) == IRQF_SHARED) { |
---|
1856 | 1921 | local_irq_save(flags); |
---|
1857 | 1922 | action->handler(irq, dev_id); |
---|
1858 | 1923 | local_irq_restore(flags); |
---|
.. | .. |
---|
2473 | 2538 | * __request_percpu_irq - allocate a percpu interrupt line |
---|
2474 | 2539 | * @irq: Interrupt line to allocate |
---|
2475 | 2540 | * @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) |
---|
2477 | 2542 | * @devname: An ascii name for the claiming device |
---|
2478 | 2543 | * @dev_id: A percpu cookie passed back to the handler function |
---|
2479 | 2544 | * |
---|
.. | .. |
---|
2502 | 2567 | !irq_settings_is_per_cpu_devid(desc)) |
---|
2503 | 2568 | return -EINVAL; |
---|
2504 | 2569 | |
---|
2505 | | - if (flags && flags != IRQF_TIMER) |
---|
| 2570 | + if (flags & ~(IRQF_TIMER|IRQF_OOB)) |
---|
2506 | 2571 | return -EINVAL; |
---|
2507 | 2572 | |
---|
2508 | 2573 | action = kzalloc(sizeof(struct irqaction), GFP_KERNEL); |
---|