mirror of
git://nv-tegra.nvidia.com/linux-nvgpu.git
synced 2025-12-25 11:04:51 +03:00
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:
committed by
mobile promotions
parent
07ddc5aaad
commit
0214511e2e
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user