suspend.c 11.6 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
/*
 * kernel/power/suspend.c - Suspend to RAM and standby functionality.
 *
 * Copyright (c) 2003 Patrick Mochel
 * Copyright (c) 2003 Open Source Development Lab
 * Copyright (c) 2009 Rafael J. Wysocki <rjw@sisk.pl>, Novell Inc.
 *
 * This file is released under the GPLv2.
 */

#include <linux/string.h>
#include <linux/delay.h>
#include <linux/errno.h>
#include <linux/init.h>
#include <linux/console.h>
#include <linux/cpu.h>
17
#include <linux/cpuidle.h>
18
#include <linux/syscalls.h>
19
#include <linux/gfp.h>
20 21 22 23 24
#include <linux/io.h>
#include <linux/kernel.h>
#include <linux/list.h>
#include <linux/mm.h>
#include <linux/slab.h>
25
#include <linux/export.h>
26
#include <linux/suspend.h>
27
#include <linux/syscore_ops.h>
28
#include <linux/ftrace.h>
29
#include <trace/events/power.h>
30
#include <linux/compiler.h>
31 32 33

#include "power.h"

34
const char *pm_labels[] = { "mem", "standby", "freeze", NULL };
35
const char *pm_states[PM_SUSPEND_MAX];
36

37
static const struct platform_suspend_ops *suspend_ops;
38
static const struct platform_freeze_ops *freeze_ops;
39 40 41
static DECLARE_WAIT_QUEUE_HEAD(suspend_freeze_wait_head);
static bool suspend_freeze_wake;

42 43 44 45 46 47 48
void freeze_set_ops(const struct platform_freeze_ops *ops)
{
	lock_system_sleep();
	freeze_ops = ops;
	unlock_system_sleep();
}

49 50 51 52 53 54 55
static void freeze_begin(void)
{
	suspend_freeze_wake = false;
}

static void freeze_enter(void)
{
56
	cpuidle_use_deepest_state(true);
57
	cpuidle_resume();
58
	wait_event(suspend_freeze_wait_head, suspend_freeze_wake);
59
	cpuidle_pause();
60
	cpuidle_use_deepest_state(false);
61 62 63 64 65 66 67 68 69
}

void freeze_wake(void)
{
	suspend_freeze_wake = true;
	wake_up(&suspend_freeze_wait_head);
}
EXPORT_SYMBOL_GPL(freeze_wake);

70 71 72 73 74 75 76 77 78 79
static bool valid_state(suspend_state_t state)
{
	/*
	 * PM_SUSPEND_STANDBY and PM_SUSPEND_MEM states need low level
	 * support and need to be valid to the low level
	 * implementation, no valid callback implies that none are valid.
	 */
	return suspend_ops && suspend_ops->valid && suspend_ops->valid(state);
}

80 81 82 83 84 85 86 87 88 89 90
/*
 * If this is set, the "mem" label always corresponds to the deepest sleep state
 * available, the "standby" label corresponds to the second deepest sleep state
 * available (if any), and the "freeze" label corresponds to the remaining
 * available sleep state (if there is one).
 */
static bool relative_states;

static int __init sleep_states_setup(char *str)
{
	relative_states = !strncmp(str, "1", 1);
91
	pm_states[PM_SUSPEND_FREEZE] = pm_labels[relative_states ? 0 : 2];
92 93 94 95 96
	return 1;
}

__setup("relative_sleep_states=", sleep_states_setup);

97
/**
98 99
 * suspend_set_ops - Set the global suspend method table.
 * @ops: Suspend operations to use.
100
 */
101
void suspend_set_ops(const struct platform_suspend_ops *ops)
102
{
103
	suspend_state_t i;
104
	int j = 0;
105

106
	lock_system_sleep();
107

108
	suspend_ops = ops;
109
	for (i = PM_SUSPEND_MEM; i >= PM_SUSPEND_STANDBY; i--)
110 111 112 113 114 115
		if (valid_state(i)) {
			pm_states[i] = pm_labels[j++];
		} else if (!relative_states) {
			pm_states[i] = NULL;
			j++;
		}
116

117
	pm_states[PM_SUSPEND_FREEZE] = pm_labels[j];
118

119
	unlock_system_sleep();
120
}
121
EXPORT_SYMBOL_GPL(suspend_set_ops);
122 123

/**
124
 * suspend_valid_only_mem - Generic memory-only valid callback.
125
 *
126 127 128
 * Platform drivers that implement mem suspend only and only need to check for
 * that in their .valid() callback can use this instead of rolling their own
 * .valid() callback.
129 130 131 132 133
 */
int suspend_valid_only_mem(suspend_state_t state)
{
	return state == PM_SUSPEND_MEM;
}
134
EXPORT_SYMBOL_GPL(suspend_valid_only_mem);
135

136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194
static bool sleep_state_supported(suspend_state_t state)
{
	return state == PM_SUSPEND_FREEZE || (suspend_ops && suspend_ops->enter);
}

static int platform_suspend_prepare(suspend_state_t state)
{
	return state != PM_SUSPEND_FREEZE && suspend_ops->prepare ?
		suspend_ops->prepare() : 0;
}

static int platform_suspend_prepare_late(suspend_state_t state)
{
	return state != PM_SUSPEND_FREEZE && suspend_ops->prepare_late ?
		suspend_ops->prepare_late() : 0;
}

static void platform_suspend_wake(suspend_state_t state)
{
	if (state != PM_SUSPEND_FREEZE && suspend_ops->wake)
		suspend_ops->wake();
}

static void platform_suspend_finish(suspend_state_t state)
{
	if (state != PM_SUSPEND_FREEZE && suspend_ops->finish)
		suspend_ops->finish();
}

static int platform_suspend_begin(suspend_state_t state)
{
	if (state == PM_SUSPEND_FREEZE && freeze_ops && freeze_ops->begin)
		return freeze_ops->begin();
	else if (suspend_ops->begin)
		return suspend_ops->begin(state);
	else
		return 0;
}

static void platform_suspend_end(suspend_state_t state)
{
	if (state == PM_SUSPEND_FREEZE && freeze_ops && freeze_ops->end)
		freeze_ops->end();
	else if (suspend_ops->end)
		suspend_ops->end();
}

static void platform_suspend_recover(suspend_state_t state)
{
	if (state != PM_SUSPEND_FREEZE && suspend_ops->recover)
		suspend_ops->recover();
}

static bool platform_suspend_again(suspend_state_t state)
{
	return state != PM_SUSPEND_FREEZE && suspend_ops->suspend_again ?
		suspend_ops->suspend_again() : false;
}

195 196 197 198 199 200 201 202 203 204 205 206 207
static int suspend_test(int level)
{
#ifdef CONFIG_PM_DEBUG
	if (pm_test_level == level) {
		printk(KERN_INFO "suspend debug: Waiting for 5 seconds.\n");
		mdelay(5000);
		return 1;
	}
#endif /* !CONFIG_PM_DEBUG */
	return 0;
}

/**
208
 * suspend_prepare - Prepare for entering system sleep state.
209
 *
210 211 212
 * Common code run for every system sleep state that can be entered (except for
 * hibernation).  Run suspend notifiers, allocate the "suspend" console and
 * freeze processes.
213
 */
214
static int suspend_prepare(suspend_state_t state)
215 216 217
{
	int error;

218
	if (!sleep_state_supported(state))
219 220 221 222 223 224 225 226
		return -EPERM;

	pm_prepare_console();

	error = pm_notifier_call_chain(PM_SUSPEND_PREPARE);
	if (error)
		goto Finish;

227
	trace_suspend_resume(TPS("freeze_processes"), 0, true);
228
	error = suspend_freeze_processes();
229
	trace_suspend_resume(TPS("freeze_processes"), 0, false);
230
	if (!error)
231 232
		return 0;

233 234
	suspend_stats.failed_freeze++;
	dpm_save_failed_step(SUSPEND_FREEZE);
235 236 237 238 239 240 241
 Finish:
	pm_notifier_call_chain(PM_POST_SUSPEND);
	pm_restore_console();
	return error;
}

/* default implementation */
242
void __weak arch_suspend_disable_irqs(void)
243 244 245 246 247
{
	local_irq_disable();
}

/* default implementation */
248
void __weak arch_suspend_enable_irqs(void)
249 250 251 252 253
{
	local_irq_enable();
}

/**
254 255 256
 * suspend_enter - Make the system enter the given sleep state.
 * @state: System sleep state to enter.
 * @wakeup: Returns information that the sleep state should not be re-entered.
257
 *
258
 * This function should be called after devices have been suspended.
259
 */
260
static int suspend_enter(suspend_state_t state, bool *wakeup)
261 262 263
{
	int error;

264 265 266
	error = platform_suspend_prepare(state);
	if (error)
		goto Platform_finish;
267

268
	error = dpm_suspend_late(PMSG_SUSPEND);
269
	if (error) {
270
		printk(KERN_ERR "PM: late suspend of devices failed\n");
271
		goto Platform_finish;
272
	}
273 274 275 276 277
	error = dpm_suspend_noirq(PMSG_SUSPEND);
	if (error) {
		printk(KERN_ERR "PM: noirq suspend of devices failed\n");
		goto Devices_early_resume;
	}
278 279 280
	error = platform_suspend_prepare_late(state);
	if (error)
		goto Platform_wake;
281

282 283 284
	if (suspend_test(TEST_PLATFORM))
		goto Platform_wake;

285 286 287 288 289 290 291
	/*
	 * PM_SUSPEND_FREEZE equals
	 * frozen processes + suspended devices + idle processors.
	 * Thus we should invoke freeze_enter() soon after
	 * all the devices are suspended.
	 */
	if (state == PM_SUSPEND_FREEZE) {
292
		trace_suspend_resume(TPS("machine_suspend"), state, true);
293
		freeze_enter();
294
		trace_suspend_resume(TPS("machine_suspend"), state, false);
295 296 297
		goto Platform_wake;
	}

298 299 300 301 302 303 304
	error = disable_nonboot_cpus();
	if (error || suspend_test(TEST_CPUS))
		goto Enable_cpus;

	arch_suspend_disable_irqs();
	BUG_ON(!irqs_disabled());

305
	error = syscore_suspend();
306
	if (!error) {
307 308
		*wakeup = pm_wakeup_pending();
		if (!(suspend_test(TEST_CORE) || *wakeup)) {
309 310
			trace_suspend_resume(TPS("machine_suspend"),
				state, true);
311
			error = suspend_ops->enter(state);
312 313
			trace_suspend_resume(TPS("machine_suspend"),
				state, false);
314 315
			events_check_enabled = false;
		}
316
		syscore_resume();
317 318 319 320 321 322 323 324 325
	}

	arch_suspend_enable_irqs();
	BUG_ON(irqs_disabled());

 Enable_cpus:
	enable_nonboot_cpus();

 Platform_wake:
326
	platform_suspend_wake(state);
327 328 329 330
	dpm_resume_noirq(PMSG_RESUME);

 Devices_early_resume:
	dpm_resume_early(PMSG_RESUME);
331

332
 Platform_finish:
333
	platform_suspend_finish(state);
334 335 336 337
	return error;
}

/**
338 339
 * suspend_devices_and_enter - Suspend devices and enter system sleep state.
 * @state: System sleep state to enter.
340 341 342 343
 */
int suspend_devices_and_enter(suspend_state_t state)
{
	int error;
344
	bool wakeup = false;
345

346
	if (!sleep_state_supported(state))
347 348
		return -ENOSYS;

349 350 351 352
	error = platform_suspend_begin(state);
	if (error)
		goto Close;

353 354 355 356
	suspend_console();
	suspend_test_start();
	error = dpm_suspend_start(PMSG_SUSPEND);
	if (error) {
357
		pr_err("PM: Some devices failed to suspend, or early wake event detected\n");
358 359 360 361 362 363
		goto Recover_platform;
	}
	suspend_test_finish("suspend devices");
	if (suspend_test(TEST_DEVICES))
		goto Recover_platform;

364 365
	do {
		error = suspend_enter(state, &wakeup);
366
	} while (!error && !wakeup && platform_suspend_again(state));
367 368 369 370 371

 Resume_devices:
	suspend_test_start();
	dpm_resume_end(PMSG_RESUME);
	suspend_test_finish("resume devices");
372
	trace_suspend_resume(TPS("resume_console"), state, true);
373
	resume_console();
374
	trace_suspend_resume(TPS("resume_console"), state, false);
375

376 377
 Close:
	platform_suspend_end(state);
378 379 380
	return error;

 Recover_platform:
381
	platform_suspend_recover(state);
382 383 384 385
	goto Resume_devices;
}

/**
386
 * suspend_finish - Clean up before finishing the suspend sequence.
387
 *
388 389
 * Call platform code to clean up, restart processes, and free the console that
 * we've allocated. This routine is not called for hibernation.
390 391 392 393 394 395 396 397 398
 */
static void suspend_finish(void)
{
	suspend_thaw_processes();
	pm_notifier_call_chain(PM_POST_SUSPEND);
	pm_restore_console();
}

/**
399 400
 * enter_state - Do common work needed to enter system sleep state.
 * @state: System sleep state to enter.
401
 *
402 403 404
 * Make sure that no one else is trying to put the system into a sleep state.
 * Fail if that's not the case.  Otherwise, prepare for system suspend, make the
 * system enter the given sleep state and clean up after wakeup.
405
 */
406
static int enter_state(suspend_state_t state)
407 408 409
{
	int error;

410
	trace_suspend_resume(TPS("suspend_enter"), state, true);
411 412 413 414 415 416 417 418 419 420 421
	if (state == PM_SUSPEND_FREEZE) {
#ifdef CONFIG_PM_DEBUG
		if (pm_test_level != TEST_NONE && pm_test_level <= TEST_CPUS) {
			pr_warning("PM: Unsupported test mode for freeze state,"
				   "please choose none/freezer/devices/platform.\n");
			return -EAGAIN;
		}
#endif
	} else if (!valid_state(state)) {
		return -EINVAL;
	}
422 423 424
	if (!mutex_trylock(&pm_mutex))
		return -EBUSY;

425 426 427
	if (state == PM_SUSPEND_FREEZE)
		freeze_begin();

428
	trace_suspend_resume(TPS("sync_filesystems"), 0, true);
429 430 431
	printk(KERN_INFO "PM: Syncing filesystems ... ");
	sys_sync();
	printk("done.\n");
432
	trace_suspend_resume(TPS("sync_filesystems"), 0, false);
433

434
	pr_debug("PM: Preparing system for %s sleep\n", pm_states[state]);
435
	error = suspend_prepare(state);
436 437 438 439 440 441
	if (error)
		goto Unlock;

	if (suspend_test(TEST_FREEZER))
		goto Finish;

442
	trace_suspend_resume(TPS("suspend_enter"), state, false);
443
	pr_debug("PM: Entering %s sleep\n", pm_states[state]);
444
	pm_restrict_gfp_mask();
445
	error = suspend_devices_and_enter(state);
446
	pm_restore_gfp_mask();
447 448 449 450 451 452 453 454 455 456

 Finish:
	pr_debug("PM: Finishing wakeup.\n");
	suspend_finish();
 Unlock:
	mutex_unlock(&pm_mutex);
	return error;
}

/**
457 458
 * pm_suspend - Externally visible function for suspending the system.
 * @state: System sleep state to enter.
459
 *
460 461
 * Check if the value of @state represents one of the supported states,
 * execute enter_state() and update system suspend statistics.
462 463 464
 */
int pm_suspend(suspend_state_t state)
{
465 466 467 468 469 470 471 472 473 474 475
	int error;

	if (state <= PM_SUSPEND_ON || state >= PM_SUSPEND_MAX)
		return -EINVAL;

	error = enter_state(state);
	if (error) {
		suspend_stats.fail++;
		dpm_save_failed_errno(error);
	} else {
		suspend_stats.success++;
476
	}
477
	return error;
478 479
}
EXPORT_SYMBOL(pm_suspend);