Commit 10b888d6 authored by Yinghai Lu's avatar Yinghai Lu Committed by Ingo Molnar

irq, x86: fix lock status with numa_migrate_irq_desc

Eric Paris reported:

> I have an hp dl785g5 which is unable to successfully run
> 2.6.29-0.66.rc3.fc11.x86_64 or 2.6.29-rc2-next-20090126.  During bootup
> (early in userspace daemons starting) I get the below BUG, which quickly
> renders the machine dead.  I assume it is because sparse_irq_lock never
> gets released when the BUG kills that task.

Adjust lock sequence when migrating a descriptor with
CONFIG_NUMA_MIGRATE_IRQ_DESC enabled.
Signed-off-by: default avatarYinghai Lu <yinghai@kernel.org>
Signed-off-by: default avatarIngo Molnar <mingo@elte.hu>
parent 9a8ecae8
...@@ -2528,14 +2528,15 @@ static void irq_complete_move(struct irq_desc **descp) ...@@ -2528,14 +2528,15 @@ static void irq_complete_move(struct irq_desc **descp)
vector = ~get_irq_regs()->orig_ax; vector = ~get_irq_regs()->orig_ax;
me = smp_processor_id(); me = smp_processor_id();
if (vector == cfg->vector && cpumask_test_cpu(me, cfg->domain)) {
#ifdef CONFIG_NUMA_MIGRATE_IRQ_DESC #ifdef CONFIG_NUMA_MIGRATE_IRQ_DESC
*descp = desc = move_irq_desc(desc, me); *descp = desc = move_irq_desc(desc, me);
/* get the new one */ /* get the new one */
cfg = desc->chip_data; cfg = desc->chip_data;
#endif #endif
if (vector == cfg->vector && cpumask_test_cpu(me, cfg->domain))
send_cleanup_vector(cfg); send_cleanup_vector(cfg);
}
} }
#else #else
static inline void irq_complete_move(struct irq_desc **descp) {} static inline void irq_complete_move(struct irq_desc **descp) {}
......
...@@ -71,7 +71,7 @@ static struct irq_desc *__real_move_irq_desc(struct irq_desc *old_desc, ...@@ -71,7 +71,7 @@ static struct irq_desc *__real_move_irq_desc(struct irq_desc *old_desc,
desc = irq_desc_ptrs[irq]; desc = irq_desc_ptrs[irq];
if (desc && old_desc != desc) if (desc && old_desc != desc)
goto out_unlock; goto out_unlock;
node = cpu_to_node(cpu); node = cpu_to_node(cpu);
desc = kzalloc_node(sizeof(*desc), GFP_ATOMIC, node); desc = kzalloc_node(sizeof(*desc), GFP_ATOMIC, node);
...@@ -84,10 +84,15 @@ static struct irq_desc *__real_move_irq_desc(struct irq_desc *old_desc, ...@@ -84,10 +84,15 @@ static struct irq_desc *__real_move_irq_desc(struct irq_desc *old_desc,
init_copy_one_irq_desc(irq, old_desc, desc, cpu); init_copy_one_irq_desc(irq, old_desc, desc, cpu);
irq_desc_ptrs[irq] = desc; irq_desc_ptrs[irq] = desc;
spin_unlock_irqrestore(&sparse_irq_lock, flags);
/* free the old one */ /* free the old one */
free_one_irq_desc(old_desc, desc); free_one_irq_desc(old_desc, desc);
spin_unlock(&old_desc->lock);
kfree(old_desc); kfree(old_desc);
spin_lock(&desc->lock);
return desc;
out_unlock: out_unlock:
spin_unlock_irqrestore(&sparse_irq_lock, flags); spin_unlock_irqrestore(&sparse_irq_lock, flags);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment