From: Greg Kroah-Hartman Date: Tue, 10 Jan 2012 18:19:25 +0000 (-0800) Subject: 3.1-stable patches X-Git-Tag: v3.2.1~7 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=f73a8b6849c92152184e62af0d90b96258f69dcf;p=thirdparty%2Fkernel%2Fstable-queue.git 3.1-stable patches added patches: pm-sleep-fix-race-between-cpu-hotplug-and-freezer.patch --- diff --git a/queue-3.1/pm-sleep-fix-race-between-cpu-hotplug-and-freezer.patch b/queue-3.1/pm-sleep-fix-race-between-cpu-hotplug-and-freezer.patch new file mode 100644 index 00000000000..412f3171e92 --- /dev/null +++ b/queue-3.1/pm-sleep-fix-race-between-cpu-hotplug-and-freezer.patch @@ -0,0 +1,125 @@ +From 79cfbdfa87e84992d509e6c1648a18e1d7e68c20 Mon Sep 17 00:00:00 2001 +From: "Srivatsa S. Bhat" +Date: Thu, 3 Nov 2011 00:59:25 +0100 +Subject: PM / Sleep: Fix race between CPU hotplug and freezer + +From: "Srivatsa S. Bhat" + +commit 79cfbdfa87e84992d509e6c1648a18e1d7e68c20 upstream. + +The CPU hotplug notifications sent out by the _cpu_up() and _cpu_down() +functions depend on the value of the 'tasks_frozen' argument passed to them +(which indicates whether tasks have been frozen or not). +(Examples for such CPU hotplug notifications: CPU_ONLINE, CPU_ONLINE_FROZEN, +CPU_DEAD, CPU_DEAD_FROZEN). + +Thus, it is essential that while the callbacks for those notifications are +running, the state of the system with respect to the tasks being frozen or +not remains unchanged, *throughout that duration*. Hence there is a need for +synchronizing the CPU hotplug code with the freezer subsystem. + +Since the freezer is involved only in the Suspend/Hibernate call paths, this +patch hooks the CPU hotplug code to the suspend/hibernate notifiers +PM_[SUSPEND|HIBERNATE]_PREPARE and PM_POST_[SUSPEND|HIBERNATE] to prevent +the race between CPU hotplug and freezer, thus ensuring that CPU hotplug +notifications will always be run with the state of the system really being +what the notifications indicate, _throughout_ their execution time. + +Signed-off-by: Srivatsa S. Bhat +Signed-off-by: Rafael J. Wysocki +Signed-off-by: Greg Kroah-Hartman + +--- + kernel/cpu.c | 74 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ + 1 file changed, 74 insertions(+) + +--- a/kernel/cpu.c ++++ b/kernel/cpu.c +@@ -15,6 +15,7 @@ + #include + #include + #include ++#include + + #ifdef CONFIG_SMP + /* Serializes the updates to cpu_online_mask, cpu_present_mask */ +@@ -476,6 +477,79 @@ static int alloc_frozen_cpus(void) + return 0; + } + core_initcall(alloc_frozen_cpus); ++ ++/* ++ * Prevent regular CPU hotplug from racing with the freezer, by disabling CPU ++ * hotplug when tasks are about to be frozen. Also, don't allow the freezer ++ * to continue until any currently running CPU hotplug operation gets ++ * completed. ++ * To modify the 'cpu_hotplug_disabled' flag, we need to acquire the ++ * 'cpu_add_remove_lock'. And this same lock is also taken by the regular ++ * CPU hotplug path and released only after it is complete. Thus, we ++ * (and hence the freezer) will block here until any currently running CPU ++ * hotplug operation gets completed. ++ */ ++void cpu_hotplug_disable_before_freeze(void) ++{ ++ cpu_maps_update_begin(); ++ cpu_hotplug_disabled = 1; ++ cpu_maps_update_done(); ++} ++ ++ ++/* ++ * When tasks have been thawed, re-enable regular CPU hotplug (which had been ++ * disabled while beginning to freeze tasks). ++ */ ++void cpu_hotplug_enable_after_thaw(void) ++{ ++ cpu_maps_update_begin(); ++ cpu_hotplug_disabled = 0; ++ cpu_maps_update_done(); ++} ++ ++/* ++ * When callbacks for CPU hotplug notifications are being executed, we must ++ * ensure that the state of the system with respect to the tasks being frozen ++ * or not, as reported by the notification, remains unchanged *throughout the ++ * duration* of the execution of the callbacks. ++ * Hence we need to prevent the freezer from racing with regular CPU hotplug. ++ * ++ * This synchronization is implemented by mutually excluding regular CPU ++ * hotplug and Suspend/Hibernate call paths by hooking onto the Suspend/ ++ * Hibernate notifications. ++ */ ++static int ++cpu_hotplug_pm_callback(struct notifier_block *nb, ++ unsigned long action, void *ptr) ++{ ++ switch (action) { ++ ++ case PM_SUSPEND_PREPARE: ++ case PM_HIBERNATION_PREPARE: ++ cpu_hotplug_disable_before_freeze(); ++ break; ++ ++ case PM_POST_SUSPEND: ++ case PM_POST_HIBERNATION: ++ cpu_hotplug_enable_after_thaw(); ++ break; ++ ++ default: ++ return NOTIFY_DONE; ++ } ++ ++ return NOTIFY_OK; ++} ++ ++ ++int cpu_hotplug_pm_sync_init(void) ++{ ++ pm_notifier(cpu_hotplug_pm_callback, 0); ++ return 0; ++} ++core_initcall(cpu_hotplug_pm_sync_init); ++ + #endif /* CONFIG_PM_SLEEP_SMP */ + + /** diff --git a/queue-3.1/series b/queue-3.1/series index 309006d59dd..dc002c8f383 100644 --- a/queue-3.1/series +++ b/queue-3.1/series @@ -35,3 +35,4 @@ ohci-final-fix-for-nvidia-problems-i-hope.patch igmp-avoid-zero-delay-when-receiving-odd-mixture-of-igmp-queries.patch asix-fix-infinite-loop-in-rx_fixup.patch bonding-fix-error-handling-if-slave-is-busy-v2.patch +pm-sleep-fix-race-between-cpu-hotplug-and-freezer.patch