xref: /OK3568_Linux_fs/kernel/drivers/gpu/arm/mali400/mali/platform/arm/arm_core_scaling.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1 /*
2  * Copyright (C) 2013-2014, 2016-2017 ARM Limited. All rights reserved.
3  *
4  * This program is free software and is provided to you under the terms of the GNU General Public License version 2
5  * as published by the Free Software Foundation, and any use by you of this program is subject to the terms of such GNU licence.
6  *
7  * A copy of the licence is included with the program, and can also be obtained from Free Software
8  * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
9  */
10 
11 /**
12  * @file arm_core_scaling.c
13  * Example core scaling policy.
14  */
15 
16 #include "arm_core_scaling.h"
17 
18 #include <linux/mali/mali_utgard.h>
19 #include "mali_kernel_common.h"
20 
21 #include <linux/workqueue.h>
22 
23 static int num_cores_total;
24 static int num_cores_enabled;
25 
26 static struct work_struct wq_work;
27 
set_num_cores(struct work_struct * work)28 static void set_num_cores(struct work_struct *work)
29 {
30 	int err = mali_perf_set_num_pp_cores(num_cores_enabled);
31 	MALI_DEBUG_ASSERT(0 == err);
32 	MALI_IGNORE(err);
33 }
34 
enable_one_core(void)35 static void enable_one_core(void)
36 {
37 	if (num_cores_enabled < num_cores_total) {
38 		++num_cores_enabled;
39 		schedule_work(&wq_work);
40 		MALI_DEBUG_PRINT(3, ("Core scaling: Enabling one more core\n"));
41 	}
42 
43 	MALI_DEBUG_ASSERT(1 <= num_cores_enabled);
44 	MALI_DEBUG_ASSERT(num_cores_total >= num_cores_enabled);
45 }
46 
disable_one_core(void)47 static void disable_one_core(void)
48 {
49 	if (1 < num_cores_enabled) {
50 		--num_cores_enabled;
51 		schedule_work(&wq_work);
52 		MALI_DEBUG_PRINT(3, ("Core scaling: Disabling one core\n"));
53 	}
54 
55 	MALI_DEBUG_ASSERT(1 <= num_cores_enabled);
56 	MALI_DEBUG_ASSERT(num_cores_total >= num_cores_enabled);
57 }
58 
enable_max_num_cores(void)59 static void enable_max_num_cores(void)
60 {
61 	if (num_cores_enabled < num_cores_total) {
62 		num_cores_enabled = num_cores_total;
63 		schedule_work(&wq_work);
64 		MALI_DEBUG_PRINT(3, ("Core scaling: Enabling maximum number of cores\n"));
65 	}
66 
67 	MALI_DEBUG_ASSERT(num_cores_total == num_cores_enabled);
68 }
69 
mali_core_scaling_init(int num_pp_cores)70 void mali_core_scaling_init(int num_pp_cores)
71 {
72 	INIT_WORK(&wq_work, set_num_cores);
73 
74 	num_cores_total   = num_pp_cores;
75 	num_cores_enabled = num_pp_cores;
76 
77 	/* NOTE: Mali is not fully initialized at this point. */
78 }
79 
mali_core_scaling_sync(int num_cores)80 void mali_core_scaling_sync(int num_cores)
81 {
82 	num_cores_enabled = num_cores;
83 }
84 
mali_core_scaling_term(void)85 void mali_core_scaling_term(void)
86 {
87 	flush_scheduled_work();
88 }
89 
90 #define PERCENT_OF(percent, max) ((int) ((percent)*(max)/100.0 + 0.5))
91 
mali_core_scaling_update(struct mali_gpu_utilization_data * data)92 void mali_core_scaling_update(struct mali_gpu_utilization_data *data)
93 {
94 	/*
95 	 * This function implements a very trivial PP core scaling algorithm.
96 	 *
97 	 * It is _NOT_ of production quality.
98 	 * The only intention behind this algorithm is to exercise and test the
99 	 * core scaling functionality of the driver.
100 	 * It is _NOT_ tuned for neither power saving nor performance!
101 	 *
102 	 * Other metrics than PP utilization need to be considered as well
103 	 * in order to make a good core scaling algorithm.
104 	 */
105 
106 	MALI_DEBUG_PRINT(3, ("Utilization: (%3d, %3d, %3d), cores enabled: %d/%d\n", data->utilization_gpu, data->utilization_gp, data->utilization_pp, num_cores_enabled, num_cores_total));
107 
108 	/* NOTE: this function is normally called directly from the utilization callback which is in
109 	 * timer context. */
110 
111 	if (PERCENT_OF(90, 256) < data->utilization_pp) {
112 		enable_max_num_cores();
113 	} else if (PERCENT_OF(50, 256) < data->utilization_pp) {
114 		enable_one_core();
115 	} else if (PERCENT_OF(40, 256) < data->utilization_pp) {
116 		/* do nothing */
117 	} else if (PERCENT_OF(0, 256) < data->utilization_pp) {
118 		disable_one_core();
119 	} else {
120 		/* do nothing */
121 	}
122 }
123