History

Merge branch 'irq-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull irq fix from Thomas Gleixner: "A single fix for a cpu hotplug race vs. interrupt descriptors: Prevent irq setup/teardown across the cpu starting/dying parts of cpu hotplug so that the starting/dying cpu has a stable view of the descriptor space. This has been an issue for all architectures in the cpu dying phase, where interrupts are migrated away from the dying cpu. In the starting phase its mostly a x86 issue vs the vector space update" * 'irq-urgent-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: hotplug: Prevent alloc/free of irq descriptors during cpu up/down

Linus Torvalds committed 11 years ago

Commit c4bc6802 parents 59c3cb5 a8994183 files · +27 −6Browse files

Showing the changes to kernel (2 of 3 files). Show all

Unified · Split

2 files
  1. kernel/cpu.c +21 −1
  2. kernel/irq/internals.h +0 −4
kernel/cpu.c+21−1
@@ -21,6 +21,7 @@ · 20 unmodified lines
21#include <linux/suspend.h>21#include <linux/suspend.h>
22#include <linux/lockdep.h>22#include <linux/lockdep.h>
23#include <linux/tick.h>23#include <linux/tick.h>
24#include <linux/irq.h>
24#include <trace/events/power.h>25#include <trace/events/power.h>
25 26
26#include "smpboot.h"27#include "smpboot.h"
@@ -392,13 +393,19 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen) · 365 unmodified lines
392 smpboot_park_threads(cpu);393 smpboot_park_threads(cpu);
393 394
394 /*395 /*
395 * So now all preempt/rcu users must observe !cpu_active().396 * Prevent irq alloc/free while the dying cpu reorganizes the
397 * interrupt affinities.
396 */398 */
399 irq_lock_sparse();
397 400
401 /*
402 * So now all preempt/rcu users must observe !cpu_active().
403 */
398 err = __stop_machine(take_cpu_down, &tcd_param, cpumask_of(cpu));404 err = __stop_machine(take_cpu_down, &tcd_param, cpumask_of(cpu));
399 if (err) {405 if (err) {
400 /* CPU didn't die: tell everyone. Can't complain. */406 /* CPU didn't die: tell everyone. Can't complain. */
401 cpu_notify_nofail(CPU_DOWN_FAILED | mod, hcpu);407 cpu_notify_nofail(CPU_DOWN_FAILED | mod, hcpu);
408 irq_unlock_sparse();
402 goto out_release;409 goto out_release;
403 }410 }
404 BUG_ON(cpu_online(cpu));411 BUG_ON(cpu_online(cpu));
@@ -415,6 +422,9 @@ static int __ref _cpu_down(unsigned int cpu, int tasks_frozen) · 10 unmodified lines
415 smp_mb(); /* Read from cpu_dead_idle before __cpu_die(). */422 smp_mb(); /* Read from cpu_dead_idle before __cpu_die(). */
416 per_cpu(cpu_dead_idle, cpu) = false;423 per_cpu(cpu_dead_idle, cpu) = false;
417 424
425 /* Interrupts are moved away from the dying cpu, reenable alloc/free */
426 irq_unlock_sparse();
427
418 hotplug_cpu__broadcast_tick_pull(cpu);428 hotplug_cpu__broadcast_tick_pull(cpu);
419 /* This actually kills the CPU. */429 /* This actually kills the CPU. */
420 __cpu_die(cpu);430 __cpu_die(cpu);
@@ -517,8 +527,18 @@ static int _cpu_up(unsigned int cpu, int tasks_frozen) · 96 unmodified lines
517 goto out_notify;527 goto out_notify;
518 }528 }
519 529
530 /*
531 * Some architectures have to walk the irq descriptors to
532 * setup the vector space for the cpu which comes online.
533 * Prevent irq alloc/free across the bringup.
534 */
535 irq_lock_sparse();
536
520 /* Arch-specific enabling code. */537 /* Arch-specific enabling code. */
521 ret = __cpu_up(cpu, idle);538 ret = __cpu_up(cpu, idle);
539
540 irq_unlock_sparse();
541
522 if (ret != 0)542 if (ret != 0)
523 goto out_notify;543 goto out_notify;
524 BUG_ON(!cpu_online(cpu));544 BUG_ON(!cpu_online(cpu));
kernel/irq/internals.h+0−4
@@ -76,12 +76,8 @@ extern void unmask_threaded_irq(struct irq_desc *desc); · 75 unmodified lines
76 76
77#ifdef CONFIG_SPARSE_IRQ77#ifdef CONFIG_SPARSE_IRQ
78static inline void irq_mark_irq(unsigned int irq) { }78static inline void irq_mark_irq(unsigned int irq) { }
79extern void irq_lock_sparse(void);
80extern void irq_unlock_sparse(void);
81#else79#else
82extern void irq_mark_irq(unsigned int irq);80extern void irq_mark_irq(unsigned int irq);
83static inline void irq_lock_sparse(void) { }
84static inline void irq_unlock_sparse(void) { }
85#endif81#endif
86 82
87extern void init_kstat_irqs(struct irq_desc *desc, int node, int nr);83extern void init_kstat_irqs(struct irq_desc *desc, int node, int nr);