summaryrefslogtreecommitdiffstats
path: root/drivers/devfreq
diff options
context:
space:
mode:
authorMary Do <mdo@nvidia.com>2020-06-09 12:01:16 -0400
committermobile promotions <svcmobile_promotions@nvidia.com>2020-06-16 13:53:50 -0400
commit87aa75c4ecd60a13056e32a00876b48591a520ec (patch)
treeef7c532de3fb85a799d9b67197c3b9817e55dbf0 /drivers/devfreq
parent4c608d479ed156b1b3d73ca6002501d24e1bb538 (diff)
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 Reviewed-by: automaticguardword <automaticguardword@nvidia.com> Reviewed-by: Automatic_Commit_Validation_User Reviewed-by: Mubushir Rahman <mubushirr@nvidia.com> Reviewed-by: Peng Liu <pengliu@nvidia.com> Reviewed-by: Winnie Hsu <whsu@nvidia.com> Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> GVS: Gerrit_Virtual_Submit Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
Diffstat (limited to 'drivers/devfreq')
-rw-r--r--drivers/devfreq/governor_pod_scaling.c64
1 files changed, 61 insertions, 3 deletions
diff --git a/drivers/devfreq/governor_pod_scaling.c b/drivers/devfreq/governor_pod_scaling.c
index 45864bef0..9c5006dda 100644
--- a/drivers/devfreq/governor_pod_scaling.c
+++ b/drivers/devfreq/governor_pod_scaling.c
@@ -1,5 +1,5 @@
1/* 1/*
2 * Copyright (c) 2012-2019, NVIDIA CORPORATION. All rights reserved. 2 * Copyright (c) 2012-2020, NVIDIA CORPORATION. All rights reserved.
3 * 3 *
4 * This program is free software; you can redistribute it and/or modify it 4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License, 5 * under the terms and conditions of the GNU General Public License,
@@ -61,6 +61,7 @@ static struct devfreq_governor nvhost_podgov;
61 61
62struct podgov_info_rec { 62struct podgov_info_rec {
63 int enable; 63 int enable;
64 int suspended;
64 int init; 65 int init;
65 66
66 ktime_t last_scale; 67 ktime_t last_scale;
@@ -559,6 +560,22 @@ static int nvhost_pod_estimate_freq(struct devfreq *df,
559 ktime_t now; 560 ktime_t now;
560 unsigned long long norm_load; 561 unsigned long long norm_load;
561 562
563 /* If the device is suspended, clear the history and set frequency to
564 * min freq.
565 */
566 if (pg->suspended) {
567 *freq = df->min_freq;
568 pg->last_scale = ktime_get();
569 i = 0;
570 for (; i < MAX_HISTORY_BUF_SIZE; i++)
571 pg->cycles_history_buf[i] = 0;
572 pg->history_count = 0;
573 pg->history_next = 0;
574 pg->recent_high = 0;
575 pg->freq_avg = 0;
576 return 0;
577 }
578
562 /* Ensure maximal clock when scaling is disabled */ 579 /* Ensure maximal clock when scaling is disabled */
563 if (!pg->enable) { 580 if (!pg->enable) {
564 *freq = df->max_freq; 581 *freq = df->max_freq;
@@ -681,6 +698,7 @@ static int nvhost_pod_init(struct devfreq *df)
681 698
682 /* Set scaling parameter defaults */ 699 /* Set scaling parameter defaults */
683 podgov->enable = 1; 700 podgov->enable = 1;
701 podgov->suspended = 0;
684 702
685 podgov->p_load_max = 900; 703 podgov->p_load_max = 900;
686 podgov->p_load_target = 700; 704 podgov->p_load_target = 700;
@@ -784,6 +802,46 @@ static void nvhost_pod_exit(struct devfreq *df)
784 kfree(podgov); 802 kfree(podgov);
785} 803}
786 804
805/******************************************************************************
806 * nvhost_pod_suspend(struct devfreq *df)
807 *
808 * Suspends the governor.
809 *****************************************************************************/
810
811static void nvhost_pod_suspend(struct devfreq *df)
812{
813 // Record suspension in our own data structure because we'll have to
814 // erase and restore devfreq's for this to work.
815 struct podgov_info_rec *pg = df->data;
816
817 pg->suspended = 1;
818
819 // Update frequency for the final time before going into suspension.
820 mutex_lock(&df->lock);
821 df->suspended = false;
822 update_devfreq(df);
823 df->suspended = true;
824 mutex_unlock(&df->lock);
825 devfreq_monitor_suspend(df);
826}
827
828/******************************************************************************
829 * nvhost_pod_resume(struct devfreq *df)
830 *
831 * Resumes the governor.
832 *****************************************************************************/
833
834static void nvhost_pod_resume(struct devfreq *df)
835{
836 // Update our data structure's suspension field
837 struct podgov_info_rec *pg = df->data;
838
839 pg->suspended = 0;
840
841 // Resume
842 devfreq_monitor_resume(df);
843}
844
787static int nvhost_pod_event_handler(struct devfreq *df, 845static int nvhost_pod_event_handler(struct devfreq *df,
788 unsigned int event, void *data) 846 unsigned int event, void *data)
789{ 847{
@@ -800,10 +858,10 @@ static int nvhost_pod_event_handler(struct devfreq *df,
800 devfreq_interval_update(df, (unsigned int *)data); 858 devfreq_interval_update(df, (unsigned int *)data);
801 break; 859 break;
802 case DEVFREQ_GOV_SUSPEND: 860 case DEVFREQ_GOV_SUSPEND:
803 devfreq_monitor_suspend(df); 861 nvhost_pod_suspend(df);
804 break; 862 break;
805 case DEVFREQ_GOV_RESUME: 863 case DEVFREQ_GOV_RESUME:
806 devfreq_monitor_resume(df); 864 nvhost_pod_resume(df);
807 break; 865 break;
808 default: 866 default:
809 break; 867 break;