diff options
author | Terje Bergstrom <tbergstrom@nvidia.com> | 2013-10-09 11:33:38 +0300 |
---|---|---|
committer | Terje Bergstrom <tbergstrom@nvidia.com> | 2013-10-21 02:09:54 -0700 |
commit | af5d5ba19435cc0bed1c3aedf2428bdf80378e33 (patch) | |
tree | 6d164171ac2af9584bbfe4751845e7d6c26ee14b /drivers/base | |
parent | 2d762e20947a6be8abd401febf0321a67b7b430c (diff) |
PM / QoS: add dev_pm_qos_update_request_timeout()
Add dev_pm_qos_update_request_timeout() that works in the same way as
pm_qos_request_timeout().
Bug 1364240
Change-Id: I9da700df443f48099eac929055e9fe2db4c2f540
Signed-off-by: Terje Bergstrom <tbergstrom@nvidia.com>
Reviewed-on: http://git-master/r/288808
Diffstat (limited to 'drivers/base')
-rw-r--r-- | drivers/base/power/qos.c | 46 |
1 files changed, 46 insertions, 0 deletions
diff --git a/drivers/base/power/qos.c b/drivers/base/power/qos.c index 71671c42ef45..102da70948c1 100644 --- a/drivers/base/power/qos.c +++ b/drivers/base/power/qos.c @@ -42,6 +42,7 @@ #include <linux/export.h> #include <linux/pm_runtime.h> #include <linux/err.h> +#include <linux/workqueue.h> #include "power.h" @@ -265,6 +266,21 @@ void dev_pm_qos_constraints_destroy(struct device *dev) } /** + * dev_pm_qos_work_fn - the timeout handler of dev_pm_qos_update_request_timeout + * @work: work struct for the delayed work (timeout) + * + * This cancels the timeout request by falling back to the default at timeout. + */ +static void dev_pm_qos_work_fn(struct work_struct *work) +{ + struct dev_pm_qos_request *req = container_of(to_delayed_work(work), + struct dev_pm_qos_request, + work); + + dev_pm_qos_update_request(req, 0); +} + +/** * dev_pm_qos_add_request - inserts new qos request into the list * @dev: target device for the constraint * @req: pointer to a preallocated handle @@ -305,6 +321,8 @@ int dev_pm_qos_add_request(struct device *dev, struct dev_pm_qos_request *req, else if (!dev->power.qos) ret = dev_pm_qos_constraints_allocate(dev); + INIT_DELAYED_WORK(&req->work, dev_pm_qos_work_fn); + if (!ret) { req->dev = dev; req->type = type; @@ -398,12 +416,37 @@ static int __dev_pm_qos_remove_request(struct dev_pm_qos_request *req) if (IS_ERR_OR_NULL(req->dev->power.qos)) return -ENODEV; + if (delayed_work_pending(&req->work)) + cancel_delayed_work_sync(&req->work); + ret = apply_constraint(req, PM_QOS_REMOVE_REQ, PM_QOS_DEFAULT_VALUE); memset(req, 0, sizeof(*req)); return ret; } /** + * dev_pm_qos_update_request_timeout - modifies an existing qos request + * temporarily. + * @req : handle to list element holding a pm_qos request to use + * @new_value: defines the temporal qos request + * @timeout_us: the effective duration of this qos request in usecs. + * + * After timeout_us, this qos request is cancelled automatically. + */ +int dev_pm_qos_update_request_timeout(struct dev_pm_qos_request *req, + s32 new_value, unsigned long timeout_us) +{ + if (delayed_work_pending(&req->work)) + cancel_delayed_work_sync(&req->work); + + dev_pm_qos_update_request(req, new_value); + schedule_delayed_work(&req->work, usecs_to_jiffies(timeout_us)); + + return 0; +} +EXPORT_SYMBOL_GPL(dev_pm_qos_update_request_timeout); + +/** * dev_pm_qos_remove_request - modifies an existing qos request * @req: handle to request list element * @@ -422,6 +465,9 @@ int dev_pm_qos_remove_request(struct dev_pm_qos_request *req) { int ret; + if (delayed_work_pending(&req->work)) + cancel_delayed_work_sync(&req->work); + mutex_lock(&dev_pm_qos_mtx); ret = __dev_pm_qos_remove_request(req); mutex_unlock(&dev_pm_qos_mtx); |