diff mbox

[06/12] PM / devfreq: Check the entered min/max_freq is supported or not

Message ID 1503538979-22693-7-git-send-email-cw00.choi@samsung.com (mailing list archive)
State Deferred
Headers show

Commit Message

Chanwoo Choi Aug. 24, 2017, 1:42 a.m. UTC
The existing {min|max}_freq_store() only check the range of
entered frequency. If the unsupported frequency is entered
and the entered frequency is within the ranges, {min|max}_freq_store()
will store it to devfreq->{min|max}_freq. And then when some user
try to read the {min|max}_freq, the devfreq show the unsupported
frequency value.

In order to fix this issue, this patch checks whether the entered
frequency is supported or not by OPP interface.

Signed-off-by: Chanwoo Choi <cw00.choi@samsung.com>
---
 drivers/devfreq/devfreq.c | 35 +++++++++++++++++++++++++++++++----
 1 file changed, 31 insertions(+), 4 deletions(-)
diff mbox

Patch

diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index 56f8a0473834..f10017fe400f 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -97,6 +97,25 @@  static unsigned long find_available_max_freq(struct devfreq *devfreq)
 	return max_freq;
 }
 
+static int is_supported_freq(struct devfreq *devfreq, unsigned long freq)
+{
+	struct device *dev = devfreq->dev.parent;
+	struct dev_pm_opp *opp;
+	int ret = 0;
+
+	/* Check whether entered frequency is supported or not */
+	opp = dev_pm_opp_find_freq_exact(dev, freq, true);
+	if (PTR_ERR(opp) == -ERANGE)
+		opp = dev_pm_opp_find_freq_exact(dev, freq, false);
+
+	if (IS_ERR(opp))
+		ret = PTR_ERR(opp);
+
+	dev_pm_opp_put(opp);
+
+	return ret;
+}
+
 /**
  * devfreq_get_freq_level() - Lookup freq_table for the frequency
  * @devfreq:	the devfreq instance
@@ -1099,9 +1118,8 @@  static ssize_t min_freq_store(struct device *dev, struct device_attribute *attr,
 			      const char *buf, size_t count)
 {
 	struct devfreq *df = to_devfreq(dev);
-	unsigned long value;
+	unsigned long value, max;
 	int ret;
-	unsigned long max;
 
 	ret = sscanf(buf, "%lu", &value);
 	if (ret != 1)
@@ -1114,6 +1132,11 @@  static ssize_t min_freq_store(struct device *dev, struct device_attribute *attr,
 		goto unlock;
 	}
 
+	/* Check whether entered frequency is supported or not */
+	ret = is_supported_freq(df, value);
+	if (ret < 0)
+		goto unlock;
+
 	df->min_freq = value;
 	update_devfreq(df);
 	ret = count;
@@ -1126,9 +1149,8 @@  static ssize_t max_freq_store(struct device *dev, struct device_attribute *attr,
 			      const char *buf, size_t count)
 {
 	struct devfreq *df = to_devfreq(dev);
-	unsigned long value;
+	unsigned long value, min;
 	int ret;
-	unsigned long min;
 
 	ret = sscanf(buf, "%lu", &value);
 	if (ret != 1)
@@ -1141,6 +1163,11 @@  static ssize_t max_freq_store(struct device *dev, struct device_attribute *attr,
 		goto unlock;
 	}
 
+	/* Check whether entered frequency is supported or not */
+	ret = is_supported_freq(df, value);
+	if (ret < 0)
+		goto unlock;
+
 	df->max_freq = value;
 	update_devfreq(df);
 	ret = count;