From db4f4a0933ce2f34ceaa96e4e55de4d7b1c25f2b Mon Sep 17 00:00:00 2001 From: Rama Aparna Mallavarapu Date: Sat, 13 Oct 2018 14:54:56 -0700 Subject: [PATCH] PM/devfreq: Do not switch governors from sysfs when device is suspended There is a possibility to switch the governors from sysfs even when the device is in suspended state. This can cause a NOC error at times when trying to access the device's monitor registers in a suspended state. This change fixes this issue. Utilize suspend_count to know if the device is in suspended state or not. Check if the device is suspended before switching the governor from sysfs. Change-Id: I15055aa51daa35272be4667e5bafb8ccd7933098 Signed-off-by: Rama Aparna Mallavarapu [avajid@codeaurora.org: updated to utilize suspend_count from upstream, resolved minor merge conflicts and updated commit text] Signed-off-by: Amir Vajid --- drivers/devfreq/devfreq.c | 34 ++++++++++++++++++++-------------- 1 file changed, 20 insertions(+), 14 deletions(-) diff --git a/drivers/devfreq/devfreq.c b/drivers/devfreq/devfreq.c index 55ef66a11266..56b7fcbd2ed2 100644 --- a/drivers/devfreq/devfreq.c +++ b/drivers/devfreq/devfreq.c @@ -887,30 +887,31 @@ EXPORT_SYMBOL(devm_devfreq_remove_device); */ int devfreq_suspend_device(struct devfreq *devfreq) { - int ret; + int ret = 0; if (!devfreq) return -EINVAL; + event_mutex_lock(devfreq); if (atomic_inc_return(&devfreq->suspend_count) > 1) - return 0; + goto unlock_out; if (devfreq->governor) { - event_mutex_lock(devfreq); ret = devfreq->governor->event_handler(devfreq, DEVFREQ_GOV_SUSPEND, NULL); - event_mutex_unlock(devfreq); if (ret) - return ret; + goto unlock_out; } if (devfreq->suspend_freq) { ret = devfreq_set_target(devfreq, devfreq->suspend_freq, 0); if (ret) - return ret; + goto unlock_out; } - return 0; +unlock_out: + event_mutex_unlock(devfreq); + return ret; } EXPORT_SYMBOL(devfreq_suspend_device); @@ -924,30 +925,31 @@ EXPORT_SYMBOL(devfreq_suspend_device); */ int devfreq_resume_device(struct devfreq *devfreq) { - int ret; + int ret = 0; if (!devfreq) return -EINVAL; + event_mutex_lock(devfreq); if (atomic_dec_return(&devfreq->suspend_count) >= 1) - return 0; + goto unlock_out; if (devfreq->resume_freq) { ret = devfreq_set_target(devfreq, devfreq->resume_freq, 0); if (ret) - return ret; + goto unlock_out; } if (devfreq->governor) { - event_mutex_lock(devfreq); ret = devfreq->governor->event_handler(devfreq, DEVFREQ_GOV_RESUME, NULL); - event_mutex_unlock(devfreq); if (ret) - return ret; + goto unlock_out; } - return 0; +unlock_out: + event_mutex_unlock(devfreq); + return ret; } EXPORT_SYMBOL(devfreq_resume_device); @@ -1152,6 +1154,10 @@ static ssize_t governor_store(struct device *dev, struct device_attribute *attr, } event_mutex_lock(df); + if (atomic_read(&df->suspend_count) > 0) { + ret = -EINVAL; + goto gov_stop_out; + } if (df->governor) { ret = df->governor->event_handler(df, DEVFREQ_GOV_STOP, NULL); if (ret) {