diff options
Diffstat (limited to 'kernel/irq/manage.c')
| -rw-r--r-- | kernel/irq/manage.c | 89 |
1 files changed, 59 insertions, 30 deletions
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 704e488730a5..3164ba7ce151 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c | |||
| @@ -138,6 +138,22 @@ int irq_set_affinity(unsigned int irq, const struct cpumask *cpumask) | |||
| 138 | return 0; | 138 | return 0; |
| 139 | } | 139 | } |
| 140 | 140 | ||
| 141 | int irq_set_affinity_hint(unsigned int irq, const struct cpumask *m) | ||
| 142 | { | ||
| 143 | struct irq_desc *desc = irq_to_desc(irq); | ||
| 144 | unsigned long flags; | ||
| 145 | |||
| 146 | if (!desc) | ||
| 147 | return -EINVAL; | ||
| 148 | |||
| 149 | raw_spin_lock_irqsave(&desc->lock, flags); | ||
| 150 | desc->affinity_hint = m; | ||
| 151 | raw_spin_unlock_irqrestore(&desc->lock, flags); | ||
| 152 | |||
| 153 | return 0; | ||
| 154 | } | ||
| 155 | EXPORT_SYMBOL_GPL(irq_set_affinity_hint); | ||
| 156 | |||
| 141 | #ifndef CONFIG_AUTO_IRQ_AFFINITY | 157 | #ifndef CONFIG_AUTO_IRQ_AFFINITY |
| 142 | /* | 158 | /* |
| 143 | * Generic version of the affinity autoselector. | 159 | * Generic version of the affinity autoselector. |
| @@ -757,16 +773,6 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) | |||
| 757 | if (new->flags & IRQF_ONESHOT) | 773 | if (new->flags & IRQF_ONESHOT) |
| 758 | desc->status |= IRQ_ONESHOT; | 774 | desc->status |= IRQ_ONESHOT; |
| 759 | 775 | ||
| 760 | /* | ||
| 761 | * Force MSI interrupts to run with interrupts | ||
| 762 | * disabled. The multi vector cards can cause stack | ||
| 763 | * overflows due to nested interrupts when enough of | ||
| 764 | * them are directed to a core and fire at the same | ||
| 765 | * time. | ||
| 766 | */ | ||
| 767 | if (desc->msi_desc) | ||
| 768 | new->flags |= IRQF_DISABLED; | ||
| 769 | |||
| 770 | if (!(desc->status & IRQ_NOAUTOEN)) { | 776 | if (!(desc->status & IRQ_NOAUTOEN)) { |
| 771 | desc->depth = 0; | 777 | desc->depth = 0; |
| 772 | desc->status &= ~IRQ_DISABLED; | 778 | desc->status &= ~IRQ_DISABLED; |
| @@ -916,6 +922,12 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id) | |||
| 916 | desc->chip->disable(irq); | 922 | desc->chip->disable(irq); |
| 917 | } | 923 | } |
| 918 | 924 | ||
| 925 | #ifdef CONFIG_SMP | ||
| 926 | /* make sure affinity_hint is cleaned up */ | ||
| 927 | if (WARN_ON_ONCE(desc->affinity_hint)) | ||
| 928 | desc->affinity_hint = NULL; | ||
| 929 | #endif | ||
| 930 | |||
| 919 | raw_spin_unlock_irqrestore(&desc->lock, flags); | 931 | raw_spin_unlock_irqrestore(&desc->lock, flags); |
| 920 | 932 | ||
| 921 | unregister_handler_proc(irq, action); | 933 | unregister_handler_proc(irq, action); |
| @@ -1027,7 +1039,6 @@ EXPORT_SYMBOL(free_irq); | |||
| 1027 | * Flags: | 1039 | * Flags: |
| 1028 | * | 1040 | * |
| 1029 | * IRQF_SHARED Interrupt is shared | 1041 | * IRQF_SHARED Interrupt is shared |
| 1030 | * IRQF_DISABLED Disable local interrupts while processing | ||
| 1031 | * IRQF_SAMPLE_RANDOM The interrupt can be used for entropy | 1042 | * IRQF_SAMPLE_RANDOM The interrupt can be used for entropy |
| 1032 | * IRQF_TRIGGER_* Specify active edge(s) or level | 1043 | * IRQF_TRIGGER_* Specify active edge(s) or level |
| 1033 | * | 1044 | * |
| @@ -1041,25 +1052,6 @@ int request_threaded_irq(unsigned int irq, irq_handler_t handler, | |||
| 1041 | int retval; | 1052 | int retval; |
| 1042 | 1053 | ||
| 1043 | /* | 1054 | /* |
| 1044 | * handle_IRQ_event() always ignores IRQF_DISABLED except for | ||
| 1045 | * the _first_ irqaction (sigh). That can cause oopsing, but | ||
| 1046 | * the behavior is classified as "will not fix" so we need to | ||
| 1047 | * start nudging drivers away from using that idiom. | ||
| 1048 | */ | ||
| 1049 | if ((irqflags & (IRQF_SHARED|IRQF_DISABLED)) == | ||
| 1050 | (IRQF_SHARED|IRQF_DISABLED)) { | ||
| 1051 | pr_warning( | ||
| 1052 | "IRQ %d/%s: IRQF_DISABLED is not guaranteed on shared IRQs\n", | ||
| 1053 | irq, devname); | ||
| 1054 | } | ||
| 1055 | |||
| 1056 | #ifdef CONFIG_LOCKDEP | ||
| 1057 | /* | ||
| 1058 | * Lockdep wants atomic interrupt handlers: | ||
| 1059 | */ | ||
| 1060 | irqflags |= IRQF_DISABLED; | ||
| 1061 | #endif | ||
| 1062 | /* | ||
| 1063 | * Sanity-check: shared interrupts must pass in a real dev-ID, | 1055 | * Sanity-check: shared interrupts must pass in a real dev-ID, |
| 1064 | * otherwise we'll have trouble later trying to figure out | 1056 | * otherwise we'll have trouble later trying to figure out |
| 1065 | * which interrupt is which (messes up the interrupt freeing | 1057 | * which interrupt is which (messes up the interrupt freeing |
| @@ -1120,3 +1112,40 @@ int request_threaded_irq(unsigned int irq, irq_handler_t handler, | |||
| 1120 | return retval; | 1112 | return retval; |
| 1121 | } | 1113 | } |
| 1122 | EXPORT_SYMBOL(request_threaded_irq); | 1114 | EXPORT_SYMBOL(request_threaded_irq); |
| 1115 | |||
| 1116 | /** | ||
| 1117 | * request_any_context_irq - allocate an interrupt line | ||
| 1118 | * @irq: Interrupt line to allocate | ||
| 1119 | * @handler: Function to be called when the IRQ occurs. | ||
| 1120 | * Threaded handler for threaded interrupts. | ||
| 1121 | * @flags: Interrupt type flags | ||
| 1122 | * @name: An ascii name for the claiming device | ||
| 1123 | * @dev_id: A cookie passed back to the handler function | ||
| 1124 | * | ||
| 1125 | * This call allocates interrupt resources and enables the | ||
| 1126 | * interrupt line and IRQ handling. It selects either a | ||
| 1127 | * hardirq or threaded handling method depending on the | ||
| 1128 | * context. | ||
| 1129 | * | ||
| 1130 | * On failure, it returns a negative value. On success, | ||
| 1131 | * it returns either IRQC_IS_HARDIRQ or IRQC_IS_NESTED. | ||
| 1132 | */ | ||
| 1133 | int request_any_context_irq(unsigned int irq, irq_handler_t handler, | ||
| 1134 | unsigned long flags, const char *name, void *dev_id) | ||
| 1135 | { | ||
| 1136 | struct irq_desc *desc = irq_to_desc(irq); | ||
| 1137 | int ret; | ||
| 1138 | |||
| 1139 | if (!desc) | ||
| 1140 | return -EINVAL; | ||
| 1141 | |||
| 1142 | if (desc->status & IRQ_NESTED_THREAD) { | ||
| 1143 | ret = request_threaded_irq(irq, NULL, handler, | ||
| 1144 | flags, name, dev_id); | ||
| 1145 | return !ret ? IRQC_IS_NESTED : ret; | ||
| 1146 | } | ||
| 1147 | |||
| 1148 | ret = request_irq(irq, handler, flags, name, dev_id); | ||
| 1149 | return !ret ? IRQC_IS_HARDIRQ : ret; | ||
| 1150 | } | ||
| 1151 | EXPORT_SYMBOL_GPL(request_any_context_irq); | ||
