@@ -139,14 +139,10 @@ static void get_freq_range(struct devfreq *devfreq,
*min_freq = max(*min_freq, (unsigned long)HZ_PER_KHZ * qos_min_freq);
if (qos_max_freq != PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE)
*max_freq = min(*max_freq,
(unsigned long)HZ_PER_KHZ * qos_max_freq);
- /* Apply constraints from sysfs */
- *min_freq = max(*min_freq, devfreq->min_freq);
- *max_freq = min(*max_freq, devfreq->max_freq);
-
/* Apply constraints from OPP interface */
*min_freq = max(*min_freq, devfreq->scaling_min_freq);
*max_freq = min(*max_freq, devfreq->scaling_max_freq);
if (*min_freq > *max_freq)
@@ -688,10 +684,19 @@ static void devfreq_dev_release(struct device *dev)
"Failed to remove min_freq notifier: %d\n", err);
if (devfreq->profile->exit)
devfreq->profile->exit(devfreq->dev.parent);
+ err = dev_pm_qos_remove_request(&devfreq->user_max_freq_req);
+ if (err)
+ dev_warn(dev->parent,
+ "Failed to remove max_freq request: %d\n", err);
+ err = dev_pm_qos_remove_request(&devfreq->user_min_freq_req);
+ if (err)
+ dev_warn(dev->parent,
+ "Failed to remove min_freq request: %d\n", err);
+
mutex_destroy(&devfreq->lock);
kfree(devfreq);
}
/**
@@ -755,18 +760,26 @@ struct devfreq *devfreq_add_device(struct device *dev,
devfreq->scaling_min_freq = find_available_min_freq(devfreq);
if (!devfreq->scaling_min_freq) {
err = -EINVAL;
goto err_dev;
}
- devfreq->min_freq = devfreq->scaling_min_freq;
devfreq->scaling_max_freq = find_available_max_freq(devfreq);
if (!devfreq->scaling_max_freq) {
err = -EINVAL;
goto err_dev;
}
- devfreq->max_freq = devfreq->scaling_max_freq;
+
+ err = dev_pm_qos_add_request(dev, &devfreq->user_min_freq_req,
+ DEV_PM_QOS_MIN_FREQUENCY, 0);
+ if (err < 0)
+ goto err_dev;
+ err = dev_pm_qos_add_request(dev, &devfreq->user_max_freq_req,
+ DEV_PM_QOS_MAX_FREQUENCY,
+ PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE);
+ if (err < 0)
+ goto err_dev;
devfreq->suspend_freq = dev_pm_opp_get_suspend_opp_freq(dev);
atomic_set(&devfreq->suspend_count, 0);
devfreq->trans_table = devm_kzalloc(&devfreq->dev,
@@ -1401,14 +1414,15 @@ static ssize_t min_freq_store(struct device *dev, struct device_attribute *attr,
ret = sscanf(buf, "%lu", &value);
if (ret != 1)
return -EINVAL;
- mutex_lock(&df->lock);
- df->min_freq = value;
- update_devfreq(df);
- mutex_unlock(&df->lock);
+ /* Round down to kHz for PM QoS */
+ ret = dev_pm_qos_update_request(&df->user_min_freq_req,
+ value / HZ_PER_KHZ);
+ if (ret < 0)
+ return ret;
return count;
}
static ssize_t min_freq_show(struct device *dev, struct device_attribute *attr,
@@ -1433,18 +1447,28 @@ static ssize_t max_freq_store(struct device *dev, struct device_attribute *attr,
ret = sscanf(buf, "%lu", &value);
if (ret != 1)
return -EINVAL;
- mutex_lock(&df->lock);
-
- if (!value)
- value = ULONG_MAX;
+ /*
+ * PM QoS frequencies are in kHz so we need to convert. Convert by
+ * rounding upwards so that the acceptable interval never shrinks.
+ *
+ * For example if the user writes "666666666" to sysfs this value will
+ * be converted to 666667 kHz and back to 666667000 Hz before an OPP
+ * lookup, this ensures that an OPP of 666666666Hz is still accepted.
+ *
+ * A value of zero means "no limit".
+ */
+ if (value)
+ value = DIV_ROUND_UP(value, HZ_PER_KHZ);
+ else
+ value = PM_QOS_MAX_FREQUENCY_DEFAULT_VALUE;
- df->max_freq = value;
- update_devfreq(df);
- mutex_unlock(&df->lock);
+ ret = dev_pm_qos_update_request(&df->user_max_freq_req, value);
+ if (ret < 0)
+ return ret;
return count;
}
static DEVICE_ATTR_RW(min_freq);
@@ -11,10 +11,11 @@
#define __LINUX_DEVFREQ_H__
#include <linux/device.h>
#include <linux/notifier.h>
#include <linux/pm_opp.h>
+#include <linux/pm_qos.h>
#define DEVFREQ_NAME_LEN 16
/* DEVFREQ governor name */
#define DEVFREQ_GOV_SIMPLE_ONDEMAND "simple_ondemand"
@@ -121,12 +122,12 @@ struct devfreq_dev_profile {
* devfreq.nb to the corresponding register notifier call chain.
* @work: delayed work for load monitoring.
* @previous_freq: previously configured frequency value.
* @data: Private data of the governor. The devfreq framework does not
* touch this.
- * @min_freq: Limit minimum frequency requested by user (0: none)
- * @max_freq: Limit maximum frequency requested by user (0: none)
+ * @user_min_freq_req: PM QoS minimum frequency request from user (via sysfs)
+ * @user_max_freq_req: PM QoS maximum frequency request from user (via sysfs)
* @scaling_min_freq: Limit minimum frequency requested by OPP interface
* @scaling_max_freq: Limit maximum frequency requested by OPP interface
* @stop_polling: devfreq polling status of a device.
* @suspend_freq: frequency of a device set during suspend phase.
* @resume_freq: frequency of a device set in resume phase.
@@ -161,12 +162,12 @@ struct devfreq {
unsigned long previous_freq;
struct devfreq_dev_status last_status;
void *data; /* private data for governors */
- unsigned long min_freq;
- unsigned long max_freq;
+ struct dev_pm_qos_request user_min_freq_req;
+ struct dev_pm_qos_request user_max_freq_req;
unsigned long scaling_min_freq;
unsigned long scaling_max_freq;
bool stop_polling;
unsigned long suspend_freq;