summaryrefslogtreecommitdiffstats
path: root/drivers/devfreq/devfreq.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/devfreq/devfreq.c')
-rw-r--r--drivers/devfreq/devfreq.c38
1 files changed, 29 insertions, 9 deletions
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index 81d9df89d..7162d2bad 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -88,7 +88,7 @@ static unsigned long find_available_min_freq(struct devfreq *devfreq)
struct dev_pm_opp *opp;
unsigned long min_freq = 0;
- opp = dev_pm_opp_find_freq_ceil(devfreq->dev.parent, &min_freq);
+ opp = dev_pm_opp_find_freq_ceil_indexed(devfreq->dev.parent, &min_freq, 0);
if (IS_ERR(opp))
min_freq = 0;
else
@@ -102,7 +102,7 @@ static unsigned long find_available_max_freq(struct devfreq *devfreq)
struct dev_pm_opp *opp;
unsigned long max_freq = ULONG_MAX;
- opp = dev_pm_opp_find_freq_floor(devfreq->dev.parent, &max_freq);
+ opp = dev_pm_opp_find_freq_floor_indexed(devfreq->dev.parent, &max_freq, 0);
if (IS_ERR(opp))
max_freq = 0;
else
@@ -196,7 +196,7 @@ static int set_freq_table(struct devfreq *devfreq)
return -ENOMEM;
for (i = 0, freq = 0; i < devfreq->max_state; i++, freq++) {
- opp = dev_pm_opp_find_freq_ceil(devfreq->dev.parent, &freq);
+ opp = dev_pm_opp_find_freq_ceil_indexed(devfreq->dev.parent, &freq, 0);
if (IS_ERR(opp)) {
devm_kfree(devfreq->dev.parent, devfreq->freq_table);
return PTR_ERR(opp);
@@ -461,10 +461,14 @@ static void devfreq_monitor(struct work_struct *work)
if (err)
dev_err(&devfreq->dev, "dvfs failed with (%d) error\n", err);
+ if (devfreq->stop_polling)
+ goto out;
+
queue_delayed_work(devfreq_wq, &devfreq->work,
msecs_to_jiffies(devfreq->profile->polling_ms));
- mutex_unlock(&devfreq->lock);
+out:
+ mutex_unlock(&devfreq->lock);
trace_devfreq_monitor(devfreq);
}
@@ -483,6 +487,10 @@ void devfreq_monitor_start(struct devfreq *devfreq)
if (IS_SUPPORTED_FLAG(devfreq->governor->flags, IRQ_DRIVEN))
return;
+ mutex_lock(&devfreq->lock);
+ if (delayed_work_pending(&devfreq->work))
+ goto out;
+
switch (devfreq->profile->timer) {
case DEVFREQ_TIMER_DEFERRABLE:
INIT_DEFERRABLE_WORK(&devfreq->work, devfreq_monitor);
@@ -491,12 +499,16 @@ void devfreq_monitor_start(struct devfreq *devfreq)
INIT_DELAYED_WORK(&devfreq->work, devfreq_monitor);
break;
default:
- return;
+ goto out;
}
if (devfreq->profile->polling_ms)
queue_delayed_work(devfreq_wq, &devfreq->work,
msecs_to_jiffies(devfreq->profile->polling_ms));
+
+out:
+ devfreq->stop_polling = false;
+ mutex_unlock(&devfreq->lock);
}
EXPORT_SYMBOL(devfreq_monitor_start);
@@ -513,6 +525,14 @@ void devfreq_monitor_stop(struct devfreq *devfreq)
if (IS_SUPPORTED_FLAG(devfreq->governor->flags, IRQ_DRIVEN))
return;
+ mutex_lock(&devfreq->lock);
+ if (devfreq->stop_polling) {
+ mutex_unlock(&devfreq->lock);
+ return;
+ }
+
+ devfreq->stop_polling = true;
+ mutex_unlock(&devfreq->lock);
cancel_delayed_work_sync(&devfreq->work);
}
EXPORT_SYMBOL(devfreq_monitor_stop);
@@ -2057,18 +2077,18 @@ struct dev_pm_opp *devfreq_recommended_opp(struct device *dev,
if (flags & DEVFREQ_FLAG_LEAST_UPPER_BOUND) {
/* The freq is an upper bound. opp should be lower */
- opp = dev_pm_opp_find_freq_floor(dev, freq);
+ opp = dev_pm_opp_find_freq_floor_indexed(dev, freq, 0);
/* If not available, use the closest opp */
if (opp == ERR_PTR(-ERANGE))
- opp = dev_pm_opp_find_freq_ceil(dev, freq);
+ opp = dev_pm_opp_find_freq_ceil_indexed(dev, freq, 0);
} else {
/* The freq is an lower bound. opp should be higher */
- opp = dev_pm_opp_find_freq_ceil(dev, freq);
+ opp = dev_pm_opp_find_freq_ceil_indexed(dev, freq, 0);
/* If not available, use the closest opp */
if (opp == ERR_PTR(-ERANGE))
- opp = dev_pm_opp_find_freq_floor(dev, freq);
+ opp = dev_pm_opp_find_freq_floor_indexed(dev, freq, 0);
}
return opp;