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 <sgadagottu@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/2189371
GVS: Gerrit_Virtual_Submit
Reviewed-by: Vinod Gopalakrishnakurup <vinodg@nvidia.com>
Reviewed-by: Alex Waterman <alexw@nvidia.com>
Reviewed-by: Winnie Hsu <whsu@nvidia.com>
Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com>
Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
seshendra
2019-09-03 14:20:03 -07:00
committed by mobile promotions
parent 07ddc5aaad
commit 0214511e2e

View File

@@ -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))
if (trace == NULL) {
return -EINVAL;
}
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);
/*
* 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);
}
}
nvgpu_thread_stop(&trace->poll_task);
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);
/*
* 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);
}
}
nvgpu_mutex_release(&trace->enable_lock);
return -EPERM;
}