From 499da418c1cd838e944b088a829f356add10ed5c Mon Sep 17 00:00:00 2001 From: Sagar Kamble Date: Sun, 17 Mar 2019 22:29:17 +0530 Subject: [PATCH] gpu: nvgpu: prepare pmu sequences unit PMU commands and messages management is based on sharing the data through sequences. Functions for sending commands/allocating payload update sequence data acquiring lock and those for working on received messages read/free the sequence data releasing lock. JIRA NVGPU-1970 Change-Id: I4204dbfbf6f57b0f5a7016aed74ffea6e91ab06c Signed-off-by: Sagar Kamble Reviewed-on: https://git-master.nvidia.com/r/2079141 Reviewed-by: mobile promotions Tested-by: mobile promotions --- drivers/gpu/nvgpu/Makefile | 1 + drivers/gpu/nvgpu/Makefile.sources | 1 + drivers/gpu/nvgpu/common/pmu/clk/clk_domain.c | 8 +- drivers/gpu/nvgpu/common/pmu/pmu.c | 13 +- drivers/gpu/nvgpu/common/pmu/pmu_fw.c | 47 +-- drivers/gpu/nvgpu/common/pmu/pmu_ipc.c | 282 ++++++++---------- drivers/gpu/nvgpu/common/pmu/pmu_seq.c | 272 +++++++++++++++++ drivers/gpu/nvgpu/include/nvgpu/flcnif_cmn.h | 2 + drivers/gpu/nvgpu/include/nvgpu/pmu.h | 63 +--- drivers/gpu/nvgpu/include/nvgpu/pmu/seq.h | 146 +++++++++ .../nvgpu/include/nvgpu/pmuif/gpmuif_acr.h | 4 +- .../gpu/nvgpu/include/nvgpu/pmuif/gpmuif_ap.h | 4 +- .../nvgpu/include/nvgpu/pmuif/gpmuif_cmn.h | 2 + .../include/nvgpu/pmuif/gpmuif_perfmon.h | 2 + .../gpu/nvgpu/include/nvgpu/pmuif/gpmuif_pg.h | 4 +- .../nvgpu/include/nvgpu/pmuif/gpmuif_pmu.h | 1 + 16 files changed, 575 insertions(+), 277 deletions(-) create mode 100644 drivers/gpu/nvgpu/common/pmu/pmu_seq.c create mode 100644 drivers/gpu/nvgpu/include/nvgpu/pmu/seq.h diff --git a/drivers/gpu/nvgpu/Makefile b/drivers/gpu/nvgpu/Makefile index ea0215288..cd80799dd 100644 --- a/drivers/gpu/nvgpu/Makefile +++ b/drivers/gpu/nvgpu/Makefile @@ -88,6 +88,7 @@ nvgpu-y += \ common/init/nvgpu_init.o \ common/pmu/pmu.o \ common/pmu/pmu_ipc.o \ + common/pmu/pmu_seq.o \ common/pmu/pmu_fw.o \ common/pmu/pg/pmu_pg.o \ common/pmu/pg/pmu_aelpg.o \ diff --git a/drivers/gpu/nvgpu/Makefile.sources b/drivers/gpu/nvgpu/Makefile.sources index 78e40d049..a93a0941c 100644 --- a/drivers/gpu/nvgpu/Makefile.sources +++ b/drivers/gpu/nvgpu/Makefile.sources @@ -127,6 +127,7 @@ srcs += common/sim.c \ common/netlist/netlist_tu104.c \ common/pmu/pmu.c \ common/pmu/pmu_ipc.c \ + common/pmu/pmu_seq.c \ common/pmu/pmu_fw.c \ common/pmu/pg/pmu_pg.c \ common/pmu/pg/pmu_aelpg.c \ diff --git a/drivers/gpu/nvgpu/common/pmu/clk/clk_domain.c b/drivers/gpu/nvgpu/common/pmu/clk/clk_domain.c index b3bdedcaf..e387527a4 100644 --- a/drivers/gpu/nvgpu/common/pmu/clk/clk_domain.c +++ b/drivers/gpu/nvgpu/common/pmu/clk/clk_domain.c @@ -391,15 +391,15 @@ static int devinit_get_clocks_table_35(struct gk20a *g, switch (clocks_table_header.clocks_hal) { case CLK_TABLE_HAL_ENTRY_GV: - { vbiosclktbl1xhalentry = vbiosclktbl1xhalentry_gv; break; - } default: - { status = -EINVAL; - goto done; + break; } + + if (status == -EINVAL) { + goto done; } pclkdomainobjs->cntr_sampling_periodms = diff --git a/drivers/gpu/nvgpu/common/pmu/pmu.c b/drivers/gpu/nvgpu/common/pmu/pmu.c index 63039b5d2..0e787383c 100644 --- a/drivers/gpu/nvgpu/common/pmu/pmu.c +++ b/drivers/gpu/nvgpu/common/pmu/pmu.c @@ -158,7 +158,8 @@ static int nvgpu_init_pmu_setup_sw(struct gk20a *g) pmu->mutex[i].id = i; pmu->mutex[i].index = i; } - nvgpu_pmu_seq_init(pmu); + + nvgpu_pmu_sequences_init(&pmu->sequences); nvgpu_log_fn(g, "skip init"); goto skip_init; @@ -181,14 +182,12 @@ static int nvgpu_init_pmu_setup_sw(struct gk20a *g) pmu->mutex[i].index = i; } - pmu->seq = nvgpu_kzalloc(g, PMU_MAX_NUM_SEQUENCES * - sizeof(struct pmu_sequence)); - if (pmu->seq == NULL) { - err = -ENOMEM; + err = nvgpu_pmu_sequences_alloc(g, &pmu->sequences); + if (err != 0) { goto err_free_mutex; } - nvgpu_pmu_seq_init(pmu); + nvgpu_pmu_sequences_init(&pmu->sequences); err = nvgpu_dma_alloc_map_sys(vm, GK20A_PMU_SEQ_BUF_SIZE, &pmu->seq_buf); @@ -236,7 +235,7 @@ skip_init: err_free_seq_buf: nvgpu_dma_unmap_free(vm, &pmu->seq_buf); err_free_seq: - nvgpu_kfree(g, pmu->seq); + nvgpu_pmu_sequences_free(g, &pmu->sequences); err_free_mutex: nvgpu_kfree(g, pmu->mutex); err: diff --git a/drivers/gpu/nvgpu/common/pmu/pmu_fw.c b/drivers/gpu/nvgpu/common/pmu/pmu_fw.c index 28ab05747..3e59da3d4 100644 --- a/drivers/gpu/nvgpu/common/pmu/pmu_fw.c +++ b/drivers/gpu/nvgpu/common/pmu/pmu_fw.c @@ -971,26 +971,6 @@ static void get_pmu_init_msg_pmu_queue_params_v3( *offset = init->queue_offset + current_ptr; } -static void *get_pmu_sequence_in_alloc_ptr_v3(struct pmu_sequence *seq) -{ - return (void *)(&seq->in_v3); -} - -static void *get_pmu_sequence_in_alloc_ptr_v1(struct pmu_sequence *seq) -{ - return (void *)(&seq->in_v1); -} - -static void *get_pmu_sequence_out_alloc_ptr_v3(struct pmu_sequence *seq) -{ - return (void *)(&seq->out_v3); -} - -static void *get_pmu_sequence_out_alloc_ptr_v1(struct pmu_sequence *seq) -{ - return (void *)(&seq->out_v1); -} - static u8 pg_cmd_eng_buf_load_size_v0(struct pmu_pg_cmd *pg) { size_t tmp_size = sizeof(pg->eng_buf_load_v0); @@ -1256,9 +1236,9 @@ static int init_pmu_fw_ver_ops(struct nvgpu_pmu *pmu, u32 app_version) g->ops.pmu_ver.perfmon_cmd_init_set_mov_avg = perfmon_cmd_init_set_mov_avg_v2; g->ops.pmu_ver.get_pmu_seq_in_a_ptr = - get_pmu_sequence_in_alloc_ptr_v1; + nvgpu_get_pmu_sequence_in_alloc_ptr_v1; g->ops.pmu_ver.get_pmu_seq_out_a_ptr = - get_pmu_sequence_out_alloc_ptr_v1; + nvgpu_get_pmu_sequence_out_alloc_ptr_v1; break; case APP_VERSION_GV11B: case APP_VERSION_GV10X: @@ -1392,9 +1372,9 @@ static int init_pmu_fw_ver_ops(struct nvgpu_pmu *pmu, u32 app_version) g->ops.pmu_ver.perfmon_cmd_init_set_mov_avg = perfmon_cmd_init_set_mov_avg_v3; g->ops.pmu_ver.get_pmu_seq_in_a_ptr = - get_pmu_sequence_in_alloc_ptr_v3; + nvgpu_get_pmu_sequence_in_alloc_ptr_v3; g->ops.pmu_ver.get_pmu_seq_out_a_ptr = - get_pmu_sequence_out_alloc_ptr_v3; + nvgpu_get_pmu_sequence_out_alloc_ptr_v3; break; case APP_VERSION_GP10X: g->ops.pmu_ver.pg_cmd_eng_buf_load_size = @@ -1498,9 +1478,9 @@ static int init_pmu_fw_ver_ops(struct nvgpu_pmu *pmu, u32 app_version) g->ops.pmu_ver.perfmon_cmd_init_set_mov_avg = perfmon_cmd_init_set_mov_avg_v3; g->ops.pmu_ver.get_pmu_seq_in_a_ptr = - get_pmu_sequence_in_alloc_ptr_v3; + nvgpu_get_pmu_sequence_in_alloc_ptr_v3; g->ops.pmu_ver.get_pmu_seq_out_a_ptr = - get_pmu_sequence_out_alloc_ptr_v3; + nvgpu_get_pmu_sequence_out_alloc_ptr_v3; g->ops.pmu_ver.boardobj.boardobjgrp_pmucmd_construct_impl = boardobjgrp_pmucmd_construct_impl; g->ops.pmu_ver.boardobj.boardobjgrp_pmuset_impl = @@ -1608,9 +1588,9 @@ static int init_pmu_fw_ver_ops(struct nvgpu_pmu *pmu, u32 app_version) g->ops.pmu_ver.perfmon_cmd_init_set_mov_avg = perfmon_cmd_init_set_mov_avg_v1; g->ops.pmu_ver.get_pmu_seq_in_a_ptr = - get_pmu_sequence_in_alloc_ptr_v1; + nvgpu_get_pmu_sequence_in_alloc_ptr_v1; g->ops.pmu_ver.get_pmu_seq_out_a_ptr = - get_pmu_sequence_out_alloc_ptr_v1; + nvgpu_get_pmu_sequence_out_alloc_ptr_v1; break; default: nvgpu_err(g, "PMU code version not supported version: %d\n", @@ -1676,7 +1656,7 @@ static void nvgpu_remove_pmu_support(struct nvgpu_pmu *pmu) nvgpu_mutex_destroy(&pmu->pmu_pg.pg_mutex); nvgpu_mutex_destroy(&pmu->isr_mutex); nvgpu_mutex_destroy(&pmu->pmu_copy_lock); - nvgpu_mutex_destroy(&pmu->pmu_seq_lock); + nvgpu_pmu_sequences_free(g, &pmu->sequences); } static int init_pmu_ucode(struct nvgpu_pmu *pmu) @@ -1791,22 +1771,15 @@ int nvgpu_early_init_pmu_sw(struct gk20a *g, struct nvgpu_pmu *pmu) goto fail_isr; } - err = nvgpu_mutex_init(&pmu->pmu_seq_lock); - if (err != 0) { - goto fail_pmu_copy; - } - err = init_pmu_ucode(pmu); if (err != 0) { - goto fail_seq_lock; + goto fail_pmu_copy; } pmu->remove_support = nvgpu_remove_pmu_support; goto exit; -fail_seq_lock: -nvgpu_mutex_destroy(&pmu->pmu_seq_lock); fail_pmu_copy: nvgpu_mutex_destroy(&pmu->pmu_copy_lock); fail_isr: diff --git a/drivers/gpu/nvgpu/common/pmu/pmu_ipc.c b/drivers/gpu/nvgpu/common/pmu/pmu_ipc.c index 1a1735a08..acd91ebe5 100644 --- a/drivers/gpu/nvgpu/common/pmu/pmu_ipc.c +++ b/drivers/gpu/nvgpu/common/pmu/pmu_ipc.c @@ -32,63 +32,8 @@ #include #include #include +#include -void nvgpu_pmu_seq_init(struct nvgpu_pmu *pmu) -{ - u32 i; - - (void) memset(pmu->seq, 0, - sizeof(struct pmu_sequence) * PMU_MAX_NUM_SEQUENCES); - (void) memset(pmu->pmu_seq_tbl, 0, - sizeof(pmu->pmu_seq_tbl)); - - for (i = 0; i < PMU_MAX_NUM_SEQUENCES; i++) { - pmu->seq[i].id = (u8)i; - } -} - -static int pmu_seq_acquire(struct nvgpu_pmu *pmu, - struct pmu_sequence **pseq) -{ - struct gk20a *g = gk20a_from_pmu(pmu); - struct pmu_sequence *seq; - unsigned long index; - - nvgpu_mutex_acquire(&pmu->pmu_seq_lock); - index = find_first_zero_bit(pmu->pmu_seq_tbl, - sizeof(pmu->pmu_seq_tbl)); - if (index >= sizeof(pmu->pmu_seq_tbl)) { - nvgpu_err(g, "no free sequence available"); - nvgpu_mutex_release(&pmu->pmu_seq_lock); - return -EAGAIN; - } - nvgpu_assert(index <= INT_MAX); - set_bit((int)index, pmu->pmu_seq_tbl); - nvgpu_mutex_release(&pmu->pmu_seq_lock); - - seq = &pmu->seq[index]; - seq->state = PMU_SEQ_STATE_PENDING; - - *pseq = seq; - return 0; -} - -static void pmu_seq_release(struct nvgpu_pmu *pmu, - struct pmu_sequence *seq) -{ - struct gk20a *g = gk20a_from_pmu(pmu); - - seq->state = PMU_SEQ_STATE_FREE; - seq->callback = NULL; - seq->cb_params = NULL; - seq->out_payload = NULL; - g->ops.pmu_ver.pmu_allocation_set_dmem_size(pmu, - g->ops.pmu_ver.get_pmu_seq_in_a_ptr(seq), 0); - g->ops.pmu_ver.pmu_allocation_set_dmem_size(pmu, - g->ops.pmu_ver.get_pmu_seq_out_a_ptr(seq), 0); - - clear_bit((int)seq->id, pmu->pmu_seq_tbl); -} /* mutex */ int nvgpu_pmu_mutex_acquire(struct nvgpu_pmu *pmu, u32 id, u32 *token) { @@ -401,8 +346,9 @@ static int pmu_payload_allocate(struct gk20a *g, struct pmu_sequence *seq, struct falcon_payload_alloc *alloc) { struct nvgpu_pmu *pmu = &g->pmu; - u64 tmp; + u16 buffer_size; int err = 0; + u64 tmp; if (alloc->fb_surface == NULL && alloc->fb_size != 0x0U) { @@ -416,10 +362,12 @@ static int pmu_payload_allocate(struct gk20a *g, struct pmu_sequence *seq, } if (pmu->queue_type == QUEUE_TYPE_FB) { - seq->fbq_out_offset_in_queue_element = seq->buffer_size_used; + buffer_size = nvgpu_pmu_seq_get_buffer_size(seq); + nvgpu_pmu_seq_set_fbq_out_offset(seq, buffer_size); /* Save target address in FBQ work buffer. */ - alloc->dmem_offset = seq->buffer_size_used; - seq->buffer_size_used += alloc->dmem_size; + alloc->dmem_offset = buffer_size; + buffer_size += alloc->dmem_size; + nvgpu_pmu_seq_set_buffer_size(seq, buffer_size); } else { tmp = nvgpu_alloc(&pmu->dmem, alloc->dmem_size); nvgpu_assert(tmp <= U32_MAX); @@ -439,7 +387,7 @@ static int pmu_cmd_payload_setup_rpc(struct gk20a *g, struct pmu_cmd *cmd, { struct nvgpu_pmu *pmu = &g->pmu; struct pmu_v *pv = &g->ops.pmu_ver; - struct nvgpu_engine_fb_queue *queue = seq->cmd_queue; + struct nvgpu_engine_fb_queue *queue = nvgpu_pmu_seq_get_cmd_queue(seq); struct falcon_payload_alloc alloc; int err = 0; @@ -464,10 +412,10 @@ static int pmu_cmd_payload_setup_rpc(struct gk20a *g, struct pmu_cmd *cmd, alloc.dmem_offset, (u8 *)payload->rpc.prpc, payload->rpc.size_rpc); - alloc.dmem_offset += seq->fbq_heap_offset; + alloc.dmem_offset += nvgpu_pmu_seq_get_fbq_heap_offset(seq); - seq->in_payload_fb_queue = true; - seq->out_payload_fb_queue = true; + nvgpu_pmu_seq_set_in_payload_fb_queue(seq, true); + nvgpu_pmu_seq_set_out_payload_fb_queue(seq, true); } else { nvgpu_falcon_copy_to_dmem(&pmu->flcn, alloc.dmem_offset, payload->rpc.prpc, payload->rpc.size_rpc, 0); @@ -476,7 +424,7 @@ static int pmu_cmd_payload_setup_rpc(struct gk20a *g, struct pmu_cmd *cmd, cmd->cmd.rpc.rpc_dmem_size = payload->rpc.size_rpc; cmd->cmd.rpc.rpc_dmem_ptr = alloc.dmem_offset; - seq->out_payload = payload->rpc.prpc; + nvgpu_pmu_seq_set_out_payload(seq, payload->rpc.prpc); pv->pmu_allocation_set_dmem_size(pmu, pv->get_pmu_seq_out_a_ptr(seq), payload->rpc.size_rpc); @@ -497,16 +445,18 @@ clean_up: static int pmu_cmd_payload_setup(struct gk20a *g, struct pmu_cmd *cmd, struct pmu_payload *payload, struct pmu_sequence *seq) { - struct nvgpu_pmu *pmu = &g->pmu; + struct nvgpu_engine_fb_queue *fb_queue = + nvgpu_pmu_seq_get_cmd_queue(seq); struct pmu_v *pv = &g->ops.pmu_ver; - void *in = NULL, *out = NULL; struct falcon_payload_alloc alloc; + struct nvgpu_pmu *pmu = &g->pmu; + void *in = NULL, *out = NULL; int err = 0; nvgpu_log_fn(g, " "); if (payload != NULL) { - seq->out_payload = payload->out.buf; + nvgpu_pmu_seq_set_out_payload(seq, payload->out.buf); } memset(&alloc, 0, sizeof(struct falcon_payload_alloc)); @@ -538,16 +488,17 @@ static int pmu_cmd_payload_setup(struct gk20a *g, struct pmu_cmd *cmd, alloc.dmem_offset; if (payload->in.fb_size != 0x0U) { - seq->in_mem = alloc.fb_surface; - nvgpu_pmu_surface_describe(g, seq->in_mem, + nvgpu_pmu_seq_set_in_mem(seq, alloc.fb_surface); + nvgpu_pmu_surface_describe(g, alloc.fb_surface, (struct flcn_mem_desc_v0 *) pv->pmu_allocation_get_fb_addr(pmu, in)); - nvgpu_mem_wr_n(g, seq->in_mem, 0, + nvgpu_mem_wr_n(g, alloc.fb_surface, 0, payload->in.buf, payload->in.fb_size); if (pmu->queue_type == QUEUE_TYPE_FB) { - alloc.dmem_offset += seq->fbq_heap_offset; + alloc.dmem_offset += + nvgpu_pmu_seq_get_fbq_heap_offset(seq); *(pv->pmu_allocation_get_dmem_offset_addr(pmu, in)) = alloc.dmem_offset; } @@ -556,16 +507,18 @@ static int pmu_cmd_payload_setup(struct gk20a *g, struct pmu_cmd *cmd, /* copy payload to FBQ work buffer */ nvgpu_memcpy((u8 *) nvgpu_engine_fb_queue_get_work_buffer( - seq->cmd_queue) + + fb_queue) + alloc.dmem_offset, (u8 *)payload->in.buf, payload->in.size); - alloc.dmem_offset += seq->fbq_heap_offset; + alloc.dmem_offset += + nvgpu_pmu_seq_get_fbq_heap_offset(seq); *(pv->pmu_allocation_get_dmem_offset_addr(pmu, in)) = alloc.dmem_offset; - seq->in_payload_fb_queue = true; + nvgpu_pmu_seq_set_in_payload_fb_queue(seq, + true); } else { nvgpu_falcon_copy_to_dmem(&pmu->flcn, (pv->pmu_allocation_get_dmem_offset(pmu, in)), @@ -600,16 +553,18 @@ static int pmu_cmd_payload_setup(struct gk20a *g, struct pmu_cmd *cmd, *(pv->pmu_allocation_get_dmem_offset_addr(pmu, out)) = alloc.dmem_offset; - seq->out_mem = alloc.fb_surface; + nvgpu_pmu_seq_set_out_mem(seq, alloc.fb_surface); } else { BUG_ON(in == NULL); - seq->out_mem = seq->in_mem; + nvgpu_pmu_seq_set_out_mem(seq, + nvgpu_pmu_seq_get_in_mem(seq)); pv->pmu_allocation_set_dmem_offset(pmu, out, pv->pmu_allocation_get_dmem_offset(pmu, in)); } if (payload->out.fb_size != 0x0U) { - nvgpu_pmu_surface_describe(g, seq->out_mem, + nvgpu_pmu_surface_describe(g, + nvgpu_pmu_seq_get_out_mem(seq), (struct flcn_mem_desc_v0 *) pv->pmu_allocation_get_fb_addr(pmu, out)); @@ -618,10 +573,11 @@ static int pmu_cmd_payload_setup(struct gk20a *g, struct pmu_cmd *cmd, if (pmu->queue_type == QUEUE_TYPE_FB) { if (payload->in.buf != payload->out.buf) { *(pv->pmu_allocation_get_dmem_offset_addr(pmu, - out)) += seq->fbq_heap_offset; + out)) += + nvgpu_pmu_seq_get_fbq_heap_offset(seq); } - seq->out_payload_fb_queue = true; + nvgpu_pmu_seq_set_out_payload_fb_queue(seq, true); } pv->pmu_allocation_set_dmem_size(pmu, @@ -709,9 +665,6 @@ static int pmu_fbq_cmd_setup(struct gk20a *g, struct pmu_cmd *cmd, goto exit; } - seq->in_payload_fb_queue = false; - seq->out_payload_fb_queue = false; - /* clear work queue buffer */ memset(nvgpu_engine_fb_queue_get_work_buffer(queue), 0, nvgpu_engine_fb_queue_get_element_size(queue)); @@ -720,7 +673,7 @@ static int pmu_fbq_cmd_setup(struct gk20a *g, struct pmu_cmd *cmd, tmp = sizeof(struct nv_falcon_fbq_hdr) + cmd->hdr.size; nvgpu_assert(tmp <= (size_t)U16_MAX); - seq->buffer_size_used = (u16)tmp; + nvgpu_pmu_seq_set_buffer_size(seq, (u16)tmp); /* copy cmd into the work buffer */ nvgpu_memcpy((u8 *)flcn_cmd, (u8 *)cmd, cmd->hdr.size); @@ -729,13 +682,14 @@ static int pmu_fbq_cmd_setup(struct gk20a *g, struct pmu_cmd *cmd, nvgpu_assert(fbq_size_needed < U16_MAX); fbq_hdr->heap_size = (u16)fbq_size_needed; fbq_hdr->heap_offset = heap_offset; - seq->fbq_heap_offset = heap_offset; + nvgpu_pmu_seq_set_fbq_heap_offset(seq, heap_offset); /* * save queue index in seq structure * so can free queue element when response is received */ - seq->fbq_element_index = nvgpu_engine_fb_queue_get_position(queue); + nvgpu_pmu_seq_set_fbq_element_index(seq, + nvgpu_engine_fb_queue_get_position(queue)); exit: return err; @@ -767,25 +721,22 @@ int nvgpu_pmu_cmd_post(struct gk20a *g, struct pmu_cmd *cmd, return -EINVAL; } - err = pmu_seq_acquire(pmu, &seq); + err = nvgpu_pmu_seq_acquire(g, &pmu->sequences, &seq, callback, + cb_param); if (err != 0) { return err; } - cmd->hdr.seq_id = seq->id; + cmd->hdr.seq_id = nvgpu_pmu_seq_get_id(seq); cmd->hdr.ctrl_flags = 0; cmd->hdr.ctrl_flags |= PMU_CMD_FLAGS_STATUS; cmd->hdr.ctrl_flags |= PMU_CMD_FLAGS_INTR; - seq->callback = callback; - seq->cb_params = cb_param; - seq->out_payload = NULL; - if (pmu->queue_type == QUEUE_TYPE_FB) { fb_queue = pmu->fb_queue[queue_id]; /* Save the queue in the seq structure. */ - seq->cmd_queue = fb_queue; + nvgpu_pmu_seq_set_cmd_queue(seq, fb_queue); /* Lock the FBQ work buffer */ nvgpu_engine_fb_queue_lock_work_buffer(fb_queue); @@ -794,7 +745,7 @@ int nvgpu_pmu_cmd_post(struct gk20a *g, struct pmu_cmd *cmd, err = pmu_fbq_cmd_setup(g, cmd, fb_queue, payload, seq); if (err != 0) { nvgpu_err(g, "FBQ cmd setup failed"); - pmu_seq_release(pmu, seq); + nvgpu_pmu_seq_release(g, &pmu->sequences, seq); goto exit; } @@ -816,15 +767,20 @@ int nvgpu_pmu_cmd_post(struct gk20a *g, struct pmu_cmd *cmd, if (err != 0) { nvgpu_err(g, "payload setup failed"); - pmu_seq_release(pmu, seq); + g->ops.pmu_ver.pmu_allocation_set_dmem_size(pmu, + g->ops.pmu_ver.get_pmu_seq_in_a_ptr(seq), 0); + g->ops.pmu_ver.pmu_allocation_set_dmem_size(pmu, + g->ops.pmu_ver.get_pmu_seq_out_a_ptr(seq), 0); + + nvgpu_pmu_seq_release(g, &pmu->sequences, seq); goto exit; } - seq->state = PMU_SEQ_STATE_USED; + nvgpu_pmu_seq_set_state(seq, PMU_SEQ_STATE_USED); err = pmu_write_cmd(pmu, cmd, queue_id); if (err != 0) { - seq->state = PMU_SEQ_STATE_PENDING; + nvgpu_pmu_seq_set_state(seq, PMU_SEQ_STATE_PENDING); } exit: @@ -839,6 +795,8 @@ exit: static int pmu_payload_extract(struct nvgpu_pmu *pmu, struct pmu_sequence *seq) { + struct nvgpu_engine_fb_queue *fb_queue = + nvgpu_pmu_seq_get_cmd_queue(seq); struct gk20a *g = gk20a_from_pmu(pmu); struct pmu_v *pv = &g->ops.pmu_ver; u32 fbq_payload_offset = 0U; @@ -846,15 +804,15 @@ static int pmu_payload_extract(struct nvgpu_pmu *pmu, struct pmu_sequence *seq) nvgpu_log_fn(g, " "); - if (seq->out_payload_fb_queue) { + if (nvgpu_pmu_seq_get_out_payload_fb_queue(seq)) { fbq_payload_offset = - nvgpu_engine_fb_queue_get_offset(seq->cmd_queue) + - seq->fbq_out_offset_in_queue_element + - (seq->fbq_element_index * - nvgpu_engine_fb_queue_get_element_size(seq->cmd_queue)); + nvgpu_engine_fb_queue_get_offset(fb_queue) + + nvgpu_pmu_seq_get_fbq_out_offset(seq) + + (nvgpu_pmu_seq_get_fbq_element_index(seq) * + nvgpu_engine_fb_queue_get_element_size(fb_queue)); nvgpu_mem_rd_n(g, &pmu->super_surface_buf, fbq_payload_offset, - seq->out_payload, + nvgpu_pmu_seq_get_out_payload(seq), pv->pmu_allocation_get_dmem_size(pmu, pv->get_pmu_seq_out_a_ptr(seq))); @@ -864,7 +822,7 @@ static int pmu_payload_extract(struct nvgpu_pmu *pmu, struct pmu_sequence *seq) err = nvgpu_falcon_copy_from_dmem(&pmu->flcn, pv->pmu_allocation_get_dmem_offset(pmu, pv->get_pmu_seq_out_a_ptr(seq)), - seq->out_payload, + nvgpu_pmu_seq_get_out_payload(seq), pv->pmu_allocation_get_dmem_size(pmu, pv->get_pmu_seq_out_a_ptr(seq)), 0); if (err != 0) { @@ -877,106 +835,102 @@ static int pmu_payload_extract(struct nvgpu_pmu *pmu, struct pmu_sequence *seq) return err; } -static void pmu_payload_fbq_free(struct nvgpu_pmu *pmu, - struct pmu_sequence *seq) -{ - nvgpu_log_fn(pmu->g, " "); - - seq->out_payload_fb_queue = false; - seq->in_payload_fb_queue = false; - - nvgpu_free(&pmu->dmem, seq->fbq_heap_offset); - seq->fbq_heap_offset = 0; - - /* - * free FBQ allocated work buffer - * set FBQ element work buffer to NULL - * Clear the in use bit for the queue entry this CMD used. - */ - nvgpu_engine_fb_queue_free_element(seq->cmd_queue, - seq->fbq_element_index); -} - static void pmu_payload_free(struct nvgpu_pmu *pmu, struct pmu_sequence *seq) { + struct nvgpu_engine_fb_queue *fb_queue = + nvgpu_pmu_seq_get_cmd_queue(seq); struct gk20a *g = gk20a_from_pmu(pmu); struct pmu_v *pv = &g->ops.pmu_ver; + struct nvgpu_mem *in_mem = nvgpu_pmu_seq_get_in_mem(seq); + struct nvgpu_mem *out_mem = nvgpu_pmu_seq_get_out_mem(seq); + void *seq_in_ptr = pv->get_pmu_seq_in_a_ptr(seq); + void *seq_out_ptr = pv->get_pmu_seq_out_a_ptr(seq); + int err; nvgpu_log_fn(g, " "); - /* free FBQ payload*/ if (pmu->queue_type == QUEUE_TYPE_FB) { - pmu_payload_fbq_free(pmu, seq); + nvgpu_free(&pmu->dmem, nvgpu_pmu_seq_get_fbq_heap_offset(seq)); + + /* + * free FBQ allocated work buffer + * set FBQ element work buffer to NULL + * Clear the in use bit for the queue entry this CMD used. + */ + err = nvgpu_engine_fb_queue_free_element(fb_queue, + nvgpu_pmu_seq_get_fbq_element_index(seq)); + if (err != 0) { + nvgpu_err(g, "fb queue element free failed %d", err); + } } else { /* free DMEM space payload*/ - if (pv->pmu_allocation_get_dmem_size(pmu, - pv->get_pmu_seq_in_a_ptr(seq)) != 0U) { + if (pv->pmu_allocation_get_dmem_size(pmu, seq_in_ptr) != 0U) { nvgpu_free(&pmu->dmem, - pv->pmu_allocation_get_dmem_offset(pmu, - pv->get_pmu_seq_in_a_ptr(seq))); + pv->pmu_allocation_get_dmem_offset(pmu, + seq_in_ptr)); + + pv->pmu_allocation_set_dmem_size(pmu, seq_in_ptr, 0); } - if (pv->pmu_allocation_get_dmem_size(pmu, - pv->get_pmu_seq_out_a_ptr(seq)) != 0U) { + if (pv->pmu_allocation_get_dmem_size(pmu, seq_out_ptr) != 0U) { nvgpu_free(&pmu->dmem, - pv->pmu_allocation_get_dmem_offset(pmu, - pv->get_pmu_seq_out_a_ptr(seq))); + pv->pmu_allocation_get_dmem_offset(pmu, + seq_out_ptr)); + + pv->pmu_allocation_set_dmem_size(pmu, seq_out_ptr, 0); } } - /* free FB surface payload */ - if (seq->out_mem != NULL) { - (void) memset(pv->pmu_allocation_get_fb_addr(pmu, - pv->get_pmu_seq_out_a_ptr(seq)), 0x0, - pv->pmu_allocation_get_fb_size(pmu, - pv->get_pmu_seq_out_a_ptr(seq))); + if (out_mem != NULL) { + (void) memset(pv->pmu_allocation_get_fb_addr(pmu, seq_out_ptr), + 0x0, + pv->pmu_allocation_get_fb_size(pmu, seq_out_ptr)); - nvgpu_pmu_surface_free(g, seq->out_mem); - if (seq->out_mem != seq->in_mem) { - nvgpu_kfree(g, seq->out_mem); - } else { - seq->out_mem = NULL; + nvgpu_pmu_surface_free(g, out_mem); + if (out_mem != in_mem) { + nvgpu_kfree(g, out_mem); } } - if (seq->in_mem != NULL) { - (void) memset(pv->pmu_allocation_get_fb_addr(pmu, - pv->get_pmu_seq_in_a_ptr(seq)), 0x0, - pv->pmu_allocation_get_fb_size(pmu, - pv->get_pmu_seq_in_a_ptr(seq))); + if (in_mem != NULL) { + (void) memset(pv->pmu_allocation_get_fb_addr(pmu, seq_in_ptr), + 0x0, + pv->pmu_allocation_get_fb_size(pmu, seq_in_ptr)); - nvgpu_pmu_surface_free(g, seq->in_mem); - nvgpu_kfree(g, seq->in_mem); - seq->in_mem = NULL; + nvgpu_pmu_surface_free(g, in_mem); + nvgpu_kfree(g, in_mem); } + + nvgpu_pmu_seq_payload_free(g, seq); } static int pmu_response_handle(struct nvgpu_pmu *pmu, struct pmu_msg *msg) { struct gk20a *g = gk20a_from_pmu(pmu); + enum pmu_seq_state state; struct pmu_sequence *seq; int err = 0; + u8 id; nvgpu_log_fn(g, " "); - seq = &pmu->seq[msg->hdr.seq_id]; + seq = nvgpu_pmu_sequences_get_seq(&pmu->sequences, msg->hdr.seq_id); + state = nvgpu_pmu_seq_get_state(seq); + id = nvgpu_pmu_seq_get_id(seq); - if (seq->state != PMU_SEQ_STATE_USED && - seq->state != PMU_SEQ_STATE_CANCELLED) { - nvgpu_err(g, "msg for an unknown sequence %d", seq->id); + if (state != PMU_SEQ_STATE_USED) { + nvgpu_err(g, "msg for an unknown sequence %u", (u32) id); err = -EINVAL; goto exit; } if (msg->hdr.unit_id == PMU_UNIT_RC && msg->msg.rc.msg_type == PMU_RC_MSG_TYPE_UNHANDLED_CMD) { - nvgpu_err(g, "unhandled cmd: seq %d", seq->id); + nvgpu_err(g, "unhandled cmd: seq %u", (u32) id); err = -EINVAL; - } else if (seq->state != PMU_SEQ_STATE_CANCELLED) { - err = pmu_payload_extract(pmu, seq); } else { - seq->callback = NULL; + err = pmu_payload_extract(pmu, seq); } exit: @@ -988,11 +942,9 @@ exit: */ pmu_payload_free(pmu, seq); - if (seq->callback != NULL) { - seq->callback(g, msg, seq->cb_params, err); - } + nvgpu_pmu_seq_callback(g, seq, msg, err); - pmu_seq_release(pmu, seq); + nvgpu_pmu_seq_release(g, &pmu->sequences, seq); /* TBD: notify client waiting for available dmem */ diff --git a/drivers/gpu/nvgpu/common/pmu/pmu_seq.c b/drivers/gpu/nvgpu/common/pmu/pmu_seq.c new file mode 100644 index 000000000..d8d8aab6c --- /dev/null +++ b/drivers/gpu/nvgpu/common/pmu/pmu_seq.c @@ -0,0 +1,272 @@ +/* + * Copyright (c) 2017-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 + +void *nvgpu_get_pmu_sequence_in_alloc_ptr_v3(struct pmu_sequence *seq) +{ + return (void *)(&seq->in_v3); +} + +void *nvgpu_get_pmu_sequence_in_alloc_ptr_v1(struct pmu_sequence *seq) +{ + return (void *)(&seq->in_v1); +} + +void *nvgpu_get_pmu_sequence_out_alloc_ptr_v3(struct pmu_sequence *seq) +{ + return (void *)(&seq->out_v3); +} + +void *nvgpu_get_pmu_sequence_out_alloc_ptr_v1(struct pmu_sequence *seq) +{ + return (void *)(&seq->out_v1); +} + +int nvgpu_pmu_sequences_alloc(struct gk20a *g, + struct pmu_sequences *sequences) +{ + int err; + + sequences->seq = nvgpu_kzalloc(g, PMU_MAX_NUM_SEQUENCES * + sizeof(struct pmu_sequence)); + if (sequences->seq == NULL) { + return -ENOMEM; + } + + err = nvgpu_mutex_init(&sequences->pmu_seq_lock); + if (err != 0) { + nvgpu_kfree(g, sequences->seq); + return err; + } + + return 0; +} + +void nvgpu_pmu_sequences_free(struct gk20a *g, + struct pmu_sequences *sequences) +{ + nvgpu_mutex_destroy(&sequences->pmu_seq_lock); + nvgpu_kfree(g, sequences->seq); +} + +void nvgpu_pmu_sequences_init(struct pmu_sequences *sequences) +{ + u32 i; + + (void) memset(sequences->seq, 0, + sizeof(struct pmu_sequence) * PMU_MAX_NUM_SEQUENCES); + (void) memset(sequences->pmu_seq_tbl, 0, + sizeof(sequences->pmu_seq_tbl)); + + for (i = 0; i < PMU_MAX_NUM_SEQUENCES; i++) { + sequences->seq[i].id = (u8)i; + } +} + +void nvgpu_pmu_seq_payload_free(struct gk20a *g, struct pmu_sequence *seq) +{ + nvgpu_log_fn(g, " "); + + seq->out_payload_fb_queue = false; + seq->in_payload_fb_queue = false; + seq->fbq_heap_offset = 0; + seq->in_mem = NULL; + seq->out_mem = NULL; +} + +int nvgpu_pmu_seq_acquire(struct gk20a *g, + struct pmu_sequences *sequences, + struct pmu_sequence **pseq, + pmu_callback callback, void *cb_params) +{ + struct pmu_sequence *seq; + unsigned long index; + + nvgpu_mutex_acquire(&sequences->pmu_seq_lock); + index = find_first_zero_bit(sequences->pmu_seq_tbl, + sizeof(sequences->pmu_seq_tbl)); + if (index >= sizeof(sequences->pmu_seq_tbl)) { + nvgpu_err(g, "no free sequence available"); + nvgpu_mutex_release(&sequences->pmu_seq_lock); + return -EAGAIN; + } + nvgpu_assert(index <= U32_MAX); + set_bit((int)index, sequences->pmu_seq_tbl); + nvgpu_mutex_release(&sequences->pmu_seq_lock); + + seq = &sequences->seq[index]; + seq->state = PMU_SEQ_STATE_PENDING; + seq->callback = callback; + seq->cb_params = cb_params; + seq->out_payload = NULL; + seq->in_payload_fb_queue = false; + seq->out_payload_fb_queue = false; + + *pseq = seq; + return 0; +} + +void nvgpu_pmu_seq_release(struct gk20a *g, + struct pmu_sequences *sequences, + struct pmu_sequence *seq) +{ + seq->state = PMU_SEQ_STATE_FREE; + seq->callback = NULL; + seq->cb_params = NULL; + seq->out_payload = NULL; + + nvgpu_mutex_acquire(&sequences->pmu_seq_lock); + clear_bit((int)seq->id, sequences->pmu_seq_tbl); + nvgpu_mutex_release(&sequences->pmu_seq_lock); +} + +u16 nvgpu_pmu_seq_get_fbq_out_offset(struct pmu_sequence *seq) +{ + return seq->fbq_out_offset_in_queue_element; +} + +void nvgpu_pmu_seq_set_fbq_out_offset(struct pmu_sequence *seq, u16 size) +{ + seq->fbq_out_offset_in_queue_element = size; +} + +u16 nvgpu_pmu_seq_get_buffer_size(struct pmu_sequence *seq) +{ + return seq->buffer_size_used; +} + +void nvgpu_pmu_seq_set_buffer_size(struct pmu_sequence *seq, u16 size) +{ + seq->buffer_size_used = size; +} + +struct nvgpu_engine_fb_queue *nvgpu_pmu_seq_get_cmd_queue( + struct pmu_sequence *seq) +{ + return seq->cmd_queue; +} + +void nvgpu_pmu_seq_set_cmd_queue(struct pmu_sequence *seq, + struct nvgpu_engine_fb_queue *fb_queue) +{ + seq->cmd_queue = fb_queue; +} + +u16 nvgpu_pmu_seq_get_fbq_heap_offset(struct pmu_sequence *seq) +{ + return seq->fbq_heap_offset; +} + +void nvgpu_pmu_seq_set_fbq_heap_offset(struct pmu_sequence *seq, u16 size) +{ + seq->fbq_heap_offset = size; +} + +u8 *nvgpu_pmu_seq_get_out_payload(struct pmu_sequence *seq) +{ + return seq->out_payload; +} + +void nvgpu_pmu_seq_set_out_payload(struct pmu_sequence *seq, u8 *payload) +{ + seq->out_payload = payload; +} + +void nvgpu_pmu_seq_set_in_payload_fb_queue(struct pmu_sequence *seq, bool state) +{ + seq->in_payload_fb_queue = state; +} + +bool nvgpu_pmu_seq_get_out_payload_fb_queue(struct pmu_sequence *seq) +{ + return seq->out_payload_fb_queue; +} + +void nvgpu_pmu_seq_set_out_payload_fb_queue(struct pmu_sequence *seq, + bool state) +{ + seq->out_payload_fb_queue = state; +} + +struct nvgpu_mem *nvgpu_pmu_seq_get_in_mem(struct pmu_sequence *seq) +{ + return seq->in_mem; +} + +void nvgpu_pmu_seq_set_in_mem(struct pmu_sequence *seq, struct nvgpu_mem *mem) +{ + seq->in_mem = mem; +} + +struct nvgpu_mem *nvgpu_pmu_seq_get_out_mem(struct pmu_sequence *seq) +{ + return seq->out_mem; +} + +void nvgpu_pmu_seq_set_out_mem(struct pmu_sequence *seq, struct nvgpu_mem *mem) +{ + seq->out_mem = mem; +} + +u32 nvgpu_pmu_seq_get_fbq_element_index(struct pmu_sequence *seq) +{ + return seq->fbq_element_index; +} + +void nvgpu_pmu_seq_set_fbq_element_index(struct pmu_sequence *seq, u32 index) +{ + seq->fbq_element_index = index; +} + +u8 nvgpu_pmu_seq_get_id(struct pmu_sequence *seq) +{ + return seq->id; +} + +enum pmu_seq_state nvgpu_pmu_seq_get_state(struct pmu_sequence *seq) +{ + return seq->state; +} + +void nvgpu_pmu_seq_set_state(struct pmu_sequence *seq, enum pmu_seq_state state) +{ + seq->state = state; +} + +struct pmu_sequence *nvgpu_pmu_sequences_get_seq(struct pmu_sequences *seqs, + u8 id) +{ + return &seqs->seq[id]; +} + +void nvgpu_pmu_seq_callback(struct gk20a *g, struct pmu_sequence *seq, + struct pmu_msg *msg, int err) +{ + if (seq->callback != NULL) { + seq->callback(g, msg, seq->cb_params, err); + } +} diff --git a/drivers/gpu/nvgpu/include/nvgpu/flcnif_cmn.h b/drivers/gpu/nvgpu/include/nvgpu/flcnif_cmn.h index 99218ca71..3a4fe726b 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/flcnif_cmn.h +++ b/drivers/gpu/nvgpu/include/nvgpu/flcnif_cmn.h @@ -23,6 +23,8 @@ #ifndef NVGPU_FLCNIF_CMN_H #define NVGPU_FLCNIF_CMN_H +#include + #define PMU_CMD_SUBMIT_PAYLOAD_PARAMS_FB_SIZE_UNUSED 0U struct falc_u64 { diff --git a/drivers/gpu/nvgpu/include/nvgpu/pmu.h b/drivers/gpu/nvgpu/include/nvgpu/pmu.h index 9fbfca2c7..ab4d8820f 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/pmu.h +++ b/drivers/gpu/nvgpu/include/nvgpu/pmu.h @@ -34,6 +34,7 @@ #include #include #include +#include #define nvgpu_pmu_dbg(g, fmt, args...) \ nvgpu_log(g, gpu_dbg_pmu, fmt, ##args) @@ -98,11 +99,6 @@ #define GK20A_PMU_UCODE_NB_MAX_OVERLAY 32U #define GK20A_PMU_UCODE_NB_MAX_DATE_LENGTH 64U -#define PMU_MAX_NUM_SEQUENCES (256U) -#define PMU_SEQ_BIT_SHIFT (5U) -#define PMU_SEQ_TBL_SIZE \ - (PMU_MAX_NUM_SEQUENCES >> PMU_SEQ_BIT_SHIFT) - #define GK20A_PMU_DMAIDX_UCODE U32(0) #define GK20A_PMU_DMAIDX_VIRT U32(1) #define GK20A_PMU_DMAIDX_PHYS_VID U32(2) @@ -112,13 +108,6 @@ #define GK20A_PMU_DMAIDX_PELPG U32(6) #define GK20A_PMU_DMAIDX_END U32(7) -enum pmu_seq_state { - PMU_SEQ_STATE_FREE = 0, - PMU_SEQ_STATE_PENDING, - PMU_SEQ_STATE_USED, - PMU_SEQ_STATE_CANCELLED -}; - #define PMU_BAR0_SUCCESS 0U #define PMU_BAR0_HOST_READ_TOUT 1U #define PMU_BAR0_HOST_WRITE_TOUT 2U @@ -200,9 +189,6 @@ enum pmu_seq_state { (_size), _cb, _cbp, false); \ } while (false) -typedef void (*pmu_callback)(struct gk20a *g, struct pmu_msg *msg, void *param, - u32 status); - struct rpc_handler_payload { void *rpc_buff; bool is_mem_free_set; @@ -263,47 +249,6 @@ struct pmu_mutex { u32 ref_cnt; }; -struct pmu_sequence { - u8 id; - enum pmu_seq_state state; - u32 desc; - union { - struct pmu_allocation_v1 in_v1; - struct pmu_allocation_v2 in_v2; - struct pmu_allocation_v3 in_v3; - }; - struct nvgpu_mem *in_mem; - union { - struct pmu_allocation_v1 out_v1; - struct pmu_allocation_v2 out_v2; - struct pmu_allocation_v3 out_v3; - }; - struct nvgpu_mem *out_mem; - u8 *out_payload; - pmu_callback callback; - void *cb_params; - - /* fb queue that is associated with this seq */ - struct nvgpu_engine_fb_queue *cmd_queue; - /* fbq element that is associated with this seq */ - u8 *fbq_work_buffer; - u32 fbq_element_index; - /* flags if queue element has an in payload */ - bool in_payload_fb_queue; - /* flags if queue element has an out payload */ - bool out_payload_fb_queue; - /* Heap location this cmd will use in the nvgpu managed heap */ - u16 fbq_heap_offset; - /* - * Track the amount of the "work buffer" (queue_buffer) that - * has been used so far, as the outbound frame is assembled - * (first FB Queue hdr, then CMD, then payloads). - */ - u16 buffer_size_used; - /* offset to out data in the queue element */ - u16 fbq_out_offset_in_queue_element; -}; - struct nvgpu_pmu { struct gk20a *g; struct nvgpu_falcon flcn; @@ -332,14 +277,12 @@ struct nvgpu_pmu { struct nvgpu_engine_fb_queue *fb_queue[PMU_QUEUE_COUNT]; - struct pmu_sequence *seq; - unsigned long pmu_seq_tbl[PMU_SEQ_TBL_SIZE]; + struct pmu_sequences sequences; struct pmu_mutex *mutex; u32 mutex_cnt; struct nvgpu_mutex pmu_copy_lock; - struct nvgpu_mutex pmu_seq_lock; struct nvgpu_allocator dmem; @@ -397,8 +340,6 @@ struct pg_init_sequence_list { }; /* PMU IPC Methods */ -void nvgpu_pmu_seq_init(struct nvgpu_pmu *pmu); - int nvgpu_pmu_mutex_acquire(struct nvgpu_pmu *pmu, u32 id, u32 *token); int nvgpu_pmu_mutex_release(struct nvgpu_pmu *pmu, u32 id, u32 *token); diff --git a/drivers/gpu/nvgpu/include/nvgpu/pmu/seq.h b/drivers/gpu/nvgpu/include/nvgpu/pmu/seq.h new file mode 100644 index 000000000..c43d3d36a --- /dev/null +++ b/drivers/gpu/nvgpu/include/nvgpu/pmu/seq.h @@ -0,0 +1,146 @@ +/* + * Copyright (c) 2017-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. + */ + +#ifndef NVGPU_PMU_SEQ_H +#define NVGPU_PMU_SEQ_H + +#include +#include + +struct nvgpu_engine_fb_queue; +struct nvgpu_mem; +struct pmu_msg; +struct gk20a; + +#define PMU_MAX_NUM_SEQUENCES (256U) +#define PMU_SEQ_BIT_SHIFT (5U) +#define PMU_SEQ_TBL_SIZE \ + (PMU_MAX_NUM_SEQUENCES >> PMU_SEQ_BIT_SHIFT) + +typedef void (*pmu_callback)(struct gk20a *g, struct pmu_msg *msg, void *param, + u32 status); + +enum pmu_seq_state { + PMU_SEQ_STATE_FREE = 0, + PMU_SEQ_STATE_PENDING, + PMU_SEQ_STATE_USED +}; + +struct pmu_sequence { + u8 id; + enum pmu_seq_state state; + union { + struct pmu_allocation_v1 in_v1; + struct pmu_allocation_v2 in_v2; + struct pmu_allocation_v3 in_v3; + }; + struct nvgpu_mem *in_mem; + union { + struct pmu_allocation_v1 out_v1; + struct pmu_allocation_v2 out_v2; + struct pmu_allocation_v3 out_v3; + }; + struct nvgpu_mem *out_mem; + u8 *out_payload; + pmu_callback callback; + void *cb_params; + + /* fb queue that is associated with this seq */ + struct nvgpu_engine_fb_queue *cmd_queue; + /* fbq element that is associated with this seq */ + u8 *fbq_work_buffer; + u32 fbq_element_index; + /* flags if queue element has an in payload */ + bool in_payload_fb_queue; + /* flags if queue element has an out payload */ + bool out_payload_fb_queue; + /* Heap location this cmd will use in the nvgpu managed heap */ + u16 fbq_heap_offset; + /* + * Track the amount of the "work buffer" (queue_buffer) that + * has been used so far, as the outbound frame is assembled + * (first FB Queue hdr, then CMD, then payloads). + */ + u16 buffer_size_used; + /* offset to out data in the queue element */ + u16 fbq_out_offset_in_queue_element; +}; + +struct pmu_sequences { + struct pmu_sequence *seq; + struct nvgpu_mutex pmu_seq_lock; + unsigned long pmu_seq_tbl[PMU_SEQ_TBL_SIZE]; +}; + +void *nvgpu_get_pmu_sequence_in_alloc_ptr_v3(struct pmu_sequence *seq); +void *nvgpu_get_pmu_sequence_in_alloc_ptr_v1(struct pmu_sequence *seq); +void *nvgpu_get_pmu_sequence_out_alloc_ptr_v3(struct pmu_sequence *seq); +void *nvgpu_get_pmu_sequence_out_alloc_ptr_v1(struct pmu_sequence *seq); + +int nvgpu_pmu_sequences_alloc(struct gk20a *g, + struct pmu_sequences *sequences); +void nvgpu_pmu_sequences_free(struct gk20a *g, + struct pmu_sequences *sequences); +void nvgpu_pmu_sequences_init(struct pmu_sequences *sequences); +void nvgpu_pmu_seq_payload_free(struct gk20a *g, struct pmu_sequence *seq); +int nvgpu_pmu_seq_acquire(struct gk20a *g, + struct pmu_sequences *sequences, + struct pmu_sequence **pseq, + pmu_callback callback, void *cb_params); +void nvgpu_pmu_seq_release(struct gk20a *g, + struct pmu_sequences *sequences, + struct pmu_sequence *seq); +u16 nvgpu_pmu_seq_get_fbq_out_offset(struct pmu_sequence *seq); +void nvgpu_pmu_seq_set_fbq_out_offset(struct pmu_sequence *seq, u16 size); +u16 nvgpu_pmu_seq_get_buffer_size(struct pmu_sequence *seq); +void nvgpu_pmu_seq_set_buffer_size(struct pmu_sequence *seq, u16 size); +struct nvgpu_engine_fb_queue *nvgpu_pmu_seq_get_cmd_queue( + struct pmu_sequence *seq); +void nvgpu_pmu_seq_set_cmd_queue(struct pmu_sequence *seq, + struct nvgpu_engine_fb_queue *fb_queue); +u16 nvgpu_pmu_seq_get_fbq_heap_offset(struct pmu_sequence *seq); +void nvgpu_pmu_seq_set_fbq_heap_offset(struct pmu_sequence *seq, u16 size); +u8 *nvgpu_pmu_seq_get_out_payload(struct pmu_sequence *seq); +void nvgpu_pmu_seq_set_out_payload(struct pmu_sequence *seq, u8 *payload); +void nvgpu_pmu_seq_set_in_payload_fb_queue(struct pmu_sequence *seq, + bool state); +bool nvgpu_pmu_seq_get_out_payload_fb_queue(struct pmu_sequence *seq); +void nvgpu_pmu_seq_set_out_payload_fb_queue(struct pmu_sequence *seq, + bool state); +struct nvgpu_mem *nvgpu_pmu_seq_get_in_mem(struct pmu_sequence *seq); +void nvgpu_pmu_seq_set_in_mem(struct pmu_sequence *seq, + struct nvgpu_mem *mem); +struct nvgpu_mem *nvgpu_pmu_seq_get_out_mem(struct pmu_sequence *seq); +void nvgpu_pmu_seq_set_out_mem(struct pmu_sequence *seq, + struct nvgpu_mem *mem); +u32 nvgpu_pmu_seq_get_fbq_element_index(struct pmu_sequence *seq); +void nvgpu_pmu_seq_set_fbq_element_index(struct pmu_sequence *seq, u32 index); +u8 nvgpu_pmu_seq_get_id(struct pmu_sequence *seq); +enum pmu_seq_state nvgpu_pmu_seq_get_state(struct pmu_sequence *seq); +void nvgpu_pmu_seq_set_state(struct pmu_sequence *seq, + enum pmu_seq_state state); +struct pmu_sequence *nvgpu_pmu_sequences_get_seq(struct pmu_sequences *seqs, + u8 id); +void nvgpu_pmu_seq_callback(struct gk20a *g, struct pmu_sequence *seq, + struct pmu_msg *msg, int err); + +#endif /* NVGPU_PMU_SEQ_H */ diff --git a/drivers/gpu/nvgpu/include/nvgpu/pmuif/gpmuif_acr.h b/drivers/gpu/nvgpu/include/nvgpu/pmuif/gpmuif_acr.h index b33b71b43..934d62369 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/pmuif/gpmuif_acr.h +++ b/drivers/gpu/nvgpu/include/nvgpu/pmuif/gpmuif_acr.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2017-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"), @@ -22,6 +22,8 @@ #ifndef NVGPU_PMUIF_GPMUIF_ACR_H #define NVGPU_PMUIF_GPMUIF_ACR_H +#include + /* ACR Commands/Message structures */ enum { diff --git a/drivers/gpu/nvgpu/include/nvgpu/pmuif/gpmuif_ap.h b/drivers/gpu/nvgpu/include/nvgpu/pmuif/gpmuif_ap.h index 776fce8ef..e6f975870 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/pmuif/gpmuif_ap.h +++ b/drivers/gpu/nvgpu/include/nvgpu/pmuif/gpmuif_ap.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2017-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"), @@ -22,6 +22,8 @@ #ifndef NVGPU_PMUIF_GPMUIF_AP_H #define NVGPU_PMUIF_GPMUIF_AP_H +#include + /* PMU Command/Message Interfaces for Adaptive Power */ /* Macro to get Histogram index */ #define PMU_AP_HISTOGRAM(idx) (idx) diff --git a/drivers/gpu/nvgpu/include/nvgpu/pmuif/gpmuif_cmn.h b/drivers/gpu/nvgpu/include/nvgpu/pmuif/gpmuif_cmn.h index f07cda32c..bc03ad1d4 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/pmuif/gpmuif_cmn.h +++ b/drivers/gpu/nvgpu/include/nvgpu/pmuif/gpmuif_cmn.h @@ -22,6 +22,8 @@ #ifndef NVGPU_PMUIF_GPMUIF_CMN_H #define NVGPU_PMUIF_GPMUIF_CMN_H +#include + /* * Defines the logical queue IDs that must be used when submitting * commands to the PMU diff --git a/drivers/gpu/nvgpu/include/nvgpu/pmuif/gpmuif_perfmon.h b/drivers/gpu/nvgpu/include/nvgpu/pmuif/gpmuif_perfmon.h index 0f134aa10..f51e4b8ed 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/pmuif/gpmuif_perfmon.h +++ b/drivers/gpu/nvgpu/include/nvgpu/pmuif/gpmuif_perfmon.h @@ -22,6 +22,8 @@ #ifndef NVGPU_PMUIF_GPMUIF_PERFMON_H #define NVGPU_PMUIF_GPMUIF_PERFMON_H +#include + /*perfmon task defines*/ #define PMU_DOMAIN_GROUP_PSTATE 0U diff --git a/drivers/gpu/nvgpu/include/nvgpu/pmuif/gpmuif_pg.h b/drivers/gpu/nvgpu/include/nvgpu/pmuif/gpmuif_pg.h index 69a7ea47e..0d83c715c 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/pmuif/gpmuif_pg.h +++ b/drivers/gpu/nvgpu/include/nvgpu/pmuif/gpmuif_pg.h @@ -1,5 +1,5 @@ /* - * Copyright (c) 2017-2018, NVIDIA CORPORATION. All rights reserved. + * Copyright (c) 2017-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"), @@ -22,6 +22,8 @@ #ifndef NVGPU_PMUIF_GPMUIF_PG_H #define NVGPU_PMUIF_GPMUIF_PG_H +#include + #include "gpmuif_ap.h" #include "gpmuif_pg_rppg.h" diff --git a/drivers/gpu/nvgpu/include/nvgpu/pmuif/gpmuif_pmu.h b/drivers/gpu/nvgpu/include/nvgpu/pmuif/gpmuif_pmu.h index bed538cbe..87061a2c7 100644 --- a/drivers/gpu/nvgpu/include/nvgpu/pmuif/gpmuif_pmu.h +++ b/drivers/gpu/nvgpu/include/nvgpu/pmuif/gpmuif_pmu.h @@ -23,6 +23,7 @@ #define NVGPU_PMUIF_GPMUIF_PMU_H #include +#include #include "gpmuif_cmn.h" /* Make sure size of this structure is a multiple of 4 bytes */