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
This commit is contained in:
commit
950d0a10d1
|
@ -23,6 +23,7 @@
|
||||||
#include <linux/errno.h>
|
#include <linux/errno.h>
|
||||||
#include <linux/topology.h>
|
#include <linux/topology.h>
|
||||||
#include <linux/wait.h>
|
#include <linux/wait.h>
|
||||||
|
#include <linux/module.h>
|
||||||
|
|
||||||
#include <asm/irq.h>
|
#include <asm/irq.h>
|
||||||
#include <asm/ptrace.h>
|
#include <asm/ptrace.h>
|
||||||
|
@ -547,7 +548,15 @@ static inline struct msi_desc *irq_data_get_msi(struct irq_data *d)
|
||||||
return d->msi_desc;
|
return d->msi_desc;
|
||||||
}
|
}
|
||||||
|
|
||||||
int irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node);
|
int __irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node,
|
||||||
|
struct module *owner);
|
||||||
|
|
||||||
|
static inline int irq_alloc_descs(int irq, unsigned int from, unsigned int cnt,
|
||||||
|
int node)
|
||||||
|
{
|
||||||
|
return __irq_alloc_descs(irq, from, cnt, node, THIS_MODULE);
|
||||||
|
}
|
||||||
|
|
||||||
void irq_free_descs(unsigned int irq, unsigned int cnt);
|
void irq_free_descs(unsigned int irq, unsigned int cnt);
|
||||||
int irq_reserve_irqs(unsigned int from, unsigned int cnt);
|
int irq_reserve_irqs(unsigned int from, unsigned int cnt);
|
||||||
|
|
||||||
|
|
|
@ -66,6 +66,7 @@ struct irq_desc {
|
||||||
#ifdef CONFIG_PROC_FS
|
#ifdef CONFIG_PROC_FS
|
||||||
struct proc_dir_entry *dir;
|
struct proc_dir_entry *dir;
|
||||||
#endif
|
#endif
|
||||||
|
struct module *owner;
|
||||||
const char *name;
|
const char *name;
|
||||||
} ____cacheline_internodealigned_in_smp;
|
} ____cacheline_internodealigned_in_smp;
|
||||||
|
|
||||||
|
|
|
@ -246,7 +246,7 @@ void irq_setup_generic_chip(struct irq_chip_generic *gc, u32 msk,
|
||||||
gc->mask_cache = irq_reg_readl(gc->reg_base + ct->regs.mask);
|
gc->mask_cache = irq_reg_readl(gc->reg_base + ct->regs.mask);
|
||||||
|
|
||||||
for (i = gc->irq_base; msk; msk >>= 1, i++) {
|
for (i = gc->irq_base; msk; msk >>= 1, i++) {
|
||||||
if (!msk & 0x01)
|
if (!(msk & 0x01))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
if (flags & IRQ_GC_INIT_NESTED_LOCK)
|
if (flags & IRQ_GC_INIT_NESTED_LOCK)
|
||||||
|
@ -301,7 +301,7 @@ void irq_remove_generic_chip(struct irq_chip_generic *gc, u32 msk,
|
||||||
raw_spin_unlock(&gc_lock);
|
raw_spin_unlock(&gc_lock);
|
||||||
|
|
||||||
for (; msk; msk >>= 1, i++) {
|
for (; msk; msk >>= 1, i++) {
|
||||||
if (!msk & 0x01)
|
if (!(msk & 0x01))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* Remove handler first. That will mask the irq line */
|
/* Remove handler first. That will mask the irq line */
|
||||||
|
|
|
@ -70,7 +70,8 @@ static inline void desc_smp_init(struct irq_desc *desc, int node) { }
|
||||||
static inline int desc_node(struct irq_desc *desc) { return 0; }
|
static inline int desc_node(struct irq_desc *desc) { return 0; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static void desc_set_defaults(unsigned int irq, struct irq_desc *desc, int node)
|
static void desc_set_defaults(unsigned int irq, struct irq_desc *desc, int node,
|
||||||
|
struct module *owner)
|
||||||
{
|
{
|
||||||
int cpu;
|
int cpu;
|
||||||
|
|
||||||
|
@ -86,6 +87,7 @@ static void desc_set_defaults(unsigned int irq, struct irq_desc *desc, int node)
|
||||||
desc->irq_count = 0;
|
desc->irq_count = 0;
|
||||||
desc->irqs_unhandled = 0;
|
desc->irqs_unhandled = 0;
|
||||||
desc->name = NULL;
|
desc->name = NULL;
|
||||||
|
desc->owner = owner;
|
||||||
for_each_possible_cpu(cpu)
|
for_each_possible_cpu(cpu)
|
||||||
*per_cpu_ptr(desc->kstat_irqs, cpu) = 0;
|
*per_cpu_ptr(desc->kstat_irqs, cpu) = 0;
|
||||||
desc_smp_init(desc, node);
|
desc_smp_init(desc, node);
|
||||||
|
@ -128,7 +130,7 @@ static void free_masks(struct irq_desc *desc)
|
||||||
static inline void free_masks(struct irq_desc *desc) { }
|
static inline void free_masks(struct irq_desc *desc) { }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
static struct irq_desc *alloc_desc(int irq, int node)
|
static struct irq_desc *alloc_desc(int irq, int node, struct module *owner)
|
||||||
{
|
{
|
||||||
struct irq_desc *desc;
|
struct irq_desc *desc;
|
||||||
gfp_t gfp = GFP_KERNEL;
|
gfp_t gfp = GFP_KERNEL;
|
||||||
|
@ -147,7 +149,7 @@ static struct irq_desc *alloc_desc(int irq, int node)
|
||||||
raw_spin_lock_init(&desc->lock);
|
raw_spin_lock_init(&desc->lock);
|
||||||
lockdep_set_class(&desc->lock, &irq_desc_lock_class);
|
lockdep_set_class(&desc->lock, &irq_desc_lock_class);
|
||||||
|
|
||||||
desc_set_defaults(irq, desc, node);
|
desc_set_defaults(irq, desc, node, owner);
|
||||||
|
|
||||||
return desc;
|
return desc;
|
||||||
|
|
||||||
|
@ -173,13 +175,14 @@ static void free_desc(unsigned int irq)
|
||||||
kfree(desc);
|
kfree(desc);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int alloc_descs(unsigned int start, unsigned int cnt, int node)
|
static int alloc_descs(unsigned int start, unsigned int cnt, int node,
|
||||||
|
struct module *owner)
|
||||||
{
|
{
|
||||||
struct irq_desc *desc;
|
struct irq_desc *desc;
|
||||||
int i;
|
int i;
|
||||||
|
|
||||||
for (i = 0; i < cnt; i++) {
|
for (i = 0; i < cnt; i++) {
|
||||||
desc = alloc_desc(start + i, node);
|
desc = alloc_desc(start + i, node, owner);
|
||||||
if (!desc)
|
if (!desc)
|
||||||
goto err;
|
goto err;
|
||||||
mutex_lock(&sparse_irq_lock);
|
mutex_lock(&sparse_irq_lock);
|
||||||
|
@ -227,7 +230,7 @@ int __init early_irq_init(void)
|
||||||
nr_irqs = initcnt;
|
nr_irqs = initcnt;
|
||||||
|
|
||||||
for (i = 0; i < initcnt; i++) {
|
for (i = 0; i < initcnt; i++) {
|
||||||
desc = alloc_desc(i, node);
|
desc = alloc_desc(i, node, NULL);
|
||||||
set_bit(i, allocated_irqs);
|
set_bit(i, allocated_irqs);
|
||||||
irq_insert_desc(i, desc);
|
irq_insert_desc(i, desc);
|
||||||
}
|
}
|
||||||
|
@ -261,7 +264,7 @@ int __init early_irq_init(void)
|
||||||
alloc_masks(&desc[i], GFP_KERNEL, node);
|
alloc_masks(&desc[i], GFP_KERNEL, node);
|
||||||
raw_spin_lock_init(&desc[i].lock);
|
raw_spin_lock_init(&desc[i].lock);
|
||||||
lockdep_set_class(&desc[i].lock, &irq_desc_lock_class);
|
lockdep_set_class(&desc[i].lock, &irq_desc_lock_class);
|
||||||
desc_set_defaults(i, &desc[i], node);
|
desc_set_defaults(i, &desc[i], node, NULL);
|
||||||
}
|
}
|
||||||
return arch_early_irq_init();
|
return arch_early_irq_init();
|
||||||
}
|
}
|
||||||
|
@ -276,8 +279,16 @@ static void free_desc(unsigned int irq)
|
||||||
dynamic_irq_cleanup(irq);
|
dynamic_irq_cleanup(irq);
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline int alloc_descs(unsigned int start, unsigned int cnt, int node)
|
static inline int alloc_descs(unsigned int start, unsigned int cnt, int node,
|
||||||
|
struct module *owner)
|
||||||
{
|
{
|
||||||
|
u32 i;
|
||||||
|
|
||||||
|
for (i = 0; i < cnt; i++) {
|
||||||
|
struct irq_desc *desc = irq_to_desc(start + i);
|
||||||
|
|
||||||
|
desc->owner = owner;
|
||||||
|
}
|
||||||
return start;
|
return start;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -337,7 +348,8 @@ EXPORT_SYMBOL_GPL(irq_free_descs);
|
||||||
* Returns the first irq number or error code
|
* Returns the first irq number or error code
|
||||||
*/
|
*/
|
||||||
int __ref
|
int __ref
|
||||||
irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node)
|
__irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node,
|
||||||
|
struct module *owner)
|
||||||
{
|
{
|
||||||
int start, ret;
|
int start, ret;
|
||||||
|
|
||||||
|
@ -366,13 +378,13 @@ irq_alloc_descs(int irq, unsigned int from, unsigned int cnt, int node)
|
||||||
|
|
||||||
bitmap_set(allocated_irqs, start, cnt);
|
bitmap_set(allocated_irqs, start, cnt);
|
||||||
mutex_unlock(&sparse_irq_lock);
|
mutex_unlock(&sparse_irq_lock);
|
||||||
return alloc_descs(start, cnt, node);
|
return alloc_descs(start, cnt, node, owner);
|
||||||
|
|
||||||
err:
|
err:
|
||||||
mutex_unlock(&sparse_irq_lock);
|
mutex_unlock(&sparse_irq_lock);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(irq_alloc_descs);
|
EXPORT_SYMBOL_GPL(__irq_alloc_descs);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* irq_reserve_irqs - mark irqs allocated
|
* irq_reserve_irqs - mark irqs allocated
|
||||||
|
@ -440,7 +452,7 @@ void dynamic_irq_cleanup(unsigned int irq)
|
||||||
unsigned long flags;
|
unsigned long flags;
|
||||||
|
|
||||||
raw_spin_lock_irqsave(&desc->lock, flags);
|
raw_spin_lock_irqsave(&desc->lock, flags);
|
||||||
desc_set_defaults(irq, desc, desc_node(desc));
|
desc_set_defaults(irq, desc, desc_node(desc), NULL);
|
||||||
raw_spin_unlock_irqrestore(&desc->lock, flags);
|
raw_spin_unlock_irqrestore(&desc->lock, flags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -883,6 +883,8 @@ __setup_irq(unsigned int irq, struct irq_desc *desc, struct irqaction *new)
|
||||||
|
|
||||||
if (desc->irq_data.chip == &no_irq_chip)
|
if (desc->irq_data.chip == &no_irq_chip)
|
||||||
return -ENOSYS;
|
return -ENOSYS;
|
||||||
|
if (!try_module_get(desc->owner))
|
||||||
|
return -ENODEV;
|
||||||
/*
|
/*
|
||||||
* Some drivers like serial.c use request_irq() heavily,
|
* Some drivers like serial.c use request_irq() heavily,
|
||||||
* so we have to be careful not to interfere with a
|
* 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)
|
||||||
*/
|
*/
|
||||||
nested = irq_settings_is_nested_thread(desc);
|
nested = irq_settings_is_nested_thread(desc);
|
||||||
if (nested) {
|
if (nested) {
|
||||||
if (!new->thread_fn)
|
if (!new->thread_fn) {
|
||||||
return -EINVAL;
|
ret = -EINVAL;
|
||||||
|
goto out_mput;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* Replace the primary handler which was provided from
|
* Replace the primary handler which was provided from
|
||||||
* the driver for non nested interrupt handling by the
|
* 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)
|
||||||
|
|
||||||
t = kthread_create(irq_thread, new, "irq/%d-%s", irq,
|
t = kthread_create(irq_thread, new, "irq/%d-%s", irq,
|
||||||
new->name);
|
new->name);
|
||||||
if (IS_ERR(t))
|
if (IS_ERR(t)) {
|
||||||
return PTR_ERR(t);
|
ret = PTR_ERR(t);
|
||||||
|
goto out_mput;
|
||||||
|
}
|
||||||
/*
|
/*
|
||||||
* We keep the reference to the task struct even if
|
* We keep the reference to the task struct even if
|
||||||
* the thread dies to avoid that the interrupt code
|
* the thread dies to avoid that the interrupt code
|
||||||
|
@ -1095,6 +1101,8 @@ out_thread:
|
||||||
kthread_stop(t);
|
kthread_stop(t);
|
||||||
put_task_struct(t);
|
put_task_struct(t);
|
||||||
}
|
}
|
||||||
|
out_mput:
|
||||||
|
module_put(desc->owner);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1203,6 +1211,7 @@ static struct irqaction *__free_irq(unsigned int irq, void *dev_id)
|
||||||
put_task_struct(action->thread);
|
put_task_struct(action->thread);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
module_put(desc->owner);
|
||||||
return action;
|
return action;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1322,6 +1331,7 @@ int request_threaded_irq(unsigned int irq, irq_handler_t handler,
|
||||||
if (!thread_fn)
|
if (!thread_fn)
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
handler = irq_default_primary_handler;
|
handler = irq_default_primary_handler;
|
||||||
|
irqflags |= IRQF_ONESHOT;
|
||||||
}
|
}
|
||||||
|
|
||||||
action = kzalloc(sizeof(struct irqaction), GFP_KERNEL);
|
action = kzalloc(sizeof(struct irqaction), GFP_KERNEL);
|
||||||
|
|
Loading…
Reference in New Issue