diff options
author | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2019-11-07 13:48:31 +0100 |
---|---|---|
committer | Rafael J. Wysocki <rafael.j.wysocki@intel.com> | 2019-11-07 13:48:31 +0100 |
commit | 2b328421e4ed1a8dca6261d302ec0b7c9f915a5b (patch) | |
tree | 7238e03f5a06c48913a95ba763f6f050b8ee50c8 /drivers/devfreq/devfreq.c | |
parent | c389ec67b7f8e028438643c4af4bbff550192187 (diff) | |
parent | fee22854c0273569836de2039d9c432ea4df2cfc (diff) | |
download | talos-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.c | 33 |
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++) |