diff options
Diffstat (limited to 'drivers/gpu/nvgpu/common/pmu')
-rw-r--r-- | drivers/gpu/nvgpu/common/pmu/pmu_ipc.c | 35 | ||||
-rw-r--r-- | drivers/gpu/nvgpu/common/pmu/pmu_perfmon.c | 136 |
2 files changed, 165 insertions, 6 deletions
diff --git a/drivers/gpu/nvgpu/common/pmu/pmu_ipc.c b/drivers/gpu/nvgpu/common/pmu/pmu_ipc.c index 829fee19..2811a4b0 100644 --- a/drivers/gpu/nvgpu/common/pmu/pmu_ipc.c +++ b/drivers/gpu/nvgpu/common/pmu/pmu_ipc.c | |||
@@ -925,8 +925,9 @@ int nvgpu_pmu_process_message(struct nvgpu_pmu *pmu) | |||
925 | nvgpu_pmu_process_init_msg(pmu, &msg); | 925 | nvgpu_pmu_process_init_msg(pmu, &msg); |
926 | if (g->ops.pmu.init_wpr_region != NULL) | 926 | if (g->ops.pmu.init_wpr_region != NULL) |
927 | g->ops.pmu.init_wpr_region(g); | 927 | g->ops.pmu.init_wpr_region(g); |
928 | |||
928 | if (nvgpu_is_enabled(g, NVGPU_PMU_PERFMON)) | 929 | if (nvgpu_is_enabled(g, NVGPU_PMU_PERFMON)) |
929 | nvgpu_pmu_init_perfmon(pmu); | 930 | g->ops.pmu.pmu_init_perfmon(pmu); |
930 | 931 | ||
931 | return 0; | 932 | return 0; |
932 | } | 933 | } |
@@ -978,6 +979,8 @@ static void pmu_rpc_handler(struct gk20a *g, struct pmu_msg *msg, | |||
978 | void *param, u32 handle, u32 status) | 979 | void *param, u32 handle, u32 status) |
979 | { | 980 | { |
980 | struct nv_pmu_rpc_header rpc; | 981 | struct nv_pmu_rpc_header rpc; |
982 | struct nvgpu_pmu *pmu = &g->pmu; | ||
983 | struct nv_pmu_rpc_struct_perfmon_query *rpc_param; | ||
981 | 984 | ||
982 | memset(&rpc, 0, sizeof(struct nv_pmu_rpc_header)); | 985 | memset(&rpc, 0, sizeof(struct nv_pmu_rpc_header)); |
983 | if (param) | 986 | if (param) |
@@ -990,10 +993,36 @@ static void pmu_rpc_handler(struct gk20a *g, struct pmu_msg *msg, | |||
990 | } | 993 | } |
991 | 994 | ||
992 | switch (msg->hdr.unit_id) { | 995 | switch (msg->hdr.unit_id) { |
996 | case PMU_UNIT_PERFMON_T18X: | ||
997 | case PMU_UNIT_PERFMON: | ||
998 | switch (rpc.function) { | ||
999 | case NV_PMU_RPC_ID_PERFMON_T18X_INIT: | ||
1000 | nvgpu_pmu_dbg(g, | ||
1001 | "reply NV_PMU_RPC_ID_PERFMON_INIT"); | ||
1002 | pmu->perfmon_ready = 1; | ||
1003 | break; | ||
1004 | case NV_PMU_RPC_ID_PERFMON_T18X_START: | ||
1005 | nvgpu_pmu_dbg(g, | ||
1006 | "reply NV_PMU_RPC_ID_PERFMON_START"); | ||
1007 | break; | ||
1008 | case NV_PMU_RPC_ID_PERFMON_T18X_STOP: | ||
1009 | nvgpu_pmu_dbg(g, | ||
1010 | "reply NV_PMU_RPC_ID_PERFMON_STOP"); | ||
1011 | break; | ||
1012 | case NV_PMU_RPC_ID_PERFMON_T18X_QUERY: | ||
1013 | nvgpu_pmu_dbg(g, | ||
1014 | "reply NV_PMU_RPC_ID_PERFMON_QUERY"); | ||
1015 | rpc_param = (struct nv_pmu_rpc_struct_perfmon_query *)param; | ||
1016 | pmu->load = rpc_param->sample_buffer[0]; | ||
1017 | pmu->perfmon_query = 1; | ||
1018 | /* set perfmon_query to 1 after load is copied */ | ||
1019 | break; | ||
1020 | } | ||
1021 | break; | ||
993 | /* TBD case will be added */ | 1022 | /* TBD case will be added */ |
994 | default: | 1023 | default: |
995 | nvgpu_err(g, " Invalid RPC response, stats 0x%x", | 1024 | nvgpu_err(g, " Invalid RPC response, stats 0x%x", |
996 | rpc.flcn_status); | 1025 | rpc.flcn_status); |
997 | break; | 1026 | break; |
998 | } | 1027 | } |
999 | 1028 | ||
diff --git a/drivers/gpu/nvgpu/common/pmu/pmu_perfmon.c b/drivers/gpu/nvgpu/common/pmu/pmu_perfmon.c index 2b952868..25d81b60 100644 --- a/drivers/gpu/nvgpu/common/pmu/pmu_perfmon.c +++ b/drivers/gpu/nvgpu/common/pmu/pmu_perfmon.c | |||
@@ -221,11 +221,18 @@ int nvgpu_pmu_load_update(struct gk20a *g) | |||
221 | 221 | ||
222 | if (!pmu->perfmon_ready) { | 222 | if (!pmu->perfmon_ready) { |
223 | pmu->load_shadow = 0; | 223 | pmu->load_shadow = 0; |
224 | pmu->load = 0; | ||
224 | return 0; | 225 | return 0; |
225 | } | 226 | } |
226 | 227 | ||
227 | nvgpu_flcn_copy_from_dmem(pmu->flcn, pmu->sample_buffer, | 228 | if (g->ops.pmu.pmu_perfmon_get_samples_rpc) { |
228 | (u8 *)&load, 2, 0); | 229 | nvgpu_pmu_perfmon_get_samples_rpc(pmu); |
230 | load = pmu->load; | ||
231 | } else { | ||
232 | nvgpu_flcn_copy_from_dmem(pmu->flcn, pmu->sample_buffer, | ||
233 | (u8 *)&load, 2 * 1, 0); | ||
234 | } | ||
235 | |||
229 | pmu->load_shadow = load / 10; | 236 | pmu->load_shadow = load / 10; |
230 | pmu->load_avg = (((9*pmu->load_avg) + pmu->load_shadow) / 10); | 237 | pmu->load_avg = (((9*pmu->load_avg) + pmu->load_shadow) / 10); |
231 | 238 | ||
@@ -288,6 +295,129 @@ int nvgpu_pmu_handle_perfmon_event(struct nvgpu_pmu *pmu, | |||
288 | 295 | ||
289 | /* restart sampling */ | 296 | /* restart sampling */ |
290 | if (pmu->perfmon_sampling_enabled) | 297 | if (pmu->perfmon_sampling_enabled) |
291 | return nvgpu_pmu_perfmon_start_sampling(pmu); | 298 | return g->ops.pmu.pmu_perfmon_start_sampling(&(g->pmu)); |
299 | |||
292 | return 0; | 300 | return 0; |
293 | } | 301 | } |
302 | |||
303 | /* Perfmon RPC */ | ||
304 | int nvgpu_pmu_init_perfmon_rpc(struct nvgpu_pmu *pmu) | ||
305 | { | ||
306 | struct gk20a *g = gk20a_from_pmu(pmu); | ||
307 | struct nv_pmu_rpc_struct_perfmon_init rpc; | ||
308 | int status = 0; | ||
309 | |||
310 | if (!nvgpu_is_enabled(g, NVGPU_PMU_PERFMON)) | ||
311 | return 0; | ||
312 | |||
313 | nvgpu_log_fn(g, " "); | ||
314 | |||
315 | memset(&rpc, 0, sizeof(struct nv_pmu_rpc_struct_perfmon_init)); | ||
316 | pmu->perfmon_ready = 0; | ||
317 | |||
318 | gk20a_pmu_init_perfmon_counter(g); | ||
319 | |||
320 | /* microseconds interval between pmu polls perf counters */ | ||
321 | rpc.sample_periodus = 16700; | ||
322 | /* number of sample periods below lower threshold | ||
323 | * before pmu triggers perfmon decrease event | ||
324 | */ | ||
325 | rpc.to_decrease_count = 15; | ||
326 | /* index of base counter, aka. always ticking counter */ | ||
327 | rpc.base_counter_id = 6; | ||
328 | /* moving average window for sample periods */ | ||
329 | rpc.samples_in_moving_avg = 17; | ||
330 | /* number of perfmon counters | ||
331 | * counter #3 (GR and CE2) for gk20a | ||
332 | */ | ||
333 | rpc.num_counters = 1; | ||
334 | |||
335 | memset(rpc.counter, 0, sizeof(struct pmu_perfmon_counter_v3) * | ||
336 | NV_PMU_PERFMON_MAX_COUNTERS); | ||
337 | /* Counter used to count GR busy cycles */ | ||
338 | rpc.counter[0].index = 3; | ||
339 | |||
340 | nvgpu_pmu_dbg(g, "RPC post NV_PMU_RPC_ID_PERFMON_INIT"); | ||
341 | PMU_RPC_EXECUTE(status, pmu, PERFMON_T18X, INIT, &rpc, 0); | ||
342 | if (status) { | ||
343 | nvgpu_err(g, "Failed to execute RPC, status=0x%x", status); | ||
344 | goto exit; | ||
345 | } | ||
346 | |||
347 | exit: | ||
348 | return 0; | ||
349 | } | ||
350 | |||
351 | int nvgpu_pmu_perfmon_start_sampling_rpc(struct nvgpu_pmu *pmu) | ||
352 | { | ||
353 | struct gk20a *g = gk20a_from_pmu(pmu); | ||
354 | struct nv_pmu_rpc_struct_perfmon_start rpc; | ||
355 | int status = 0; | ||
356 | |||
357 | if (!nvgpu_is_enabled(g, NVGPU_PMU_PERFMON)) | ||
358 | return 0; | ||
359 | |||
360 | nvgpu_log_fn(g, " "); | ||
361 | |||
362 | memset(&rpc, 0, sizeof(struct nv_pmu_rpc_struct_perfmon_start)); | ||
363 | rpc.group_id = PMU_DOMAIN_GROUP_PSTATE; | ||
364 | rpc.state_id = pmu->perfmon_state_id[PMU_DOMAIN_GROUP_PSTATE]; | ||
365 | rpc.flags = PMU_PERFMON_FLAG_ENABLE_INCREASE | | ||
366 | PMU_PERFMON_FLAG_ENABLE_DECREASE | | ||
367 | PMU_PERFMON_FLAG_CLEAR_PREV; | ||
368 | |||
369 | rpc.counter[0].upper_threshold = 3000; | ||
370 | rpc.counter[0].lower_threshold = 1000; | ||
371 | |||
372 | nvgpu_pmu_dbg(g, "RPC post NV_PMU_RPC_ID_PERFMON_START\n"); | ||
373 | PMU_RPC_EXECUTE(status, pmu, PERFMON_T18X, START, &rpc, 0); | ||
374 | if (status) | ||
375 | nvgpu_err(g, "Failed to execute RPC, status=0x%x", status); | ||
376 | |||
377 | return status; | ||
378 | } | ||
379 | |||
380 | int nvgpu_pmu_perfmon_stop_sampling_rpc(struct nvgpu_pmu *pmu) | ||
381 | { | ||
382 | struct gk20a *g = gk20a_from_pmu(pmu); | ||
383 | struct nv_pmu_rpc_struct_perfmon_stop rpc; | ||
384 | int status = 0; | ||
385 | |||
386 | if (!nvgpu_is_enabled(g, NVGPU_PMU_PERFMON)) | ||
387 | return 0; | ||
388 | |||
389 | nvgpu_log_fn(g, " "); | ||
390 | |||
391 | memset(&rpc, 0, sizeof(struct nv_pmu_rpc_struct_perfmon_stop)); | ||
392 | /* PERFMON Stop */ | ||
393 | nvgpu_pmu_dbg(g, "RPC post NV_PMU_RPC_ID_PERFMON_STOP\n"); | ||
394 | PMU_RPC_EXECUTE(status, pmu, PERFMON_T18X, STOP, &rpc, 0); | ||
395 | if (status) | ||
396 | nvgpu_err(g, "Failed to execute RPC, status=0x%x", status); | ||
397 | |||
398 | return status; | ||
399 | } | ||
400 | |||
401 | int nvgpu_pmu_perfmon_get_samples_rpc(struct nvgpu_pmu *pmu) | ||
402 | { | ||
403 | struct gk20a *g = gk20a_from_pmu(pmu); | ||
404 | struct nv_pmu_rpc_struct_perfmon_query rpc; | ||
405 | int status = 0; | ||
406 | |||
407 | if (!nvgpu_is_enabled(g, NVGPU_PMU_PERFMON)) | ||
408 | return 0; | ||
409 | |||
410 | nvgpu_log_fn(g, " "); | ||
411 | pmu->perfmon_query = 0; | ||
412 | memset(&rpc, 0, sizeof(struct nv_pmu_rpc_struct_perfmon_query)); | ||
413 | /* PERFMON QUERY */ | ||
414 | nvgpu_pmu_dbg(g, "RPC post NV_PMU_RPC_ID_PERFMON_QUERY\n"); | ||
415 | PMU_RPC_EXECUTE(status, pmu, PERFMON_T18X, QUERY, &rpc, 0); | ||
416 | if (status) | ||
417 | nvgpu_err(g, "Failed to execute RPC, status=0x%x", status); | ||
418 | |||
419 | pmu_wait_message_cond(pmu, gk20a_get_gr_idle_timeout(g), | ||
420 | &pmu->perfmon_query, 1); | ||
421 | |||
422 | return status; | ||
423 | } | ||