devfreq: stop podgov polling when disabled through sysfs

The pod governor allows scaling to be enabled/disabled through
sysfs. In the current implementation the devfreq_monitor keeps polling
periodically even when scaling is disabled. This patch disables the
timer when scaling is disabled.

NVGPU-20

Change-Id: I6842585afec48dbc9a2fe5aee96867c68612a127
Signed-off-by: Peter Boonstoppel <pboonstoppel@nvidia.com>
Reviewed-on: https://git-master/r/1485185
(cherry picked from linux-4.9 commit 96ebb9e97b84092a852274f90e214d3976944b78)
Reviewed-on: https://git-master.nvidia.com/r/1770152
Reviewed-by: Mikko Perttunen <mperttunen@nvidia.com>
GVS: Gerrit_Virtual_Submit
Reviewed-by: Timo Alho <talho@nvidia.com>
Tested-by: Timo Alho <talho@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
Peter Boonstoppel
2017-05-18 14:54:43 -07:00
committed by Laxman Dewangan
parent 3c30f1e47b
commit 297a2218f1

View File

@@ -84,6 +84,8 @@ struct podgov_info_rec {
struct kobj_attribute enable_3d_scaling_attr; struct kobj_attribute enable_3d_scaling_attr;
struct kobj_attribute user_attr; struct kobj_attribute user_attr;
struct kobj_attribute freq_request_attr; struct kobj_attribute freq_request_attr;
struct mutex lock;
}; };
/******************************************************************************* /*******************************************************************************
@@ -127,42 +129,50 @@ static void scaling_limit(struct devfreq *df, unsigned long *freq)
static void podgov_enable(struct devfreq *df, int enable) static void podgov_enable(struct devfreq *df, int enable)
{ {
struct device *dev = df->dev.parent; struct device *dev = df->dev.parent;
struct podgov_info_rec *podgov; struct podgov_info_rec *podgov = df->data;
bool polling;
/* make sure the device is alive before doing any scaling */ /* make sure the device is alive before doing any scaling */
pm_runtime_get_noresume(dev); pm_runtime_get_noresume(dev);
mutex_lock(&podgov->lock);
mutex_lock(&df->lock); mutex_lock(&df->lock);
podgov = df->data;
trace_podgov_enabled(df->dev.parent, enable); trace_podgov_enabled(df->dev.parent, enable);
/* bad configuration. quit. */ /* bad configuration. quit. */
if (df->min_freq == df->max_freq) if (df->min_freq == df->max_freq) {
goto exit_unlock; mutex_unlock(&df->lock);
mutex_unlock(&podgov->lock);
pm_runtime_put(dev);
return;
}
/* store the enable information */ /* store the enable information */
podgov->enable = enable; podgov->enable = enable;
/* skip local adjustment if we are enabling or the device is /* skip local adjustment if we are enabling or the device is
* suspended */ * suspended */
if (enable || !pm_runtime_active(dev)) if (!enable && pm_runtime_active(dev)) {
goto exit_unlock; /* full speed */
podgov->adjustment_frequency = df->max_freq;
podgov->adjustment_type = ADJUSTMENT_LOCAL;
update_devfreq(df);
}
/* full speed */ polling = podgov->enable && !podgov->p_user;
podgov->adjustment_frequency = df->max_freq;
podgov->adjustment_type = ADJUSTMENT_LOCAL;
update_devfreq(df);
/* Need to unlock to call devfreq_monitor_suspend/resume()
* still holding podgov->lock to guarantee atomicity
*/
mutex_unlock(&df->lock); mutex_unlock(&df->lock);
pm_runtime_put(dev); if (polling)
devfreq_monitor_resume(df);
else
devfreq_monitor_suspend(df);
return; mutex_unlock(&podgov->lock);
exit_unlock:
mutex_unlock(&df->lock);
pm_runtime_put(dev); pm_runtime_put(dev);
} }
@@ -177,14 +187,15 @@ exit_unlock:
static void podgov_set_user_ctl(struct devfreq *df, int user) static void podgov_set_user_ctl(struct devfreq *df, int user)
{ {
struct device *dev = df->dev.parent; struct device *dev = df->dev.parent;
struct podgov_info_rec *podgov; struct podgov_info_rec *podgov = df->data;
int old_user; int old_user;
bool polling;
/* make sure the device is alive before doing any scaling */ /* make sure the device is alive before doing any scaling */
pm_runtime_get_noresume(dev); pm_runtime_get_noresume(dev);
mutex_lock(&podgov->lock);
mutex_lock(&df->lock); mutex_lock(&df->lock);
podgov = df->data;
trace_podgov_set_user_ctl(df->dev.parent, user); trace_podgov_set_user_ctl(df->dev.parent, user);
@@ -194,22 +205,26 @@ static void podgov_set_user_ctl(struct devfreq *df, int user)
/* skip scaling, if scaling (or the whole device) is turned off /* skip scaling, if scaling (or the whole device) is turned off
* - or the scaling already was in user mode */ * - or the scaling already was in user mode */
if (!pm_runtime_active(dev) || !podgov->enable || if (pm_runtime_active(dev) && podgov->enable && user && !old_user) {
!(user && !old_user)) /* write request */
goto exit_unlock; podgov->adjustment_frequency = podgov->p_freq_request;
podgov->adjustment_type = ADJUSTMENT_LOCAL;
update_devfreq(df);
}
/* write request */ polling = podgov->enable && !podgov->p_user;
podgov->adjustment_frequency = podgov->p_freq_request;
podgov->adjustment_type = ADJUSTMENT_LOCAL;
update_devfreq(df);
/* Need to unlock to call devfreq_monitor_suspend/resume()
* still holding podgov->lock to guarantee atomicity
*/
mutex_unlock(&df->lock); mutex_unlock(&df->lock);
pm_runtime_put(dev);
return; if (polling)
devfreq_monitor_resume(df);
else
devfreq_monitor_suspend(df);
exit_unlock: mutex_unlock(&podgov->lock);
mutex_unlock(&df->lock);
pm_runtime_put(dev); pm_runtime_put(dev);
} }
@@ -622,6 +637,8 @@ static int nvhost_pod_init(struct devfreq *df)
podgov->power_manager = df; podgov->power_manager = df;
mutex_init(&podgov->lock);
attr = &podgov->enable_3d_scaling_attr; attr = &podgov->enable_3d_scaling_attr;
attr->attr.name = "enable_3d_scaling"; attr->attr.name = "enable_3d_scaling";
attr->attr.mode = S_IWUSR | S_IRUGO; attr->attr.mode = S_IWUSR | S_IRUGO;