PM / QoS: Make it possible to expose device latency tolerance to userspace
authorMika Westerberg <mika.westerberg@linux.intel.com>
Mon, 27 Jul 2015 15:03:56 +0000 (18:03 +0300)
committerLee Jones <lee.jones@linaro.org>
Tue, 28 Jul 2015 07:50:41 +0000 (08:50 +0100)
Typically when a device is created the bus core it belongs to (for example
PCI) does not know if the device supports things like latency tolerance.
This is left to the driver that binds to the device in question. However,
at that time the device has already been created and there is no way to set
its dev->power.set_latency_tolerance anymore.

So follow what has been done for other PM QoS attributes as well and allow
drivers to expose and hide latency tolerance from userspace, if the device
supports it.

Acked-by: Rafael J. Wysocki <rafael.j.wysocki@intel.com>
Signed-off-by: Mika Westerberg <mika.westerberg@linux.intel.com>
Signed-off-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Signed-off-by: Lee Jones <lee.jones@linaro.org>
drivers/base/power/power.h
drivers/base/power/qos.c
drivers/base/power/sysfs.c
include/linux/pm_qos.h

index f1a5d95e7b207816ef522ef0c9b20de192fdc28e..998fa6b230844391b023b5ba8d4f0a22f9c645b0 100644 (file)
@@ -73,6 +73,8 @@ extern int pm_qos_sysfs_add_resume_latency(struct device *dev);
 extern void pm_qos_sysfs_remove_resume_latency(struct device *dev);
 extern int pm_qos_sysfs_add_flags(struct device *dev);
 extern void pm_qos_sysfs_remove_flags(struct device *dev);
+extern int pm_qos_sysfs_add_latency_tolerance(struct device *dev);
+extern void pm_qos_sysfs_remove_latency_tolerance(struct device *dev);
 
 #else /* CONFIG_PM */
 
index e56d538d039e4220276ea772d9cd6c2ccd95d1d2..7f3646e459cbacd399c6ac7520dd1e37aa2bcb10 100644 (file)
@@ -883,3 +883,40 @@ int dev_pm_qos_update_user_latency_tolerance(struct device *dev, s32 val)
        mutex_unlock(&dev_pm_qos_mtx);
        return ret;
 }
+
+/**
+ * dev_pm_qos_expose_latency_tolerance - Expose latency tolerance to userspace
+ * @dev: Device whose latency tolerance to expose
+ */
+int dev_pm_qos_expose_latency_tolerance(struct device *dev)
+{
+       int ret;
+
+       if (!dev->power.set_latency_tolerance)
+               return -EINVAL;
+
+       mutex_lock(&dev_pm_qos_sysfs_mtx);
+       ret = pm_qos_sysfs_add_latency_tolerance(dev);
+       mutex_unlock(&dev_pm_qos_sysfs_mtx);
+
+       return ret;
+}
+EXPORT_SYMBOL_GPL(dev_pm_qos_expose_latency_tolerance);
+
+/**
+ * dev_pm_qos_hide_latency_tolerance - Hide latency tolerance from userspace
+ * @dev: Device whose latency tolerance to hide
+ */
+void dev_pm_qos_hide_latency_tolerance(struct device *dev)
+{
+       mutex_lock(&dev_pm_qos_sysfs_mtx);
+       pm_qos_sysfs_remove_latency_tolerance(dev);
+       mutex_unlock(&dev_pm_qos_sysfs_mtx);
+
+       /* Remove the request from user space now */
+       pm_runtime_get_sync(dev);
+       dev_pm_qos_update_user_latency_tolerance(dev,
+               PM_QOS_LATENCY_TOLERANCE_NO_CONSTRAINT);
+       pm_runtime_put(dev);
+}
+EXPORT_SYMBOL_GPL(dev_pm_qos_hide_latency_tolerance);
index d2be3f9c211cbba39d2c685eb481c54ac2ed3a23..a7b46798c81d0452149907e153ae149830fdbceb 100644 (file)
@@ -738,6 +738,17 @@ void pm_qos_sysfs_remove_flags(struct device *dev)
        sysfs_unmerge_group(&dev->kobj, &pm_qos_flags_attr_group);
 }
 
+int pm_qos_sysfs_add_latency_tolerance(struct device *dev)
+{
+       return sysfs_merge_group(&dev->kobj,
+                                &pm_qos_latency_tolerance_attr_group);
+}
+
+void pm_qos_sysfs_remove_latency_tolerance(struct device *dev)
+{
+       sysfs_unmerge_group(&dev->kobj, &pm_qos_latency_tolerance_attr_group);
+}
+
 void rpm_sysfs_remove(struct device *dev)
 {
        sysfs_unmerge_group(&dev->kobj, &pm_runtime_attr_group);
index 7b3ae0cffc05beb1bb891fff982d3713806d99d1..0f65d36c2a75153c4f0c1b47f2ff351ca5365239 100644 (file)
@@ -161,6 +161,8 @@ void dev_pm_qos_hide_flags(struct device *dev);
 int dev_pm_qos_update_flags(struct device *dev, s32 mask, bool set);
 s32 dev_pm_qos_get_user_latency_tolerance(struct device *dev);
 int dev_pm_qos_update_user_latency_tolerance(struct device *dev, s32 val);
+int dev_pm_qos_expose_latency_tolerance(struct device *dev);
+void dev_pm_qos_hide_latency_tolerance(struct device *dev);
 
 static inline s32 dev_pm_qos_requested_resume_latency(struct device *dev)
 {
@@ -229,6 +231,9 @@ static inline s32 dev_pm_qos_get_user_latency_tolerance(struct device *dev)
                        { return PM_QOS_LATENCY_TOLERANCE_NO_CONSTRAINT; }
 static inline int dev_pm_qos_update_user_latency_tolerance(struct device *dev, s32 val)
                        { return 0; }
+static inline int dev_pm_qos_expose_latency_tolerance(struct device *dev)
+                       { return 0; }
+static inline void dev_pm_qos_hide_latency_tolerance(struct device *dev) {}
 
 static inline s32 dev_pm_qos_requested_resume_latency(struct device *dev) { return 0; }
 static inline s32 dev_pm_qos_requested_flags(struct device *dev) { return 0; }