summaryrefslogtreecommitdiffstats
path: root/drivers/gpu
diff options
context:
space:
mode:
authorMahantesh Kumbar <mkumbar@nvidia.com>2017-06-06 05:56:32 -0400
committermobile promotions <svcmobile_promotions@nvidia.com>2017-06-12 14:03:37 -0400
commit69dee6a648ad434b75e1a9c64b022ee45d3ff87b (patch)
treeeba316aa07b17760afb1609b331bb3cf0602e545 /drivers/gpu
parent914bb78a7dc0687b349310cc28613ea4a4c0be33 (diff)
gpu: nvgpu: reorganize PMU init
- Moved PMU init code from pmu_gk20a.c to "drivers/gpu/nvgpu/common/pmu/pmu.c" file - Moved below related methods SW/HW init, init msg handler, deinit/destroy, PMU state machine -Created HAL methods to read message queue tail & supported mutex count. -prepend with nvgpu_ for pmu init global mehtods JIRA NVGPU-56 JIRA NVGPU-92 Change-Id: Iea9efc194fefa74fb5641d2b2f4633577d2c3a47 Signed-off-by: Mahantesh Kumbar <mkumbar@nvidia.com> Reviewed-on: http://git-master/r/1480002 Reviewed-by: svccoveritychecker <svccoveritychecker@nvidia.com> GVS: Gerrit_Virtual_Submit Reviewed-by: Terje Bergstrom <tbergstrom@nvidia.com>
Diffstat (limited to 'drivers/gpu')
-rw-r--r--drivers/gpu/nvgpu/Makefile.nvgpu1
-rw-r--r--drivers/gpu/nvgpu/common/linux/debug_pmu.c8
-rw-r--r--drivers/gpu/nvgpu/common/pmu/pmu.c425
-rw-r--r--drivers/gpu/nvgpu/gk20a/gk20a.c5
-rw-r--r--drivers/gpu/nvgpu/gk20a/gk20a.h3
-rw-r--r--drivers/gpu/nvgpu/gk20a/pmu_gk20a.c443
-rw-r--r--drivers/gpu/nvgpu/gk20a/pmu_gk20a.h17
-rw-r--r--drivers/gpu/nvgpu/gm20b/pmu_gm20b.c2
-rw-r--r--drivers/gpu/nvgpu/gp106/pmu_gp106.c2
-rw-r--r--drivers/gpu/nvgpu/gp10b/pmu_gp10b.c2
-rw-r--r--drivers/gpu/nvgpu/include/nvgpu/pmu.h24
11 files changed, 492 insertions, 440 deletions
diff --git a/drivers/gpu/nvgpu/Makefile.nvgpu b/drivers/gpu/nvgpu/Makefile.nvgpu
index 35e9d84a..f398e384 100644
--- a/drivers/gpu/nvgpu/Makefile.nvgpu
+++ b/drivers/gpu/nvgpu/Makefile.nvgpu
@@ -58,6 +58,7 @@ nvgpu-y := \
58 common/rbtree.o \ 58 common/rbtree.o \
59 common/vbios/bios.o \ 59 common/vbios/bios.o \
60 common/falcon/falcon.o \ 60 common/falcon/falcon.o \
61 common/pmu/pmu.o \
61 common/pmu/pmu_ipc.o \ 62 common/pmu/pmu_ipc.o \
62 gk20a/gk20a.o \ 63 gk20a/gk20a.o \
63 gk20a/bus_gk20a.o \ 64 gk20a/bus_gk20a.o \
diff --git a/drivers/gpu/nvgpu/common/linux/debug_pmu.c b/drivers/gpu/nvgpu/common/linux/debug_pmu.c
index 918672db..7d9f5ac3 100644
--- a/drivers/gpu/nvgpu/common/linux/debug_pmu.c
+++ b/drivers/gpu/nvgpu/common/linux/debug_pmu.c
@@ -75,7 +75,7 @@ static int mscg_stat_show(struct seq_file *s, void *data)
75 if (err) 75 if (err)
76 return err; 76 return err;
77 77
78 gk20a_pmu_get_pg_stats(g, 78 nvgpu_pmu_get_pg_stats(g,
79 PMU_PG_ELPG_ENGINE_ID_MS, &pg_stat_data); 79 PMU_PG_ELPG_ENGINE_ID_MS, &pg_stat_data);
80 gk20a_idle(g); 80 gk20a_idle(g);
81 } 81 }
@@ -133,7 +133,7 @@ static int mscg_transitions_show(struct seq_file *s, void *data)
133 if (err) 133 if (err)
134 return err; 134 return err;
135 135
136 gk20a_pmu_get_pg_stats(g, 136 nvgpu_pmu_get_pg_stats(g,
137 PMU_PG_ELPG_ENGINE_ID_MS, &pg_stat_data); 137 PMU_PG_ELPG_ENGINE_ID_MS, &pg_stat_data);
138 gk20a_idle(g); 138 gk20a_idle(g);
139 } 139 }
@@ -169,7 +169,7 @@ static int elpg_stat_show(struct seq_file *s, void *data)
169 if (err) 169 if (err)
170 return err; 170 return err;
171 171
172 gk20a_pmu_get_pg_stats(g, 172 nvgpu_pmu_get_pg_stats(g,
173 PMU_PG_ELPG_ENGINE_ID_GRAPHICS, &pg_stat_data); 173 PMU_PG_ELPG_ENGINE_ID_GRAPHICS, &pg_stat_data);
174 gk20a_idle(g); 174 gk20a_idle(g);
175 } 175 }
@@ -226,7 +226,7 @@ static int elpg_transitions_show(struct seq_file *s, void *data)
226 if (err) 226 if (err)
227 return err; 227 return err;
228 228
229 gk20a_pmu_get_pg_stats(g, 229 nvgpu_pmu_get_pg_stats(g,
230 PMU_PG_ELPG_ENGINE_ID_GRAPHICS, &pg_stat_data); 230 PMU_PG_ELPG_ENGINE_ID_GRAPHICS, &pg_stat_data);
231 gk20a_idle(g); 231 gk20a_idle(g);
232 } 232 }
diff --git a/drivers/gpu/nvgpu/common/pmu/pmu.c b/drivers/gpu/nvgpu/common/pmu/pmu.c
new file mode 100644
index 00000000..90db07b4
--- /dev/null
+++ b/drivers/gpu/nvgpu/common/pmu/pmu.c
@@ -0,0 +1,425 @@
1/*
2 * Copyright (c) 2017, NVIDIA CORPORATION. All rights reserved.
3 *
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,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 */
13
14#include <nvgpu/pmu.h>
15#include <nvgpu/dma.h>
16#include <nvgpu/log.h>
17#include <nvgpu/pmuif/nvgpu_gpmu_cmdif.h>
18
19#include "gk20a/gk20a.h"
20
21static int nvgpu_pg_init_task(void *arg);
22
23static int nvgpu_init_task_pg_init(struct gk20a *g)
24{
25 struct nvgpu_pmu *pmu = &g->pmu;
26 char thread_name[64];
27 int err = 0;
28
29 nvgpu_log_fn(g, " ");
30
31 nvgpu_cond_init(&pmu->pg_init.wq);
32
33 snprintf(thread_name, sizeof(thread_name),
34 "nvgpu_pg_init_%s", g->name);
35
36 err = nvgpu_thread_create(&pmu->pg_init.state_task, g,
37 nvgpu_pg_init_task, thread_name);
38 if (err)
39 nvgpu_err(g, "failed to start nvgpu_pg_init thread");
40
41 return err;
42}
43
44static int nvgpu_init_pmu_setup_sw(struct gk20a *g)
45{
46 struct nvgpu_pmu *pmu = &g->pmu;
47 struct mm_gk20a *mm = &g->mm;
48 struct vm_gk20a *vm = mm->pmu.vm;
49 unsigned int i;
50 int err = 0;
51 u8 *ptr;
52
53 nvgpu_log_fn(g, " ");
54
55 /* start with elpg disabled until first enable call */
56 pmu->elpg_refcnt = 0;
57
58 /* Create thread to handle PMU state machine */
59 nvgpu_init_task_pg_init(g);
60
61 if (pmu->sw_ready) {
62 for (i = 0; i < pmu->mutex_cnt; i++) {
63 pmu->mutex[i].id = i;
64 pmu->mutex[i].index = i;
65 }
66 nvgpu_pmu_seq_init(pmu);
67
68 nvgpu_log_fn(g, "skip init");
69 goto skip_init;
70 }
71
72 /* no infoRom script from vbios? */
73
74 /* TBD: sysmon subtask */
75
76 if (IS_ENABLED(CONFIG_TEGRA_GK20A_PERFMON))
77 pmu->perfmon_sampling_enabled = true;
78
79 pmu->mutex_cnt = g->ops.pmu.pmu_mutex_size();
80 pmu->mutex = nvgpu_kzalloc(g, pmu->mutex_cnt *
81 sizeof(struct pmu_mutex));
82 if (!pmu->mutex) {
83 err = -ENOMEM;
84 goto err;
85 }
86
87 for (i = 0; i < pmu->mutex_cnt; i++) {
88 pmu->mutex[i].id = i;
89 pmu->mutex[i].index = i;
90 }
91
92 pmu->seq = nvgpu_kzalloc(g, PMU_MAX_NUM_SEQUENCES *
93 sizeof(struct pmu_sequence));
94 if (!pmu->seq) {
95 err = -ENOMEM;
96 goto err_free_mutex;
97 }
98
99 nvgpu_pmu_seq_init(pmu);
100
101 err = nvgpu_dma_alloc_map_sys(vm, GK20A_PMU_SEQ_BUF_SIZE,
102 &pmu->seq_buf);
103 if (err) {
104 nvgpu_err(g, "failed to allocate memory");
105 goto err_free_seq;
106 }
107
108 ptr = (u8 *)pmu->seq_buf.cpu_va;
109
110 /* TBD: remove this if ZBC save/restore is handled by PMU
111 * end an empty ZBC sequence for now
112 */
113 ptr[0] = 0x16; /* opcode EXIT */
114 ptr[1] = 0; ptr[2] = 1; ptr[3] = 0;
115 ptr[4] = 0; ptr[5] = 0; ptr[6] = 0; ptr[7] = 0;
116
117 pmu->seq_buf.size = GK20A_PMU_SEQ_BUF_SIZE;
118
119 err = nvgpu_dma_alloc_map(vm, GK20A_PMU_TRACE_BUFSIZE,
120 &pmu->trace_buf);
121 if (err) {
122 nvgpu_err(g, "failed to allocate pmu trace buffer\n");
123 goto err_free_seq_buf;
124 }
125
126 pmu->sw_ready = true;
127
128skip_init:
129 nvgpu_log_fn(g, "done");
130 return 0;
131 err_free_seq_buf:
132 nvgpu_dma_unmap_free(vm, &pmu->seq_buf);
133 err_free_seq:
134 nvgpu_kfree(g, pmu->seq);
135 err_free_mutex:
136 nvgpu_kfree(g, pmu->mutex);
137 err:
138 nvgpu_log_fn(g, "fail");
139 return err;
140}
141
142static int nvgpu_init_pmu_reset_enable_hw(struct gk20a *g)
143{
144 struct nvgpu_pmu *pmu = &g->pmu;
145
146 nvgpu_log_fn(g, " ");
147
148 pmu_enable_hw(pmu, true);
149
150 return 0;
151}
152
153int nvgpu_init_pmu_support(struct gk20a *g)
154{
155 struct nvgpu_pmu *pmu = &g->pmu;
156 u32 err;
157
158 nvgpu_log_fn(g, " ");
159
160 if (pmu->initialized)
161 return 0;
162
163 err = nvgpu_init_pmu_reset_enable_hw(g);
164 if (err)
165 return err;
166
167 if (g->support_pmu) {
168 err = nvgpu_init_pmu_setup_sw(g);
169 if (err)
170 return err;
171 err = g->ops.pmu.pmu_setup_hw_and_bootstrap(g);
172 if (err)
173 return err;
174
175 nvgpu_pmu_state_change(g, PMU_STATE_STARTING, false);
176 }
177
178 return err;
179}
180
181int nvgpu_pmu_process_init_msg(struct nvgpu_pmu *pmu,
182 struct pmu_msg *msg)
183{
184 struct gk20a *g = gk20a_from_pmu(pmu);
185 struct pmu_v *pv = &g->ops.pmu_ver;
186 union pmu_init_msg_pmu *init;
187 struct pmu_sha1_gid_data gid_data;
188 u32 i, tail = 0;
189
190 nvgpu_log_fn(g, " ");
191
192 nvgpu_pmu_dbg(g, "init received\n");
193
194 g->ops.pmu.pmu_msgq_tail(pmu, &tail, QUEUE_GET);
195
196 pmu_copy_from_dmem(pmu, tail,
197 (u8 *)&msg->hdr, PMU_MSG_HDR_SIZE, 0);
198 if (msg->hdr.unit_id != PMU_UNIT_INIT) {
199 nvgpu_err(g, "expecting init msg");
200 return -EINVAL;
201 }
202
203 pmu_copy_from_dmem(pmu, tail + PMU_MSG_HDR_SIZE,
204 (u8 *)&msg->msg, msg->hdr.size - PMU_MSG_HDR_SIZE, 0);
205
206 if (msg->msg.init.msg_type != PMU_INIT_MSG_TYPE_PMU_INIT) {
207 nvgpu_err(g, "expecting init msg");
208 return -EINVAL;
209 }
210
211 tail += ALIGN(msg->hdr.size, PMU_DMEM_ALIGNMENT);
212 g->ops.pmu.pmu_msgq_tail(pmu, &tail, QUEUE_SET);
213
214 init = pv->get_pmu_msg_pmu_init_msg_ptr(&(msg->msg.init));
215 if (!pmu->gid_info.valid) {
216
217 pmu_copy_from_dmem(pmu,
218 pv->get_pmu_init_msg_pmu_sw_mg_off(init),
219 (u8 *)&gid_data,
220 sizeof(struct pmu_sha1_gid_data), 0);
221
222 pmu->gid_info.valid =
223 (*(u32 *)gid_data.signature == PMU_SHA1_GID_SIGNATURE);
224
225 if (pmu->gid_info.valid) {
226
227 BUG_ON(sizeof(pmu->gid_info.gid) !=
228 sizeof(gid_data.gid));
229
230 memcpy(pmu->gid_info.gid, gid_data.gid,
231 sizeof(pmu->gid_info.gid));
232 }
233 }
234
235 for (i = 0; i < PMU_QUEUE_COUNT; i++)
236 nvgpu_pmu_queue_init(pmu, i, init);
237
238 if (!nvgpu_alloc_initialized(&pmu->dmem)) {
239 /* Align start and end addresses */
240 u32 start = ALIGN(pv->get_pmu_init_msg_pmu_sw_mg_off(init),
241 PMU_DMEM_ALLOC_ALIGNMENT);
242 u32 end = (pv->get_pmu_init_msg_pmu_sw_mg_off(init) +
243 pv->get_pmu_init_msg_pmu_sw_mg_size(init)) &
244 ~(PMU_DMEM_ALLOC_ALIGNMENT - 1);
245 u32 size = end - start;
246
247 nvgpu_bitmap_allocator_init(g, &pmu->dmem, "gk20a_pmu_dmem",
248 start, size, PMU_DMEM_ALLOC_ALIGNMENT, 0);
249 }
250
251 pmu->pmu_ready = true;
252
253 nvgpu_pmu_state_change(g, PMU_STATE_INIT_RECEIVED, true);
254
255 nvgpu_pmu_dbg(g, "init received end\n");
256
257 return 0;
258}
259
260static void pmu_setup_hw_enable_elpg(struct gk20a *g)
261{
262 struct nvgpu_pmu *pmu = &g->pmu;
263
264 nvgpu_log_fn(g, " ");
265
266 pmu->initialized = true;
267 nvgpu_pmu_state_change(g, PMU_STATE_STARTED, false);
268
269 if (g->ops.pmu_ver.is_pmu_zbc_save_supported) {
270 /* Save zbc table after PMU is initialized. */
271 pmu->zbc_ready = true;
272 gk20a_pmu_save_zbc(g, 0xf);
273 }
274
275 if (g->elpg_enabled) {
276 /* Init reg with prod values*/
277 if (g->ops.pmu.pmu_setup_elpg)
278 g->ops.pmu.pmu_setup_elpg(g);
279 gk20a_pmu_enable_elpg(g);
280 }
281
282 nvgpu_udelay(50);
283
284 /* Enable AELPG */
285 if (g->aelpg_enabled) {
286 gk20a_aelpg_init(g);
287 gk20a_aelpg_init_and_enable(g, PMU_AP_CTRL_ID_GRAPHICS);
288 }
289}
290
291void nvgpu_pmu_state_change(struct gk20a *g, u32 pmu_state,
292 bool post_change_event)
293{
294 struct nvgpu_pmu *pmu = &g->pmu;
295
296 nvgpu_pmu_dbg(g, "pmu_state - %d", pmu_state);
297
298 pmu->pmu_state = pmu_state;
299
300 if (post_change_event) {
301 pmu->pg_init.state_change = true;
302 nvgpu_cond_signal(&pmu->pg_init.wq);
303 }
304
305 /* make status visible */
306 smp_mb();
307}
308
309static int nvgpu_pg_init_task(void *arg)
310{
311 struct gk20a *g = (struct gk20a *)arg;
312 struct nvgpu_pmu *pmu = &g->pmu;
313 struct nvgpu_pg_init *pg_init = &pmu->pg_init;
314 u32 pmu_state = 0;
315
316 nvgpu_log_fn(g, "thread start");
317
318 while (true) {
319
320 NVGPU_COND_WAIT(&pg_init->wq,
321 (pg_init->state_change == true), 0);
322
323 pmu->pg_init.state_change = false;
324 pmu_state = ACCESS_ONCE(pmu->pmu_state);
325
326 if (pmu_state == PMU_STATE_EXIT) {
327 nvgpu_pmu_dbg(g, "pmu state exit");
328 break;
329 }
330
331 switch (pmu_state) {
332 case PMU_STATE_INIT_RECEIVED:
333 nvgpu_pmu_dbg(g, "pmu starting");
334 if (g->can_elpg)
335 nvgpu_pmu_init_powergating(g);
336 break;
337 case PMU_STATE_ELPG_BOOTED:
338 nvgpu_pmu_dbg(g, "elpg booted");
339 nvgpu_pmu_init_bind_fecs(g);
340 break;
341 case PMU_STATE_LOADING_PG_BUF:
342 nvgpu_pmu_dbg(g, "loaded pg buf");
343 nvgpu_pmu_setup_hw_load_zbc(g);
344 break;
345 case PMU_STATE_LOADING_ZBC:
346 nvgpu_pmu_dbg(g, "loaded zbc");
347 pmu_setup_hw_enable_elpg(g);
348 break;
349 case PMU_STATE_STARTED:
350 nvgpu_pmu_dbg(g, "PMU booted");
351 break;
352 default:
353 nvgpu_pmu_dbg(g, "invalid state");
354 break;
355 }
356
357 }
358
359 while (!nvgpu_thread_should_stop(&pg_init->state_task))
360 nvgpu_msleep(5);
361
362 nvgpu_log_fn(g, "thread exit");
363
364 return 0;
365}
366
367int nvgpu_pmu_destroy(struct gk20a *g)
368{
369 struct nvgpu_pmu *pmu = &g->pmu;
370 struct pmu_pg_stats_data pg_stat_data = { 0 };
371 struct nvgpu_timeout timeout;
372 int i;
373
374 nvgpu_log_fn(g, " ");
375
376 if (!g->support_pmu)
377 return 0;
378
379 /* make sure the pending operations are finished before we continue */
380 if (nvgpu_thread_is_running(&pmu->pg_init.state_task)) {
381
382 /* post PMU_STATE_EXIT to exit PMU state machine loop */
383 nvgpu_pmu_state_change(g, PMU_STATE_EXIT, true);
384
385 /* Make thread stop*/
386 nvgpu_thread_stop(&pmu->pg_init.state_task);
387
388 /* wait to confirm thread stopped */
389 nvgpu_timeout_init(g, &timeout, 1000, NVGPU_TIMER_RETRY_TIMER);
390 do {
391 if (!nvgpu_thread_is_running(&pmu->pg_init.state_task))
392 break;
393 nvgpu_udelay(2);
394 } while (!nvgpu_timeout_expired_msg(&timeout,
395 "timeout - waiting PMU state machine thread stop"));
396 }
397
398 nvgpu_pmu_get_pg_stats(g,
399 PMU_PG_ELPG_ENGINE_ID_GRAPHICS, &pg_stat_data);
400
401 gk20a_pmu_disable_elpg(g);
402 pmu->initialized = false;
403
404 /* update the s/w ELPG residency counters */
405 g->pg_ingating_time_us += (u64)pg_stat_data.ingating_time;
406 g->pg_ungating_time_us += (u64)pg_stat_data.ungating_time;
407 g->pg_gating_cnt += pg_stat_data.gating_cnt;
408
409 nvgpu_mutex_acquire(&pmu->isr_mutex);
410 pmu->isr_enabled = false;
411 nvgpu_mutex_release(&pmu->isr_mutex);
412
413 for (i = 0; i < PMU_QUEUE_COUNT; i++)
414 nvgpu_mutex_destroy(&pmu->queue[i].mutex);
415
416 nvgpu_pmu_state_change(g, PMU_STATE_OFF, false);
417 pmu->pmu_ready = false;
418 pmu->perfmon_ready = false;
419 pmu->zbc_ready = false;
420 g->ops.pmu.lspmuwprinitdone = false;
421 g->ops.pmu.fecsbootstrapdone = false;
422
423 nvgpu_log_fn(g, "done");
424 return 0;
425}
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.c b/drivers/gpu/nvgpu/gk20a/gk20a.c
index b038cd81..8624d601 100644
--- a/drivers/gpu/nvgpu/gk20a/gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/gk20a.c
@@ -24,6 +24,7 @@
24#include <nvgpu/timers.h> 24#include <nvgpu/timers.h>
25#include <nvgpu/soc.h> 25#include <nvgpu/soc.h>
26#include <nvgpu/enabled.h> 26#include <nvgpu/enabled.h>
27#include <nvgpu/pmu.h>
27 28
28#include <trace/events/gk20a.h> 29#include <trace/events/gk20a.h>
29 30
@@ -130,7 +131,7 @@ int gk20a_prepare_poweroff(struct gk20a *g)
130 131
131 /* disable elpg before gr or fifo suspend */ 132 /* disable elpg before gr or fifo suspend */
132 if (g->ops.pmu.is_pmu_supported(g)) 133 if (g->ops.pmu.is_pmu_supported(g))
133 ret |= gk20a_pmu_destroy(g); 134 ret |= nvgpu_pmu_destroy(g);
134 135
135 ret |= gk20a_gr_suspend(g); 136 ret |= gk20a_gr_suspend(g);
136 ret |= gk20a_mm_suspend(g); 137 ret |= gk20a_mm_suspend(g);
@@ -259,7 +260,7 @@ int gk20a_finalize_poweron(struct gk20a *g)
259#endif 260#endif
260 261
261 if (g->ops.pmu.is_pmu_supported(g)) { 262 if (g->ops.pmu.is_pmu_supported(g)) {
262 err = gk20a_init_pmu_support(g); 263 err = nvgpu_init_pmu_support(g);
263 if (err) { 264 if (err) {
264 nvgpu_err(g, "failed to init gk20a pmu"); 265 nvgpu_err(g, "failed to init gk20a pmu");
265 goto done; 266 goto done;
diff --git a/drivers/gpu/nvgpu/gk20a/gk20a.h b/drivers/gpu/nvgpu/gk20a/gk20a.h
index 269f0d68..1d867912 100644
--- a/drivers/gpu/nvgpu/gk20a/gk20a.h
+++ b/drivers/gpu/nvgpu/gk20a/gk20a.h
@@ -741,6 +741,9 @@ struct gpu_ops {
741 struct pmu_queue *queue, u32 *head, bool set); 741 struct pmu_queue *queue, u32 *head, bool set);
742 int (*pmu_queue_tail)(struct nvgpu_pmu *pmu, 742 int (*pmu_queue_tail)(struct nvgpu_pmu *pmu,
743 struct pmu_queue *queue, u32 *tail, bool set); 743 struct pmu_queue *queue, u32 *tail, bool set);
744 void (*pmu_msgq_tail)(struct nvgpu_pmu *pmu,
745 u32 *tail, bool set);
746 u32 (*pmu_mutex_size)(void);
744 int (*pmu_mutex_acquire)(struct nvgpu_pmu *pmu, 747 int (*pmu_mutex_acquire)(struct nvgpu_pmu *pmu,
745 u32 id, u32 *token); 748 u32 id, u32 *token);
746 int (*pmu_mutex_release)(struct nvgpu_pmu *pmu, 749 int (*pmu_mutex_release)(struct nvgpu_pmu *pmu,
diff --git a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c
index deab46c8..03728378 100644
--- a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c
+++ b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.c
@@ -43,19 +43,10 @@
43#define gk20a_dbg_pmu(fmt, arg...) \ 43#define gk20a_dbg_pmu(fmt, arg...) \
44 gk20a_dbg(gpu_dbg_pmu, fmt, ##arg) 44 gk20a_dbg(gpu_dbg_pmu, fmt, ##arg)
45 45
46int gk20a_pmu_get_pg_stats(struct gk20a *g,
47 u32 pg_engine_id,
48 struct pmu_pg_stats_data *pg_stat_data);
49static void ap_callback_init_and_enable_ctrl( 46static void ap_callback_init_and_enable_ctrl(
50 struct gk20a *g, struct pmu_msg *msg, 47 struct gk20a *g, struct pmu_msg *msg,
51 void *param, u32 seq_desc, u32 status); 48 void *param, u32 seq_desc, u32 status);
52 49
53static int nvgpu_init_task_pg_init(struct gk20a *g);
54static void nvgpu_pmu_state_change(struct gk20a *g, u32 pmu_state,
55 bool post_change_event);
56
57static int pmu_init_powergating(struct gk20a *g);
58
59static u32 pmu_perfmon_cntr_sz_v0(struct nvgpu_pmu *pmu) 50static u32 pmu_perfmon_cntr_sz_v0(struct nvgpu_pmu *pmu)
60{ 51{
61 return sizeof(struct pmu_perfmon_counter_v0); 52 return sizeof(struct pmu_perfmon_counter_v0);
@@ -2783,6 +2774,25 @@ int gk20a_pmu_queue_tail(struct nvgpu_pmu *pmu, struct pmu_queue *queue,
2783 return 0; 2774 return 0;
2784} 2775}
2785 2776
2777void gk20a_pmu_msgq_tail(struct nvgpu_pmu *pmu, u32 *tail, bool set)
2778{
2779 struct gk20a *g = gk20a_from_pmu(pmu);
2780 u32 queue_tail_size = 0;
2781
2782 if (g->ops.pmu.pmu_get_queue_tail_size)
2783 queue_tail_size = g->ops.pmu.pmu_get_queue_tail_size();
2784
2785 BUG_ON(!tail || !queue_tail_size);
2786
2787 if (!set)
2788 *tail = pwr_pmu_msgq_tail_val_v(
2789 gk20a_readl(g, pwr_pmu_msgq_tail_r()));
2790 else
2791 gk20a_writel(g,
2792 pwr_pmu_msgq_tail_r(),
2793 pwr_pmu_msgq_tail_val_f(*tail));
2794}
2795
2786void gk20a_remove_pmu_support(struct nvgpu_pmu *pmu) 2796void gk20a_remove_pmu_support(struct nvgpu_pmu *pmu)
2787{ 2797{
2788 struct gk20a *g = gk20a_from_pmu(pmu); 2798 struct gk20a *g = gk20a_from_pmu(pmu);
@@ -2801,17 +2811,6 @@ void gk20a_remove_pmu_support(struct nvgpu_pmu *pmu)
2801 nvgpu_mutex_destroy(&pmu->pmu_seq_lock); 2811 nvgpu_mutex_destroy(&pmu->pmu_seq_lock);
2802} 2812}
2803 2813
2804static int gk20a_init_pmu_reset_enable_hw(struct gk20a *g)
2805{
2806 struct nvgpu_pmu *pmu = &g->pmu;
2807
2808 gk20a_dbg_fn("");
2809
2810 pmu_enable_hw(pmu, true);
2811
2812 return 0;
2813}
2814
2815static int gk20a_prepare_ucode(struct gk20a *g) 2814static int gk20a_prepare_ucode(struct gk20a *g)
2816{ 2815{
2817 struct nvgpu_pmu *pmu = &g->pmu; 2816 struct nvgpu_pmu *pmu = &g->pmu;
@@ -2851,103 +2850,6 @@ static int gk20a_prepare_ucode(struct gk20a *g)
2851 return err; 2850 return err;
2852} 2851}
2853 2852
2854static int gk20a_init_pmu_setup_sw(struct gk20a *g)
2855{
2856 struct nvgpu_pmu *pmu = &g->pmu;
2857 struct mm_gk20a *mm = &g->mm;
2858 struct vm_gk20a *vm = mm->pmu.vm;
2859 unsigned int i;
2860 int err = 0;
2861 u8 *ptr;
2862
2863 gk20a_dbg_fn("");
2864
2865 /* start with elpg disabled until first enable call */
2866 pmu->elpg_refcnt = 0;
2867
2868 /* Create thread to handle PMU state machine */
2869 nvgpu_init_task_pg_init(g);
2870
2871 if (pmu->sw_ready) {
2872 for (i = 0; i < pmu->mutex_cnt; i++) {
2873 pmu->mutex[i].id = i;
2874 pmu->mutex[i].index = i;
2875 }
2876 nvgpu_pmu_seq_init(pmu);
2877
2878 gk20a_dbg_fn("skip init");
2879 goto skip_init;
2880 }
2881
2882 /* no infoRom script from vbios? */
2883
2884 /* TBD: sysmon subtask */
2885
2886 if (IS_ENABLED(CONFIG_TEGRA_GK20A_PERFMON))
2887 pmu->perfmon_sampling_enabled = true;
2888
2889 pmu->mutex_cnt = pwr_pmu_mutex__size_1_v();
2890 pmu->mutex = nvgpu_kzalloc(g, pmu->mutex_cnt *
2891 sizeof(struct pmu_mutex));
2892 if (!pmu->mutex) {
2893 err = -ENOMEM;
2894 goto err;
2895 }
2896
2897 for (i = 0; i < pmu->mutex_cnt; i++) {
2898 pmu->mutex[i].id = i;
2899 pmu->mutex[i].index = i;
2900 }
2901
2902 pmu->seq = nvgpu_kzalloc(g, PMU_MAX_NUM_SEQUENCES *
2903 sizeof(struct pmu_sequence));
2904 if (!pmu->seq) {
2905 err = -ENOMEM;
2906 goto err_free_mutex;
2907 }
2908
2909 nvgpu_pmu_seq_init(pmu);
2910
2911 err = nvgpu_dma_alloc_map_sys(vm, GK20A_PMU_SEQ_BUF_SIZE,
2912 &pmu->seq_buf);
2913 if (err) {
2914 nvgpu_err(g, "failed to allocate memory");
2915 goto err_free_seq;
2916 }
2917
2918 ptr = (u8 *)pmu->seq_buf.cpu_va;
2919
2920 /* TBD: remove this if ZBC save/restore is handled by PMU
2921 * end an empty ZBC sequence for now */
2922 ptr[0] = 0x16; /* opcode EXIT */
2923 ptr[1] = 0; ptr[2] = 1; ptr[3] = 0;
2924 ptr[4] = 0; ptr[5] = 0; ptr[6] = 0; ptr[7] = 0;
2925
2926 pmu->seq_buf.size = GK20A_PMU_SEQ_BUF_SIZE;
2927
2928 err = nvgpu_dma_alloc_map(vm, GK20A_PMU_TRACE_BUFSIZE,
2929 &pmu->trace_buf);
2930 if (err) {
2931 nvgpu_err(g, "failed to allocate pmu trace buffer");
2932 goto err_free_seq_buf;
2933 }
2934
2935 pmu->sw_ready = true;
2936
2937skip_init:
2938 gk20a_dbg_fn("done");
2939 return 0;
2940 err_free_seq_buf:
2941 nvgpu_dma_unmap_free(vm, &pmu->seq_buf);
2942 err_free_seq:
2943 nvgpu_kfree(g, pmu->seq);
2944 err_free_mutex:
2945 nvgpu_kfree(g, pmu->mutex);
2946 err:
2947 gk20a_dbg_fn("fail");
2948 return err;
2949}
2950
2951static void pmu_handle_pg_buf_config_msg(struct gk20a *g, struct pmu_msg *msg, 2853static void pmu_handle_pg_buf_config_msg(struct gk20a *g, struct pmu_msg *msg,
2952 void *param, u32 handle, u32 status) 2854 void *param, u32 handle, u32 status)
2953{ 2855{
@@ -3006,99 +2908,7 @@ static int gk20a_init_pmu_setup_hw1(struct gk20a *g)
3006 2908
3007} 2909}
3008 2910
3009static void pmu_setup_hw_load_zbc(struct gk20a *g); 2911int nvgpu_pmu_init_bind_fecs(struct gk20a *g)
3010static void pmu_setup_hw_enable_elpg(struct gk20a *g);
3011
3012static void nvgpu_pmu_state_change(struct gk20a *g, u32 pmu_state,
3013 bool post_change_event)
3014{
3015 struct nvgpu_pmu *pmu = &g->pmu;
3016
3017 pmu->pmu_state = pmu_state;
3018
3019 if (post_change_event) {
3020 pmu->pg_init.state_change = true;
3021 nvgpu_cond_signal(&pmu->pg_init.wq);
3022 }
3023
3024 /* make status visible */
3025 smp_mb();
3026}
3027
3028static int nvgpu_pg_init_task(void *arg)
3029{
3030 struct gk20a *g = (struct gk20a *)arg;
3031 struct nvgpu_pmu *pmu = &g->pmu;
3032 struct nvgpu_pg_init *pg_init = &pmu->pg_init;
3033 u32 pmu_state = 0;
3034
3035 while (true) {
3036
3037 NVGPU_COND_WAIT(&pg_init->wq,
3038 (pg_init->state_change == true), 0);
3039
3040 pmu->pg_init.state_change = false;
3041 pmu_state = ACCESS_ONCE(pmu->pmu_state);
3042
3043 if (pmu_state == PMU_STATE_EXIT) {
3044 gk20a_dbg_pmu("pmu state exit");
3045 break;
3046 }
3047
3048 switch (pmu_state) {
3049 case PMU_STATE_INIT_RECEIVED:
3050 gk20a_dbg_pmu("pmu starting");
3051 if (g->can_elpg)
3052 pmu_init_powergating(g);
3053 break;
3054 case PMU_STATE_ELPG_BOOTED:
3055 gk20a_dbg_pmu("elpg booted");
3056 gk20a_init_pmu_bind_fecs(g);
3057 break;
3058 case PMU_STATE_LOADING_PG_BUF:
3059 gk20a_dbg_pmu("loaded pg buf");
3060 pmu_setup_hw_load_zbc(g);
3061 break;
3062 case PMU_STATE_LOADING_ZBC:
3063 gk20a_dbg_pmu("loaded zbc");
3064 pmu_setup_hw_enable_elpg(g);
3065 break;
3066 case PMU_STATE_STARTED:
3067 gk20a_dbg_pmu("PMU booted");
3068 break;
3069 default:
3070 gk20a_dbg_pmu("invalid state");
3071 break;
3072 }
3073
3074 }
3075
3076 while (!nvgpu_thread_should_stop(&pg_init->state_task))
3077 nvgpu_msleep(5);
3078
3079 return 0;
3080}
3081
3082static int nvgpu_init_task_pg_init(struct gk20a *g)
3083{
3084 struct nvgpu_pmu *pmu = &g->pmu;
3085 char thread_name[64];
3086 int err = 0;
3087
3088 nvgpu_cond_init(&pmu->pg_init.wq);
3089
3090 snprintf(thread_name, sizeof(thread_name),
3091 "nvgpu_pg_init_%s", g->name);
3092
3093 err = nvgpu_thread_create(&pmu->pg_init.state_task, g,
3094 nvgpu_pg_init_task, thread_name);
3095 if (err)
3096 nvgpu_err(g, "failed to start nvgpu_pg_init thread");
3097
3098 return err;
3099}
3100
3101int gk20a_init_pmu_bind_fecs(struct gk20a *g)
3102{ 2912{
3103 struct nvgpu_pmu *pmu = &g->pmu; 2913 struct nvgpu_pmu *pmu = &g->pmu;
3104 struct pmu_cmd cmd; 2914 struct pmu_cmd cmd;
@@ -3137,7 +2947,7 @@ int gk20a_init_pmu_bind_fecs(struct gk20a *g)
3137 return err; 2947 return err;
3138} 2948}
3139 2949
3140static void pmu_setup_hw_load_zbc(struct gk20a *g) 2950void nvgpu_pmu_setup_hw_load_zbc(struct gk20a *g)
3141{ 2951{
3142 struct nvgpu_pmu *pmu = &g->pmu; 2952 struct nvgpu_pmu *pmu = &g->pmu;
3143 struct pmu_cmd cmd; 2953 struct pmu_cmd cmd;
@@ -3172,43 +2982,6 @@ static void pmu_setup_hw_load_zbc(struct gk20a *g)
3172 nvgpu_pmu_state_change(g, PMU_STATE_LOADING_ZBC, false); 2982 nvgpu_pmu_state_change(g, PMU_STATE_LOADING_ZBC, false);
3173} 2983}
3174 2984
3175static void pmu_setup_hw_enable_elpg(struct gk20a *g)
3176{
3177 struct nvgpu_pmu *pmu = &g->pmu;
3178
3179 /*
3180 * FIXME: To enable ELPG, we increase the PMU ext2priv timeout unit to
3181 * 7. This prevents PMU stalling on Host register accesses. Once the
3182 * cause for this hang is discovered and fixed, this WAR should be
3183 * removed.
3184 */
3185 gk20a_writel(g, 0x10a164, 0x109ff);
3186
3187 pmu->initialized = true;
3188 nvgpu_pmu_state_change(g, PMU_STATE_STARTED, false);
3189
3190 if (g->ops.pmu_ver.is_pmu_zbc_save_supported) {
3191 /* Save zbc table after PMU is initialized. */
3192 pmu->zbc_ready = true;
3193 gk20a_pmu_save_zbc(g, 0xf);
3194 }
3195
3196 if (g->elpg_enabled) {
3197 /* Init reg with prod values*/
3198 if (g->ops.pmu.pmu_setup_elpg)
3199 g->ops.pmu.pmu_setup_elpg(g);
3200 gk20a_pmu_enable_elpg(g);
3201 }
3202
3203 nvgpu_udelay(50);
3204
3205 /* Enable AELPG */
3206 if (g->aelpg_enabled) {
3207 gk20a_aelpg_init(g);
3208 gk20a_aelpg_init_and_enable(g, PMU_AP_CTRL_ID_GRAPHICS);
3209 }
3210}
3211
3212static void gk20a_write_dmatrfbase(struct gk20a *g, u32 addr) 2985static void gk20a_write_dmatrfbase(struct gk20a *g, u32 addr)
3213{ 2986{
3214 gk20a_writel(g, pwr_falcon_dmatrfbase_r(), addr); 2987 gk20a_writel(g, pwr_falcon_dmatrfbase_r(), addr);
@@ -3254,6 +3027,8 @@ void gk20a_init_pmu_ops(struct gpu_ops *gops)
3254 gops->pmu.pmu_get_queue_tail_size = pwr_pmu_queue_tail__size_1_v; 3027 gops->pmu.pmu_get_queue_tail_size = pwr_pmu_queue_tail__size_1_v;
3255 gops->pmu.pmu_queue_head = gk20a_pmu_queue_head; 3028 gops->pmu.pmu_queue_head = gk20a_pmu_queue_head;
3256 gops->pmu.pmu_queue_tail = gk20a_pmu_queue_tail; 3029 gops->pmu.pmu_queue_tail = gk20a_pmu_queue_tail;
3030 gops->pmu.pmu_msgq_tail = gk20a_pmu_msgq_tail;
3031 gops->pmu.pmu_mutex_size = pwr_pmu_mutex__size_1_v;
3257 gops->pmu.pmu_mutex_acquire = gk20a_pmu_mutex_acquire; 3032 gops->pmu.pmu_mutex_acquire = gk20a_pmu_mutex_acquire;
3258 gops->pmu.pmu_mutex_release = gk20a_pmu_mutex_release; 3033 gops->pmu.pmu_mutex_release = gk20a_pmu_mutex_release;
3259 gops->pmu.pmu_setup_elpg = NULL; 3034 gops->pmu.pmu_setup_elpg = NULL;
@@ -3279,34 +3054,6 @@ void gk20a_init_pmu_ops(struct gpu_ops *gops)
3279 gops->pmu.reset = gk20a_pmu_reset; 3054 gops->pmu.reset = gk20a_pmu_reset;
3280} 3055}
3281 3056
3282int gk20a_init_pmu_support(struct gk20a *g)
3283{
3284 struct nvgpu_pmu *pmu = &g->pmu;
3285 u32 err;
3286
3287 gk20a_dbg_fn("");
3288
3289 if (pmu->initialized)
3290 return 0;
3291
3292 err = gk20a_init_pmu_reset_enable_hw(g);
3293 if (err)
3294 return err;
3295
3296 if (g->support_pmu) {
3297 err = gk20a_init_pmu_setup_sw(g);
3298 if (err)
3299 return err;
3300 err = g->ops.pmu.pmu_setup_hw_and_bootstrap(g);
3301 if (err)
3302 return err;
3303
3304 nvgpu_pmu_state_change(g, PMU_STATE_STARTING, false);
3305 }
3306
3307 return err;
3308}
3309
3310static void pmu_handle_pg_elpg_msg(struct gk20a *g, struct pmu_msg *msg, 3057static void pmu_handle_pg_elpg_msg(struct gk20a *g, struct pmu_msg *msg,
3311 void *param, u32 handle, u32 status) 3058 void *param, u32 handle, u32 status)
3312{ 3059{
@@ -3453,7 +3200,8 @@ static int pmu_pg_init_send(struct gk20a *g, u32 pg_engine_id)
3453 3200
3454 return 0; 3201 return 0;
3455} 3202}
3456static int pmu_init_powergating(struct gk20a *g) 3203
3204int nvgpu_pmu_init_powergating(struct gk20a *g)
3457{ 3205{
3458 struct nvgpu_pmu *pmu = &g->pmu; 3206 struct nvgpu_pmu *pmu = &g->pmu;
3459 u32 pg_engine_id; 3207 u32 pg_engine_id;
@@ -3613,84 +3361,6 @@ int nvgpu_pmu_init_perfmon(struct nvgpu_pmu *pmu)
3613 return 0; 3361 return 0;
3614} 3362}
3615 3363
3616int nvgpu_pmu_process_init_msg(struct nvgpu_pmu *pmu,
3617 struct pmu_msg *msg)
3618{
3619 struct gk20a *g = gk20a_from_pmu(pmu);
3620 struct pmu_v *pv = &g->ops.pmu_ver;
3621 union pmu_init_msg_pmu *init;
3622 struct pmu_sha1_gid_data gid_data;
3623 u32 i, tail = 0;
3624 gk20a_dbg_pmu("init received\n");
3625
3626 tail = pwr_pmu_msgq_tail_val_v(
3627 gk20a_readl(g, pwr_pmu_msgq_tail_r()));
3628
3629 pmu_copy_from_dmem(pmu, tail,
3630 (u8 *)&msg->hdr, PMU_MSG_HDR_SIZE, 0);
3631 if (msg->hdr.unit_id != PMU_UNIT_INIT) {
3632 nvgpu_err(g, "expecting init msg");
3633 return -EINVAL;
3634 }
3635
3636 pmu_copy_from_dmem(pmu, tail + PMU_MSG_HDR_SIZE,
3637 (u8 *)&msg->msg, msg->hdr.size - PMU_MSG_HDR_SIZE, 0);
3638
3639 if (msg->msg.init.msg_type != PMU_INIT_MSG_TYPE_PMU_INIT) {
3640 nvgpu_err(g, "expecting init msg");
3641 return -EINVAL;
3642 }
3643
3644 tail += ALIGN(msg->hdr.size, PMU_DMEM_ALIGNMENT);
3645 gk20a_writel(g, pwr_pmu_msgq_tail_r(),
3646 pwr_pmu_msgq_tail_val_f(tail));
3647
3648 init = pv->get_pmu_msg_pmu_init_msg_ptr(&(msg->msg.init));
3649 if (!pmu->gid_info.valid) {
3650
3651 pmu_copy_from_dmem(pmu,
3652 pv->get_pmu_init_msg_pmu_sw_mg_off(init),
3653 (u8 *)&gid_data,
3654 sizeof(struct pmu_sha1_gid_data), 0);
3655
3656 pmu->gid_info.valid =
3657 (*(u32 *)gid_data.signature == PMU_SHA1_GID_SIGNATURE);
3658
3659 if (pmu->gid_info.valid) {
3660
3661 BUG_ON(sizeof(pmu->gid_info.gid) !=
3662 sizeof(gid_data.gid));
3663
3664 memcpy(pmu->gid_info.gid, gid_data.gid,
3665 sizeof(pmu->gid_info.gid));
3666 }
3667 }
3668
3669 for (i = 0; i < PMU_QUEUE_COUNT; i++)
3670 nvgpu_pmu_queue_init(pmu, i, init);
3671
3672 if (!nvgpu_alloc_initialized(&pmu->dmem)) {
3673 /* Align start and end addresses */
3674 u32 start = ALIGN(pv->get_pmu_init_msg_pmu_sw_mg_off(init),
3675 PMU_DMEM_ALLOC_ALIGNMENT);
3676 u32 end = (pv->get_pmu_init_msg_pmu_sw_mg_off(init) +
3677 pv->get_pmu_init_msg_pmu_sw_mg_size(init)) &
3678 ~(PMU_DMEM_ALLOC_ALIGNMENT - 1);
3679 u32 size = end - start;
3680 nvgpu_bitmap_allocator_init(g, &pmu->dmem, "gk20a_pmu_dmem",
3681 start, size,
3682 PMU_DMEM_ALLOC_ALIGNMENT, 0);
3683 }
3684
3685 pmu->pmu_ready = true;
3686
3687 nvgpu_pmu_state_change(g, PMU_STATE_INIT_RECEIVED, true);
3688
3689 gk20a_dbg_pmu("init received end\n");
3690
3691 return 0;
3692}
3693
3694static void pmu_handle_zbc_msg(struct gk20a *g, struct pmu_msg *msg, 3364static void pmu_handle_zbc_msg(struct gk20a *g, struct pmu_msg *msg,
3695 void *param, u32 handle, u32 status) 3365 void *param, u32 handle, u32 status)
3696{ 3366{
@@ -4413,66 +4083,6 @@ int gk20a_pmu_perfmon_enable(struct gk20a *g, bool enable)
4413 return err; 4083 return err;
4414} 4084}
4415 4085
4416int gk20a_pmu_destroy(struct gk20a *g)
4417{
4418 struct nvgpu_pmu *pmu = &g->pmu;
4419 struct pmu_pg_stats_data pg_stat_data = { 0 };
4420 struct nvgpu_timeout timeout;
4421 int i;
4422
4423 gk20a_dbg_fn("");
4424
4425 if (!g->support_pmu)
4426 return 0;
4427
4428 /* make sure the pending operations are finished before we continue */
4429 if (nvgpu_thread_is_running(&pmu->pg_init.state_task)) {
4430
4431 /* post PMU_STATE_EXIT to exit PMU state machine loop */
4432 nvgpu_pmu_state_change(g, PMU_STATE_EXIT, true);
4433
4434 /* Make thread stop*/
4435 nvgpu_thread_stop(&pmu->pg_init.state_task);
4436
4437 /* wait to confirm thread stopped */
4438 nvgpu_timeout_init(g, &timeout, 1000, NVGPU_TIMER_RETRY_TIMER);
4439 do {
4440 if (!nvgpu_thread_is_running(&pmu->pg_init.state_task))
4441 break;
4442 nvgpu_udelay(2);
4443 } while (!nvgpu_timeout_expired_msg(&timeout,
4444 "timeout - waiting PMU state machine thread stop"));
4445 }
4446
4447 gk20a_pmu_get_pg_stats(g,
4448 PMU_PG_ELPG_ENGINE_ID_GRAPHICS, &pg_stat_data);
4449
4450 gk20a_pmu_disable_elpg(g);
4451 pmu->initialized = false;
4452
4453 /* update the s/w ELPG residency counters */
4454 g->pg_ingating_time_us += (u64)pg_stat_data.ingating_time;
4455 g->pg_ungating_time_us += (u64)pg_stat_data.ungating_time;
4456 g->pg_gating_cnt += pg_stat_data.gating_cnt;
4457
4458 nvgpu_mutex_acquire(&pmu->isr_mutex);
4459 pmu->isr_enabled = false;
4460 nvgpu_mutex_release(&pmu->isr_mutex);
4461
4462 for (i = 0; i < PMU_QUEUE_COUNT; i++)
4463 nvgpu_mutex_destroy(&pmu->queue[i].mutex);
4464
4465 nvgpu_pmu_state_change(g, PMU_STATE_OFF, false);
4466 pmu->pmu_ready = false;
4467 pmu->perfmon_ready = false;
4468 pmu->zbc_ready = false;
4469 g->ops.pmu.lspmuwprinitdone = false;
4470 g->ops.pmu.fecsbootstrapdone = false;
4471
4472 gk20a_dbg_fn("done");
4473 return 0;
4474}
4475
4476int gk20a_pmu_load_norm(struct gk20a *g, u32 *load) 4086int gk20a_pmu_load_norm(struct gk20a *g, u32 *load)
4477{ 4087{
4478 *load = g->pmu.load_shadow; 4088 *load = g->pmu.load_shadow;
@@ -4543,8 +4153,7 @@ void gk20a_pmu_elpg_statistics(struct gk20a *g, u32 pg_engine_id,
4543 pg_stat_data->avg_exit_latency_us = stats.pg_avg_exit_time_us; 4153 pg_stat_data->avg_exit_latency_us = stats.pg_avg_exit_time_us;
4544} 4154}
4545 4155
4546int gk20a_pmu_get_pg_stats(struct gk20a *g, 4156int nvgpu_pmu_get_pg_stats(struct gk20a *g, u32 pg_engine_id,
4547 u32 pg_engine_id,
4548 struct pmu_pg_stats_data *pg_stat_data) 4157 struct pmu_pg_stats_data *pg_stat_data)
4549{ 4158{
4550 struct nvgpu_pmu *pmu = &g->pmu; 4159 struct nvgpu_pmu *pmu = &g->pmu;
diff --git a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h
index a53329b4..1c29b380 100644
--- a/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h
+++ b/drivers/gpu/nvgpu/gk20a/pmu_gk20a.h
@@ -63,15 +63,6 @@ struct pmu_surface {
63 struct flcn_mem_desc_v0 params; 63 struct flcn_mem_desc_v0 params;
64}; 64};
65 65
66/*PG defines used by nvpgu-pmu*/
67struct pmu_pg_stats_data {
68 u32 gating_cnt;
69 u32 ingating_time;
70 u32 ungating_time;
71 u32 avg_entry_latency_us;
72 u32 avg_exit_latency_us;
73};
74
75#define PMU_PG_IDLE_THRESHOLD_SIM 1000 66#define PMU_PG_IDLE_THRESHOLD_SIM 1000
76#define PMU_PG_POST_POWERUP_IDLE_THRESHOLD_SIM 4000000 67#define PMU_PG_POST_POWERUP_IDLE_THRESHOLD_SIM 4000000
77/* TBD: QT or else ? */ 68/* TBD: QT or else ? */
@@ -105,10 +96,6 @@ struct pmu_pg_stats_data {
105#define APCTRL_MINIMUM_TARGET_SAVING_DEFAULT_US (10000) 96#define APCTRL_MINIMUM_TARGET_SAVING_DEFAULT_US (10000)
106#define APCTRL_POWER_BREAKEVEN_DEFAULT_US (2000) 97#define APCTRL_POWER_BREAKEVEN_DEFAULT_US (2000)
107#define APCTRL_CYCLES_PER_SAMPLE_MAX_DEFAULT (200) 98#define APCTRL_CYCLES_PER_SAMPLE_MAX_DEFAULT (200)
108/*PG defines used by nvpgu-pmu*/
109
110int gk20a_init_pmu_support(struct gk20a *g);
111int gk20a_init_pmu_bind_fecs(struct gk20a *g);
112 99
113bool gk20a_pmu_is_interrupted(struct nvgpu_pmu *pmu); 100bool gk20a_pmu_is_interrupted(struct nvgpu_pmu *pmu);
114void gk20a_pmu_isr(struct gk20a *g); 101void gk20a_pmu_isr(struct gk20a *g);
@@ -131,8 +118,8 @@ int gk20a_pmu_queue_head(struct nvgpu_pmu *pmu, struct pmu_queue *queue,
131 u32 *head, bool set); 118 u32 *head, bool set);
132int gk20a_pmu_queue_tail(struct nvgpu_pmu *pmu, struct pmu_queue *queue, 119int gk20a_pmu_queue_tail(struct nvgpu_pmu *pmu, struct pmu_queue *queue,
133 u32 *tail, bool set); 120 u32 *tail, bool set);
121void gk20a_pmu_msgq_tail(struct nvgpu_pmu *pmu, u32 *tail, bool set);
134 122
135int gk20a_pmu_destroy(struct gk20a *g);
136int gk20a_pmu_load_norm(struct gk20a *g, u32 *load); 123int gk20a_pmu_load_norm(struct gk20a *g, u32 *load);
137int gk20a_pmu_load_update(struct gk20a *g); 124int gk20a_pmu_load_update(struct gk20a *g);
138void gk20a_pmu_reset_load_counters(struct gk20a *g); 125void gk20a_pmu_reset_load_counters(struct gk20a *g);
@@ -174,8 +161,6 @@ int gk20a_pmu_vidmem_surface_alloc(struct gk20a *g, struct nvgpu_mem *mem,
174 u32 size); 161 u32 size);
175int gk20a_pmu_sysmem_surface_alloc(struct gk20a *g, struct nvgpu_mem *mem, 162int gk20a_pmu_sysmem_surface_alloc(struct gk20a *g, struct nvgpu_mem *mem,
176 u32 size); 163 u32 size);
177int gk20a_pmu_get_pg_stats(struct gk20a *g,
178 u32 pg_engine_id, struct pmu_pg_stats_data *pg_stat_data);
179bool nvgpu_find_hex_in_string(char *strings, struct gk20a *g, u32 *hex_pos); 164bool nvgpu_find_hex_in_string(char *strings, struct gk20a *g, u32 *hex_pos);
180 165
181int nvgpu_pmu_perfmon_start_sampling(struct nvgpu_pmu *pmu); 166int nvgpu_pmu_perfmon_start_sampling(struct nvgpu_pmu *pmu);
diff --git a/drivers/gpu/nvgpu/gm20b/pmu_gm20b.c b/drivers/gpu/nvgpu/gm20b/pmu_gm20b.c
index 4fafc8f1..d501163f 100644
--- a/drivers/gpu/nvgpu/gm20b/pmu_gm20b.c
+++ b/drivers/gpu/nvgpu/gm20b/pmu_gm20b.c
@@ -294,6 +294,8 @@ void gm20b_init_pmu_ops(struct gpu_ops *gops)
294 gops->pmu.pmu_get_queue_tail_size = pwr_pmu_queue_tail__size_1_v; 294 gops->pmu.pmu_get_queue_tail_size = pwr_pmu_queue_tail__size_1_v;
295 gops->pmu.pmu_queue_head = gk20a_pmu_queue_head; 295 gops->pmu.pmu_queue_head = gk20a_pmu_queue_head;
296 gops->pmu.pmu_queue_tail = gk20a_pmu_queue_tail; 296 gops->pmu.pmu_queue_tail = gk20a_pmu_queue_tail;
297 gops->pmu.pmu_msgq_tail = gk20a_pmu_msgq_tail;
298 gops->pmu.pmu_mutex_size = pwr_pmu_mutex__size_1_v;
297 gops->pmu.pmu_mutex_acquire = gk20a_pmu_mutex_acquire; 299 gops->pmu.pmu_mutex_acquire = gk20a_pmu_mutex_acquire;
298 gops->pmu.pmu_mutex_release = gk20a_pmu_mutex_release; 300 gops->pmu.pmu_mutex_release = gk20a_pmu_mutex_release;
299 gops->pmu.lspmuwprinitdone = 0; 301 gops->pmu.lspmuwprinitdone = 0;
diff --git a/drivers/gpu/nvgpu/gp106/pmu_gp106.c b/drivers/gpu/nvgpu/gp106/pmu_gp106.c
index a9b44019..9c32d7a3 100644
--- a/drivers/gpu/nvgpu/gp106/pmu_gp106.c
+++ b/drivers/gpu/nvgpu/gp106/pmu_gp106.c
@@ -424,6 +424,8 @@ void gp106_init_pmu_ops(struct gpu_ops *gops)
424 gops->pmu.pmu_get_queue_tail_size = pwr_pmu_queue_tail__size_1_v; 424 gops->pmu.pmu_get_queue_tail_size = pwr_pmu_queue_tail__size_1_v;
425 gops->pmu.pmu_queue_head = gk20a_pmu_queue_head; 425 gops->pmu.pmu_queue_head = gk20a_pmu_queue_head;
426 gops->pmu.pmu_queue_tail = gk20a_pmu_queue_tail; 426 gops->pmu.pmu_queue_tail = gk20a_pmu_queue_tail;
427 gops->pmu.pmu_msgq_tail = gk20a_pmu_msgq_tail;
428 gops->pmu.pmu_mutex_size = pwr_pmu_mutex__size_1_v;
427 gops->pmu.pmu_mutex_acquire = gk20a_pmu_mutex_acquire; 429 gops->pmu.pmu_mutex_acquire = gk20a_pmu_mutex_acquire;
428 gops->pmu.pmu_mutex_release = gk20a_pmu_mutex_release; 430 gops->pmu.pmu_mutex_release = gk20a_pmu_mutex_release;
429 gops->pmu.lspmuwprinitdone = 0; 431 gops->pmu.lspmuwprinitdone = 0;
diff --git a/drivers/gpu/nvgpu/gp10b/pmu_gp10b.c b/drivers/gpu/nvgpu/gp10b/pmu_gp10b.c
index c89e910c..cd6bf97a 100644
--- a/drivers/gpu/nvgpu/gp10b/pmu_gp10b.c
+++ b/drivers/gpu/nvgpu/gp10b/pmu_gp10b.c
@@ -415,6 +415,8 @@ void gp10b_init_pmu_ops(struct gpu_ops *gops)
415 gops->pmu.pmu_get_queue_tail_size = pwr_pmu_queue_tail__size_1_v; 415 gops->pmu.pmu_get_queue_tail_size = pwr_pmu_queue_tail__size_1_v;
416 gops->pmu.pmu_queue_head = gk20a_pmu_queue_head; 416 gops->pmu.pmu_queue_head = gk20a_pmu_queue_head;
417 gops->pmu.pmu_queue_tail = gk20a_pmu_queue_tail; 417 gops->pmu.pmu_queue_tail = gk20a_pmu_queue_tail;
418 gops->pmu.pmu_msgq_tail = gk20a_pmu_msgq_tail;
419 gops->pmu.pmu_mutex_size = pwr_pmu_mutex__size_1_v;
418 gops->pmu.pmu_mutex_acquire = gk20a_pmu_mutex_acquire; 420 gops->pmu.pmu_mutex_acquire = gk20a_pmu_mutex_acquire;
419 gops->pmu.pmu_mutex_release = gk20a_pmu_mutex_release; 421 gops->pmu.pmu_mutex_release = gk20a_pmu_mutex_release;
420 gops->pmu.lspmuwprinitdone = false; 422 gops->pmu.lspmuwprinitdone = false;
diff --git a/drivers/gpu/nvgpu/include/nvgpu/pmu.h b/drivers/gpu/nvgpu/include/nvgpu/pmu.h
index f447e910..a4d1e0ee 100644
--- a/drivers/gpu/nvgpu/include/nvgpu/pmu.h
+++ b/drivers/gpu/nvgpu/include/nvgpu/pmu.h
@@ -335,6 +335,15 @@ struct nvgpu_pmu {
335 struct nvgpu_firmware *fw; 335 struct nvgpu_firmware *fw;
336}; 336};
337 337
338/*PG defines used by nvpgu-pmu*/
339struct pmu_pg_stats_data {
340 u32 gating_cnt;
341 u32 ingating_time;
342 u32 ungating_time;
343 u32 avg_entry_latency_us;
344 u32 avg_exit_latency_us;
345};
346
338/* PMU IPC Methods */ 347/* PMU IPC Methods */
339void nvgpu_pmu_seq_init(struct nvgpu_pmu *pmu); 348void nvgpu_pmu_seq_init(struct nvgpu_pmu *pmu);
340 349
@@ -361,7 +370,20 @@ int nvgpu_pmu_handle_therm_event(struct nvgpu_pmu *pmu,
361 struct nv_pmu_therm_msg *msg); 370 struct nv_pmu_therm_msg *msg);
362 371
363/* PMU init */ 372/* PMU init */
373int nvgpu_init_pmu_support(struct gk20a *g);
374int nvgpu_pmu_destroy(struct gk20a *g);
364int nvgpu_pmu_process_init_msg(struct nvgpu_pmu *pmu, 375int nvgpu_pmu_process_init_msg(struct nvgpu_pmu *pmu,
365 struct pmu_msg *msg); 376 struct pmu_msg *msg);
377
378void nvgpu_pmu_state_change(struct gk20a *g, u32 pmu_state,
379 bool post_change_event);
380
381/* PG */
382int nvgpu_pmu_init_powergating(struct gk20a *g);
383int nvgpu_pmu_init_bind_fecs(struct gk20a *g);
384void nvgpu_pmu_setup_hw_load_zbc(struct gk20a *g);
385
386int nvgpu_pmu_get_pg_stats(struct gk20a *g, u32 pg_engine_id,
387 struct pmu_pg_stats_data *pg_stat_data);
366 388
367#endif /* __NVGPU_PMU_H__ */ 389#endif /* __NVGPU_PMU_H__ */