summaryrefslogtreecommitdiffstats
path: root/drivers/devfreq/devfreq.c
diff options
context:
space:
mode:
authorRafael J. Wysocki <rafael.j.wysocki@intel.com>2019-11-07 13:48:31 +0100
committerRafael J. Wysocki <rafael.j.wysocki@intel.com>2019-11-07 13:48:31 +0100
commit2b328421e4ed1a8dca6261d302ec0b7c9f915a5b (patch)
tree7238e03f5a06c48913a95ba763f6f050b8ee50c8 /drivers/devfreq/devfreq.c
parentc389ec67b7f8e028438643c4af4bbff550192187 (diff)
parentfee22854c0273569836de2039d9c432ea4df2cfc (diff)
downloadtalos-op-linux-2b328421e4ed1a8dca6261d302ec0b7c9f915a5b.tar.gz
talos-op-linux-2b328421e4ed1a8dca6261d302ec0b7c9f915a5b.zip
Merge tag 'devfreq-next-for-5.5' of git://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/linux
Pull devfreq updates for v5.5 from Chanwoo Choi: "1. Update devfreq core - Check NULL governor in available_governors_show sysfs in order to prevent showing wrong governor information. - Fix race condition between devfreq_update_status() and trans_stat_show() - Add new 'interrupt-driven' flag for devfreq goveroris. Each devfreq driver can add their own interrupt-driven governor (NIVIDIA Tegra30 ACTMON governor). It needs to use the following sysfs interface to get the new polling interval in order to change the NVIDIA Tegra30 hardware's polling interval. : /sys/class/devfreq/devfreqX/polling_interval So, if 'interrupt-driven' flag of devfreq governor is 1, the devfreq governor is able to use the 'polling_interval' sysfs interface to get the new polling interval value. But, the devfreq core doesn't schedule out the polling work for this governor like NVIDIA Tegra30 ACTMON governor. 2. Update devfreq drivers - For exynos-bus.c, remove unused property from dt-binding documentation - For tegra30-devfreq.c, update the internal behavior like fixing the overflow integer issue and clean-up code. 3. Update devfreq-event driver - For exynos-ppmu.c, add exynos_ppmu.h dt-binding file for 'event-data-type' filed. and update dt-binging documentation. Also, Fix minor coding style." * tag 'devfreq-next-for-5.5' of git://git.kernel.org/pub/scm/linux/kernel/git/chanwoo/linux: (25 commits) PM / devfreq: tegra30: Tune up MCCPU boost-down coefficient PM / devfreq: tegra30: Support variable polling interval PM / devfreq: Add new interrupt_driven flag for governors PM / devfreq: tegra30: Use kHz units for dependency threshold PM / devfreq: tegra30: Disable consecutive interrupts when appropriate PM / devfreq: tegra30: Don't enable already enabled consecutive interrupts PM / devfreq: tegra30: Include appropriate header PM / devfreq: tegra30: Constify structs PM / devfreq: tegra30: Don't enable consecutive-down interrupt on startup PM / devfreq: tegra30: Reset boosting on startup PM / devfreq: tegra30: Move clk-notifier's registration to governor's start PM / devfreq: tegra30: Use CPUFreq notifier PM / devfreq: tegra30: Use kHz units uniformly in the code PM / devfreq: tegra30: Fix integer overflow on CPU's freq max out PM / devfreq: tegra30: Drop write-barrier PM / devfreq: tegra30: Handle possible round-rate error PM / devfreq: tegra30: Keep interrupt disabled while governor is stopped PM / devfreq: tegra30: Change irq type to unsigned int PM / devfreq: exynos-ppmu: remove useless assignment PM / devfreq: Lock devfreq in trans_stat_show ...
Diffstat (limited to 'drivers/devfreq/devfreq.c')
-rw-r--r--drivers/devfreq/devfreq.c33
1 files changed, 28 insertions, 5 deletions
diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c
index 446490c9d635..f840e61e5a27 100644
--- a/drivers/devfreq/devfreq.c
+++ b/drivers/devfreq/devfreq.c
@@ -160,6 +160,7 @@ int devfreq_update_status(struct devfreq *devfreq, unsigned long freq)
int lev, prev_lev, ret = 0;
unsigned long cur_time;
+ lockdep_assert_held(&devfreq->lock);
cur_time = jiffies;
/* Immediately exit if previous_freq is not initialized yet. */
@@ -409,6 +410,9 @@ static void devfreq_monitor(struct work_struct *work)
*/
void devfreq_monitor_start(struct devfreq *devfreq)
{
+ if (devfreq->governor->interrupt_driven)
+ return;
+
INIT_DEFERRABLE_WORK(&devfreq->work, devfreq_monitor);
if (devfreq->profile->polling_ms)
queue_delayed_work(devfreq_wq, &devfreq->work,
@@ -426,6 +430,9 @@ EXPORT_SYMBOL(devfreq_monitor_start);
*/
void devfreq_monitor_stop(struct devfreq *devfreq)
{
+ if (devfreq->governor->interrupt_driven)
+ return;
+
cancel_delayed_work_sync(&devfreq->work);
}
EXPORT_SYMBOL(devfreq_monitor_stop);
@@ -453,6 +460,10 @@ void devfreq_monitor_suspend(struct devfreq *devfreq)
devfreq_update_status(devfreq, devfreq->previous_freq);
devfreq->stop_polling = true;
mutex_unlock(&devfreq->lock);
+
+ if (devfreq->governor->interrupt_driven)
+ return;
+
cancel_delayed_work_sync(&devfreq->work);
}
EXPORT_SYMBOL(devfreq_monitor_suspend);
@@ -473,11 +484,15 @@ void devfreq_monitor_resume(struct devfreq *devfreq)
if (!devfreq->stop_polling)
goto out;
+ if (devfreq->governor->interrupt_driven)
+ goto out_update;
+
if (!delayed_work_pending(&devfreq->work) &&
devfreq->profile->polling_ms)
queue_delayed_work(devfreq_wq, &devfreq->work,
msecs_to_jiffies(devfreq->profile->polling_ms));
+out_update:
devfreq->last_stat_updated = jiffies;
devfreq->stop_polling = false;
@@ -509,6 +524,9 @@ void devfreq_interval_update(struct devfreq *devfreq, unsigned int *delay)
if (devfreq->stop_polling)
goto out;
+ if (devfreq->governor->interrupt_driven)
+ goto out;
+
/* if new delay is zero, stop polling */
if (!new_delay) {
mutex_unlock(&devfreq->lock);
@@ -625,7 +643,7 @@ struct devfreq *devfreq_add_device(struct device *dev,
devfreq = find_device_devfreq(dev);
mutex_unlock(&devfreq_list_lock);
if (!IS_ERR(devfreq)) {
- dev_err(dev, "%s: Unable to create devfreq for the device.\n",
+ dev_err(dev, "%s: devfreq device already exists!\n",
__func__);
err = -EINVAL;
goto err_out;
@@ -1195,7 +1213,7 @@ static ssize_t available_governors_show(struct device *d,
* The devfreq with immutable governor (e.g., passive) shows
* only own governor.
*/
- if (df->governor->immutable) {
+ if (df->governor && df->governor->immutable) {
count = scnprintf(&buf[count], DEVFREQ_NAME_LEN,
"%s ", df->governor_name);
/*
@@ -1397,12 +1415,17 @@ static ssize_t trans_stat_show(struct device *dev,
int i, j;
unsigned int max_state = devfreq->profile->max_state;
- if (!devfreq->stop_polling &&
- devfreq_update_status(devfreq, devfreq->previous_freq))
- return 0;
if (max_state == 0)
return sprintf(buf, "Not Supported.\n");
+ mutex_lock(&devfreq->lock);
+ if (!devfreq->stop_polling &&
+ devfreq_update_status(devfreq, devfreq->previous_freq)) {
+ mutex_unlock(&devfreq->lock);
+ return 0;
+ }
+ mutex_unlock(&devfreq->lock);
+
len = sprintf(buf, " From : To\n");
len += sprintf(buf + len, " :");
for (i = 0; i < max_state; i++)
OpenPOWER on IntegriCloud