PM / QoS: add pm_qos_update_request_timeout() API
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>
This commit is contained in:
parent
a36cf844c5
commit
c4772d192c
|
@ -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,
|
||||
|
@ -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 {
|
||||
|
@ -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);
|
||||
|
|
|
@ -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
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -279,6 +295,9 @@ 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,
|
||||
|
@ -286,6 +305,34 @@ void pm_qos_update_request(struct pm_qos_request *req,
|
|||
}
|
||||
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
|
||||
|
@ -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);
|
||||
|
|
Loading…
Reference in New Issue