From f347fde22f1297e4f022600d201780d5ead78114 Mon Sep 17 00:00:00 2001 From: Joshua Bakita Date: Wed, 25 Sep 2024 16:09:09 -0400 Subject: Delete no-longer-needed nvgpu headers The dependency on these was removed in commit 8340d234. --- include/gk20a/fecs_trace_gk20a.c | 744 --------------------------------------- 1 file changed, 744 deletions(-) delete mode 100644 include/gk20a/fecs_trace_gk20a.c (limited to 'include/gk20a/fecs_trace_gk20a.c') diff --git a/include/gk20a/fecs_trace_gk20a.c b/include/gk20a/fecs_trace_gk20a.c deleted file mode 100644 index 5c1c5e0..0000000 --- a/include/gk20a/fecs_trace_gk20a.c +++ /dev/null @@ -1,744 +0,0 @@ -/* - * Copyright (c) 2016-2019, NVIDIA CORPORATION. All rights reserved. - * - * Permission is hereby granted, free of charge, to any person obtaining a - * copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation - * the rights to use, copy, modify, merge, publish, distribute, sublicense, - * and/or sell copies of the Software, and to permit persons to whom the - * Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in - * all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR - * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL - * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER - * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING - * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER - * DEALINGS IN THE SOFTWARE. - */ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#include "fecs_trace_gk20a.h" -#include "gk20a.h" -#include "gr_gk20a.h" - -#include -#include - -#include -#include - -struct gk20a_fecs_trace_hash_ent { - u32 context_ptr; - pid_t pid; - struct hlist_node node; -}; - -struct gk20a_fecs_trace { - - DECLARE_HASHTABLE(pid_hash_table, GK20A_FECS_TRACE_HASH_BITS); - struct nvgpu_mutex hash_lock; - 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 -u32 gk20a_fecs_trace_record_ts_tag_invalid_ts_v(void) -{ - return ctxsw_prog_record_timestamp_timestamp_hi_tag_invalid_timestamp_v(); -} - -u32 gk20a_fecs_trace_record_ts_tag_v(u64 ts) -{ - return ctxsw_prog_record_timestamp_timestamp_hi_tag_v((u32) (ts >> 32)); -} - -u64 gk20a_fecs_trace_record_ts_timestamp_v(u64 ts) -{ - return ts & ~(((u64)ctxsw_prog_record_timestamp_timestamp_hi_tag_m()) << 32); -} - -static u32 gk20a_fecs_trace_fecs_context_ptr(struct gk20a *g, struct channel_gk20a *ch) -{ - return (u32) (nvgpu_inst_block_addr(g, &ch->inst_block) >> 12LL); -} - -int gk20a_fecs_trace_num_ts(void) -{ - return (ctxsw_prog_record_timestamp_record_size_in_bytes_v() - - sizeof(struct gk20a_fecs_trace_record)) / sizeof(u64); -} - -struct gk20a_fecs_trace_record *gk20a_fecs_trace_get_record( - struct gk20a *g, int idx) -{ - struct nvgpu_mem *mem = &g->gr.global_ctx_buffer[FECS_TRACE_BUFFER].mem; - - return (struct gk20a_fecs_trace_record *) - ((u8 *) mem->cpu_va - + (idx * ctxsw_prog_record_timestamp_record_size_in_bytes_v())); -} - -bool gk20a_fecs_trace_is_valid_record(struct gk20a_fecs_trace_record *r) -{ - /* - * testing magic_hi should suffice. magic_lo is sometimes used - * as a sequence number in experimental ucode. - */ - return (r->magic_hi - == ctxsw_prog_record_timestamp_magic_value_hi_v_value_v()); -} - -int gk20a_fecs_trace_get_read_index(struct gk20a *g) -{ - return gr_gk20a_elpg_protected_call(g, - gk20a_readl(g, gr_fecs_mailbox1_r())); -} - -int gk20a_fecs_trace_get_write_index(struct gk20a *g) -{ - return gr_gk20a_elpg_protected_call(g, - gk20a_readl(g, gr_fecs_mailbox0_r())); -} - -static int gk20a_fecs_trace_set_read_index(struct gk20a *g, int index) -{ - nvgpu_log(g, gpu_dbg_ctxsw, "set read=%d", index); - return gr_gk20a_elpg_protected_call(g, - (gk20a_writel(g, gr_fecs_mailbox1_r(), index), 0)); -} - -void gk20a_fecs_trace_hash_dump(struct gk20a *g) -{ - u32 bkt; - struct gk20a_fecs_trace_hash_ent *ent; - struct gk20a_fecs_trace *trace = g->fecs_trace; - - nvgpu_log(g, gpu_dbg_ctxsw, "dumping hash table"); - - nvgpu_mutex_acquire(&trace->hash_lock); - hash_for_each(trace->pid_hash_table, bkt, ent, node) - { - nvgpu_log(g, gpu_dbg_ctxsw, " ent=%p bkt=%x context_ptr=%x pid=%d", - ent, bkt, ent->context_ptr, ent->pid); - - } - nvgpu_mutex_release(&trace->hash_lock); -} - -static int gk20a_fecs_trace_hash_add(struct gk20a *g, u32 context_ptr, pid_t pid) -{ - struct gk20a_fecs_trace_hash_ent *he; - struct gk20a_fecs_trace *trace = g->fecs_trace; - - nvgpu_log(g, gpu_dbg_fn | gpu_dbg_ctxsw, - "adding hash entry context_ptr=%x -> pid=%d", context_ptr, pid); - - he = nvgpu_kzalloc(g, sizeof(*he)); - if (unlikely(!he)) { - nvgpu_warn(g, - "can't alloc new hash entry for context_ptr=%x pid=%d", - context_ptr, pid); - return -ENOMEM; - } - - he->context_ptr = context_ptr; - he->pid = pid; - nvgpu_mutex_acquire(&trace->hash_lock); - hash_add(trace->pid_hash_table, &he->node, context_ptr); - nvgpu_mutex_release(&trace->hash_lock); - return 0; -} - -static void gk20a_fecs_trace_hash_del(struct gk20a *g, u32 context_ptr) -{ - struct hlist_node *tmp; - struct gk20a_fecs_trace_hash_ent *ent; - struct gk20a_fecs_trace *trace = g->fecs_trace; - - nvgpu_log(g, gpu_dbg_fn | gpu_dbg_ctxsw, - "freeing hash entry context_ptr=%x", context_ptr); - - nvgpu_mutex_acquire(&trace->hash_lock); - hash_for_each_possible_safe(trace->pid_hash_table, ent, tmp, node, - context_ptr) { - if (ent->context_ptr == context_ptr) { - hash_del(&ent->node); - nvgpu_log(g, gpu_dbg_ctxsw, - "freed hash entry=%p context_ptr=%x", ent, - ent->context_ptr); - nvgpu_kfree(g, ent); - break; - } - } - nvgpu_mutex_release(&trace->hash_lock); -} - -static void gk20a_fecs_trace_free_hash_table(struct gk20a *g) -{ - u32 bkt; - struct hlist_node *tmp; - struct gk20a_fecs_trace_hash_ent *ent; - struct gk20a_fecs_trace *trace = g->fecs_trace; - - nvgpu_log(g, gpu_dbg_fn | gpu_dbg_ctxsw, "trace=%p", trace); - - nvgpu_mutex_acquire(&trace->hash_lock); - hash_for_each_safe(trace->pid_hash_table, bkt, tmp, ent, node) { - hash_del(&ent->node); - nvgpu_kfree(g, ent); - } - nvgpu_mutex_release(&trace->hash_lock); - -} - -static pid_t gk20a_fecs_trace_find_pid(struct gk20a *g, u32 context_ptr) -{ - struct gk20a_fecs_trace_hash_ent *ent; - struct gk20a_fecs_trace *trace = g->fecs_trace; - pid_t pid = 0; - - nvgpu_mutex_acquire(&trace->hash_lock); - hash_for_each_possible(trace->pid_hash_table, ent, node, context_ptr) { - if (ent->context_ptr == context_ptr) { - nvgpu_log(g, gpu_dbg_ctxsw, - "found context_ptr=%x -> pid=%d", - ent->context_ptr, ent->pid); - pid = ent->pid; - break; - } - } - nvgpu_mutex_release(&trace->hash_lock); - - return pid; -} - -/* - * Converts HW entry format to userspace-facing format and pushes it to the - * queue. - */ -static int gk20a_fecs_trace_ring_read(struct gk20a *g, int index) -{ - int i; - struct nvgpu_gpu_ctxsw_trace_entry entry = { }; - struct gk20a_fecs_trace *trace = g->fecs_trace; - pid_t cur_pid; - pid_t new_pid; - int count = 0; - - /* for now, only one VM */ - const int vmid = 0; - - struct gk20a_fecs_trace_record *r = - gk20a_fecs_trace_get_record(g, index); - - nvgpu_log(g, gpu_dbg_fn | gpu_dbg_ctxsw, - "consuming record trace=%p read=%d record=%p", trace, index, r); - - if (unlikely(!gk20a_fecs_trace_is_valid_record(r))) { - nvgpu_warn(g, - "trace=%p read=%d record=%p magic_lo=%08x magic_hi=%08x (invalid)", - trace, index, r, r->magic_lo, r->magic_hi); - return -EINVAL; - } - - /* Clear magic_hi to detect cases where CPU could read write index - * before FECS record is actually written to DRAM. This should not - * as we force FECS writes to SYSMEM by reading through PRAMIN. - */ - r->magic_hi = 0; - - cur_pid = gk20a_fecs_trace_find_pid(g, r->context_ptr); - new_pid = gk20a_fecs_trace_find_pid(g, r->new_context_ptr); - - nvgpu_log(g, gpu_dbg_fn | gpu_dbg_ctxsw, - "context_ptr=%x (pid=%d) new_context_ptr=%x (pid=%d)", - r->context_ptr, cur_pid, r->new_context_ptr, new_pid); - - entry.context_id = r->context_id; - entry.vmid = vmid; - - /* break out FECS record into trace events */ - for (i = 0; i < gk20a_fecs_trace_num_ts(); i++) { - - entry.tag = gk20a_fecs_trace_record_ts_tag_v(r->ts[i]); - entry.timestamp = gk20a_fecs_trace_record_ts_timestamp_v(r->ts[i]); - entry.timestamp <<= GK20A_FECS_TRACE_PTIMER_SHIFT; - - nvgpu_log(g, gpu_dbg_ctxsw, - "tag=%x timestamp=%llx context_id=%08x new_context_id=%08x", - entry.tag, entry.timestamp, r->context_id, - r->new_context_id); - - switch (nvgpu_gpu_ctxsw_tags_to_common_tags(entry.tag)) { - case NVGPU_GPU_CTXSW_TAG_RESTORE_START: - case NVGPU_GPU_CTXSW_TAG_CONTEXT_START: - entry.context_id = r->new_context_id; - entry.pid = new_pid; - break; - - case NVGPU_GPU_CTXSW_TAG_CTXSW_REQ_BY_HOST: - case NVGPU_GPU_CTXSW_TAG_FE_ACK: - case NVGPU_GPU_CTXSW_TAG_FE_ACK_WFI: - case NVGPU_GPU_CTXSW_TAG_FE_ACK_GFXP: - case NVGPU_GPU_CTXSW_TAG_FE_ACK_CTAP: - case NVGPU_GPU_CTXSW_TAG_FE_ACK_CILP: - case NVGPU_GPU_CTXSW_TAG_SAVE_END: - entry.context_id = r->context_id; - entry.pid = cur_pid; - break; - - default: - /* tags are not guaranteed to start at the beginning */ - WARN_ON(entry.tag && (entry.tag != NVGPU_GPU_CTXSW_TAG_INVALID_TIMESTAMP)); - continue; - } - - nvgpu_log(g, gpu_dbg_ctxsw, "tag=%x context_id=%x pid=%lld", - entry.tag, entry.context_id, entry.pid); - - if (!entry.context_id) - continue; - - gk20a_ctxsw_trace_write(g, &entry); - count++; - } - - gk20a_ctxsw_trace_wake_up(g, vmid); - return count; -} - -int gk20a_fecs_trace_poll(struct gk20a *g) -{ - struct gk20a_fecs_trace *trace = g->fecs_trace; - - int read = 0; - int write = 0; - int cnt; - int err; - - err = gk20a_busy(g); - if (unlikely(err)) - return err; - - nvgpu_mutex_acquire(&trace->poll_lock); - write = gk20a_fecs_trace_get_write_index(g); - if (unlikely((write < 0) || (write >= GK20A_FECS_TRACE_NUM_RECORDS))) { - nvgpu_err(g, - "failed to acquire write index, write=%d", write); - err = write; - goto done; - } - - read = gk20a_fecs_trace_get_read_index(g); - - cnt = CIRC_CNT(write, read, GK20A_FECS_TRACE_NUM_RECORDS); - if (!cnt) - goto done; - - nvgpu_log(g, gpu_dbg_ctxsw, - "circular buffer: read=%d (mailbox=%d) write=%d cnt=%d", - read, gk20a_fecs_trace_get_read_index(g), write, cnt); - - /* Ensure all FECS writes have made it to SYSMEM */ - g->ops.mm.fb_flush(g); - - if (nvgpu_is_enabled(g, NVGPU_FECS_TRACE_FEATURE_CONTROL)) { - /* Bits 30:0 of MAILBOX1 represents actual read pointer value */ - read = read & (~(BIT32(NVGPU_FECS_TRACE_FEATURE_CONTROL_BIT))); - } - - while (read != write) { - cnt = gk20a_fecs_trace_ring_read(g, read); - if (cnt > 0) { - nvgpu_log(g, gpu_dbg_ctxsw, - "number of trace entries added: %d", cnt); - } - - /* Get to next record. */ - read = (read + 1) & (GK20A_FECS_TRACE_NUM_RECORDS - 1); - } - - if (nvgpu_is_enabled(g, NVGPU_FECS_TRACE_FEATURE_CONTROL)) { - /* - * In the next step, read pointer is going to be updated. - * So, MSB of read pointer should be set back to 1. This will - * keep FECS trace enabled. - */ - read = read | (BIT32(NVGPU_FECS_TRACE_FEATURE_CONTROL_BIT)); - } - - /* ensure FECS records has been updated before incrementing read index */ - nvgpu_wmb(); - gk20a_fecs_trace_set_read_index(g, read); - -done: - nvgpu_mutex_release(&trace->poll_lock); - gk20a_idle(g); - return err; -} - -static int gk20a_fecs_trace_periodic_polling(void *arg) -{ - struct gk20a *g = (struct gk20a *)arg; - struct gk20a_fecs_trace *trace = g->fecs_trace; - - pr_info("%s: running\n", __func__); - - while (!nvgpu_thread_should_stop(&trace->poll_task)) { - - nvgpu_usleep_range(GK20A_FECS_TRACE_FRAME_PERIOD_US, - GK20A_FECS_TRACE_FRAME_PERIOD_US * 2); - - gk20a_fecs_trace_poll(g); - } - - return 0; -} - -size_t gk20a_fecs_trace_buffer_size(struct gk20a *g) -{ - return GK20A_FECS_TRACE_NUM_RECORDS - * ctxsw_prog_record_timestamp_record_size_in_bytes_v(); -} - -int gk20a_fecs_trace_init(struct gk20a *g) -{ - struct gk20a_fecs_trace *trace; - int err; - - trace = nvgpu_kzalloc(g, sizeof(struct gk20a_fecs_trace)); - if (!trace) { - nvgpu_warn(g, "failed to allocate fecs_trace"); - return -ENOMEM; - } - g->fecs_trace = trace; - - err = nvgpu_mutex_init(&trace->poll_lock); - if (err) - goto clean; - err = nvgpu_mutex_init(&trace->hash_lock); - 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: - nvgpu_kfree(g, trace); - g->fecs_trace = NULL; - return err; -} - -int gk20a_fecs_trace_bind_channel(struct gk20a *g, - struct channel_gk20a *ch) -{ - /* - * map our circ_buf to the context space and store the GPU VA - * in the context header. - */ - - u32 lo; - u32 hi; - u64 addr; - struct tsg_gk20a *tsg; - struct nvgpu_gr_ctx *ch_ctx; - struct gk20a_fecs_trace *trace = g->fecs_trace; - struct nvgpu_mem *mem; - u32 context_ptr = gk20a_fecs_trace_fecs_context_ptr(g, ch); - u32 aperture_mask; - - tsg = tsg_gk20a_from_ch(ch); - if (tsg == NULL) { - nvgpu_err(g, "chid: %d is not bound to tsg", ch->chid); - return -EINVAL; - } - - nvgpu_log(g, gpu_dbg_fn|gpu_dbg_ctxsw, - "chid=%d context_ptr=%x inst_block=%llx", - ch->chid, context_ptr, - nvgpu_inst_block_addr(g, &ch->inst_block)); - - tsg = tsg_gk20a_from_ch(ch); - if (!tsg) - return -EINVAL; - - ch_ctx = &tsg->gr_ctx; - mem = &ch_ctx->mem; - - if (!trace) - return -ENOMEM; - - mem = &g->gr.global_ctx_buffer[FECS_TRACE_BUFFER].mem; - - if (nvgpu_is_enabled(g, NVGPU_FECS_TRACE_VA)) { - addr = ch_ctx->global_ctx_buffer_va[FECS_TRACE_BUFFER_VA]; - nvgpu_log(g, gpu_dbg_ctxsw, "gpu_va=%llx", addr); - aperture_mask = 0; - } else { - addr = nvgpu_inst_block_addr(g, mem); - nvgpu_log(g, gpu_dbg_ctxsw, "pa=%llx", addr); - aperture_mask = nvgpu_aperture_mask(g, mem, - ctxsw_prog_main_image_context_timestamp_buffer_ptr_hi_target_sys_mem_noncoherent_f(), - ctxsw_prog_main_image_context_timestamp_buffer_ptr_hi_target_sys_mem_coherent_f(), - ctxsw_prog_main_image_context_timestamp_buffer_ptr_hi_target_vid_mem_f()); - } - if (!addr) - return -ENOMEM; - - lo = u64_lo32(addr); - hi = u64_hi32(addr); - - mem = &ch_ctx->mem; - - nvgpu_log(g, gpu_dbg_ctxsw, "addr_hi=%x addr_lo=%x count=%d", hi, - lo, GK20A_FECS_TRACE_NUM_RECORDS); - - nvgpu_mem_wr(g, mem, - ctxsw_prog_main_image_context_timestamp_buffer_control_o(), - ctxsw_prog_main_image_context_timestamp_buffer_control_num_records_f( - GK20A_FECS_TRACE_NUM_RECORDS)); - - if (nvgpu_is_enabled(g, NVGPU_FECS_TRACE_VA)) - mem = &ch->ctx_header; - - nvgpu_mem_wr(g, mem, - ctxsw_prog_main_image_context_timestamp_buffer_ptr_o(), - lo); - nvgpu_mem_wr(g, mem, - ctxsw_prog_main_image_context_timestamp_buffer_ptr_hi_o(), - ctxsw_prog_main_image_context_timestamp_buffer_ptr_v_f(hi) | - aperture_mask); - - /* pid (process identifier) in user space, corresponds to tgid (thread - * group id) in kernel space. - */ - gk20a_fecs_trace_hash_add(g, context_ptr, tsg->tgid); - - return 0; -} - -int gk20a_fecs_trace_unbind_channel(struct gk20a *g, struct channel_gk20a *ch) -{ - u32 context_ptr = gk20a_fecs_trace_fecs_context_ptr(g, ch); - - if (g->fecs_trace) { - nvgpu_log(g, gpu_dbg_fn|gpu_dbg_ctxsw, - "ch=%p context_ptr=%x", ch, context_ptr); - - if (g->ops.fecs_trace.is_enabled(g)) { - if (g->ops.fecs_trace.flush) - g->ops.fecs_trace.flush(g); - gk20a_fecs_trace_poll(g); - } - gk20a_fecs_trace_hash_del(g, context_ptr); - } - return 0; -} - -int gk20a_fecs_trace_reset(struct gk20a *g) -{ - nvgpu_log(g, gpu_dbg_fn|gpu_dbg_ctxsw, " "); - - if (!g->ops.fecs_trace.is_enabled(g)) - return 0; - - gk20a_fecs_trace_poll(g); - return gk20a_fecs_trace_set_read_index(g, 0); -} - -int gk20a_fecs_trace_deinit(struct gk20a *g) -{ - struct gk20a_fecs_trace *trace = g->fecs_trace; - - if (!trace->init) - return 0; - - /* - * 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; - return 0; -} - -int gk20a_gr_max_entries(struct gk20a *g, - struct nvgpu_gpu_ctxsw_trace_filter *filter) -{ - int n; - int tag; - - /* Compute number of entries per record, with given filter */ - for (n = 0, tag = 0; tag < gk20a_fecs_trace_num_ts(); tag++) - n += (NVGPU_GPU_CTXSW_FILTER_ISSET(tag, filter) != 0); - - /* Return max number of entries generated for the whole ring */ - return n * GK20A_FECS_TRACE_NUM_RECORDS; -} - -int gk20a_fecs_trace_enable(struct gk20a *g) -{ - struct gk20a_fecs_trace *trace = g->fecs_trace; - int write; - int err = 0; - - if (!trace) - return -EINVAL; - - nvgpu_mutex_acquire(&trace->enable_lock); - trace->enable_count++; - - if (trace->enable_count == 1U) { - /* 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 (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); - - /* - * 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"); - goto done; - } - } - -done: - nvgpu_mutex_release(&trace->enable_lock); - return err; -} - -int gk20a_fecs_trace_disable(struct gk20a *g) -{ - struct gk20a_fecs_trace *trace = g->fecs_trace; - int read = 0; - - 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); - - } - nvgpu_mutex_release(&trace->enable_lock); - - return -EPERM; -} - -bool gk20a_fecs_trace_is_enabled(struct gk20a *g) -{ - struct gk20a_fecs_trace *trace = g->fecs_trace; - - return (trace && nvgpu_thread_is_running(&trace->poll_task)); -} - -void gk20a_fecs_trace_reset_buffer(struct gk20a *g) -{ - nvgpu_log(g, gpu_dbg_fn|gpu_dbg_ctxsw, " "); - - gk20a_fecs_trace_set_read_index(g, - gk20a_fecs_trace_get_write_index(g)); -} -#endif /* CONFIG_GK20A_CTXSW_TRACE */ -- cgit v1.2.2