diff options
| author | Linus Torvalds <torvalds@linux-foundation.org> | 2011-08-17 13:23:50 -0400 |
|---|---|---|
| committer | Linus Torvalds <torvalds@linux-foundation.org> | 2011-08-17 13:23:50 -0400 |
| commit | 950d0a10d12578a270f3dfa9fd76fe5c2deb343f (patch) | |
| tree | 2467458b05ab13dd8875e43f3701fbc0c38cef0d | |
| parent | ab7e2dbf9b5da4d4eb4fdb019cc8881fbeb1299b (diff) | |
| parent | b6873807a7143b7d6d8b06809295e559d07d7deb (diff) | |
Merge branch 'irq-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip
* 'irq-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/linux-2.6-tip:
irq: Track the owner of irq descriptor
irq: Always set IRQF_ONESHOT if no primary handler is specified
genirq: Fix wrong bit operation
| -rw-r--r-- | include/linux/irq.h | 11 | ||||
| -rw-r--r-- | include/linux/irqdesc.h | 1 | ||||
| -rw-r--r-- | kernel/irq/generic-chip.c | 4 | ||||
| -rw-r--r-- | kernel/irq/irqdesc.c | 36 | ||||
| -rw-r--r-- | kernel/irq/manage.c | 18 |
5 files changed, 51 insertions, 19 deletions
diff --git a/include/linux/irq.h b/include/linux/irq.h index 87a06f345bd2..59517300a315 100644 --- a/include/linux/irq.h +++ b/include/linux/irq.h | |||
| @@ -23,6 +23,7 @@ | |||
| 23 | #include <linux/errno.h> | 23 | #include <linux/errno.h> |
| 24 | #include <linux/topology.h> | 24 | #include <linux/topology.h> |
| 25 | #include <linux/wait.h> | 25 | #include <linux/wait.h> |
| 26 | #include <linux/module.h> | ||
| 26 | 27 | ||
| 27 | #include <asm/irq.h> | 28 | #include <asm/irq.h> |
| 28 | #include <asm/ptrace.h> | 29 | #include <asm/ptrace.h> |
| @@ -547,7 +548,15 @@ static inline struct msi_desc *irq_data_get_msi(struct irq_data *d) | |||
| 547 | return d->msi_desc; | 548 | return d->msi_desc; |
| 548 | } | 549 | } |
| 549 | 550 | ||
| 550 | int irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node); | 551 | int __irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node, |
| 552 | struct module *owner); | ||
| 553 | |||
| 554 | static inline int irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, | ||
| 555 | int node) | ||
| 556 | { | ||
| 557 | return __irq_alloc_descs(irq, from, cnt, node, THIS_MODULE); | ||
| 558 | } | ||
| 559 | |||
| 551 | void irq_free_descs(unsigned int irq, unsigned int cnt); | 560 | void irq_free_descs(unsigned int irq, unsigned int cnt); |
| 552 | int irq_reserve_irqs(unsigned int from, unsigned int cnt); | 561 | int irq_reserve_irqs(unsigned int from, unsigned int cnt); |
| 553 | 562 | ||
diff --git a/include/linux/irqdesc.h b/include/linux/irqdesc.h index 2d921b35212c..150134ac709a 100644 --- a/include/linux/irqdesc.h +++ b/include/linux/irqdesc.h | |||
| @@ -66,6 +66,7 @@ struct irq_desc { | |||
| 66 | #ifdef CONFIG_PROC_FS | 66 | #ifdef CONFIG_PROC_FS |
| 67 | struct proc_dir_entry *dir; | 67 | struct proc_dir_entry *dir; |
| 68 | #endif | 68 | #endif |
| 69 | struct module *owner; | ||
| 69 | const char *name; | 70 | const char *name; |
| 70 | } ____cacheline_internodealigned_in_smp; | 71 | } ____cacheline_internodealigned_in_smp; |
| 71 | 72 | ||
diff --git a/kernel/irq/generic-chip.c b/kernel/irq/generic-chip.c index 3a2cab407b93..e38544dddb18 100644 --- a/kernel/irq/generic-chip.c +++ b/kernel/irq/generic-chip.c | |||
| @@ -246,7 +246,7 @@ void irq_setup_generic_chip(struct irq_chip_generic *gc, u32 msk, | |||
| 246 | gc->mask_cache = irq_reg_readl(gc->reg_base + ct->regs.mask); | 246 | gc->mask_cache = irq_reg_readl(gc->reg_base + ct->regs.mask); |
| 247 | 247 | ||
| 248 | for (i = gc->irq_base; msk; msk >>= 1, i++) { | 248 | for (i = gc->irq_base; msk; msk >>= 1, i++) { |
| 249 | if (!msk & 0x01) | 249 | if (!(msk & 0x01)) |
| 250 | continue; | 250 | continue; |
| 251 | 251 | ||
| 252 | if (flags & IRQ_GC_INIT_NESTED_LOCK) | 252 | if (flags & IRQ_GC_INIT_NESTED_LOCK) |
| @@ -301,7 +301,7 @@ void irq_remove_generic_chip(struct irq_chip_generic *gc, u32 msk, | |||
| 301 | raw_spin_unlock(&gc_lock); | 301 | raw_spin_unlock(&gc_lock); |
| 302 | 302 | ||
| 303 | for (; msk; msk >>= 1, i++) { | 303 | for (; msk; msk >>= 1, i++) { |
| 304 | if (!msk & 0x01) | 304 | if (!(msk & 0x01)) |
| 305 | continue; | 305 | continue; |
| 306 | 306 | ||
| 307 | /* Remove handler first. That will mask the irq line */ | 307 | /* Remove handler first. That will mask the irq line */ |
diff --git a/kernel/irq/irqdesc.c b/kernel/irq/irqdesc.c index 4c60a50e66b2..cb65d0360e31 100644 --- a/kernel/irq/irqdesc.c +++ b/kernel/irq/irqdesc.c | |||
| @@ -70,7 +70,8 @@ static inline void desc_smp_init(struct irq_desc *desc, int node) { } | |||
| 70 | static inline int desc_node(struct irq_desc *desc) { return 0; } | 70 | static inline int desc_node(struct irq_desc *desc) { return 0; } |
| 71 | #endif | 71 | #endif |
| 72 | 72 | ||
| 73 | static void desc_set_defaults(unsigned int irq, struct irq_desc *desc, int node) | 73 | static void desc_set_defaults(unsigned int irq, struct irq_desc *desc, int node, |
| 74 | struct module *owner) | ||
| 74 | { | 75 | { |
| 75 | int cpu; | 76 | int cpu; |
| 76 | 77 | ||
| @@ -86,6 +87,7 @@ static void desc_set_defaults(unsigned int irq, struct irq_desc *desc, int node) | |||
| 86 | desc->irq_count = 0; | 87 | desc->irq_count = 0; |
| 87 | desc->irqs_unhandled = 0; | 88 | desc->irqs_unhandled = 0; |
| 88 | desc->name = NULL; | 89 | desc->name = NULL; |
| 90 | desc->owner = owner; | ||
| 89 | for_each_possible_cpu(cpu) | 91 | for_each_possible_cpu(cpu) |
| 90 | *per_cpu_ptr(desc->kstat_irqs, cpu) = 0; | 92 | *per_cpu_ptr(desc->kstat_irqs, cpu) = 0; |
| 91 | desc_smp_init(desc, node); | 93 | desc_smp_init(desc, node); |
| @@ -128,7 +130,7 @@ static void free_masks(struct irq_desc *desc) | |||
| 128 | static inline void free_masks(struct irq_desc *desc) { } | 130 | static inline void free_masks(struct irq_desc *desc) { } |
| 129 | #endif | 131 | #endif |
| 130 | 132 | ||
| 131 | static struct irq_desc *alloc_desc(int irq, int node) | 133 | static struct irq_desc *alloc_desc(int irq, int node, struct module *owner) |
| 132 | { | 134 | { |
| 133 | struct irq_desc *desc; | 135 | struct irq_desc *desc; |
| 134 | gfp_t gfp = GFP_KERNEL; | 136 | gfp_t gfp = GFP_KERNEL; |
| @@ -147,7 +149,7 @@ static struct irq_desc *alloc_desc(int irq, int node) | |||
| 147 | raw_spin_lock_init(&desc->lock); | 149 | raw_spin_lock_init(&desc->lock); |
| 148 | lockdep_set_class(&desc->lock, &irq_desc_lock_class); | 150 | lockdep_set_class(&desc->lock, &irq_desc_lock_class); |
| 149 | 151 | ||
| 150 | desc_set_defaults(irq, desc, node); | 152 | desc_set_defaults(irq, desc, node, owner); |
| 151 | 153 | ||
| 152 | return desc; | 154 | return desc; |
| 153 | 155 | ||
| @@ -173,13 +175,14 @@ static void free_desc(unsigned int irq) | |||
| 173 | kfree(desc); | 175 | kfree(desc); |
| 174 | } | 176 | } |
| 175 | 177 | ||
| 176 | static int alloc_descs(unsigned int start, unsigned int cnt, int node) | 178 | static int alloc_descs(unsigned int start, unsigned int cnt, int node, |
| 179 | struct module *owner) | ||
| 177 | { | 180 | { |
| 178 | struct irq_desc *desc; | 181 | struct irq_desc *desc; |
| 179 | int i; | 182 | int i; |
| 180 | 183 | ||
| 181 | for (i = 0; i < cnt; i++) { | 184 | for (i = 0; i < cnt; i++) { |
| 182 | desc = alloc_desc(start + i, node); | 185 | desc = alloc_desc(start + i, node, owner); |
| 183 | if (!desc) | 186 | if (!desc) |
| 184 | goto err; | 187 | goto err; |
| 185 | mutex_lock(&sparse_irq_lock); | 188 | mutex_lock(&sparse_irq_lock); |
| @@ -227,7 +230,7 @@ int __init early_irq_init(void) | |||
| 227 | nr_irqs = initcnt; | 230 | nr_irqs = initcnt; |
| 228 | 231 | ||
| 229 | for (i = 0; i < initcnt; i++) { | 232 | for (i = 0; i < initcnt; i++) { |
| 230 | desc = alloc_desc(i, node); | 233 | desc = alloc_desc(i, node, NULL); |
| 231 | set_bit(i, allocated_irqs); | 234 | set_bit(i, allocated_irqs); |
| 232 | irq_insert_desc(i, desc); | 235 | irq_insert_desc(i, desc); |
| 233 | } | 236 | } |
| @@ -261,7 +264,7 @@ int __init early_irq_init(void) | |||
| 261 | alloc_masks(&desc[i], GFP_KERNEL, node); | 264 | alloc_masks(&desc[i], GFP_KERNEL, node); |
| 262 | raw_spin_lock_init(&desc[i].lock); | 265 | raw_spin_lock_init(&desc[i].lock); |
| 263 | lockdep_set_class(&desc[i].lock, &irq_desc_lock_class); | 266 | lockdep_set_class(&desc[i].lock, &irq_desc_lock_class); |
| 264 | desc_set_defaults(i, &desc[i], node); | 267 | desc_set_defaults(i, &desc[i], node, NULL); |
| 265 | } | 268 | } |
| 266 | return arch_early_irq_init(); | 269 | return arch_early_irq_init(); |
| 267 | } | 270 | } |
| @@ -276,8 +279,16 @@ static void free_desc(unsigned int irq) | |||
| 276 | dynamic_irq_cleanup(irq); | 279 | dynamic_irq_cleanup(irq); |
| 277 | } | 280 | } |
| 278 | 281 | ||
| 279 | static inline int alloc_descs(unsigned int start, unsigned int cnt, int node) | 282 | static inline int alloc_descs(unsigned int start, unsigned int cnt, int node, |
| 283 | struct module *owner) | ||
| 280 | { | 284 | { |
| 285 | u32 i; | ||
| 286 | |||
| 287 | for (i = 0; i < cnt; i++) { | ||
| 288 | struct irq_desc *desc = irq_to_desc(start + i); | ||
| 289 | |||
| 290 | desc->owner = owner; | ||
| 291 | } | ||
| 281 | return start; | 292 | return start; |
| 282 | } | 293 | } |
| 283 | 294 | ||
| @@ -337,7 +348,8 @@ EXPORT_SYMBOL_GPL(irq_free_descs); | |||
| 337 | * Returns the first irq number or error code | 348 | * Returns the first irq number or error code |
| 338 | */ | 349 | */ |
| 339 | int __ref | 350 | int __ref |
| 340 | irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node) | 351 | __irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node, |
| 352 | struct module *owner) | ||
| 341 | { | 353 | { |
| 342 | int start, ret; | 354 | int start, ret; |
| 343 | 355 | ||
| @@ -366,13 +378,13 @@ irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node) | |||
| 366 | 378 | ||
| 367 | bitmap_set(allocated_irqs, start, cnt); | 379 | bitmap_set(allocated_irqs, start, cnt); |
| 368 | mutex_unlock(&sparse_irq_lock); | 380 | mutex_unlock(&sparse_irq_lock); |
| 369 | return alloc_descs(start, cnt, node); | 381 | return alloc_descs(start, cnt, node, owner); |
| 370 | 382 | ||
| 371 | err: | 383 | err: |
| 372 | mutex_unlock(&sparse_irq_lock); | 384 | mutex_unlock(&sparse_irq_lock); |
| 373 | return ret; | 385 | return ret; |
| 374 | } | 386 | } |
| 375 | EXPORT_SYMBOL_GPL(irq_alloc_descs); | 387 | EXPORT_SYMBOL_GPL(__irq_alloc_descs); |
| 376 | 388 | ||
| 377 | /** | 389 | /** |
| 378 | * irq_reserve_irqs - mark irqs allocated | 390 | * irq_reserve_irqs - mark irqs allocated |
| @@ -440,7 +452,7 @@ void dynamic_irq_cleanup(unsigned int irq) | |||
| 440 | unsigned long flags; | 452 | unsigned long flags; |
| 441 | 453 | ||
| 442 | raw_spin_lock_irqsave(&desc->lock, flags); | 454 | raw_spin_lock_irqsave(&desc->lock, flags); |
| 443 | desc_set_defaults(irq, desc, desc_node(desc)); | 455 | desc_set_defaults(irq, desc, desc_node(desc), NULL); |
| 444 | raw_spin_unlock_irqrestore(&desc->lock, flags); | 456 | raw_spin_unlock_irqrestore(&desc->lock, flags); |
| 445 | } | 457 | } |
| 446 | 458 | ||
diff --git a/kernel/irq/manage.c b/kernel/irq/manage.c index 0a7840aeb0fb..2e9425889fa8 100644 --- a/kernel/irq/manage.c +++ b/kernel/irq/manage.c | |||
| @@ -883,6 +883,8 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) | |||
| 883 | 883 | ||
| 884 | if (desc->irq_data.chip == &no_irq_chip) | 884 | if (desc->irq_data.chip == &no_irq_chip) |
| 885 | return -ENOSYS; | 885 | return -ENOSYS; |
| 886 | if (!try_module_get(desc->owner)) | ||
| 887 | return -ENODEV; | ||
| 886 | /* | 888 | /* |
| 887 | * Some drivers like serial.c use request_irq() heavily, | 889 | * Some drivers like serial.c use request_irq() heavily, |
| 888 | * so we have to be careful not to interfere with a | 890 | * so we have to be careful not to interfere with a |
| @@ -906,8 +908,10 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) | |||
| 906 | */ | 908 | */ |
| 907 | nested = irq_settings_is_nested_thread(desc); | 909 | nested = irq_settings_is_nested_thread(desc); |
| 908 | if (nested) { | 910 | if (nested) { |
| 909 | if (!new->thread_fn) | 911 | if (!new->thread_fn) { |
| 910 | return -EINVAL; | 912 | ret = -EINVAL; |
| 913 | goto out_mput; | ||
| 914 | } | ||
| 911 | /* | 915 | /* |
| 912 | * Replace the primary handler which was provided from | 916 | * Replace the primary handler which was provided from |
| 913 | * the driver for non nested interrupt handling by the | 917 | * the driver for non nested interrupt handling by the |
| @@ -929,8 +933,10 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new) | |||
| 929 | 933 | ||
| 930 | t = kthread_create(irq_thread, new, "irq/%d-%s", irq, | 934 | t = kthread_create(irq_thread, new, "irq/%d-%s", irq, |
| 931 | new->name); | 935 | new->name); |
| 932 | if (IS_ERR(t)) | 936 | if (IS_ERR(t)) { |
| 933 | return PTR_ERR(t); | 937 | ret = PTR_ERR(t); |
| 938 | goto out_mput; | ||
| 939 | } | ||
| 934 | /* | 940 | /* |
| 935 | * We keep the reference to the task struct even if | 941 | * We keep the reference to the task struct even if |
| 936 | * the thread dies to avoid that the interrupt code | 942 | * the thread dies to avoid that the interrupt code |
| @@ -1095,6 +1101,8 @@ out_thread: | |||
| 1095 | kthread_stop(t); | 1101 | kthread_stop(t); |
| 1096 | put_task_struct(t); | 1102 | put_task_struct(t); |
| 1097 | } | 1103 | } |
| 1104 | out_mput: | ||
| 1105 | module_put(desc->owner); | ||
| 1098 | return ret; | 1106 | return ret; |
| 1099 | } | 1107 | } |
| 1100 | 1108 | ||
| @@ -1203,6 +1211,7 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id) | |||
| 1203 | put_task_struct(action->thread); | 1211 | put_task_struct(action->thread); |
| 1204 | } | 1212 | } |
| 1205 | 1213 | ||
| 1214 | module_put(desc->owner); | ||
| 1206 | return action; | 1215 | return action; |
| 1207 | } | 1216 | } |
| 1208 | 1217 | ||
| @@ -1322,6 +1331,7 @@ int request_threaded_irq(unsigned int irq, irq_handler_t handler, | |||
| 1322 | if (!thread_fn) | 1331 | if (!thread_fn) |
| 1323 | return -EINVAL; | 1332 | return -EINVAL; |
| 1324 | handler = irq_default_primary_handler; | 1333 | handler = irq_default_primary_handler; |
| 1334 | irqflags |= IRQF_ONESHOT; | ||
| 1325 | } | 1335 | } |
| 1326 | 1336 | ||
| 1327 | action = kzalloc(sizeof(struct irqaction), GFP_KERNEL); | 1337 | action = kzalloc(sizeof(struct irqaction), GFP_KERNEL); |
