suspend.c 11.3 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_end(PMSG_SUSPEND);
269 270
	if (error) {
		printk(KERN_ERR "PM: Some devices failed to power down\n");
271
		goto Platform_finish;
272
	}
273 274 275
	error = platform_suspend_prepare_late(state);
	if (error)
		goto Platform_wake;
276

277 278 279
	if (suspend_test(TEST_PLATFORM))
		goto Platform_wake;

280 281 282 283 284 285 286
	/*
	 * 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) {
287
		trace_suspend_resume(TPS("machine_suspend"), state, true);
288
		freeze_enter();
289
		trace_suspend_resume(TPS("machine_suspend"), state, false);
290 291 292
		goto Platform_wake;
	}

293 294 295 296 297 298 299
	error = disable_nonboot_cpus();
	if (error || suspend_test(TEST_CPUS))
		goto Enable_cpus;

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

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

	arch_suspend_enable_irqs();
	BUG_ON(irqs_disabled());

 Enable_cpus:
	enable_nonboot_cpus();

 Platform_wake:
321
	platform_suspend_wake(state);
322
	dpm_resume_start(PMSG_RESUME);
323

324
 Platform_finish:
325
	platform_suspend_finish(state);
326 327 328 329
	return error;
}

/**
330 331
 * suspend_devices_and_enter - Suspend devices and enter system sleep state.
 * @state: System sleep state to enter.
332 333 334 335
 */
int suspend_devices_and_enter(suspend_state_t state)
{
	int error;
336
	bool wakeup = false;
337

338
	if (!sleep_state_supported(state))
339 340
		return -ENOSYS;

341 342 343 344
	error = platform_suspend_begin(state);
	if (error)
		goto Close;

345 346 347 348
	suspend_console();
	suspend_test_start();
	error = dpm_suspend_start(PMSG_SUSPEND);
	if (error) {
349
		pr_err("PM: Some devices failed to suspend, or early wake event detected\n");
350 351 352 353 354 355
		goto Recover_platform;
	}
	suspend_test_finish("suspend devices");
	if (suspend_test(TEST_DEVICES))
		goto Recover_platform;

356 357
	do {
		error = suspend_enter(state, &wakeup);
358
	} while (!error && !wakeup && platform_suspend_again(state));
359 360 361 362 363 364

 Resume_devices:
	suspend_test_start();
	dpm_resume_end(PMSG_RESUME);
	suspend_test_finish("resume devices");
	resume_console();
365

366 367
 Close:
	platform_suspend_end(state);
368 369 370
	return error;

 Recover_platform:
371
	platform_suspend_recover(state);
372 373 374 375
	goto Resume_devices;
}

/**
376
 * suspend_finish - Clean up before finishing the suspend sequence.
377
 *
378 379
 * Call platform code to clean up, restart processes, and free the console that
 * we've allocated. This routine is not called for hibernation.
380 381 382 383 384 385 386 387 388
 */
static void suspend_finish(void)
{
	suspend_thaw_processes();
	pm_notifier_call_chain(PM_POST_SUSPEND);
	pm_restore_console();
}

/**
389 390
 * enter_state - Do common work needed to enter system sleep state.
 * @state: System sleep state to enter.
391
 *
392 393 394
 * 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.
395
 */
396
static int enter_state(suspend_state_t state)
397 398 399
{
	int error;

400
	trace_suspend_resume(TPS("suspend_enter"), state, true);
401 402 403 404 405 406 407 408 409 410 411
	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;
	}
412 413 414
	if (!mutex_trylock(&pm_mutex))
		return -EBUSY;

415 416 417
	if (state == PM_SUSPEND_FREEZE)
		freeze_begin();

418
	trace_suspend_resume(TPS("sync_filesystems"), 0, true);
419 420 421
	printk(KERN_INFO "PM: Syncing filesystems ... ");
	sys_sync();
	printk("done.\n");
422
	trace_suspend_resume(TPS("sync_filesystems"), 0, false);
423

424
	pr_debug("PM: Preparing system for %s sleep\n", pm_states[state]);
425
	error = suspend_prepare(state);
426 427 428 429 430 431
	if (error)
		goto Unlock;

	if (suspend_test(TEST_FREEZER))
		goto Finish;

432
	trace_suspend_resume(TPS("suspend_enter"), state, false);
433
	pr_debug("PM: Entering %s sleep\n", pm_states[state]);
434
	pm_restrict_gfp_mask();
435
	error = suspend_devices_and_enter(state);
436
	pm_restore_gfp_mask();
437 438 439 440 441 442 443 444 445 446

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

/**
447 448
 * pm_suspend - Externally visible function for suspending the system.
 * @state: System sleep state to enter.
449
 *
450 451
 * Check if the value of @state represents one of the supported states,
 * execute enter_state() and update system suspend statistics.
452 453 454
 */
int pm_suspend(suspend_state_t state)
{
455 456 457 458 459 460 461 462 463 464 465
	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++;
466
	}
467
	return error;
468 469
}
EXPORT_SYMBOL(pm_suspend);