aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/kexec.c7
-rw-r--r--kernel/power/console.c6
-rw-r--r--kernel/power/disk.c22
-rw-r--r--kernel/power/main.c8
-rw-r--r--kernel/power/user.c8
-rw-r--r--kernel/printk.c15
-rw-r--r--kernel/trace/trace_hw_branches.c64
7 files changed, 85 insertions, 45 deletions
diff --git a/kernel/kexec.c b/kernel/kexec.c
index 8a6d7b08864e..483899578259 100644
--- a/kernel/kexec.c
+++ b/kernel/kexec.c
@@ -1465,6 +1465,11 @@ int kernel_kexec(void)
1465 error = device_power_down(PMSG_FREEZE); 1465 error = device_power_down(PMSG_FREEZE);
1466 if (error) 1466 if (error)
1467 goto Enable_irqs; 1467 goto Enable_irqs;
1468
1469 /* Suspend system devices */
1470 error = sysdev_suspend(PMSG_FREEZE);
1471 if (error)
1472 goto Power_up_devices;
1468 } else 1473 } else
1469#endif 1474#endif
1470 { 1475 {
@@ -1477,6 +1482,8 @@ int kernel_kexec(void)
1477 1482
1478#ifdef CONFIG_KEXEC_JUMP 1483#ifdef CONFIG_KEXEC_JUMP
1479 if (kexec_image->preserve_context) { 1484 if (kexec_image->preserve_context) {
1485 sysdev_resume();
1486 Power_up_devices:
1480 device_power_up(PMSG_RESTORE); 1487 device_power_up(PMSG_RESTORE);
1481 Enable_irqs: 1488 Enable_irqs:
1482 local_irq_enable(); 1489 local_irq_enable();
diff --git a/kernel/power/console.c b/kernel/power/console.c
index b8628be2a465..a3961b205de7 100644
--- a/kernel/power/console.c
+++ b/kernel/power/console.c
@@ -78,6 +78,12 @@ void pm_restore_console(void)
78 } 78 }
79 set_console(orig_fgconsole); 79 set_console(orig_fgconsole);
80 release_console_sem(); 80 release_console_sem();
81
82 if (vt_waitactive(orig_fgconsole)) {
83 pr_debug("Resume: Can't switch VCs.");
84 return;
85 }
86
81 kmsg_redirect = orig_kmsg; 87 kmsg_redirect = orig_kmsg;
82} 88}
83#endif 89#endif
diff --git a/kernel/power/disk.c b/kernel/power/disk.c
index 432ee575c9ee..4a4a206b1979 100644
--- a/kernel/power/disk.c
+++ b/kernel/power/disk.c
@@ -227,6 +227,12 @@ static int create_image(int platform_mode)
227 "aborting hibernation\n"); 227 "aborting hibernation\n");
228 goto Enable_irqs; 228 goto Enable_irqs;
229 } 229 }
230 sysdev_suspend(PMSG_FREEZE);
231 if (error) {
232 printk(KERN_ERR "PM: Some devices failed to power down, "
233 "aborting hibernation\n");
234 goto Power_up_devices;
235 }
230 236
231 if (hibernation_test(TEST_CORE)) 237 if (hibernation_test(TEST_CORE))
232 goto Power_up; 238 goto Power_up;
@@ -242,9 +248,11 @@ static int create_image(int platform_mode)
242 if (!in_suspend) 248 if (!in_suspend)
243 platform_leave(platform_mode); 249 platform_leave(platform_mode);
244 Power_up: 250 Power_up:
251 sysdev_resume();
245 /* NOTE: device_power_up() is just a resume() for devices 252 /* NOTE: device_power_up() is just a resume() for devices
246 * that suspended with irqs off ... no overall powerup. 253 * that suspended with irqs off ... no overall powerup.
247 */ 254 */
255 Power_up_devices:
248 device_power_up(in_suspend ? 256 device_power_up(in_suspend ?
249 (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE); 257 (error ? PMSG_RECOVER : PMSG_THAW) : PMSG_RESTORE);
250 Enable_irqs: 258 Enable_irqs:
@@ -335,6 +343,7 @@ static int resume_target_kernel(void)
335 "aborting resume\n"); 343 "aborting resume\n");
336 goto Enable_irqs; 344 goto Enable_irqs;
337 } 345 }
346 sysdev_suspend(PMSG_QUIESCE);
338 /* We'll ignore saved state, but this gets preempt count (etc) right */ 347 /* We'll ignore saved state, but this gets preempt count (etc) right */
339 save_processor_state(); 348 save_processor_state();
340 error = restore_highmem(); 349 error = restore_highmem();
@@ -357,6 +366,7 @@ static int resume_target_kernel(void)
357 swsusp_free(); 366 swsusp_free();
358 restore_processor_state(); 367 restore_processor_state();
359 touch_softlockup_watchdog(); 368 touch_softlockup_watchdog();
369 sysdev_resume();
360 device_power_up(PMSG_RECOVER); 370 device_power_up(PMSG_RECOVER);
361 Enable_irqs: 371 Enable_irqs:
362 local_irq_enable(); 372 local_irq_enable();
@@ -440,6 +450,7 @@ int hibernation_platform_enter(void)
440 local_irq_disable(); 450 local_irq_disable();
441 error = device_power_down(PMSG_HIBERNATE); 451 error = device_power_down(PMSG_HIBERNATE);
442 if (!error) { 452 if (!error) {
453 sysdev_suspend(PMSG_HIBERNATE);
443 hibernation_ops->enter(); 454 hibernation_ops->enter();
444 /* We should never get here */ 455 /* We should never get here */
445 while (1); 456 while (1);
@@ -595,6 +606,12 @@ static int software_resume(void)
595 unsigned int flags; 606 unsigned int flags;
596 607
597 /* 608 /*
609 * If the user said "noresume".. bail out early.
610 */
611 if (noresume)
612 return 0;
613
614 /*
598 * name_to_dev_t() below takes a sysfs buffer mutex when sysfs 615 * name_to_dev_t() below takes a sysfs buffer mutex when sysfs
599 * is configured into the kernel. Since the regular hibernate 616 * is configured into the kernel. Since the regular hibernate
600 * trigger path is via sysfs which takes a buffer mutex before 617 * trigger path is via sysfs which takes a buffer mutex before
@@ -610,6 +627,11 @@ static int software_resume(void)
610 mutex_unlock(&pm_mutex); 627 mutex_unlock(&pm_mutex);
611 return -ENOENT; 628 return -ENOENT;
612 } 629 }
630 /*
631 * Some device discovery might still be in progress; we need
632 * to wait for this to finish.
633 */
634 wait_for_device_probe();
613 swsusp_resume_device = name_to_dev_t(resume_file); 635 swsusp_resume_device = name_to_dev_t(resume_file);
614 pr_debug("PM: Resume from partition %s\n", resume_file); 636 pr_debug("PM: Resume from partition %s\n", resume_file);
615 } else { 637 } else {
diff --git a/kernel/power/main.c b/kernel/power/main.c
index b4d219016b6c..c9632f841f64 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -298,8 +298,12 @@ static int suspend_enter(suspend_state_t state)
298 goto Done; 298 goto Done;
299 } 299 }
300 300
301 if (!suspend_test(TEST_CORE)) 301 error = sysdev_suspend(PMSG_SUSPEND);
302 error = suspend_ops->enter(state); 302 if (!error) {
303 if (!suspend_test(TEST_CORE))
304 error = suspend_ops->enter(state);
305 sysdev_resume();
306 }
303 307
304 device_power_up(PMSG_RESUME); 308 device_power_up(PMSG_RESUME);
305 Done: 309 Done:
diff --git a/kernel/power/user.c b/kernel/power/user.c
index 005b93d839ba..6c85359364f2 100644
--- a/kernel/power/user.c
+++ b/kernel/power/user.c
@@ -95,15 +95,15 @@ static int snapshot_open(struct inode *inode, struct file *filp)
95 data->swap = swsusp_resume_device ? 95 data->swap = swsusp_resume_device ?
96 swap_type_of(swsusp_resume_device, 0, NULL) : -1; 96 swap_type_of(swsusp_resume_device, 0, NULL) : -1;
97 data->mode = O_RDONLY; 97 data->mode = O_RDONLY;
98 error = pm_notifier_call_chain(PM_RESTORE_PREPARE); 98 error = pm_notifier_call_chain(PM_HIBERNATION_PREPARE);
99 if (error) 99 if (error)
100 pm_notifier_call_chain(PM_POST_RESTORE); 100 pm_notifier_call_chain(PM_POST_HIBERNATION);
101 } else { 101 } else {
102 data->swap = -1; 102 data->swap = -1;
103 data->mode = O_WRONLY; 103 data->mode = O_WRONLY;
104 error = pm_notifier_call_chain(PM_HIBERNATION_PREPARE); 104 error = pm_notifier_call_chain(PM_RESTORE_PREPARE);
105 if (error) 105 if (error)
106 pm_notifier_call_chain(PM_POST_HIBERNATION); 106 pm_notifier_call_chain(PM_POST_RESTORE);
107 } 107 }
108 if (error) 108 if (error)
109 atomic_inc(&snapshot_device_available); 109 atomic_inc(&snapshot_device_available);
diff --git a/kernel/printk.c b/kernel/printk.c
index 69188f226a93..e3602d0755b0 100644
--- a/kernel/printk.c
+++ b/kernel/printk.c
@@ -73,7 +73,6 @@ EXPORT_SYMBOL(oops_in_progress);
73 * driver system. 73 * driver system.
74 */ 74 */
75static DECLARE_MUTEX(console_sem); 75static DECLARE_MUTEX(console_sem);
76static DECLARE_MUTEX(secondary_console_sem);
77struct console *console_drivers; 76struct console *console_drivers;
78EXPORT_SYMBOL_GPL(console_drivers); 77EXPORT_SYMBOL_GPL(console_drivers);
79 78
@@ -891,12 +890,14 @@ void suspend_console(void)
891 printk("Suspending console(s) (use no_console_suspend to debug)\n"); 890 printk("Suspending console(s) (use no_console_suspend to debug)\n");
892 acquire_console_sem(); 891 acquire_console_sem();
893 console_suspended = 1; 892 console_suspended = 1;
893 up(&console_sem);
894} 894}
895 895
896void resume_console(void) 896void resume_console(void)
897{ 897{
898 if (!console_suspend_enabled) 898 if (!console_suspend_enabled)
899 return; 899 return;
900 down(&console_sem);
900 console_suspended = 0; 901 console_suspended = 0;
901 release_console_sem(); 902 release_console_sem();
902} 903}
@@ -912,11 +913,9 @@ void resume_console(void)
912void acquire_console_sem(void) 913void acquire_console_sem(void)
913{ 914{
914 BUG_ON(in_interrupt()); 915 BUG_ON(in_interrupt());
915 if (console_suspended) {
916 down(&secondary_console_sem);
917 return;
918 }
919 down(&console_sem); 916 down(&console_sem);
917 if (console_suspended)
918 return;
920 console_locked = 1; 919 console_locked = 1;
921 console_may_schedule = 1; 920 console_may_schedule = 1;
922} 921}
@@ -926,6 +925,10 @@ int try_acquire_console_sem(void)
926{ 925{
927 if (down_trylock(&console_sem)) 926 if (down_trylock(&console_sem))
928 return -1; 927 return -1;
928 if (console_suspended) {
929 up(&console_sem);
930 return -1;
931 }
929 console_locked = 1; 932 console_locked = 1;
930 console_may_schedule = 0; 933 console_may_schedule = 0;
931 return 0; 934 return 0;
@@ -979,7 +982,7 @@ void release_console_sem(void)
979 unsigned wake_klogd = 0; 982 unsigned wake_klogd = 0;
980 983
981 if (console_suspended) { 984 if (console_suspended) {
982 up(&secondary_console_sem); 985 up(&console_sem);
983 return; 986 return;
984 } 987 }
985 988
diff --git a/kernel/trace/trace_hw_branches.c b/kernel/trace/trace_hw_branches.c
index 3561aace075c..7bfdf4c2347f 100644
--- a/kernel/trace/trace_hw_branches.c
+++ b/kernel/trace/trace_hw_branches.c
@@ -3,17 +3,15 @@
3 * 3 *
4 * Copyright (C) 2008-2009 Intel Corporation. 4 * Copyright (C) 2008-2009 Intel Corporation.
5 * Markus Metzger <markus.t.metzger@gmail.com>, 2008-2009 5 * Markus Metzger <markus.t.metzger@gmail.com>, 2008-2009
6 *
7 */ 6 */
8 7#include <linux/spinlock.h>
9#include <linux/module.h> 8#include <linux/kallsyms.h>
10#include <linux/fs.h>
11#include <linux/debugfs.h> 9#include <linux/debugfs.h>
12#include <linux/ftrace.h> 10#include <linux/ftrace.h>
13#include <linux/kallsyms.h> 11#include <linux/module.h>
14#include <linux/mutex.h>
15#include <linux/cpu.h> 12#include <linux/cpu.h>
16#include <linux/smp.h> 13#include <linux/smp.h>
14#include <linux/fs.h>
17 15
18#include <asm/ds.h> 16#include <asm/ds.h>
19 17
@@ -23,16 +21,17 @@
23 21
24#define SIZEOF_BTS (1 << 13) 22#define SIZEOF_BTS (1 << 13)
25 23
26/* The tracer mutex protects the below per-cpu tracer array. 24/*
27 It needs to be held to: 25 * The tracer lock protects the below per-cpu tracer array.
28 - start tracing on all cpus 26 * It needs to be held to:
29 - stop tracing on all cpus 27 * - start tracing on all cpus
30 - start tracing on a single hotplug cpu 28 * - stop tracing on all cpus
31 - stop tracing on a single hotplug cpu 29 * - start tracing on a single hotplug cpu
32 - read the trace from all cpus 30 * - stop tracing on a single hotplug cpu
33 - read the trace from a single cpu 31 * - read the trace from all cpus
34*/ 32 * - read the trace from a single cpu
35static DEFINE_MUTEX(bts_tracer_mutex); 33 */
34static DEFINE_SPINLOCK(bts_tracer_lock);
36static DEFINE_PER_CPU(struct bts_tracer *, tracer); 35static DEFINE_PER_CPU(struct bts_tracer *, tracer);
37static DEFINE_PER_CPU(unsigned char[SIZEOF_BTS], buffer); 36static DEFINE_PER_CPU(unsigned char[SIZEOF_BTS], buffer);
38 37
@@ -47,7 +46,7 @@ static struct trace_array *hw_branch_trace __read_mostly;
47 * Start tracing on the current cpu. 46 * Start tracing on the current cpu.
48 * The argument is ignored. 47 * The argument is ignored.
49 * 48 *
50 * pre: bts_tracer_mutex must be locked. 49 * pre: bts_tracer_lock must be locked.
51 */ 50 */
52static void bts_trace_start_cpu(void *arg) 51static void bts_trace_start_cpu(void *arg)
53{ 52{
@@ -66,19 +65,19 @@ static void bts_trace_start_cpu(void *arg)
66 65
67static void bts_trace_start(struct trace_array *tr) 66static void bts_trace_start(struct trace_array *tr)
68{ 67{
69 mutex_lock(&bts_tracer_mutex); 68 spin_lock(&bts_tracer_lock);
70 69
71 on_each_cpu(bts_trace_start_cpu, NULL, 1); 70 on_each_cpu(bts_trace_start_cpu, NULL, 1);
72 trace_hw_branches_enabled = 1; 71 trace_hw_branches_enabled = 1;
73 72
74 mutex_unlock(&bts_tracer_mutex); 73 spin_unlock(&bts_tracer_lock);
75} 74}
76 75
77/* 76/*
78 * Stop tracing on the current cpu. 77 * Stop tracing on the current cpu.
79 * The argument is ignored. 78 * The argument is ignored.
80 * 79 *
81 * pre: bts_tracer_mutex must be locked. 80 * pre: bts_tracer_lock must be locked.
82 */ 81 */
83static void bts_trace_stop_cpu(void *arg) 82static void bts_trace_stop_cpu(void *arg)
84{ 83{
@@ -90,12 +89,12 @@ static void bts_trace_stop_cpu(void *arg)
90 89
91static void bts_trace_stop(struct trace_array *tr) 90static void bts_trace_stop(struct trace_array *tr)
92{ 91{
93 mutex_lock(&bts_tracer_mutex); 92 spin_lock(&bts_tracer_lock);
94 93
95 trace_hw_branches_enabled = 0; 94 trace_hw_branches_enabled = 0;
96 on_each_cpu(bts_trace_stop_cpu, NULL, 1); 95 on_each_cpu(bts_trace_stop_cpu, NULL, 1);
97 96
98 mutex_unlock(&bts_tracer_mutex); 97 spin_unlock(&bts_tracer_lock);
99} 98}
100 99
101static int __cpuinit bts_hotcpu_handler(struct notifier_block *nfb, 100static int __cpuinit bts_hotcpu_handler(struct notifier_block *nfb,
@@ -103,7 +102,7 @@ static int __cpuinit bts_hotcpu_handler(struct notifier_block *nfb,
103{ 102{
104 unsigned int cpu = (unsigned long)hcpu; 103 unsigned int cpu = (unsigned long)hcpu;
105 104
106 mutex_lock(&bts_tracer_mutex); 105 spin_lock(&bts_tracer_lock);
107 106
108 if (!trace_hw_branches_enabled) 107 if (!trace_hw_branches_enabled)
109 goto out; 108 goto out;
@@ -119,7 +118,7 @@ static int __cpuinit bts_hotcpu_handler(struct notifier_block *nfb,
119 } 118 }
120 119
121 out: 120 out:
122 mutex_unlock(&bts_tracer_mutex); 121 spin_unlock(&bts_tracer_lock);
123 return NOTIFY_DONE; 122 return NOTIFY_DONE;
124} 123}
125 124
@@ -127,20 +126,18 @@ static struct notifier_block bts_hotcpu_notifier __cpuinitdata = {
127 .notifier_call = bts_hotcpu_handler 126 .notifier_call = bts_hotcpu_handler
128}; 127};
129 128
130static int __cpuinit bts_trace_init(struct trace_array *tr) 129static int bts_trace_init(struct trace_array *tr)
131{ 130{
132 hw_branch_trace = tr; 131 hw_branch_trace = tr;
133 132
134 register_hotcpu_notifier(&bts_hotcpu_notifier);
135 bts_trace_start(tr); 133 bts_trace_start(tr);
136 134
137 return 0; 135 return 0;
138} 136}
139 137
140static void __cpuinit bts_trace_reset(struct trace_array *tr) 138static void bts_trace_reset(struct trace_array *tr)
141{ 139{
142 bts_trace_stop(tr); 140 bts_trace_stop(tr);
143 unregister_hotcpu_notifier(&bts_hotcpu_notifier);
144} 141}
145 142
146static void bts_trace_print_header(struct seq_file *m) 143static void bts_trace_print_header(struct seq_file *m)
@@ -227,7 +224,7 @@ static void trace_bts_at(const struct bts_trace *trace, void *at)
227/* 224/*
228 * Collect the trace on the current cpu and write it into the ftrace buffer. 225 * Collect the trace on the current cpu and write it into the ftrace buffer.
229 * 226 *
230 * pre: bts_tracer_mutex must be locked 227 * pre: bts_tracer_lock must be locked
231 */ 228 */
232static void trace_bts_cpu(void *arg) 229static void trace_bts_cpu(void *arg)
233{ 230{
@@ -263,11 +260,11 @@ out:
263 260
264static void trace_bts_prepare(struct trace_iterator *iter) 261static void trace_bts_prepare(struct trace_iterator *iter)
265{ 262{
266 mutex_lock(&bts_tracer_mutex); 263 spin_lock(&bts_tracer_lock);
267 264
268 on_each_cpu(trace_bts_cpu, iter->tr, 1); 265 on_each_cpu(trace_bts_cpu, iter->tr, 1);
269 266
270 mutex_unlock(&bts_tracer_mutex); 267 spin_unlock(&bts_tracer_lock);
271} 268}
272 269
273static void trace_bts_close(struct trace_iterator *iter) 270static void trace_bts_close(struct trace_iterator *iter)
@@ -277,11 +274,11 @@ static void trace_bts_close(struct trace_iterator *iter)
277 274
278void trace_hw_branch_oops(void) 275void trace_hw_branch_oops(void)
279{ 276{
280 mutex_lock(&bts_tracer_mutex); 277 spin_lock(&bts_tracer_lock);
281 278
282 trace_bts_cpu(hw_branch_trace); 279 trace_bts_cpu(hw_branch_trace);
283 280
284 mutex_unlock(&bts_tracer_mutex); 281 spin_unlock(&bts_tracer_lock);
285} 282}
286 283
287struct tracer bts_tracer __read_mostly = 284struct tracer bts_tracer __read_mostly =
@@ -299,6 +296,7 @@ struct tracer bts_tracer __read_mostly =
299 296
300__init static int init_bts_trace(void) 297__init static int init_bts_trace(void)
301{ 298{
299 register_hotcpu_notifier(&bts_hotcpu_notifier);
302 return register_tracer(&bts_tracer); 300 return register_tracer(&bts_tracer);
303} 301}
304device_initcall(init_bts_trace); 302device_initcall(init_bts_trace);