mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-22 09:11:26 +03:00
podgov: Clear history and set freq before suspend
While the device is active, devfreq calls into podgov to set the device frequency based on the device workload. When the device goes into suspension, devfreq would do one last call into podgov before going into suspension. However, because podgov decides the frequency based on the history of previous loads, if the load drops suddenly (i.e. going from 100% to 0%), this last call might result in the frequency set high and kept high until devfreq resumes running. In this change, podgov would check if the device has been suspended, and if so, it would clear the history and set the frequency to min freq before suspending devfreq. As a result, whenever the device is suspended, its frequency will be set to min freq. Bug 200613859 Change-Id: I1ad2fd563407d53177a84f8fddbf47b699fa97b5 Signed-off-by: Mary Do <mdo@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2358085 (cherry picked from commit 87aa75c4ecd60a13056e32a00876b48591a520ec) Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2363435 Tested-by: mobile promotions <svcmobile_promotions@nvidia.com> Reviewed-by: automaticguardword <automaticguardword@nvidia.com> Reviewed-by: Winnie Hsu <whsu@nvidia.com> Reviewed-by: Alex Waterman <alexw@nvidia.com> Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> GVS: Gerrit_Virtual_Submit
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright (c) 2012-2019, NVIDIA CORPORATION. All rights reserved.
|
||||
* Copyright (c) 2012-2020, NVIDIA CORPORATION. All rights reserved.
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
@@ -61,6 +61,7 @@ static struct devfreq_governor nvhost_podgov;
|
||||
|
||||
struct podgov_info_rec {
|
||||
int enable;
|
||||
int suspended;
|
||||
int init;
|
||||
|
||||
ktime_t last_scale;
|
||||
@@ -555,6 +556,22 @@ static int nvhost_pod_estimate_freq(struct devfreq *df,
|
||||
ktime_t now;
|
||||
unsigned long long norm_load;
|
||||
|
||||
/* If the device is suspended, clear the history and set frequency to
|
||||
* min freq.
|
||||
*/
|
||||
if (pg->suspended) {
|
||||
*freq = df->min_freq;
|
||||
pg->last_scale = ktime_get();
|
||||
i = 0;
|
||||
for (; i < MAX_HISTORY_BUF_SIZE; i++)
|
||||
pg->cycles_history_buf[i] = 0;
|
||||
pg->history_count = 0;
|
||||
pg->history_next = 0;
|
||||
pg->recent_high = 0;
|
||||
pg->freq_avg = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Ensure maximal clock when scaling is disabled */
|
||||
if (!pg->enable) {
|
||||
*freq = df->max_freq;
|
||||
@@ -677,6 +694,7 @@ static int nvhost_pod_init(struct devfreq *df)
|
||||
|
||||
/* Set scaling parameter defaults */
|
||||
podgov->enable = 1;
|
||||
podgov->suspended = 0;
|
||||
|
||||
podgov->p_load_max = 900;
|
||||
podgov->p_load_target = 700;
|
||||
@@ -780,6 +798,46 @@ static void nvhost_pod_exit(struct devfreq *df)
|
||||
kfree(podgov);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* nvhost_pod_suspend(struct devfreq *df)
|
||||
*
|
||||
* Suspends the governor.
|
||||
*****************************************************************************/
|
||||
|
||||
static void nvhost_pod_suspend(struct devfreq *df)
|
||||
{
|
||||
// Record suspension in our own data structure because we'll have to
|
||||
// erase and restore devfreq's for this to work.
|
||||
struct podgov_info_rec *pg = df->data;
|
||||
|
||||
pg->suspended = 1;
|
||||
|
||||
// Update frequency for the final time before going into suspension.
|
||||
mutex_lock(&df->lock);
|
||||
df->suspended = false;
|
||||
update_devfreq(df);
|
||||
df->suspended = true;
|
||||
mutex_unlock(&df->lock);
|
||||
devfreq_monitor_suspend(df);
|
||||
}
|
||||
|
||||
/******************************************************************************
|
||||
* nvhost_pod_resume(struct devfreq *df)
|
||||
*
|
||||
* Resumes the governor.
|
||||
*****************************************************************************/
|
||||
|
||||
static void nvhost_pod_resume(struct devfreq *df)
|
||||
{
|
||||
// Update our data structure's suspension field
|
||||
struct podgov_info_rec *pg = df->data;
|
||||
|
||||
pg->suspended = 0;
|
||||
|
||||
// Resume
|
||||
devfreq_monitor_resume(df);
|
||||
}
|
||||
|
||||
static int nvhost_pod_event_handler(struct devfreq *df,
|
||||
unsigned int event, void *data)
|
||||
{
|
||||
@@ -796,10 +854,10 @@ static int nvhost_pod_event_handler(struct devfreq *df,
|
||||
devfreq_interval_update(df, (unsigned int *)data);
|
||||
break;
|
||||
case DEVFREQ_GOV_SUSPEND:
|
||||
devfreq_monitor_suspend(df);
|
||||
nvhost_pod_suspend(df);
|
||||
break;
|
||||
case DEVFREQ_GOV_RESUME:
|
||||
devfreq_monitor_resume(df);
|
||||
nvhost_pod_resume(df);
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
|
||||
Reference in New Issue
Block a user