Skip to content

Commit

Permalink
PM / QoS: add pm_qos_update_request_timeout() API
Browse files Browse the repository at this point in the history
The new API, pm_qos_update_request_timeout() is to provide a timeout
with pm_qos_update_request.

For example, pm_qos_update_request_timeout(req, 100, 1000), means that
QoS request on req with value 100 will be active for 1000 microseconds.
After 1000 microseconds, the QoS request thru req is reset. If there
were another pm_qos_update_request(req, x) during the 1000 us, this
new request with value x will override as this is another request on the
same req handle. A new request on the same req handle will always
override the previous request whether it is the conventional request or
it is the new timeout request.

Signed-off-by: MyungJoo Ham <myungjoo.ham@samsung.com>
Signed-off-by: Kyungmin Park <kyungmin.park@samsung.com>
Acked-by: Mark Gross <markgross@thegnar.org>
Signed-off-by: Rafael J. Wysocki <rjw@sisk.pl>
  • Loading branch information
MyungJoo Ham authored and Rafael J. Wysocki committed Mar 28, 2012
1 parent a36cf84 commit c4772d1
Show file tree
Hide file tree
Showing 2 changed files with 54 additions and 0 deletions.
4 changes: 4 additions & 0 deletions include/linux/pm_qos.h
Original file line number Diff line number Diff line change
Expand Up @@ -8,6 +8,7 @@
#include <linux/notifier.h>
#include <linux/miscdevice.h>
#include <linux/device.h>
#include <linux/workqueue.h>

enum {
PM_QOS_RESERVED = 0,
Expand All @@ -29,6 +30,7 @@ enum {
struct pm_qos_request {
struct plist_node node;
int pm_qos_class;
struct delayed_work work; /* for pm_qos_update_request_timeout */
};

struct dev_pm_qos_request {
Expand Down Expand Up @@ -73,6 +75,8 @@ void pm_qos_add_request(struct pm_qos_request *req, int pm_qos_class,
s32 value);
void pm_qos_update_request(struct pm_qos_request *req,
s32 new_value);
void pm_qos_update_request_timeout(struct pm_qos_request *req,
s32 new_value, unsigned long timeout_us);
void pm_qos_remove_request(struct pm_qos_request *req);

int pm_qos_request(int pm_qos_class);
Expand Down
50 changes: 50 additions & 0 deletions kernel/power/qos.c
Original file line number Diff line number Diff line change
Expand Up @@ -229,6 +229,21 @@ int pm_qos_request_active(struct pm_qos_request *req)
}
EXPORT_SYMBOL_GPL(pm_qos_request_active);

/**
* pm_qos_work_fn - the timeout handler of 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 pm_qos_work_fn(struct work_struct *work)
{
struct pm_qos_request *req = container_of(to_delayed_work(work),
struct pm_qos_request,
work);

pm_qos_update_request(req, PM_QOS_DEFAULT_VALUE);
}

/**
* pm_qos_add_request - inserts new qos request into the list
* @req: pointer to a preallocated handle
Expand All @@ -253,6 +268,7 @@ void pm_qos_add_request(struct pm_qos_request *req,
return;
}
req->pm_qos_class = pm_qos_class;
INIT_DELAYED_WORK(&req->work, pm_qos_work_fn);
pm_qos_update_target(pm_qos_array[pm_qos_class]->constraints,
&req->node, PM_QOS_ADD_REQ, value);
}
Expand All @@ -279,13 +295,44 @@ void pm_qos_update_request(struct pm_qos_request *req,
return;
}

if (delayed_work_pending(&req->work))
cancel_delayed_work_sync(&req->work);

if (new_value != req->node.prio)
pm_qos_update_target(
pm_qos_array[req->pm_qos_class]->constraints,
&req->node, PM_QOS_UPDATE_REQ, new_value);
}
EXPORT_SYMBOL_GPL(pm_qos_update_request);

/**
* 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.
*/
void pm_qos_update_request_timeout(struct pm_qos_request *req, s32 new_value,
unsigned long timeout_us)
{
if (!req)
return;
if (WARN(!pm_qos_request_active(req),
"%s called for unknown object.", __func__))
return;

if (delayed_work_pending(&req->work))
cancel_delayed_work_sync(&req->work);

if (new_value != req->node.prio)
pm_qos_update_target(
pm_qos_array[req->pm_qos_class]->constraints,
&req->node, PM_QOS_UPDATE_REQ, new_value);

schedule_delayed_work(&req->work, usecs_to_jiffies(timeout_us));
}

/**
* pm_qos_remove_request - modifies an existing qos request
* @req: handle to request list element
Expand All @@ -305,6 +352,9 @@ void pm_qos_remove_request(struct pm_qos_request *req)
return;
}

if (delayed_work_pending(&req->work))
cancel_delayed_work_sync(&req->work);

pm_qos_update_target(pm_qos_array[req->pm_qos_class]->constraints,
&req->node, PM_QOS_REMOVE_REQ,
PM_QOS_DEFAULT_VALUE);
Expand Down

0 comments on commit c4772d1

Please sign in to comment.