Commit 5c0f6c79 authored by Dmitry Osipenko's avatar Dmitry Osipenko Committed by Chanwoo Choi

PM / devfreq: Add new interrupt_driven flag for governors

Currently interrupt-driven governors (like NVIDIA Tegra30 ACTMON governor)
are used to set polling_ms=0 in order to avoid periodic polling of device
status by devfreq core. This means that polling interval can't be changed
by userspace for such governors.

The new governor flag allows interrupt-driven governors to convey that
devfreq core shouldn't perform polling of device status and thus generic
devfreq polling interval could be supported by these governors now.
Signed-off-by: default avatarDmitry Osipenko <digetx@gmail.com>
Reviewed-by: default avatarChanwoo Choi <cw00.choi@samsung.com>
Signed-off-by: default avatarChanwoo Choi <cw00.choi@samsung.com>
parent 28615e37
...@@ -410,6 +410,9 @@ static void devfreq_monitor(struct work_struct *work) ...@@ -410,6 +410,9 @@ static void devfreq_monitor(struct work_struct *work)
*/ */
void devfreq_monitor_start(struct devfreq *devfreq) void devfreq_monitor_start(struct devfreq *devfreq)
{ {
if (devfreq->governor->interrupt_driven)
return;
INIT_DEFERRABLE_WORK(&devfreq->work, devfreq_monitor); INIT_DEFERRABLE_WORK(&devfreq->work, devfreq_monitor);
if (devfreq->profile->polling_ms) if (devfreq->profile->polling_ms)
queue_delayed_work(devfreq_wq, &devfreq->work, queue_delayed_work(devfreq_wq, &devfreq->work,
...@@ -427,6 +430,9 @@ EXPORT_SYMBOL(devfreq_monitor_start); ...@@ -427,6 +430,9 @@ EXPORT_SYMBOL(devfreq_monitor_start);
*/ */
void devfreq_monitor_stop(struct devfreq *devfreq) void devfreq_monitor_stop(struct devfreq *devfreq)
{ {
if (devfreq->governor->interrupt_driven)
return;
cancel_delayed_work_sync(&devfreq->work); cancel_delayed_work_sync(&devfreq->work);
} }
EXPORT_SYMBOL(devfreq_monitor_stop); EXPORT_SYMBOL(devfreq_monitor_stop);
...@@ -454,6 +460,10 @@ void devfreq_monitor_suspend(struct devfreq *devfreq) ...@@ -454,6 +460,10 @@ void devfreq_monitor_suspend(struct devfreq *devfreq)
devfreq_update_status(devfreq, devfreq->previous_freq); devfreq_update_status(devfreq, devfreq->previous_freq);
devfreq->stop_polling = true; devfreq->stop_polling = true;
mutex_unlock(&devfreq->lock); mutex_unlock(&devfreq->lock);
if (devfreq->governor->interrupt_driven)
return;
cancel_delayed_work_sync(&devfreq->work); cancel_delayed_work_sync(&devfreq->work);
} }
EXPORT_SYMBOL(devfreq_monitor_suspend); EXPORT_SYMBOL(devfreq_monitor_suspend);
...@@ -474,11 +484,15 @@ void devfreq_monitor_resume(struct devfreq *devfreq) ...@@ -474,11 +484,15 @@ void devfreq_monitor_resume(struct devfreq *devfreq)
if (!devfreq->stop_polling) if (!devfreq->stop_polling)
goto out; goto out;
if (devfreq->governor->interrupt_driven)
goto out_update;
if (!delayed_work_pending(&devfreq->work) && if (!delayed_work_pending(&devfreq->work) &&
devfreq->profile->polling_ms) devfreq->profile->polling_ms)
queue_delayed_work(devfreq_wq, &devfreq->work, queue_delayed_work(devfreq_wq, &devfreq->work,
msecs_to_jiffies(devfreq->profile->polling_ms)); msecs_to_jiffies(devfreq->profile->polling_ms));
out_update:
devfreq->last_stat_updated = jiffies; devfreq->last_stat_updated = jiffies;
devfreq->stop_polling = false; devfreq->stop_polling = false;
...@@ -510,6 +524,9 @@ void devfreq_interval_update(struct devfreq *devfreq, unsigned int *delay) ...@@ -510,6 +524,9 @@ void devfreq_interval_update(struct devfreq *devfreq, unsigned int *delay)
if (devfreq->stop_polling) if (devfreq->stop_polling)
goto out; goto out;
if (devfreq->governor->interrupt_driven)
goto out;
/* if new delay is zero, stop polling */ /* if new delay is zero, stop polling */
if (!new_delay) { if (!new_delay) {
mutex_unlock(&devfreq->lock); mutex_unlock(&devfreq->lock);
......
...@@ -31,6 +31,8 @@ ...@@ -31,6 +31,8 @@
* @name: Governor's name * @name: Governor's name
* @immutable: Immutable flag for governor. If the value is 1, * @immutable: Immutable flag for governor. If the value is 1,
* this govenror is never changeable to other governor. * this govenror is never changeable to other governor.
* @interrupt_driven: Devfreq core won't schedule polling work for this
* governor if value is set to 1.
* @get_target_freq: Returns desired operating frequency for the device. * @get_target_freq: Returns desired operating frequency for the device.
* Basically, get_target_freq will run * Basically, get_target_freq will run
* devfreq_dev_profile.get_dev_status() to get the * devfreq_dev_profile.get_dev_status() to get the
...@@ -49,6 +51,7 @@ struct devfreq_governor { ...@@ -49,6 +51,7 @@ struct devfreq_governor {
const char name[DEVFREQ_NAME_LEN]; const char name[DEVFREQ_NAME_LEN];
const unsigned int immutable; const unsigned int immutable;
const unsigned int interrupt_driven;
int (*get_target_freq)(struct devfreq *this, unsigned long *freq); int (*get_target_freq)(struct devfreq *this, unsigned long *freq);
int (*event_handler)(struct devfreq *devfreq, int (*event_handler)(struct devfreq *devfreq,
unsigned int event, void *data); unsigned int event, void *data);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment