e95d60df0feccbd37d3f899888cca63d1c214cd4
[firefly-linux-kernel-4.4.55.git] / drivers / gpu / arm / mali400 / mali / platform / rk30 / arm_core_scaling.c
1 /*
2  * This confidential and proprietary software may be used only as
3  * authorised by a licensing agreement from ARM Limited
4  * (C) COPYRIGHT 2013-2014 ARM Limited
5  * ALL RIGHTS RESERVED
6  * The entire notice above must be reproduced on all authorised
7  * copies and copies may only be made to the extent permitted
8  * by a licensing agreement from ARM Limited.
9  */
10
11 /**
12  * @file arm_core_scaling.c
13  * Example core scaling policy.
14  */
15
16 /* #define ENABLE_DEBUG_LOG */
17 #include "custom_log.h"
18
19 #include "arm_core_scaling.h"
20
21 #include <linux/mali/mali_utgard.h>
22 #include "mali_kernel_common.h"
23
24 #include <linux/workqueue.h>
25
26 static int num_cores_total;
27 static int num_cores_enabled;
28
29 /**
30  * 对连续的 request_to_disable_on_core 的计数.
31  */
32 static int count_of_requests_to_disable_one_core;
33 /**
34  * 在 count_of_requests_to_disable_one_core 等于本 value 的时候,
35  * 将执行确实的 disable_one_core 操作.
36  */
37 #define NUM_OF_REQUESTS_TO_REALLY_DISABLE_ONE_CORE              (10)
38
39 static struct work_struct wq_work;
40
41 static void set_num_cores(struct work_struct *work)
42 {
43         int err = mali_perf_set_num_pp_cores(num_cores_enabled);
44
45         MALI_DEBUG_ASSERT(0 == err);
46         MALI_IGNORE(err);
47 }
48
49 static void enable_one_core(void)
50 {
51         if (num_cores_enabled < num_cores_total) {
52                 ++num_cores_enabled;
53                 schedule_work(&wq_work);
54                 MALI_DEBUG_PRINT(3, ("Core scaling: Enabling one more core\n"));
55         }
56
57         MALI_DEBUG_ASSERT(1 <= num_cores_enabled);
58         MALI_DEBUG_ASSERT(num_cores_total >= num_cores_enabled);
59 }
60
61 static void disable_one_core(void)
62 {
63         if (1 < num_cores_enabled) {
64                 --num_cores_enabled;
65                 schedule_work(&wq_work);
66                 MALI_DEBUG_PRINT(3, ("Core scaling: Disabling one core\n"));
67         }
68
69         MALI_DEBUG_ASSERT(1 <= num_cores_enabled);
70         MALI_DEBUG_ASSERT(num_cores_total >= num_cores_enabled);
71 }
72
73 static void enable_max_num_cores(void)
74 {
75         if (num_cores_enabled < num_cores_total) {
76                 num_cores_enabled = num_cores_total;
77                 schedule_work(&wq_work);
78                 MALI_DEBUG_PRINT(3,
79                                  ("Core scaling: Enabling max num of cores\n"));
80         }
81
82         MALI_DEBUG_ASSERT(num_cores_total == num_cores_enabled);
83 }
84
85 void mali_core_scaling_init(int num_pp_cores)
86 {
87         INIT_WORK(&wq_work, set_num_cores);
88
89         num_cores_total   = num_pp_cores;
90         num_cores_enabled = num_pp_cores;
91
92         /* NOTE: Mali is not fully initialized at this point. */
93 }
94
95 void mali_core_scaling_sync(int num_cores)
96 {
97         num_cores_enabled = num_cores;
98 }
99
100 void mali_core_scaling_term(void)
101 {
102         flush_scheduled_work();
103 }
104
105 #define PERCENT_OF(percent, max) ((int) ((percent)*(max)/100.0 + 0.5))
106
107 void mali_core_scaling_update(struct mali_gpu_utilization_data *data)
108 {
109         /*
110          * This function implements a very trivial PP core scaling algorithm.
111          *
112          * It is _NOT_ of production quality.
113          * The only intention behind this algorithm is to exercise and test the
114          * core scaling functionality of the driver.
115          * It is _NOT_ tuned for neither power saving nor performance!
116          *
117          * Other metrics than PP utilization need to be considered as well
118          * in order to make a good core scaling algorithm.
119          */
120
121         MALI_DEBUG_PRINT(3,
122                          ("Utilization:(%3d, %3d, %3d), cores enabled: %d/%d\n",
123                           data->utilization_gpu,
124                           data->utilization_gp,
125                           data->utilization_pp,
126                           num_cores_enabled,
127                           num_cores_total));
128
129         /* NOTE:
130          * this function
131          * is normally called directly
132          *      from the utilization callback
133          *              which is in timer context. */
134
135         if (PERCENT_OF(90, 256) < data->utilization_pp) {
136                 V("to enable max num of pp_cores.");
137                 enable_max_num_cores();
138                 count_of_requests_to_disable_one_core = 0;
139         } else if (PERCENT_OF(50, 256) < data->utilization_pp) {
140                 V("to enable more one pp_core.");
141                 enable_one_core();
142                 count_of_requests_to_disable_one_core = 0;
143         } else if (PERCENT_OF(40, 256) < data->utilization_pp) {
144                 count_of_requests_to_disable_one_core = 0;
145         } else if (PERCENT_OF(0, 256) < data->utilization_pp) {
146                 count_of_requests_to_disable_one_core++;
147                 if (count_of_requests_to_disable_one_core
148                         >= NUM_OF_REQUESTS_TO_REALLY_DISABLE_ONE_CORE) {
149                         V("to disable a pp_core.");
150                         disable_one_core();
151                         count_of_requests_to_disable_one_core = 0;
152                 }
153         } else {
154                 count_of_requests_to_disable_one_core = 0;
155         }
156 }