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:
Mary Do
2020-06-09 09:01:16 -07:00
committed by Laxman Dewangan
parent cd1ab69066
commit 3961eaa5a4

View File

@@ -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;