2442 lines · 60.9 KB · C
RawDownload
// SPDX-License-Identifier: GPL-2.0/* * drivers/base/power/main.c - Where the driver meets power management. * * Copyright (c) 2003 Patrick Mochel * Copyright (c) 2003 Open Source Development Lab * * The driver model core calls device_pm_add() when a device is registered. * This will initialize the embedded device_pm_info object in the device * and add it to the list of power-controlled devices. sysfs entries for * controlling device power management will also be added. * * A separate list is used for keeping track of power info, because the power * domain dependencies may differ from the ancestral dependencies that the * subsystem list maintains. */ #define pr_fmt(fmt) "PM: " fmt#define dev_fmt pr_fmt #include <linux/device.h>#include <linux/export.h>#include <linux/mutex.h>#include <linux/pm.h>#include <linux/pm_runtime.h>#include <linux/pm-trace.h>#include <linux/pm_wakeirq.h>#include <linux/interrupt.h>#include <linux/sched.h>#include <linux/sched/debug.h>#include <linux/sysctl.h>#include <linux/async.h>#include <linux/suspend.h>#include <trace/events/power.h>#include <linux/cpufreq.h>#include <linux/devfreq.h>#include <linux/thermal.h>#include <linux/timer.h>#include <linux/nmi.h> #include "../base.h"#include "power.h" #undef MODULE_PARAM_PREFIX#define MODULE_PARAM_PREFIX "pm." typedef int (*pm_callback_t)(struct device *); /* * The entries in the dpm_list list are in a depth first order, simply * because children are guaranteed to be discovered after parents, and * are inserted at the back of the list on discovery. * * Since device_pm_add() may be called with a device lock held, * we must never try to acquire a device lock while holding * dpm_list_mutex. */ LIST_HEAD(dpm_list);static LIST_HEAD(dpm_prepared_list);static LIST_HEAD(dpm_suspended_list);static LIST_HEAD(dpm_late_early_list);static LIST_HEAD(dpm_noirq_list); static DEFINE_MUTEX(dpm_list_mtx);static pm_message_t pm_transition; static DEFINE_MUTEX(async_wip_mtx);static int async_error; /** * pm_hibernate_is_recovering - if recovering from hibernate due to error. * * Used to query if dev_pm_ops.thaw() is called for normal hibernation case or * recovering from some error. * * Return: true for error case, false for normal case. */bool pm_hibernate_is_recovering(void){	return pm_transition.event == PM_EVENT_RECOVER;}EXPORT_SYMBOL_GPL(pm_hibernate_is_recovering); static const char *pm_verb(int event){	switch (event) {	case PM_EVENT_SUSPEND:		return "suspend";	case PM_EVENT_RESUME:		return "resume";	case PM_EVENT_FREEZE:		return "freeze";	case PM_EVENT_QUIESCE:		return "quiesce";	case PM_EVENT_HIBERNATE:		return "hibernate";	case PM_EVENT_THAW:		return "thaw";	case PM_EVENT_RESTORE:		return "restore";	case PM_EVENT_RECOVER:		return "recover";	case PM_EVENT_POWEROFF:		return "poweroff";	default:		return "(unknown PM event)";	}} /** * device_pm_sleep_init - Initialize system suspend-related device fields. * @dev: Device object being initialized. */void device_pm_sleep_init(struct device *dev){	dev->power.is_prepared = false;	dev->power.is_suspended = false;	dev->power.is_noirq_suspended = false;	dev->power.is_late_suspended = false;	init_completion(&dev->power.completion);	complete(&dev->power.completion);	dev->power.wakeup = NULL;	INIT_LIST_HEAD(&dev->power.entry);} /** * device_pm_lock - Lock the list of active devices used by the PM core. */void device_pm_lock(void){	mutex_lock(&dpm_list_mtx);} /** * device_pm_unlock - Unlock the list of active devices used by the PM core. */void device_pm_unlock(void){	mutex_unlock(&dpm_list_mtx);} /** * device_pm_add - Add a device to the PM core's list of active devices. * @dev: Device to add to the list. */void device_pm_add(struct device *dev){	/* Skip PM setup/initialization. */	if (device_pm_not_required(dev))		return; 	pr_debug("Adding info for %s:%s\n",		 dev->bus ? dev->bus->name : "No Bus", dev_name(dev));	device_pm_check_callbacks(dev);	mutex_lock(&dpm_list_mtx);	if (dev->parent && dev->parent->power.is_prepared)		dev_warn(dev, "parent %s should not be sleeping\n",			dev_name(dev->parent));	list_add_tail(&dev->power.entry, &dpm_list);	dev->power.in_dpm_list = true;	mutex_unlock(&dpm_list_mtx);} /** * device_pm_remove - Remove a device from the PM core's list of active devices. * @dev: Device to be removed from the list. */void device_pm_remove(struct device *dev){	if (device_pm_not_required(dev))		return; 	pr_debug("Removing info for %s:%s\n",		 dev->bus ? dev->bus->name : "No Bus", dev_name(dev));	complete_all(&dev->power.completion);	mutex_lock(&dpm_list_mtx);	list_del_init(&dev->power.entry);	dev->power.in_dpm_list = false;	mutex_unlock(&dpm_list_mtx);	device_wakeup_disable(dev);	pm_runtime_remove(dev);	device_pm_check_callbacks(dev);} /** * device_pm_move_before - Move device in the PM core's list of active devices. * @deva: Device to move in dpm_list. * @devb: Device @deva should come before. */void device_pm_move_before(struct device *deva, struct device *devb){	pr_debug("Moving %s:%s before %s:%s\n",		 deva->bus ? deva->bus->name : "No Bus", dev_name(deva),		 devb->bus ? devb->bus->name : "No Bus", dev_name(devb));	/* Delete deva from dpm_list and reinsert before devb. */	list_move_tail(&deva->power.entry, &devb->power.entry);} /** * device_pm_move_after - Move device in the PM core's list of active devices. * @deva: Device to move in dpm_list. * @devb: Device @deva should come after. */void device_pm_move_after(struct device *deva, struct device *devb){	pr_debug("Moving %s:%s after %s:%s\n",		 deva->bus ? deva->bus->name : "No Bus", dev_name(deva),		 devb->bus ? devb->bus->name : "No Bus", dev_name(devb));	/* Delete deva from dpm_list and reinsert after devb. */	list_move(&deva->power.entry, &devb->power.entry);} /** * device_pm_move_last - Move device to end of the PM core's list of devices. * @dev: Device to move in dpm_list. */void device_pm_move_last(struct device *dev){	pr_debug("Moving %s:%s to end of list\n",		 dev->bus ? dev->bus->name : "No Bus", dev_name(dev));	list_move_tail(&dev->power.entry, &dpm_list);} static ktime_t initcall_debug_start(struct device *dev, void *cb){	if (!pm_print_times_enabled)		return 0; 	dev_info(dev, "calling %ps @ %i, parent: %s\n", cb,		 task_pid_nr(current),		 dev->parent ? dev_name(dev->parent) : "none");	return ktime_get();} static void initcall_debug_report(struct device *dev, ktime_t calltime,				  void *cb, int error){	ktime_t rettime; 	if (!pm_print_times_enabled)		return; 	rettime = ktime_get();	dev_info(dev, "%ps returned %d after %Ld usecs\n", cb, error,		 (unsigned long long)ktime_us_delta(rettime, calltime));} /** * dpm_wait - Wait for a PM operation to complete. * @dev: Device to wait for. * @async: If unset, wait only if the device's power.async_suspend flag is set. */static void dpm_wait(struct device *dev, bool async){	if (!dev)		return; 	/* Devices with no PM support don't use the completion. */	if (dev->power.no_pm)		return; 	if (async || (pm_async_enabled && dev->power.async_suspend))		wait_for_completion(&dev->power.completion);} static int dpm_wait_fn(struct device *dev, void *async_ptr){	dpm_wait(dev, *((bool *)async_ptr));	return 0;} static void dpm_wait_for_children(struct device *dev, bool async){	device_for_each_child(dev, &async, dpm_wait_fn);} static void dpm_wait_for_suppliers(struct device *dev, bool async){	struct device_link *link;	int idx; 	idx = device_links_read_lock(); 	/*	 * If the supplier goes away right after we've checked the link to it,	 * we'll wait for its completion to change the state, but that's fine,	 * because the only things that will block as a result are the SRCU	 * callbacks freeing the link objects for the links in the list we're	 * walking.	 */	dev_for_each_link_to_supplier(link, dev)		if (READ_ONCE(link->status) != DL_STATE_DORMANT &&		    !device_link_flag_is_sync_state_only(link->flags))			dpm_wait(link->supplier, async); 	device_links_read_unlock(idx);} static bool dpm_wait_for_superior(struct device *dev, bool async){	struct device *parent; 	/*	 * If the device is resumed asynchronously and the parent's callback	 * deletes both the device and the parent itself, the parent object may	 * be freed while this function is running, so avoid that by reference	 * counting the parent once more unless the device has been deleted	 * already (in which case return right away).	 */	mutex_lock(&dpm_list_mtx); 	if (!device_pm_initialized(dev)) {		mutex_unlock(&dpm_list_mtx);		return false;	} 	parent = get_device(dev->parent); 	mutex_unlock(&dpm_list_mtx); 	dpm_wait(parent, async);	put_device(parent); 	dpm_wait_for_suppliers(dev, async); 	/*	 * If the parent's callback has deleted the device, attempting to resume	 * it would be invalid, so avoid doing that then.	 */	return device_pm_initialized(dev);} static void dpm_wait_for_consumers(struct device *dev, bool async){	struct device_link *link;	int idx; 	idx = device_links_read_lock(); 	/*	 * The status of a device link can only be changed from "dormant" by a	 * probe, but that cannot happen during system suspend/resume.  In	 * theory it can change to "dormant" at that time, but then it is	 * reasonable to wait for the target device anyway (eg. if it goes	 * away, it's better to wait for it to go away completely and then	 * continue instead of trying to continue in parallel with its	 * unregistration).	 */	dev_for_each_link_to_consumer(link, dev)		if (READ_ONCE(link->status) != DL_STATE_DORMANT &&		    !device_link_flag_is_sync_state_only(link->flags))			dpm_wait(link->consumer, async); 	device_links_read_unlock(idx);} static void dpm_wait_for_subordinate(struct device *dev, bool async){	dpm_wait_for_children(dev, async);	dpm_wait_for_consumers(dev, async);} /** * pm_op - Return the PM operation appropriate for given PM event. * @ops: PM operations to choose from. * @state: PM transition of the system being carried out. */static pm_callback_t pm_op(const struct dev_pm_ops *ops, pm_message_t state){	switch (state.event) {#ifdef CONFIG_SUSPEND	case PM_EVENT_SUSPEND:		return ops->suspend;	case PM_EVENT_RESUME:		return ops->resume;#endif /* CONFIG_SUSPEND */#ifdef CONFIG_HIBERNATE_CALLBACKS	case PM_EVENT_FREEZE:	case PM_EVENT_QUIESCE:		return ops->freeze;	case PM_EVENT_POWEROFF:	case PM_EVENT_HIBERNATE:		return ops->poweroff;	case PM_EVENT_THAW:	case PM_EVENT_RECOVER:		return ops->thaw;	case PM_EVENT_RESTORE:		return ops->restore;#endif /* CONFIG_HIBERNATE_CALLBACKS */	} 	return NULL;} /** * pm_late_early_op - Return the PM operation appropriate for given PM event. * @ops: PM operations to choose from. * @state: PM transition of the system being carried out. * * Runtime PM is disabled for @dev while this function is being executed. */static pm_callback_t pm_late_early_op(const struct dev_pm_ops *ops,				      pm_message_t state){	switch (state.event) {#ifdef CONFIG_SUSPEND	case PM_EVENT_SUSPEND:		return ops->suspend_late;	case PM_EVENT_RESUME:		return ops->resume_early;#endif /* CONFIG_SUSPEND */#ifdef CONFIG_HIBERNATE_CALLBACKS	case PM_EVENT_FREEZE:	case PM_EVENT_QUIESCE:		return ops->freeze_late;	case PM_EVENT_POWEROFF:	case PM_EVENT_HIBERNATE:		return ops->poweroff_late;	case PM_EVENT_THAW:	case PM_EVENT_RECOVER:		return ops->thaw_early;	case PM_EVENT_RESTORE:		return ops->restore_early;#endif /* CONFIG_HIBERNATE_CALLBACKS */	} 	return NULL;} /** * pm_noirq_op - Return the PM operation appropriate for given PM event. * @ops: PM operations to choose from. * @state: PM transition of the system being carried out. * * The driver of @dev will not receive interrupts while this function is being * executed. */static pm_callback_t pm_noirq_op(const struct dev_pm_ops *ops, pm_message_t state){	switch (state.event) {#ifdef CONFIG_SUSPEND	case PM_EVENT_SUSPEND:		return ops->suspend_noirq;	case PM_EVENT_RESUME:		return ops->resume_noirq;#endif /* CONFIG_SUSPEND */#ifdef CONFIG_HIBERNATE_CALLBACKS	case PM_EVENT_FREEZE:	case PM_EVENT_QUIESCE:		return ops->freeze_noirq;	case PM_EVENT_POWEROFF:	case PM_EVENT_HIBERNATE:		return ops->poweroff_noirq;	case PM_EVENT_THAW:	case PM_EVENT_RECOVER:		return ops->thaw_noirq;	case PM_EVENT_RESTORE:		return ops->restore_noirq;#endif /* CONFIG_HIBERNATE_CALLBACKS */	} 	return NULL;} static void pm_dev_dbg(struct device *dev, pm_message_t state, const char *info){	dev_dbg(dev, "%s%s%s driver flags: %x\n", info, pm_verb(state.event),		((state.event & PM_EVENT_SLEEP) && device_may_wakeup(dev)) ?		", may wakeup" : "", dev->power.driver_flags);} static void pm_dev_err(struct device *dev, pm_message_t state, const char *info,			int error){	dev_err(dev, "failed to %s%s: error %d\n", pm_verb(state.event), info,		error);} static void dpm_show_time(ktime_t starttime, pm_message_t state, int error,			  const char *info){	ktime_t calltime;	u64 usecs64;	int usecs; 	calltime = ktime_get();	usecs64 = ktime_to_ns(ktime_sub(calltime, starttime));	do_div(usecs64, NSEC_PER_USEC);	usecs = usecs64;	if (usecs == 0)		usecs = 1; 	pm_pr_dbg("%s%s%s of devices %s after %ld.%03ld msecs\n",		  info ?: "", info ? " " : "", pm_verb(state.event),		  error ? "aborted" : "complete",		  usecs / USEC_PER_MSEC, usecs % USEC_PER_MSEC);} static int dpm_run_callback(pm_callback_t cb, struct device *dev,

Lines 1–500 of 2442.