diff options
| author | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-11-23 19:42:09 -0200 |
|---|---|---|
| committer | Mauro Carvalho Chehab <mchehab@redhat.com> | 2011-11-23 19:42:09 -0200 |
| commit | 12cbfd0a3c52a52c2948c91b9e62e73c468d1572 (patch) | |
| tree | 9252b3929159a83fc81ca0a48706bfa959660967 /kernel/cpu.c | |
| parent | b32e724308300a6ecead0f4895f0452a06a4291d (diff) | |
| parent | cfcfc9eca2bcbd26a8e206baeb005b055dbf8e37 (diff) | |
| download | lwn-12cbfd0a3c52a52c2948c91b9e62e73c468d1572.tar.gz lwn-12cbfd0a3c52a52c2948c91b9e62e73c468d1572.zip | |
Merge tag 'v3.2-rc2' into staging/for_v3.3
* tag 'v3.2-rc2': (3068 commits)
Linux 3.2-rc2
hfs: add sanity check for file name length
fsl-rio: fix compile error
blackfin: Fixup export.h includes
Blackfin: add serial TX IRQ in individual platform resource
virtio-pci: fix use after free
ACPI / cpuidle: Remove acpi_idle_suspend (to fix suspend regression)
drm/radeon/kms/combios: fix dynamic allocation of PM clock modes
[CPUFREQ] db8500: fix build error due to undeclared i variable
bma023: Add SFI translation for this device
vrtc: change its year offset from 1960 to 1972
ce4100: fix a build error
arm/imx: fix imx6q mmc error when mounting rootfs
arm/imx: fix AUTO_ZRELADDR selection
arm/imx: fix the references to ARCH_MX3
ARM: mx51/53: set pwm clock parent to ipg_perclk
btrfs: rename the option to nospace_cache
drm/radeon/kms/pm: switch to dynamically allocating clock mode array
drm/radeon/kms: optimize r600_pm_profile_init
drm/radeon/kms/pm: add a proper pm profile init function for fusion
...
Conflicts:
drivers/media/radio/Kconfig
Diffstat (limited to 'kernel/cpu.c')
| -rw-r--r-- | kernel/cpu.c | 76 |
1 files changed, 75 insertions, 1 deletions
diff --git a/kernel/cpu.c b/kernel/cpu.c index 12b7458f23b1..563f13609470 100644 --- a/kernel/cpu.c +++ b/kernel/cpu.c @@ -10,11 +10,12 @@ #include <linux/sched.h> #include <linux/unistd.h> #include <linux/cpu.h> -#include <linux/module.h> +#include <linux/export.h> #include <linux/kthread.h> #include <linux/stop_machine.h> #include <linux/mutex.h> #include <linux/gfp.h> +#include <linux/suspend.h> #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 */ /** |
