From 0214511e2e085b8233600467ab2b044f9f826bc8 Mon Sep 17 00:00:00 2001 From: seshendra Date: Tue, 3 Sep 2019 14:20:03 -0700 Subject: gpu: nvgpu: fix enable/disable fecs trace - This patch fixes enable/disable fecs trace logic. - Added enable_lock and enable_count to handle multiple enable/disable of fecs trace logic. - If user does trace disable twice, enable_count will become negative and when user tries to re-enable it, fecs trace will not be enabled. Bug 2672760 Bug 200542611 Change-Id: Ic7d4883b899f01dcf43058d0e7c9d1223a716c9b Signed-off-by: seshendra Reviewed-on: https://git-master.nvidia.com/r/2189371 GVS: Gerrit_Virtual_Submit Reviewed-by: Vinod Gopalakrishnakurup Reviewed-by: Alex Waterman Reviewed-by: Winnie Hsu Reviewed-by: mobile promotions Tested-by: mobile promotions --- drivers/gpu/nvgpu/gk20a/fecs_trace_gk20a.c | 141 ++++++++++++++++++----------- 1 file changed, 88 insertions(+), 53 deletions(-) (limited to 'drivers/gpu/nvgpu') diff --git a/drivers/gpu/nvgpu/gk20a/fecs_trace_gk20a.c b/drivers/gpu/nvgpu/gk20a/fecs_trace_gk20a.c index 11f1169b..ba85e3a3 100644 --- a/drivers/gpu/nvgpu/gk20a/fecs_trace_gk20a.c +++ b/drivers/gpu/nvgpu/gk20a/fecs_trace_gk20a.c @@ -59,6 +59,8 @@ struct gk20a_fecs_trace { struct nvgpu_mutex poll_lock; struct nvgpu_thread poll_task; bool init; + struct nvgpu_mutex enable_lock; + u32 enable_count; }; #ifdef CONFIG_GK20A_CTXSW_TRACE @@ -438,15 +440,23 @@ int gk20a_fecs_trace_init(struct gk20a *g) if (err) goto clean_poll_lock; + err = nvgpu_mutex_init(&trace->enable_lock); + if (err) + goto clean_hash_lock; + BUG_ON(!is_power_of_2(GK20A_FECS_TRACE_NUM_RECORDS)); hash_init(trace->pid_hash_table); __nvgpu_set_enabled(g, NVGPU_SUPPORT_FECS_CTXSW_TRACE, true); + trace->enable_count = 0; trace->init = true; return 0; +clean_hash_lock: + nvgpu_mutex_destroy(&trace->hash_lock); + clean_poll_lock: nvgpu_mutex_destroy(&trace->poll_lock); clean: @@ -579,11 +589,18 @@ int gk20a_fecs_trace_deinit(struct gk20a *g) if (!trace->init) return 0; - nvgpu_thread_stop(&trace->poll_task); + /* + * Check if tracer was enabled before attempting to stop the + * tracer thread. + */ + if (trace->enable_count > 0) { + nvgpu_thread_stop(&trace->poll_task); + } gk20a_fecs_trace_free_hash_table(g); nvgpu_mutex_destroy(&g->fecs_trace->hash_lock); nvgpu_mutex_destroy(&g->fecs_trace->poll_lock); + nvgpu_mutex_destroy(&g->fecs_trace->enable_lock); nvgpu_kfree(g, g->fecs_trace); g->fecs_trace = NULL; @@ -613,46 +630,51 @@ int gk20a_fecs_trace_enable(struct gk20a *g) if (!trace) return -EINVAL; - if (nvgpu_thread_is_running(&trace->poll_task)) - return 0; + nvgpu_mutex_acquire(&trace->enable_lock); + trace->enable_count++; - /* drop data in hw buffer */ - if (g->ops.fecs_trace.flush) - g->ops.fecs_trace.flush(g); - write = gk20a_fecs_trace_get_write_index(g); + if (trace->enable_count == 1U) { + /* drop data in hw buffer */ + if (g->ops.fecs_trace.flush) + g->ops.fecs_trace.flush(g); - if (nvgpu_is_enabled(g, NVGPU_FECS_TRACE_FEATURE_CONTROL)) { - /* - * For enabling FECS trace support, MAILBOX1's MSB - * (Bit 31:31) should be set to 1. Bits 30:0 represents - * actual pointer value. - */ - write = write | - (BIT32(NVGPU_FECS_TRACE_FEATURE_CONTROL_BIT)); - } - gk20a_fecs_trace_set_read_index(g, write); + write = gk20a_fecs_trace_get_write_index(g); - /* - * FECS ucode does a priv holdoff around the assertion of - * context reset. So, pri transactions (e.g. mailbox1 register - * write) might fail due to this. Hence, do write with ack - * i.e. write and read it back to make sure write happened for - * mailbox1. - */ - while (gk20a_fecs_trace_get_read_index(g) != write) { - nvgpu_log(g, gpu_dbg_ctxsw, "mailbox1 update failed"); + if (nvgpu_is_enabled(g, NVGPU_FECS_TRACE_FEATURE_CONTROL)) { + /* + * For enabling FECS trace support, MAILBOX1's MSB + * (Bit 31:31) should be set to 1. Bits 30:0 represents + * actual pointer value. + */ + write = write | + (BIT32(NVGPU_FECS_TRACE_FEATURE_CONTROL_BIT)); + } gk20a_fecs_trace_set_read_index(g, write); - } - err = nvgpu_thread_create(&trace->poll_task, g, - gk20a_fecs_trace_periodic_polling, __func__); - if (err) { - nvgpu_warn(g, + /* + * FECS ucode does a priv holdoff around the assertion of + * context reset. So, pri transactions (e.g. mailbox1 register + * write) might fail due to this. Hence, do write with ack + * i.e. write and read it back to make sure write happened for + * mailbox1. + */ + while (gk20a_fecs_trace_get_read_index(g) != write) { + nvgpu_log(g, gpu_dbg_ctxsw, "mailbox1 update failed"); + gk20a_fecs_trace_set_read_index(g, write); + } + + err = nvgpu_thread_create(&trace->poll_task, g, + gk20a_fecs_trace_periodic_polling, __func__); + if (err) { + nvgpu_warn(g, "failed to create FECS polling task"); - return err; + goto done; + } } - return 0; +done: + nvgpu_mutex_release(&trace->enable_lock); + return err; } int gk20a_fecs_trace_disable(struct gk20a *g) @@ -660,32 +682,45 @@ int gk20a_fecs_trace_disable(struct gk20a *g) struct gk20a_fecs_trace *trace = g->fecs_trace; int read = 0; - if (nvgpu_thread_is_running(&trace->poll_task)) - nvgpu_thread_stop(&trace->poll_task); + if (trace == NULL) { + return -EINVAL; + } - if (nvgpu_is_enabled(g, NVGPU_FECS_TRACE_FEATURE_CONTROL)) { - /* - * For disabling FECS trace support, MAILBOX1's MSB - * (Bit 31:31) should be set to 0. - */ - read = gk20a_fecs_trace_get_read_index(g) & - (~(BIT32(NVGPU_FECS_TRACE_FEATURE_CONTROL_BIT))); + nvgpu_mutex_acquire(&trace->enable_lock); + if (trace->enable_count <= 0U) { + nvgpu_mutex_release(&trace->enable_lock); + return 0; + } + trace->enable_count--; + if (trace->enable_count == 0U) { + if (nvgpu_is_enabled(g, NVGPU_FECS_TRACE_FEATURE_CONTROL)) { + /* + * For disabling FECS trace support, MAILBOX1's MSB + * (Bit 31:31) should be set to 0. + */ + read = gk20a_fecs_trace_get_read_index(g) & + (~(BIT32(NVGPU_FECS_TRACE_FEATURE_CONTROL_BIT))); - gk20a_fecs_trace_set_read_index(g, read); + gk20a_fecs_trace_set_read_index(g, read); - /* - * FECS ucode does a priv holdoff around the assertion - * of context reset. So, pri transactions (e.g. - * mailbox1 register write) might fail due to this. - * Hence, do write with ack i.e. write and read it back - * to make sure write happened for mailbox1. - */ - while (gk20a_fecs_trace_get_read_index(g) != read) { - nvgpu_log(g, gpu_dbg_ctxsw, + /* + * FECS ucode does a priv holdoff around the assertion + * of context reset. So, pri transactions (e.g. + * mailbox1 register write) might fail due to this. + * Hence, do write with ack i.e. write and read it back + * to make sure write happened for mailbox1. + */ + while (gk20a_fecs_trace_get_read_index(g) != read) { + nvgpu_log(g, gpu_dbg_ctxsw, "mailbox1 update failed"); - gk20a_fecs_trace_set_read_index(g, read); + gk20a_fecs_trace_set_read_index(g, read); + } } + + nvgpu_thread_stop(&trace->poll_task); + } + nvgpu_mutex_release(&trace->enable_lock); return -EPERM; } -- cgit v1.2.2