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: Dmitry Osipenko <digetx@gmail.com> Reviewed-by: Chanwoo Choi <cw00.choi@samsung.com> Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
This commit is contained in:
parent
28615e37be
commit
5c0f6c7959
|
|
@ -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);
|
||||||
*/
|
*/
|
||||||
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)
|
||||||
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)
|
||||||
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)
|
||||||
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 @@
|
||||||
* @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 {
|
||||||
|
|
||||||
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);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue