Commit | Line | Data |
---|---|---|
6fa3eb70 S |
1 | #include <linux/version.h> |
2 | #include <linux/workqueue.h> | |
3 | #include <linux/sched.h> | |
4 | #include <asm/atomic.h> | |
db9a41fa | 5 | #include <linux/module.h> |
6fa3eb70 S |
6 | |
7 | #if (LINUX_VERSION_CODE < KERNEL_VERSION(3,10,0)) | |
8 | #include <linux/sync.h> | |
9 | #else | |
10 | #include <../drivers/staging/android/sync.h> | |
11 | #endif | |
12 | ||
765691f5 | 13 | #include <linux/mtk_gpu_utility.h> |
db9a41fa S |
14 | #include <trace/events/gpu.h> |
15 | #ifdef GED_DVFS_ENABLE | |
16 | #include <mt_gpufreq.h> | |
17 | #endif | |
18 | ||
6fa3eb70 | 19 | #include "ged_monitor_3D_fence.h" |
db9a41fa | 20 | |
6fa3eb70 S |
21 | #include "ged_log.h" |
22 | #include "ged_base.h" | |
db9a41fa S |
23 | #include "ged_type.h" |
24 | #include "ged_dvfs.h" | |
25 | ||
26 | #include <asm/div64.h> | |
6fa3eb70 S |
27 | |
28 | static atomic_t g_i32Count = ATOMIC_INIT(0); | |
db9a41fa S |
29 | static unsigned int ged_monitor_3D_fence_debug = 0; |
30 | static unsigned int ged_monitor_3D_fence_disable = 0; | |
31 | static unsigned int ged_monitor_3D_fence_systrace = 0; | |
32 | static unsigned long g_ul3DFenceDoneTime = 0; | |
33 | ||
34 | ||
35 | extern bool mtk_get_bottom_gpu_freq(unsigned int *pui32FreqLevel); | |
6fa3eb70 S |
36 | |
37 | #ifdef GED_DEBUG_MONITOR_3D_FENCE | |
38 | extern GED_LOG_BUF_HANDLE ghLogBuf_GED; | |
39 | #endif | |
db9a41fa | 40 | extern GED_LOG_BUF_HANDLE ghLogBuf_DVFS; |
6fa3eb70 S |
41 | |
42 | typedef struct GED_MONITOR_3D_FENCE_TAG | |
43 | { | |
db9a41fa | 44 | struct sync_fence_waiter sSyncWaiter; |
6fa3eb70 | 45 | struct work_struct sWork; |
db9a41fa | 46 | struct sync_fence* psSyncFence; |
6fa3eb70 S |
47 | } GED_MONITOR_3D_FENCE; |
48 | ||
49 | static void ged_sync_cb(struct sync_fence *fence, struct sync_fence_waiter *waiter) | |
50 | { | |
51 | GED_MONITOR_3D_FENCE *psMonitor; | |
db9a41fa S |
52 | unsigned long long t; |
53 | ||
54 | t = ged_get_time(); | |
55 | ||
56 | ||
57 | do_div(t,1000); | |
58 | ||
59 | ged_monitor_3D_fence_notify(); | |
60 | ged_dvfs_cal_gpu_utilization_force(); | |
6fa3eb70 | 61 | psMonitor = GED_CONTAINER_OF(waiter, GED_MONITOR_3D_FENCE, sSyncWaiter); |
db9a41fa S |
62 | |
63 | ged_log_buf_print(ghLogBuf_DVFS, "[-] ged_monitor_3D_fence_done (ts=%llu) %p", t, psMonitor->psSyncFence); | |
64 | ||
65 | schedule_work(&psMonitor->sWork); | |
6fa3eb70 S |
66 | } |
67 | ||
68 | static void ged_monitor_3D_fence_work_cb(struct work_struct *psWork) | |
69 | { | |
70 | GED_MONITOR_3D_FENCE *psMonitor; | |
71 | ||
db9a41fa | 72 | |
6fa3eb70 | 73 | #ifdef GED_DEBUG_MONITOR_3D_FENCE |
db9a41fa | 74 | ged_log_buf_print(ghLogBuf_GED, "ged_monitor_3D_fence_work_cb"); |
6fa3eb70 S |
75 | #endif |
76 | ||
db9a41fa S |
77 | if (atomic_sub_return(1, &g_i32Count) < 1) |
78 | { | |
79 | if (0 == ged_monitor_3D_fence_disable) | |
80 | { | |
81 | unsigned int uiFreqLevelID; | |
82 | if (mtk_get_bottom_gpu_freq(&uiFreqLevelID)) | |
83 | { | |
84 | if (uiFreqLevelID > 0) | |
85 | { | |
6fa3eb70 | 86 | #ifdef GED_DEBUG_MONITOR_3D_FENCE |
db9a41fa S |
87 | ged_log_buf_print(ghLogBuf_GED, "mtk_set_bottom_gpu_freq(0)"); |
88 | #endif | |
89 | mtk_set_bottom_gpu_freq(0); | |
90 | #if 0 | |
91 | #ifdef CONFIG_MTK_SCHED_TRACERS | |
92 | if (ged_monitor_3D_fence_systrace) | |
93 | { | |
94 | unsigned long long t = cpu_clock(smp_processor_id()); | |
95 | trace_gpu_sched_switch("Smart Boost", t, 0, 0, 1); | |
96 | } | |
97 | #endif | |
6fa3eb70 | 98 | #endif |
db9a41fa S |
99 | } |
100 | } | |
101 | } | |
102 | } | |
103 | ||
104 | if (ged_monitor_3D_fence_debug > 0) | |
105 | { | |
106 | GED_LOGI("[-]3D fences count = %d\n", atomic_read(&g_i32Count)); | |
107 | } | |
6fa3eb70 S |
108 | |
109 | psMonitor = GED_CONTAINER_OF(psWork, GED_MONITOR_3D_FENCE, sWork); | |
db9a41fa S |
110 | sync_fence_put(psMonitor->psSyncFence); |
111 | ged_free(psMonitor, sizeof(GED_MONITOR_3D_FENCE)); | |
112 | } | |
113 | ||
114 | unsigned long ged_monitor_3D_fence_done_time() | |
115 | { | |
116 | return g_ul3DFenceDoneTime; | |
6fa3eb70 S |
117 | } |
118 | ||
119 | GED_ERROR ged_monitor_3D_fence_add(int fence_fd) | |
120 | { | |
db9a41fa S |
121 | int err; |
122 | unsigned long long t; | |
123 | GED_MONITOR_3D_FENCE* psMonitor; | |
124 | ||
125 | t = ged_get_time(); | |
126 | ||
127 | do_div(t,1000); | |
128 | ||
129 | psMonitor = (GED_MONITOR_3D_FENCE*)ged_alloc(sizeof(GED_MONITOR_3D_FENCE)); | |
6fa3eb70 S |
130 | |
131 | #ifdef GED_DEBUG_MONITOR_3D_FENCE | |
db9a41fa | 132 | ged_log_buf_print(ghLogBuf_GED, "[+]ged_monitor_3D_fence_add"); |
6fa3eb70 S |
133 | #endif |
134 | ||
db9a41fa S |
135 | if (!psMonitor) |
136 | { | |
137 | return GED_ERROR_OOM; | |
138 | } | |
6fa3eb70 | 139 | |
db9a41fa S |
140 | sync_fence_waiter_init(&psMonitor->sSyncWaiter, ged_sync_cb); |
141 | INIT_WORK(&psMonitor->sWork, ged_monitor_3D_fence_work_cb); | |
142 | psMonitor->psSyncFence = sync_fence_fdget(fence_fd); | |
143 | if (NULL == psMonitor->psSyncFence) | |
144 | { | |
145 | ged_free(psMonitor, sizeof(GED_MONITOR_3D_FENCE)); | |
146 | return GED_ERROR_INVALID_PARAMS; | |
147 | } | |
148 | ||
149 | ged_log_buf_print(ghLogBuf_DVFS, "[+] ged_monitor_3D_fence_add (ts=%llu) %p", t, psMonitor->psSyncFence); | |
6fa3eb70 S |
150 | |
151 | #ifdef GED_DEBUG_MONITOR_3D_FENCE | |
db9a41fa | 152 | ged_log_buf_print(ghLogBuf_GED, "[+]sync_fence_wait_async"); |
6fa3eb70 S |
153 | #endif |
154 | ||
db9a41fa | 155 | err = sync_fence_wait_async(psMonitor->psSyncFence, &psMonitor->sSyncWaiter); |
6fa3eb70 S |
156 | |
157 | #ifdef GED_DEBUG_MONITOR_3D_FENCE | |
db9a41fa | 158 | ged_log_buf_print(ghLogBuf_GED, "[-]sync_fence_wait_async, err = %d", err); |
6fa3eb70 S |
159 | #endif |
160 | ||
db9a41fa S |
161 | if ((1 == err) || (0 > err)) |
162 | { | |
163 | sync_fence_put(psMonitor->psSyncFence); | |
164 | ged_free(psMonitor, sizeof(GED_MONITOR_3D_FENCE)); | |
165 | } | |
166 | else if (0 == err) | |
167 | { | |
168 | int iCount = atomic_add_return (1, &g_i32Count); | |
169 | if (iCount > 1) | |
170 | { | |
171 | if (0 == ged_monitor_3D_fence_disable) | |
172 | { | |
173 | unsigned int uiFreqLevelID; | |
174 | if (mtk_get_bottom_gpu_freq(&uiFreqLevelID)) | |
175 | { | |
176 | #ifdef GED_DVFS_ENABLE | |
177 | if (uiFreqLevelID != mt_gpufreq_get_dvfs_table_num() - 1) | |
178 | #else | |
179 | if (uiFreqLevelID != 9999) // NEVER TRUE | |
180 | #endif | |
181 | { | |
182 | #if 0 | |
183 | #ifdef CONFIG_MTK_SCHED_TRACERS | |
184 | if (ged_monitor_3D_fence_systrace) | |
185 | { | |
186 | unsigned long long t = cpu_clock(smp_processor_id()); | |
187 | trace_gpu_sched_switch("Smart Boost", t, 1, 0, 1); | |
188 | } | |
189 | #endif | |
190 | #endif | |
6fa3eb70 | 191 | |
db9a41fa S |
192 | #ifdef GED_DVFS_ENABLE |
193 | mtk_set_bottom_gpu_freq(mt_gpufreq_get_dvfs_table_num() - 1); | |
194 | #endif | |
195 | } | |
196 | } | |
197 | } | |
198 | } | |
199 | } | |
200 | ||
201 | if (ged_monitor_3D_fence_debug > 0) | |
202 | { | |
203 | GED_LOGI("[+]3D fences count = %d\n", atomic_read(&g_i32Count)); | |
204 | } | |
6fa3eb70 | 205 | #ifdef GED_DEBUG_MONITOR_3D_FENCE |
db9a41fa | 206 | ged_log_buf_print(ghLogBuf_GED, "[-]ged_monitor_3D_fence_add, count = %d", atomic_read(&g_i32Count)); |
6fa3eb70 S |
207 | #endif |
208 | ||
db9a41fa | 209 | return GED_OK; |
6fa3eb70 S |
210 | } |
211 | ||
db9a41fa S |
212 | void ged_monitor_3D_fence_set_disable(GED_BOOL bFlag) |
213 | { | |
214 | if(bFlag!=ged_monitor_3D_fence_disable) | |
215 | { | |
216 | ged_monitor_3D_fence_disable = bFlag; | |
217 | } | |
218 | } | |
219 | ||
220 | void ged_monitor_3D_fence_notify(void) | |
221 | { | |
222 | unsigned long long t; | |
223 | ||
224 | t = ged_get_time(); | |
225 | ||
226 | do_div(t,1000); | |
227 | ||
228 | g_ul3DFenceDoneTime = (unsigned long)t; | |
229 | } | |
230 | ||
231 | ||
232 | module_param(ged_monitor_3D_fence_debug, uint, 0644); | |
233 | module_param(ged_monitor_3D_fence_disable, uint, 0644); | |
234 | module_param(ged_monitor_3D_fence_systrace, uint, 0644); |