xref: /openbmc/linux/drivers/base/power/sysfs.c (revision cbecf716ca618fd44feda6bd9a64a8179d031fc5)
15de363b6SGreg Kroah-Hartman // SPDX-License-Identifier: GPL-2.0
25de363b6SGreg Kroah-Hartman /* sysfs entries for device PM */
31da177e4SLinus Torvalds #include <linux/device.h>
4a45aca51SAbhishek Pandit-Subedi #include <linux/kobject.h>
58c65b4a6STim Schmielau #include <linux/string.h>
61b6bc32fSPaul Gortmaker #include <linux/export.h>
785dc0b8aSRafael J. Wysocki #include <linux/pm_qos.h>
853823639SRafael J. Wysocki #include <linux/pm_runtime.h>
92ca3d1ecSStephen Boyd #include <linux/pm_wakeup.h>
1060063497SArun Sharma #include <linux/atomic.h>
118d4b9d1bSArjan van de Ven #include <linux/jiffies.h>
121da177e4SLinus Torvalds #include "power.h"
131da177e4SLinus Torvalds 
140ac85241SDavid Brownell /*
1553823639SRafael J. Wysocki  *	control - Report/change current runtime PM setting of the device
1653823639SRafael J. Wysocki  *
1753823639SRafael J. Wysocki  *	Runtime power management of a device can be blocked with the help of
1853823639SRafael J. Wysocki  *	this attribute.  All devices have one of the following two values for
1953823639SRafael J. Wysocki  *	the power/control file:
2053823639SRafael J. Wysocki  *
2153823639SRafael J. Wysocki  *	 + "auto\n" to allow the device to be power managed at run time;
2253823639SRafael J. Wysocki  *	 + "on\n" to prevent the device from being power managed at run time;
2353823639SRafael J. Wysocki  *
2453823639SRafael J. Wysocki  *	The default for all devices is "auto", which means that devices may be
2553823639SRafael J. Wysocki  *	subject to automatic power management, depending on their drivers.
2653823639SRafael J. Wysocki  *	Changing this attribute to "on" prevents the driver from power managing
2753823639SRafael J. Wysocki  *	the device at run time.  Doing that while the device is suspended causes
2853823639SRafael J. Wysocki  *	it to be woken up.
2953823639SRafael J. Wysocki  *
300ac85241SDavid Brownell  *	wakeup - Report/change current wakeup option for device
310ac85241SDavid Brownell  *
320ac85241SDavid Brownell  *	Some devices support "wakeup" events, which are hardware signals
330ac85241SDavid Brownell  *	used to activate devices from suspended or low power states.  Such
340ac85241SDavid Brownell  *	devices have one of three values for the sysfs power/wakeup file:
350ac85241SDavid Brownell  *
360ac85241SDavid Brownell  *	 + "enabled\n" to issue the events;
370ac85241SDavid Brownell  *	 + "disabled\n" not to do so; or
380ac85241SDavid Brownell  *	 + "\n" for temporary or permanent inability to issue wakeup.
390ac85241SDavid Brownell  *
400ac85241SDavid Brownell  *	(For example, unconfigured USB devices can't issue wakeups.)
410ac85241SDavid Brownell  *
420ac85241SDavid Brownell  *	Familiar examples of devices that can issue wakeup events include
430ac85241SDavid Brownell  *	keyboards and mice (both PS2 and USB styles), power buttons, modems,
440ac85241SDavid Brownell  *	"Wake-On-LAN" Ethernet links, GPIO lines, and more.  Some events
450ac85241SDavid Brownell  *	will wake the entire system from a suspend state; others may just
460ac85241SDavid Brownell  *	wake up the device (if the system as a whole is already active).
470ac85241SDavid Brownell  *	Some wakeup events use normal IRQ lines; other use special out
480ac85241SDavid Brownell  *	of band signaling.
490ac85241SDavid Brownell  *
500ac85241SDavid Brownell  *	It is the responsibility of device drivers to enable (or disable)
510ac85241SDavid Brownell  *	wakeup signaling as part of changing device power states, respecting
520ac85241SDavid Brownell  *	the policy choices provided through the driver model.
530ac85241SDavid Brownell  *
540ac85241SDavid Brownell  *	Devices may not be able to generate wakeup events from all power
550ac85241SDavid Brownell  *	states.  Also, the events may be ignored in some configurations;
560ac85241SDavid Brownell  *	for example, they might need help from other devices that aren't
570ac85241SDavid Brownell  *	active, or which may have wakeup disabled.  Some drivers rely on
580ac85241SDavid Brownell  *	wakeup events internally (unless they are disabled), keeping
590ac85241SDavid Brownell  *	their hardware in low power modes whenever they're unused.  This
600ac85241SDavid Brownell  *	saves runtime power, without requiring system-wide sleep states.
615a2eb858SRafael J. Wysocki  *
625a2eb858SRafael J. Wysocki  *	async - Report/change current async suspend setting for the device
635a2eb858SRafael J. Wysocki  *
645a2eb858SRafael J. Wysocki  *	Asynchronous suspend and resume of the device during system-wide power
655a2eb858SRafael J. Wysocki  *	state transitions can be enabled by writing "enabled" to this file.
665a2eb858SRafael J. Wysocki  *	Analogously, if "disabled" is written to this file, the device will be
675a2eb858SRafael J. Wysocki  *	suspended and resumed synchronously.
685a2eb858SRafael J. Wysocki  *
695a2eb858SRafael J. Wysocki  *	All devices have one of the following two values for power/async:
705a2eb858SRafael J. Wysocki  *
715a2eb858SRafael J. Wysocki  *	 + "enabled\n" to permit the asynchronous suspend/resume of the device;
725a2eb858SRafael J. Wysocki  *	 + "disabled\n" to forbid it;
735a2eb858SRafael J. Wysocki  *
745a2eb858SRafael J. Wysocki  *	NOTE: It generally is unsafe to permit the asynchronous suspend/resume
755a2eb858SRafael J. Wysocki  *	of a device unless it is certain that all of the PM dependencies of the
765a2eb858SRafael J. Wysocki  *	device are known to the PM core.  However, for some devices this
775a2eb858SRafael J. Wysocki  *	attribute is set to "enabled" by bus type code or device drivers and in
785a2eb858SRafael J. Wysocki  *	that cases it should be safe to leave the default value.
79c125e96fSRafael J. Wysocki  *
8015bcb91dSAlan Stern  *	autosuspend_delay_ms - Report/change a device's autosuspend_delay value
8115bcb91dSAlan Stern  *
8215bcb91dSAlan Stern  *	Some drivers don't want to carry out a runtime suspend as soon as a
8315bcb91dSAlan Stern  *	device becomes idle; they want it always to remain idle for some period
8415bcb91dSAlan Stern  *	of time before suspending it.  This period is the autosuspend_delay
8515bcb91dSAlan Stern  *	value (expressed in milliseconds) and it can be controlled by the user.
8615bcb91dSAlan Stern  *	If the value is negative then the device will never be runtime
8715bcb91dSAlan Stern  *	suspended.
8815bcb91dSAlan Stern  *
8915bcb91dSAlan Stern  *	NOTE: The autosuspend_delay_ms attribute and the autosuspend_delay
9015bcb91dSAlan Stern  *	value are used only if the driver calls pm_runtime_use_autosuspend().
9115bcb91dSAlan Stern  *
92c125e96fSRafael J. Wysocki  *	wakeup_count - Report the number of wakeup events related to the device
930ac85241SDavid Brownell  */
940ac85241SDavid Brownell 
957490e442SAlan Stern const char power_group_name[] = "power";
967490e442SAlan Stern EXPORT_SYMBOL_GPL(power_group_name);
977490e442SAlan Stern 
9853823639SRafael J. Wysocki static const char ctrl_auto[] = "auto";
9953823639SRafael J. Wysocki static const char ctrl_on[] = "on";
10053823639SRafael J. Wysocki 
control_show(struct device * dev,struct device_attribute * attr,char * buf)10153823639SRafael J. Wysocki static ssize_t control_show(struct device *dev, struct device_attribute *attr,
10253823639SRafael J. Wysocki 			    char *buf)
10353823639SRafael J. Wysocki {
104aa838896SJoe Perches 	return sysfs_emit(buf, "%s\n",
10553823639SRafael J. Wysocki 			  dev->power.runtime_auto ? ctrl_auto : ctrl_on);
10653823639SRafael J. Wysocki }
10753823639SRafael J. Wysocki 
control_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t n)10853823639SRafael J. Wysocki static ssize_t control_store(struct device * dev, struct device_attribute *attr,
10953823639SRafael J. Wysocki 			     const char * buf, size_t n)
11053823639SRafael J. Wysocki {
11169c843b4SAlan Stern 	device_lock(dev);
112325c4b3bSAndy Shevchenko 	if (sysfs_streq(buf, ctrl_auto))
11353823639SRafael J. Wysocki 		pm_runtime_allow(dev);
114325c4b3bSAndy Shevchenko 	else if (sysfs_streq(buf, ctrl_on))
11553823639SRafael J. Wysocki 		pm_runtime_forbid(dev);
11653823639SRafael J. Wysocki 	else
11769c843b4SAlan Stern 		n = -EINVAL;
11869c843b4SAlan Stern 	device_unlock(dev);
11953823639SRafael J. Wysocki 	return n;
12053823639SRafael J. Wysocki }
12153823639SRafael J. Wysocki 
12247acbd77SAndy Shevchenko static DEVICE_ATTR_RW(control);
1230fcb4eefSAlan Stern 
runtime_active_time_show(struct device * dev,struct device_attribute * attr,char * buf)12447acbd77SAndy Shevchenko static ssize_t runtime_active_time_show(struct device *dev,
125*948b3edbSJoe Perches 					struct device_attribute *attr,
126*948b3edbSJoe Perches 					char *buf)
1278d4b9d1bSArjan van de Ven {
1280996584bSUlf Hansson 	u64 tmp = pm_runtime_active_time(dev);
129*948b3edbSJoe Perches 
130a08c2a5aSThara Gopinath 	do_div(tmp, NSEC_PER_MSEC);
131*948b3edbSJoe Perches 
132*948b3edbSJoe Perches 	return sysfs_emit(buf, "%llu\n", tmp);
1338d4b9d1bSArjan van de Ven }
1348d4b9d1bSArjan van de Ven 
13547acbd77SAndy Shevchenko static DEVICE_ATTR_RO(runtime_active_time);
1368d4b9d1bSArjan van de Ven 
runtime_suspended_time_show(struct device * dev,struct device_attribute * attr,char * buf)13747acbd77SAndy Shevchenko static ssize_t runtime_suspended_time_show(struct device *dev,
138*948b3edbSJoe Perches 					   struct device_attribute *attr,
139*948b3edbSJoe Perches 					   char *buf)
1408d4b9d1bSArjan van de Ven {
1410996584bSUlf Hansson 	u64 tmp = pm_runtime_suspended_time(dev);
142*948b3edbSJoe Perches 
143a08c2a5aSThara Gopinath 	do_div(tmp, NSEC_PER_MSEC);
144*948b3edbSJoe Perches 
145*948b3edbSJoe Perches 	return sysfs_emit(buf, "%llu\n", tmp);
1468d4b9d1bSArjan van de Ven }
1478d4b9d1bSArjan van de Ven 
14847acbd77SAndy Shevchenko static DEVICE_ATTR_RO(runtime_suspended_time);
1498d4b9d1bSArjan van de Ven 
runtime_status_show(struct device * dev,struct device_attribute * attr,char * buf)15047acbd77SAndy Shevchenko static ssize_t runtime_status_show(struct device *dev,
1510fcb4eefSAlan Stern 				   struct device_attribute *attr, char *buf)
1520fcb4eefSAlan Stern {
153*948b3edbSJoe Perches 	const char *output;
1540fcb4eefSAlan Stern 
1550fcb4eefSAlan Stern 	if (dev->power.runtime_error) {
156*948b3edbSJoe Perches 		output = "error";
1570fcb4eefSAlan Stern 	} else if (dev->power.disable_depth) {
158*948b3edbSJoe Perches 		output = "unsupported";
1590fcb4eefSAlan Stern 	} else {
1600fcb4eefSAlan Stern 		switch (dev->power.runtime_status) {
1610fcb4eefSAlan Stern 		case RPM_SUSPENDED:
162*948b3edbSJoe Perches 			output = "suspended";
1630fcb4eefSAlan Stern 			break;
1640fcb4eefSAlan Stern 		case RPM_SUSPENDING:
165*948b3edbSJoe Perches 			output = "suspending";
1660fcb4eefSAlan Stern 			break;
1670fcb4eefSAlan Stern 		case RPM_RESUMING:
168*948b3edbSJoe Perches 			output = "resuming";
1690fcb4eefSAlan Stern 			break;
1700fcb4eefSAlan Stern 		case RPM_ACTIVE:
171*948b3edbSJoe Perches 			output = "active";
1720fcb4eefSAlan Stern 			break;
1730fcb4eefSAlan Stern 		default:
1740fcb4eefSAlan Stern 			return -EIO;
1750fcb4eefSAlan Stern 		}
1760fcb4eefSAlan Stern 	}
177*948b3edbSJoe Perches 	return sysfs_emit(buf, "%s\n", output);
1780fcb4eefSAlan Stern }
1790fcb4eefSAlan Stern 
18047acbd77SAndy Shevchenko static DEVICE_ATTR_RO(runtime_status);
18115bcb91dSAlan Stern 
autosuspend_delay_ms_show(struct device * dev,struct device_attribute * attr,char * buf)18215bcb91dSAlan Stern static ssize_t autosuspend_delay_ms_show(struct device *dev,
183*948b3edbSJoe Perches 					 struct device_attribute *attr,
184*948b3edbSJoe Perches 					 char *buf)
18515bcb91dSAlan Stern {
18615bcb91dSAlan Stern 	if (!dev->power.use_autosuspend)
18715bcb91dSAlan Stern 		return -EIO;
188*948b3edbSJoe Perches 
189aa838896SJoe Perches 	return sysfs_emit(buf, "%d\n", dev->power.autosuspend_delay);
19015bcb91dSAlan Stern }
19115bcb91dSAlan Stern 
autosuspend_delay_ms_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t n)19215bcb91dSAlan Stern static ssize_t autosuspend_delay_ms_store(struct device *dev,
19315bcb91dSAlan Stern 		struct device_attribute *attr, const char *buf, size_t n)
19415bcb91dSAlan Stern {
19515bcb91dSAlan Stern 	long delay;
19615bcb91dSAlan Stern 
19715bcb91dSAlan Stern 	if (!dev->power.use_autosuspend)
19815bcb91dSAlan Stern 		return -EIO;
19915bcb91dSAlan Stern 
20034da5e67SJingoo Han 	if (kstrtol(buf, 10, &delay) != 0 || delay != (int) delay)
20115bcb91dSAlan Stern 		return -EINVAL;
20215bcb91dSAlan Stern 
20369c843b4SAlan Stern 	device_lock(dev);
20415bcb91dSAlan Stern 	pm_runtime_set_autosuspend_delay(dev, delay);
20569c843b4SAlan Stern 	device_unlock(dev);
20615bcb91dSAlan Stern 	return n;
20715bcb91dSAlan Stern }
20815bcb91dSAlan Stern 
20947acbd77SAndy Shevchenko static DEVICE_ATTR_RW(autosuspend_delay_ms);
21015bcb91dSAlan Stern 
pm_qos_resume_latency_us_show(struct device * dev,struct device_attribute * attr,char * buf)21147acbd77SAndy Shevchenko static ssize_t pm_qos_resume_latency_us_show(struct device *dev,
212b02f6695SRafael J. Wysocki 					     struct device_attribute *attr,
213b02f6695SRafael J. Wysocki 					     char *buf)
21485dc0b8aSRafael J. Wysocki {
2150759e80bSRafael J. Wysocki 	s32 value = dev_pm_qos_requested_resume_latency(dev);
2160759e80bSRafael J. Wysocki 
2170759e80bSRafael J. Wysocki 	if (value == 0)
218aa838896SJoe Perches 		return sysfs_emit(buf, "n/a\n");
219f0e6d9f1SAndy Shevchenko 	if (value == PM_QOS_RESUME_LATENCY_NO_CONSTRAINT)
2200759e80bSRafael J. Wysocki 		value = 0;
2210759e80bSRafael J. Wysocki 
222aa838896SJoe Perches 	return sysfs_emit(buf, "%d\n", value);
22385dc0b8aSRafael J. Wysocki }
22485dc0b8aSRafael J. Wysocki 
pm_qos_resume_latency_us_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t n)22547acbd77SAndy Shevchenko static ssize_t pm_qos_resume_latency_us_store(struct device *dev,
22685dc0b8aSRafael J. Wysocki 					      struct device_attribute *attr,
22785dc0b8aSRafael J. Wysocki 					      const char *buf, size_t n)
22885dc0b8aSRafael J. Wysocki {
22985dc0b8aSRafael J. Wysocki 	s32 value;
23085dc0b8aSRafael J. Wysocki 	int ret;
23185dc0b8aSRafael J. Wysocki 
2320759e80bSRafael J. Wysocki 	if (!kstrtos32(buf, 0, &value)) {
2330759e80bSRafael J. Wysocki 		/*
2340759e80bSRafael J. Wysocki 		 * Prevent users from writing negative or "no constraint" values
2350759e80bSRafael J. Wysocki 		 * directly.
2360759e80bSRafael J. Wysocki 		 */
2370759e80bSRafael J. Wysocki 		if (value < 0 || value == PM_QOS_RESUME_LATENCY_NO_CONSTRAINT)
23885dc0b8aSRafael J. Wysocki 			return -EINVAL;
23985dc0b8aSRafael J. Wysocki 
2400759e80bSRafael J. Wysocki 		if (value == 0)
2410759e80bSRafael J. Wysocki 			value = PM_QOS_RESUME_LATENCY_NO_CONSTRAINT;
242325c4b3bSAndy Shevchenko 	} else if (sysfs_streq(buf, "n/a")) {
2430759e80bSRafael J. Wysocki 		value = 0;
2440759e80bSRafael J. Wysocki 	} else {
24585dc0b8aSRafael J. Wysocki 		return -EINVAL;
2460759e80bSRafael J. Wysocki 	}
24785dc0b8aSRafael J. Wysocki 
248b02f6695SRafael J. Wysocki 	ret = dev_pm_qos_update_request(dev->power.qos->resume_latency_req,
249b02f6695SRafael J. Wysocki 					value);
25085dc0b8aSRafael J. Wysocki 	return ret < 0 ? ret : n;
25185dc0b8aSRafael J. Wysocki }
25285dc0b8aSRafael J. Wysocki 
25347acbd77SAndy Shevchenko static DEVICE_ATTR_RW(pm_qos_resume_latency_us);
254e39473d0SRafael J. Wysocki 
pm_qos_latency_tolerance_us_show(struct device * dev,struct device_attribute * attr,char * buf)25547acbd77SAndy Shevchenko static ssize_t pm_qos_latency_tolerance_us_show(struct device *dev,
2562d984ad1SRafael J. Wysocki 						struct device_attribute *attr,
2572d984ad1SRafael J. Wysocki 						char *buf)
2582d984ad1SRafael J. Wysocki {
2592d984ad1SRafael J. Wysocki 	s32 value = dev_pm_qos_get_user_latency_tolerance(dev);
2602d984ad1SRafael J. Wysocki 
2612d984ad1SRafael J. Wysocki 	if (value < 0)
262973c3911SJoe Perches 		return sysfs_emit(buf, "%s\n", "auto");
263f0e6d9f1SAndy Shevchenko 	if (value == PM_QOS_LATENCY_ANY)
264973c3911SJoe Perches 		return sysfs_emit(buf, "%s\n", "any");
2652d984ad1SRafael J. Wysocki 
266aa838896SJoe Perches 	return sysfs_emit(buf, "%d\n", value);
2672d984ad1SRafael J. Wysocki }
2682d984ad1SRafael J. Wysocki 
pm_qos_latency_tolerance_us_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t n)26947acbd77SAndy Shevchenko static ssize_t pm_qos_latency_tolerance_us_store(struct device *dev,
2702d984ad1SRafael J. Wysocki 						 struct device_attribute *attr,
2712d984ad1SRafael J. Wysocki 						 const char *buf, size_t n)
2722d984ad1SRafael J. Wysocki {
2732d984ad1SRafael J. Wysocki 	s32 value;
2742d984ad1SRafael J. Wysocki 	int ret;
2752d984ad1SRafael J. Wysocki 
276ee061da8SAndrew Lutomirski 	if (kstrtos32(buf, 0, &value) == 0) {
277ee061da8SAndrew Lutomirski 		/* Users can't write negative values directly */
278ee061da8SAndrew Lutomirski 		if (value < 0)
279ee061da8SAndrew Lutomirski 			return -EINVAL;
280ee061da8SAndrew Lutomirski 	} else {
281325c4b3bSAndy Shevchenko 		if (sysfs_streq(buf, "auto"))
2822d984ad1SRafael J. Wysocki 			value = PM_QOS_LATENCY_TOLERANCE_NO_CONSTRAINT;
283325c4b3bSAndy Shevchenko 		else if (sysfs_streq(buf, "any"))
2842d984ad1SRafael J. Wysocki 			value = PM_QOS_LATENCY_ANY;
2852ca30331SDan Carpenter 		else
2862ca30331SDan Carpenter 			return -EINVAL;
2872d984ad1SRafael J. Wysocki 	}
2882d984ad1SRafael J. Wysocki 	ret = dev_pm_qos_update_user_latency_tolerance(dev, value);
2892d984ad1SRafael J. Wysocki 	return ret < 0 ? ret : n;
2902d984ad1SRafael J. Wysocki }
2912d984ad1SRafael J. Wysocki 
29247acbd77SAndy Shevchenko static DEVICE_ATTR_RW(pm_qos_latency_tolerance_us);
2932d984ad1SRafael J. Wysocki 
pm_qos_no_power_off_show(struct device * dev,struct device_attribute * attr,char * buf)294e39473d0SRafael J. Wysocki static ssize_t pm_qos_no_power_off_show(struct device *dev,
295e39473d0SRafael J. Wysocki 					struct device_attribute *attr,
296e39473d0SRafael J. Wysocki 					char *buf)
297e39473d0SRafael J. Wysocki {
298aa838896SJoe Perches 	return sysfs_emit(buf, "%d\n", !!(dev_pm_qos_requested_flags(dev)
299e39473d0SRafael J. Wysocki 					  & PM_QOS_FLAG_NO_POWER_OFF));
300e39473d0SRafael J. Wysocki }
301e39473d0SRafael J. Wysocki 
pm_qos_no_power_off_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t n)302e39473d0SRafael J. Wysocki static ssize_t pm_qos_no_power_off_store(struct device *dev,
303e39473d0SRafael J. Wysocki 					 struct device_attribute *attr,
304e39473d0SRafael J. Wysocki 					 const char *buf, size_t n)
305e39473d0SRafael J. Wysocki {
306e39473d0SRafael J. Wysocki 	int ret;
307e39473d0SRafael J. Wysocki 
308e39473d0SRafael J. Wysocki 	if (kstrtoint(buf, 0, &ret))
309e39473d0SRafael J. Wysocki 		return -EINVAL;
310e39473d0SRafael J. Wysocki 
311e39473d0SRafael J. Wysocki 	if (ret != 0 && ret != 1)
312e39473d0SRafael J. Wysocki 		return -EINVAL;
313e39473d0SRafael J. Wysocki 
314e39473d0SRafael J. Wysocki 	ret = dev_pm_qos_update_flags(dev, PM_QOS_FLAG_NO_POWER_OFF, ret);
315e39473d0SRafael J. Wysocki 	return ret < 0 ? ret : n;
316e39473d0SRafael J. Wysocki }
317e39473d0SRafael J. Wysocki 
31847acbd77SAndy Shevchenko static DEVICE_ATTR_RW(pm_qos_no_power_off);
319e39473d0SRafael J. Wysocki 
320e762318bSRafael J. Wysocki #ifdef CONFIG_PM_SLEEP
3212b4f4313SJohannes Berg static const char _enabled[] = "enabled";
3222b4f4313SJohannes Berg static const char _disabled[] = "disabled";
3232b4f4313SJohannes Berg 
wakeup_show(struct device * dev,struct device_attribute * attr,char * buf)32447acbd77SAndy Shevchenko static ssize_t wakeup_show(struct device *dev, struct device_attribute *attr,
32547acbd77SAndy Shevchenko 			   char *buf)
3260ac85241SDavid Brownell {
327aa838896SJoe Perches 	return sysfs_emit(buf, "%s\n", device_can_wakeup(dev)
3282b4f4313SJohannes Berg 			  ? (device_may_wakeup(dev) ? _enabled : _disabled)
3290ac85241SDavid Brownell 			  : "");
3300ac85241SDavid Brownell }
3310ac85241SDavid Brownell 
wakeup_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t n)33247acbd77SAndy Shevchenko static ssize_t wakeup_store(struct device *dev, struct device_attribute *attr,
3330ac85241SDavid Brownell 			    const char *buf, size_t n)
3340ac85241SDavid Brownell {
3350ac85241SDavid Brownell 	if (!device_can_wakeup(dev))
3360ac85241SDavid Brownell 		return -EINVAL;
3370ac85241SDavid Brownell 
338325c4b3bSAndy Shevchenko 	if (sysfs_streq(buf, _enabled))
3390ac85241SDavid Brownell 		device_set_wakeup_enable(dev, 1);
340325c4b3bSAndy Shevchenko 	else if (sysfs_streq(buf, _disabled))
3410ac85241SDavid Brownell 		device_set_wakeup_enable(dev, 0);
3420ac85241SDavid Brownell 	else
3430ac85241SDavid Brownell 		return -EINVAL;
3440ac85241SDavid Brownell 	return n;
3450ac85241SDavid Brownell }
3460ac85241SDavid Brownell 
34747acbd77SAndy Shevchenko static DEVICE_ATTR_RW(wakeup);
3480ac85241SDavid Brownell 
wakeup_count_show(struct device * dev,struct device_attribute * attr,char * buf)349c125e96fSRafael J. Wysocki static ssize_t wakeup_count_show(struct device *dev,
350c125e96fSRafael J. Wysocki 				 struct device_attribute *attr, char *buf)
351c125e96fSRafael J. Wysocki {
352*948b3edbSJoe Perches 	unsigned long count;
353074037ecSRafael J. Wysocki 	bool enabled = false;
354074037ecSRafael J. Wysocki 
355074037ecSRafael J. Wysocki 	spin_lock_irq(&dev->power.lock);
356074037ecSRafael J. Wysocki 	if (dev->power.wakeup) {
3572d5ed61cSRavi Chandra Sadineni 		count = dev->power.wakeup->wakeup_count;
358074037ecSRafael J. Wysocki 		enabled = true;
359074037ecSRafael J. Wysocki 	}
360074037ecSRafael J. Wysocki 	spin_unlock_irq(&dev->power.lock);
361*948b3edbSJoe Perches 
362*948b3edbSJoe Perches 	if (!enabled)
363*948b3edbSJoe Perches 		return sysfs_emit(buf, "\n");
364*948b3edbSJoe Perches 	return sysfs_emit(buf, "%lu\n", count);
365c125e96fSRafael J. Wysocki }
366c125e96fSRafael J. Wysocki 
36747acbd77SAndy Shevchenko static DEVICE_ATTR_RO(wakeup_count);
368074037ecSRafael J. Wysocki 
wakeup_active_count_show(struct device * dev,struct device_attribute * attr,char * buf)369074037ecSRafael J. Wysocki static ssize_t wakeup_active_count_show(struct device *dev,
37047acbd77SAndy Shevchenko 					struct device_attribute *attr,
37147acbd77SAndy Shevchenko 					char *buf)
372074037ecSRafael J. Wysocki {
373*948b3edbSJoe Perches 	unsigned long count;
374074037ecSRafael J. Wysocki 	bool enabled = false;
375074037ecSRafael J. Wysocki 
376074037ecSRafael J. Wysocki 	spin_lock_irq(&dev->power.lock);
377074037ecSRafael J. Wysocki 	if (dev->power.wakeup) {
378074037ecSRafael J. Wysocki 		count = dev->power.wakeup->active_count;
379074037ecSRafael J. Wysocki 		enabled = true;
380074037ecSRafael J. Wysocki 	}
381074037ecSRafael J. Wysocki 	spin_unlock_irq(&dev->power.lock);
382*948b3edbSJoe Perches 
383*948b3edbSJoe Perches 	if (!enabled)
384*948b3edbSJoe Perches 		return sysfs_emit(buf, "\n");
385*948b3edbSJoe Perches 	return sysfs_emit(buf, "%lu\n", count);
386074037ecSRafael J. Wysocki }
387074037ecSRafael J. Wysocki 
38847acbd77SAndy Shevchenko static DEVICE_ATTR_RO(wakeup_active_count);
389074037ecSRafael J. Wysocki 
wakeup_abort_count_show(struct device * dev,struct device_attribute * attr,char * buf)39030e3ce6dSRafael J. Wysocki static ssize_t wakeup_abort_count_show(struct device *dev,
39130e3ce6dSRafael J. Wysocki 				       struct device_attribute *attr,
39230e3ce6dSRafael J. Wysocki 				       char *buf)
393074037ecSRafael J. Wysocki {
394*948b3edbSJoe Perches 	unsigned long count;
395074037ecSRafael J. Wysocki 	bool enabled = false;
396074037ecSRafael J. Wysocki 
397074037ecSRafael J. Wysocki 	spin_lock_irq(&dev->power.lock);
398074037ecSRafael J. Wysocki 	if (dev->power.wakeup) {
39930e3ce6dSRafael J. Wysocki 		count = dev->power.wakeup->wakeup_count;
400074037ecSRafael J. Wysocki 		enabled = true;
401074037ecSRafael J. Wysocki 	}
402074037ecSRafael J. Wysocki 	spin_unlock_irq(&dev->power.lock);
403*948b3edbSJoe Perches 
404*948b3edbSJoe Perches 	if (!enabled)
405*948b3edbSJoe Perches 		return sysfs_emit(buf, "\n");
406*948b3edbSJoe Perches 	return sysfs_emit(buf, "%lu\n", count);
407074037ecSRafael J. Wysocki }
408074037ecSRafael J. Wysocki 
40947acbd77SAndy Shevchenko static DEVICE_ATTR_RO(wakeup_abort_count);
41030e3ce6dSRafael J. Wysocki 
wakeup_expire_count_show(struct device * dev,struct device_attribute * attr,char * buf)41130e3ce6dSRafael J. Wysocki static ssize_t wakeup_expire_count_show(struct device *dev,
41230e3ce6dSRafael J. Wysocki 					struct device_attribute *attr,
41330e3ce6dSRafael J. Wysocki 					char *buf)
41430e3ce6dSRafael J. Wysocki {
415*948b3edbSJoe Perches 	unsigned long count;
41630e3ce6dSRafael J. Wysocki 	bool enabled = false;
41730e3ce6dSRafael J. Wysocki 
41830e3ce6dSRafael J. Wysocki 	spin_lock_irq(&dev->power.lock);
41930e3ce6dSRafael J. Wysocki 	if (dev->power.wakeup) {
42030e3ce6dSRafael J. Wysocki 		count = dev->power.wakeup->expire_count;
42130e3ce6dSRafael J. Wysocki 		enabled = true;
42230e3ce6dSRafael J. Wysocki 	}
42330e3ce6dSRafael J. Wysocki 	spin_unlock_irq(&dev->power.lock);
424*948b3edbSJoe Perches 
425*948b3edbSJoe Perches 	if (!enabled)
426*948b3edbSJoe Perches 		return sysfs_emit(buf, "\n");
427*948b3edbSJoe Perches 	return sysfs_emit(buf, "%lu\n", count);
42830e3ce6dSRafael J. Wysocki }
42930e3ce6dSRafael J. Wysocki 
43047acbd77SAndy Shevchenko static DEVICE_ATTR_RO(wakeup_expire_count);
431074037ecSRafael J. Wysocki 
wakeup_active_show(struct device * dev,struct device_attribute * attr,char * buf)432074037ecSRafael J. Wysocki static ssize_t wakeup_active_show(struct device *dev,
433074037ecSRafael J. Wysocki 				  struct device_attribute *attr, char *buf)
434074037ecSRafael J. Wysocki {
435*948b3edbSJoe Perches 	unsigned int active;
436074037ecSRafael J. Wysocki 	bool enabled = false;
437074037ecSRafael J. Wysocki 
438074037ecSRafael J. Wysocki 	spin_lock_irq(&dev->power.lock);
439074037ecSRafael J. Wysocki 	if (dev->power.wakeup) {
440074037ecSRafael J. Wysocki 		active = dev->power.wakeup->active;
441074037ecSRafael J. Wysocki 		enabled = true;
442074037ecSRafael J. Wysocki 	}
443074037ecSRafael J. Wysocki 	spin_unlock_irq(&dev->power.lock);
444*948b3edbSJoe Perches 
445*948b3edbSJoe Perches 	if (!enabled)
446*948b3edbSJoe Perches 		return sysfs_emit(buf, "\n");
447*948b3edbSJoe Perches 	return sysfs_emit(buf, "%u\n", active);
448074037ecSRafael J. Wysocki }
449074037ecSRafael J. Wysocki 
45047acbd77SAndy Shevchenko static DEVICE_ATTR_RO(wakeup_active);
451074037ecSRafael J. Wysocki 
wakeup_total_time_ms_show(struct device * dev,struct device_attribute * attr,char * buf)45247acbd77SAndy Shevchenko static ssize_t wakeup_total_time_ms_show(struct device *dev,
45347acbd77SAndy Shevchenko 					 struct device_attribute *attr,
45447acbd77SAndy Shevchenko 					 char *buf)
455074037ecSRafael J. Wysocki {
456*948b3edbSJoe Perches 	s64 msec;
457074037ecSRafael J. Wysocki 	bool enabled = false;
458074037ecSRafael J. Wysocki 
459074037ecSRafael J. Wysocki 	spin_lock_irq(&dev->power.lock);
460074037ecSRafael J. Wysocki 	if (dev->power.wakeup) {
461074037ecSRafael J. Wysocki 		msec = ktime_to_ms(dev->power.wakeup->total_time);
462074037ecSRafael J. Wysocki 		enabled = true;
463074037ecSRafael J. Wysocki 	}
464074037ecSRafael J. Wysocki 	spin_unlock_irq(&dev->power.lock);
465*948b3edbSJoe Perches 
466*948b3edbSJoe Perches 	if (!enabled)
467*948b3edbSJoe Perches 		return sysfs_emit(buf, "\n");
468*948b3edbSJoe Perches 	return sysfs_emit(buf, "%lld\n", msec);
469074037ecSRafael J. Wysocki }
470074037ecSRafael J. Wysocki 
47147acbd77SAndy Shevchenko static DEVICE_ATTR_RO(wakeup_total_time_ms);
472074037ecSRafael J. Wysocki 
wakeup_max_time_ms_show(struct device * dev,struct device_attribute * attr,char * buf)47347acbd77SAndy Shevchenko static ssize_t wakeup_max_time_ms_show(struct device *dev,
474074037ecSRafael J. Wysocki 				       struct device_attribute *attr, char *buf)
475074037ecSRafael J. Wysocki {
476*948b3edbSJoe Perches 	s64 msec;
477074037ecSRafael J. Wysocki 	bool enabled = false;
478074037ecSRafael J. Wysocki 
479074037ecSRafael J. Wysocki 	spin_lock_irq(&dev->power.lock);
480074037ecSRafael J. Wysocki 	if (dev->power.wakeup) {
481074037ecSRafael J. Wysocki 		msec = ktime_to_ms(dev->power.wakeup->max_time);
482074037ecSRafael J. Wysocki 		enabled = true;
483074037ecSRafael J. Wysocki 	}
484074037ecSRafael J. Wysocki 	spin_unlock_irq(&dev->power.lock);
485*948b3edbSJoe Perches 
486*948b3edbSJoe Perches 	if (!enabled)
487*948b3edbSJoe Perches 		return sysfs_emit(buf, "\n");
488*948b3edbSJoe Perches 	return sysfs_emit(buf, "%lld\n", msec);
489074037ecSRafael J. Wysocki }
490074037ecSRafael J. Wysocki 
49147acbd77SAndy Shevchenko static DEVICE_ATTR_RO(wakeup_max_time_ms);
492074037ecSRafael J. Wysocki 
wakeup_last_time_ms_show(struct device * dev,struct device_attribute * attr,char * buf)49347acbd77SAndy Shevchenko static ssize_t wakeup_last_time_ms_show(struct device *dev,
49447acbd77SAndy Shevchenko 					struct device_attribute *attr,
49547acbd77SAndy Shevchenko 					char *buf)
496074037ecSRafael J. Wysocki {
497*948b3edbSJoe Perches 	s64 msec;
498074037ecSRafael J. Wysocki 	bool enabled = false;
499074037ecSRafael J. Wysocki 
500074037ecSRafael J. Wysocki 	spin_lock_irq(&dev->power.lock);
501074037ecSRafael J. Wysocki 	if (dev->power.wakeup) {
502074037ecSRafael J. Wysocki 		msec = ktime_to_ms(dev->power.wakeup->last_time);
503074037ecSRafael J. Wysocki 		enabled = true;
504074037ecSRafael J. Wysocki 	}
505074037ecSRafael J. Wysocki 	spin_unlock_irq(&dev->power.lock);
506*948b3edbSJoe Perches 
507*948b3edbSJoe Perches 	if (!enabled)
508*948b3edbSJoe Perches 		return sysfs_emit(buf, "\n");
509*948b3edbSJoe Perches 	return sysfs_emit(buf, "%lld\n", msec);
510074037ecSRafael J. Wysocki }
511074037ecSRafael J. Wysocki 
dpm_sysfs_wakeup_change_owner(struct device * dev,kuid_t kuid,kgid_t kgid)5123b52fc5dSChristian Brauner static inline int dpm_sysfs_wakeup_change_owner(struct device *dev, kuid_t kuid,
5133b52fc5dSChristian Brauner 						kgid_t kgid)
5143b52fc5dSChristian Brauner {
5153b52fc5dSChristian Brauner 	if (dev->power.wakeup && dev->power.wakeup->dev)
5163b52fc5dSChristian Brauner 		return device_change_owner(dev->power.wakeup->dev, kuid, kgid);
5173b52fc5dSChristian Brauner 	return 0;
5183b52fc5dSChristian Brauner }
5193b52fc5dSChristian Brauner 
52047acbd77SAndy Shevchenko static DEVICE_ATTR_RO(wakeup_last_time_ms);
52155850945SRafael J. Wysocki 
52255850945SRafael J. Wysocki #ifdef CONFIG_PM_AUTOSLEEP
wakeup_prevent_sleep_time_ms_show(struct device * dev,struct device_attribute * attr,char * buf)52347acbd77SAndy Shevchenko static ssize_t wakeup_prevent_sleep_time_ms_show(struct device *dev,
52455850945SRafael J. Wysocki 						 struct device_attribute *attr,
52555850945SRafael J. Wysocki 						 char *buf)
52655850945SRafael J. Wysocki {
527*948b3edbSJoe Perches 	s64 msec;
52855850945SRafael J. Wysocki 	bool enabled = false;
52955850945SRafael J. Wysocki 
53055850945SRafael J. Wysocki 	spin_lock_irq(&dev->power.lock);
53155850945SRafael J. Wysocki 	if (dev->power.wakeup) {
53255850945SRafael J. Wysocki 		msec = ktime_to_ms(dev->power.wakeup->prevent_sleep_time);
53355850945SRafael J. Wysocki 		enabled = true;
53455850945SRafael J. Wysocki 	}
53555850945SRafael J. Wysocki 	spin_unlock_irq(&dev->power.lock);
536*948b3edbSJoe Perches 
537*948b3edbSJoe Perches 	if (!enabled)
538*948b3edbSJoe Perches 		return sysfs_emit(buf, "\n");
539*948b3edbSJoe Perches 	return sysfs_emit(buf, "%lld\n", msec);
54055850945SRafael J. Wysocki }
54155850945SRafael J. Wysocki 
54247acbd77SAndy Shevchenko static DEVICE_ATTR_RO(wakeup_prevent_sleep_time_ms);
54355850945SRafael J. Wysocki #endif /* CONFIG_PM_AUTOSLEEP */
5443b52fc5dSChristian Brauner #else /* CONFIG_PM_SLEEP */
dpm_sysfs_wakeup_change_owner(struct device * dev,kuid_t kuid,kgid_t kgid)5453b52fc5dSChristian Brauner static inline int dpm_sysfs_wakeup_change_owner(struct device *dev, kuid_t kuid,
5463b52fc5dSChristian Brauner 						kgid_t kgid)
5473b52fc5dSChristian Brauner {
5483b52fc5dSChristian Brauner 	return 0;
5493b52fc5dSChristian Brauner }
5503b52fc5dSChristian Brauner #endif
551c125e96fSRafael J. Wysocki 
552c92445faSDominik Brodowski #ifdef CONFIG_PM_ADVANCED_DEBUG
runtime_usage_show(struct device * dev,struct device_attribute * attr,char * buf)55347acbd77SAndy Shevchenko static ssize_t runtime_usage_show(struct device *dev,
554c92445faSDominik Brodowski 				  struct device_attribute *attr, char *buf)
555c92445faSDominik Brodowski {
556aa838896SJoe Perches 	return sysfs_emit(buf, "%d\n", atomic_read(&dev->power.usage_count));
557c92445faSDominik Brodowski }
55847acbd77SAndy Shevchenko static DEVICE_ATTR_RO(runtime_usage);
559c92445faSDominik Brodowski 
runtime_active_kids_show(struct device * dev,struct device_attribute * attr,char * buf)56047acbd77SAndy Shevchenko static ssize_t runtime_active_kids_show(struct device *dev,
56147acbd77SAndy Shevchenko 					struct device_attribute *attr,
56247acbd77SAndy Shevchenko 					char *buf)
563c92445faSDominik Brodowski {
564aa838896SJoe Perches 	return sysfs_emit(buf, "%d\n", dev->power.ignore_children ?
565c92445faSDominik Brodowski 			  0 : atomic_read(&dev->power.child_count));
566c92445faSDominik Brodowski }
56747acbd77SAndy Shevchenko static DEVICE_ATTR_RO(runtime_active_kids);
568c92445faSDominik Brodowski 
runtime_enabled_show(struct device * dev,struct device_attribute * attr,char * buf)56947acbd77SAndy Shevchenko static ssize_t runtime_enabled_show(struct device *dev,
570c92445faSDominik Brodowski 				    struct device_attribute *attr, char *buf)
571c92445faSDominik Brodowski {
572973c3911SJoe Perches 	const char *output;
573973c3911SJoe Perches 
574973c3911SJoe Perches 	if (dev->power.disable_depth && !dev->power.runtime_auto)
575973c3911SJoe Perches 		output = "disabled & forbidden";
576973c3911SJoe Perches 	else if (dev->power.disable_depth)
577973c3911SJoe Perches 		output = "disabled";
578973c3911SJoe Perches 	else if (!dev->power.runtime_auto)
579973c3911SJoe Perches 		output = "forbidden";
580973c3911SJoe Perches 	else
581973c3911SJoe Perches 		output = "enabled";
582973c3911SJoe Perches 
583973c3911SJoe Perches 	return sysfs_emit(buf, "%s\n", output);
584c92445faSDominik Brodowski }
58547acbd77SAndy Shevchenko static DEVICE_ATTR_RO(runtime_enabled);
586c92445faSDominik Brodowski 
587d181b49eSRafael J. Wysocki #ifdef CONFIG_PM_SLEEP
async_show(struct device * dev,struct device_attribute * attr,char * buf)5885a2eb858SRafael J. Wysocki static ssize_t async_show(struct device *dev, struct device_attribute *attr,
5895a2eb858SRafael J. Wysocki 			  char *buf)
5905a2eb858SRafael J. Wysocki {
591aa838896SJoe Perches 	return sysfs_emit(buf, "%s\n",
5922b4f4313SJohannes Berg 			  device_async_suspend_enabled(dev) ?
5932b4f4313SJohannes Berg 			  _enabled : _disabled);
5945a2eb858SRafael J. Wysocki }
5955a2eb858SRafael J. Wysocki 
async_store(struct device * dev,struct device_attribute * attr,const char * buf,size_t n)5965a2eb858SRafael J. Wysocki static ssize_t async_store(struct device *dev, struct device_attribute *attr,
5975a2eb858SRafael J. Wysocki 			   const char *buf, size_t n)
5985a2eb858SRafael J. Wysocki {
599325c4b3bSAndy Shevchenko 	if (sysfs_streq(buf, _enabled))
6005a2eb858SRafael J. Wysocki 		device_enable_async_suspend(dev);
601325c4b3bSAndy Shevchenko 	else if (sysfs_streq(buf, _disabled))
6025a2eb858SRafael J. Wysocki 		device_disable_async_suspend(dev);
6035a2eb858SRafael J. Wysocki 	else
6045a2eb858SRafael J. Wysocki 		return -EINVAL;
6055a2eb858SRafael J. Wysocki 	return n;
6065a2eb858SRafael J. Wysocki }
6075a2eb858SRafael J. Wysocki 
60847acbd77SAndy Shevchenko static DEVICE_ATTR_RW(async);
609d181b49eSRafael J. Wysocki 
610d30d819dSRafael J. Wysocki #endif /* CONFIG_PM_SLEEP */
611c92445faSDominik Brodowski #endif /* CONFIG_PM_ADVANCED_DEBUG */
6120ac85241SDavid Brownell 
6131da177e4SLinus Torvalds static struct attribute *power_attrs[] = {
614cb8f51bdSRafael J. Wysocki #ifdef CONFIG_PM_ADVANCED_DEBUG
615c125e96fSRafael J. Wysocki #ifdef CONFIG_PM_SLEEP
616cb8f51bdSRafael J. Wysocki 	&dev_attr_async.attr,
617cb8f51bdSRafael J. Wysocki #endif
618cb8f51bdSRafael J. Wysocki 	&dev_attr_runtime_status.attr,
619cb8f51bdSRafael J. Wysocki 	&dev_attr_runtime_usage.attr,
620cb8f51bdSRafael J. Wysocki 	&dev_attr_runtime_active_kids.attr,
621cb8f51bdSRafael J. Wysocki 	&dev_attr_runtime_enabled.attr,
622cb8f51bdSRafael J. Wysocki #endif /* CONFIG_PM_ADVANCED_DEBUG */
623cb8f51bdSRafael J. Wysocki 	NULL,
624cb8f51bdSRafael J. Wysocki };
625dbb1d8b7SArvind Yadav static const struct attribute_group pm_attr_group = {
626cb8f51bdSRafael J. Wysocki 	.name	= power_group_name,
627cb8f51bdSRafael J. Wysocki 	.attrs	= power_attrs,
628cb8f51bdSRafael J. Wysocki };
629cb8f51bdSRafael J. Wysocki 
630cb8f51bdSRafael J. Wysocki static struct attribute *wakeup_attrs[] = {
631cb8f51bdSRafael J. Wysocki #ifdef CONFIG_PM_SLEEP
632cb8f51bdSRafael J. Wysocki 	&dev_attr_wakeup.attr,
633c125e96fSRafael J. Wysocki 	&dev_attr_wakeup_count.attr,
634074037ecSRafael J. Wysocki 	&dev_attr_wakeup_active_count.attr,
63530e3ce6dSRafael J. Wysocki 	&dev_attr_wakeup_abort_count.attr,
63630e3ce6dSRafael J. Wysocki 	&dev_attr_wakeup_expire_count.attr,
637074037ecSRafael J. Wysocki 	&dev_attr_wakeup_active.attr,
638074037ecSRafael J. Wysocki 	&dev_attr_wakeup_total_time_ms.attr,
639074037ecSRafael J. Wysocki 	&dev_attr_wakeup_max_time_ms.attr,
640074037ecSRafael J. Wysocki 	&dev_attr_wakeup_last_time_ms.attr,
64155850945SRafael J. Wysocki #ifdef CONFIG_PM_AUTOSLEEP
64255850945SRafael J. Wysocki 	&dev_attr_wakeup_prevent_sleep_time_ms.attr,
64355850945SRafael J. Wysocki #endif
644c125e96fSRafael J. Wysocki #endif
6451da177e4SLinus Torvalds 	NULL,
6461da177e4SLinus Torvalds };
647dbb1d8b7SArvind Yadav static const struct attribute_group pm_wakeup_attr_group = {
6487490e442SAlan Stern 	.name	= power_group_name,
649cb8f51bdSRafael J. Wysocki 	.attrs	= wakeup_attrs,
6501da177e4SLinus Torvalds };
6511da177e4SLinus Torvalds 
6527490e442SAlan Stern static struct attribute *runtime_attrs[] = {
6537490e442SAlan Stern #ifndef CONFIG_PM_ADVANCED_DEBUG
6547490e442SAlan Stern 	&dev_attr_runtime_status.attr,
6557490e442SAlan Stern #endif
6567490e442SAlan Stern 	&dev_attr_control.attr,
6577490e442SAlan Stern 	&dev_attr_runtime_suspended_time.attr,
6587490e442SAlan Stern 	&dev_attr_runtime_active_time.attr,
65915bcb91dSAlan Stern 	&dev_attr_autosuspend_delay_ms.attr,
6607490e442SAlan Stern 	NULL,
6617490e442SAlan Stern };
662dbb1d8b7SArvind Yadav static const struct attribute_group pm_runtime_attr_group = {
6637490e442SAlan Stern 	.name	= power_group_name,
6647490e442SAlan Stern 	.attrs	= runtime_attrs,
6657490e442SAlan Stern };
6667490e442SAlan Stern 
667b02f6695SRafael J. Wysocki static struct attribute *pm_qos_resume_latency_attrs[] = {
66885dc0b8aSRafael J. Wysocki 	&dev_attr_pm_qos_resume_latency_us.attr,
66985dc0b8aSRafael J. Wysocki 	NULL,
67085dc0b8aSRafael J. Wysocki };
671dbb1d8b7SArvind Yadav static const struct attribute_group pm_qos_resume_latency_attr_group = {
67285dc0b8aSRafael J. Wysocki 	.name	= power_group_name,
673b02f6695SRafael J. Wysocki 	.attrs	= pm_qos_resume_latency_attrs,
674e39473d0SRafael J. Wysocki };
675e39473d0SRafael J. Wysocki 
6762d984ad1SRafael J. Wysocki static struct attribute *pm_qos_latency_tolerance_attrs[] = {
6772d984ad1SRafael J. Wysocki 	&dev_attr_pm_qos_latency_tolerance_us.attr,
6782d984ad1SRafael J. Wysocki 	NULL,
6792d984ad1SRafael J. Wysocki };
680dbb1d8b7SArvind Yadav static const struct attribute_group pm_qos_latency_tolerance_attr_group = {
6812d984ad1SRafael J. Wysocki 	.name	= power_group_name,
6822d984ad1SRafael J. Wysocki 	.attrs	= pm_qos_latency_tolerance_attrs,
6832d984ad1SRafael J. Wysocki };
6842d984ad1SRafael J. Wysocki 
685e39473d0SRafael J. Wysocki static struct attribute *pm_qos_flags_attrs[] = {
686e39473d0SRafael J. Wysocki 	&dev_attr_pm_qos_no_power_off.attr,
687e39473d0SRafael J. Wysocki 	NULL,
688e39473d0SRafael J. Wysocki };
689dbb1d8b7SArvind Yadav static const struct attribute_group pm_qos_flags_attr_group = {
690e39473d0SRafael J. Wysocki 	.name	= power_group_name,
691e39473d0SRafael J. Wysocki 	.attrs	= pm_qos_flags_attrs,
69285dc0b8aSRafael J. Wysocki };
69385dc0b8aSRafael J. Wysocki 
dpm_sysfs_add(struct device * dev)6947490e442SAlan Stern int dpm_sysfs_add(struct device *dev)
6957490e442SAlan Stern {
6967490e442SAlan Stern 	int rc;
6977490e442SAlan Stern 
69885945c28SSudeep Holla 	/* No need to create PM sysfs if explicitly disabled. */
69985945c28SSudeep Holla 	if (device_pm_not_required(dev))
70085945c28SSudeep Holla 		return 0;
70185945c28SSudeep Holla 
7027490e442SAlan Stern 	rc = sysfs_create_group(&dev->kobj, &pm_attr_group);
703cb8f51bdSRafael J. Wysocki 	if (rc)
704cb8f51bdSRafael J. Wysocki 		return rc;
705cb8f51bdSRafael J. Wysocki 
7069a787546SRafael J. Wysocki 	if (!pm_runtime_has_no_callbacks(dev)) {
7077490e442SAlan Stern 		rc = sysfs_merge_group(&dev->kobj, &pm_runtime_attr_group);
7087490e442SAlan Stern 		if (rc)
709cb8f51bdSRafael J. Wysocki 			goto err_out;
7107490e442SAlan Stern 	}
711cb8f51bdSRafael J. Wysocki 	if (device_can_wakeup(dev)) {
712cb8f51bdSRafael J. Wysocki 		rc = sysfs_merge_group(&dev->kobj, &pm_wakeup_attr_group);
7132d984ad1SRafael J. Wysocki 		if (rc)
7142d984ad1SRafael J. Wysocki 			goto err_runtime;
715cb8f51bdSRafael J. Wysocki 	}
7162d984ad1SRafael J. Wysocki 	if (dev->power.set_latency_tolerance) {
7172d984ad1SRafael J. Wysocki 		rc = sysfs_merge_group(&dev->kobj,
7182d984ad1SRafael J. Wysocki 				       &pm_qos_latency_tolerance_attr_group);
7192d984ad1SRafael J. Wysocki 		if (rc)
7202d984ad1SRafael J. Wysocki 			goto err_wakeup;
721cb8f51bdSRafael J. Wysocki 	}
7222ca3d1ecSStephen Boyd 	rc = pm_wakeup_source_sysfs_add(dev);
7232ca3d1ecSStephen Boyd 	if (rc)
7242ca3d1ecSStephen Boyd 		goto err_latency;
725cb8f51bdSRafael J. Wysocki 	return 0;
726cb8f51bdSRafael J. Wysocki 
7272ca3d1ecSStephen Boyd  err_latency:
7282ca3d1ecSStephen Boyd 	sysfs_unmerge_group(&dev->kobj, &pm_qos_latency_tolerance_attr_group);
7292d984ad1SRafael J. Wysocki  err_wakeup:
7302d984ad1SRafael J. Wysocki 	sysfs_unmerge_group(&dev->kobj, &pm_wakeup_attr_group);
7312d984ad1SRafael J. Wysocki  err_runtime:
7322d984ad1SRafael J. Wysocki 	sysfs_unmerge_group(&dev->kobj, &pm_runtime_attr_group);
733cb8f51bdSRafael J. Wysocki  err_out:
734cb8f51bdSRafael J. Wysocki 	sysfs_remove_group(&dev->kobj, &pm_attr_group);
7357490e442SAlan Stern 	return rc;
7367490e442SAlan Stern }
7377490e442SAlan Stern 
dpm_sysfs_change_owner(struct device * dev,kuid_t kuid,kgid_t kgid)7383b52fc5dSChristian Brauner int dpm_sysfs_change_owner(struct device *dev, kuid_t kuid, kgid_t kgid)
7393b52fc5dSChristian Brauner {
7403b52fc5dSChristian Brauner 	int rc;
7413b52fc5dSChristian Brauner 
7423b52fc5dSChristian Brauner 	if (device_pm_not_required(dev))
7433b52fc5dSChristian Brauner 		return 0;
7443b52fc5dSChristian Brauner 
7453b52fc5dSChristian Brauner 	rc = sysfs_group_change_owner(&dev->kobj, &pm_attr_group, kuid, kgid);
7463b52fc5dSChristian Brauner 	if (rc)
7473b52fc5dSChristian Brauner 		return rc;
7483b52fc5dSChristian Brauner 
7499a787546SRafael J. Wysocki 	if (!pm_runtime_has_no_callbacks(dev)) {
7503b52fc5dSChristian Brauner 		rc = sysfs_group_change_owner(
7513b52fc5dSChristian Brauner 			&dev->kobj, &pm_runtime_attr_group, kuid, kgid);
7523b52fc5dSChristian Brauner 		if (rc)
7533b52fc5dSChristian Brauner 			return rc;
7543b52fc5dSChristian Brauner 	}
7553b52fc5dSChristian Brauner 
7563b52fc5dSChristian Brauner 	if (device_can_wakeup(dev)) {
7573b52fc5dSChristian Brauner 		rc = sysfs_group_change_owner(&dev->kobj, &pm_wakeup_attr_group,
7583b52fc5dSChristian Brauner 					      kuid, kgid);
7593b52fc5dSChristian Brauner 		if (rc)
7603b52fc5dSChristian Brauner 			return rc;
7613b52fc5dSChristian Brauner 
7623b52fc5dSChristian Brauner 		rc = dpm_sysfs_wakeup_change_owner(dev, kuid, kgid);
7633b52fc5dSChristian Brauner 		if (rc)
7643b52fc5dSChristian Brauner 			return rc;
7653b52fc5dSChristian Brauner 	}
7663b52fc5dSChristian Brauner 
7673b52fc5dSChristian Brauner 	if (dev->power.set_latency_tolerance) {
7683b52fc5dSChristian Brauner 		rc = sysfs_group_change_owner(
7693b52fc5dSChristian Brauner 			&dev->kobj, &pm_qos_latency_tolerance_attr_group, kuid,
7703b52fc5dSChristian Brauner 			kgid);
7713b52fc5dSChristian Brauner 		if (rc)
7723b52fc5dSChristian Brauner 			return rc;
7733b52fc5dSChristian Brauner 	}
7743b52fc5dSChristian Brauner 	return 0;
7753b52fc5dSChristian Brauner }
7763b52fc5dSChristian Brauner 
wakeup_sysfs_add(struct device * dev)777cb8f51bdSRafael J. Wysocki int wakeup_sysfs_add(struct device *dev)
778cb8f51bdSRafael J. Wysocki {
779a45aca51SAbhishek Pandit-Subedi 	int ret = sysfs_merge_group(&dev->kobj, &pm_wakeup_attr_group);
780a45aca51SAbhishek Pandit-Subedi 
781a45aca51SAbhishek Pandit-Subedi 	if (!ret)
782a45aca51SAbhishek Pandit-Subedi 		kobject_uevent(&dev->kobj, KOBJ_CHANGE);
783a45aca51SAbhishek Pandit-Subedi 
784a45aca51SAbhishek Pandit-Subedi 	return ret;
785cb8f51bdSRafael J. Wysocki }
786cb8f51bdSRafael J. Wysocki 
wakeup_sysfs_remove(struct device * dev)787cb8f51bdSRafael J. Wysocki void wakeup_sysfs_remove(struct device *dev)
788cb8f51bdSRafael J. Wysocki {
789cb8f51bdSRafael J. Wysocki 	sysfs_unmerge_group(&dev->kobj, &pm_wakeup_attr_group);
790a45aca51SAbhishek Pandit-Subedi 	kobject_uevent(&dev->kobj, KOBJ_CHANGE);
791cb8f51bdSRafael J. Wysocki }
792cb8f51bdSRafael J. Wysocki 
pm_qos_sysfs_add_resume_latency(struct device * dev)793b02f6695SRafael J. Wysocki int pm_qos_sysfs_add_resume_latency(struct device *dev)
79485dc0b8aSRafael J. Wysocki {
795b02f6695SRafael J. Wysocki 	return sysfs_merge_group(&dev->kobj, &pm_qos_resume_latency_attr_group);
79685dc0b8aSRafael J. Wysocki }
79785dc0b8aSRafael J. Wysocki 
pm_qos_sysfs_remove_resume_latency(struct device * dev)798b02f6695SRafael J. Wysocki void pm_qos_sysfs_remove_resume_latency(struct device *dev)
79985dc0b8aSRafael J. Wysocki {
800b02f6695SRafael J. Wysocki 	sysfs_unmerge_group(&dev->kobj, &pm_qos_resume_latency_attr_group);
801e39473d0SRafael J. Wysocki }
802e39473d0SRafael J. Wysocki 
pm_qos_sysfs_add_flags(struct device * dev)803e39473d0SRafael J. Wysocki int pm_qos_sysfs_add_flags(struct device *dev)
804e39473d0SRafael J. Wysocki {
805e39473d0SRafael J. Wysocki 	return sysfs_merge_group(&dev->kobj, &pm_qos_flags_attr_group);
806e39473d0SRafael J. Wysocki }
807e39473d0SRafael J. Wysocki 
pm_qos_sysfs_remove_flags(struct device * dev)808e39473d0SRafael J. Wysocki void pm_qos_sysfs_remove_flags(struct device *dev)
809e39473d0SRafael J. Wysocki {
810e39473d0SRafael J. Wysocki 	sysfs_unmerge_group(&dev->kobj, &pm_qos_flags_attr_group);
81185dc0b8aSRafael J. Wysocki }
81285dc0b8aSRafael J. Wysocki 
pm_qos_sysfs_add_latency_tolerance(struct device * dev)81313b2c4a0SMika Westerberg int pm_qos_sysfs_add_latency_tolerance(struct device *dev)
81413b2c4a0SMika Westerberg {
81513b2c4a0SMika Westerberg 	return sysfs_merge_group(&dev->kobj,
81613b2c4a0SMika Westerberg 				 &pm_qos_latency_tolerance_attr_group);
81713b2c4a0SMika Westerberg }
81813b2c4a0SMika Westerberg 
pm_qos_sysfs_remove_latency_tolerance(struct device * dev)81913b2c4a0SMika Westerberg void pm_qos_sysfs_remove_latency_tolerance(struct device *dev)
82013b2c4a0SMika Westerberg {
82113b2c4a0SMika Westerberg 	sysfs_unmerge_group(&dev->kobj, &pm_qos_latency_tolerance_attr_group);
82213b2c4a0SMika Westerberg }
82313b2c4a0SMika Westerberg 
rpm_sysfs_remove(struct device * dev)8247490e442SAlan Stern void rpm_sysfs_remove(struct device *dev)
8257490e442SAlan Stern {
8267490e442SAlan Stern 	sysfs_unmerge_group(&dev->kobj, &pm_runtime_attr_group);
8277490e442SAlan Stern }
8287490e442SAlan Stern 
dpm_sysfs_remove(struct device * dev)8297490e442SAlan Stern void dpm_sysfs_remove(struct device *dev)
8307490e442SAlan Stern {
83185945c28SSudeep Holla 	if (device_pm_not_required(dev))
83285945c28SSudeep Holla 		return;
8332d984ad1SRafael J. Wysocki 	sysfs_unmerge_group(&dev->kobj, &pm_qos_latency_tolerance_attr_group);
83437530f2bSRafael J. Wysocki 	dev_pm_qos_constraints_destroy(dev);
8357490e442SAlan Stern 	rpm_sysfs_remove(dev);
836cb8f51bdSRafael J. Wysocki 	sysfs_unmerge_group(&dev->kobj, &pm_wakeup_attr_group);
8377490e442SAlan Stern 	sysfs_remove_group(&dev->kobj, &pm_attr_group);
8387490e442SAlan Stern }
839