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