diff --git a/drivers/video/tegra/host/pva/fw_include/pva-task.h b/drivers/video/tegra/host/pva/fw_include/pva-task.h index ee1d89da..ec58f3ec 100644 --- a/drivers/video/tegra/host/pva/fw_include/pva-task.h +++ b/drivers/video/tegra/host/pva/fw_include/pva-task.h @@ -211,7 +211,7 @@ struct PVA_PACKED pva_td_s { /** @brief IOVA pointer to a pva_bin_info_t structure */ pva_iova bin_info; /** @brief IOVA pointer to a pva_bin_info_t structure */ - pva_iova ppe_bin_info; + pva_iova bin_info2; /** @brief IOVA pointer to a pva_dma_info_t structure */ pva_iova dma_info; /** IOVA pointer to a pva_circular_info_t structure */ diff --git a/drivers/video/tegra/host/pva/pva_dma.c b/drivers/video/tegra/host/pva/pva_dma.c index 4b357e8e..75bbc01c 100644 --- a/drivers/video/tegra/host/pva/pva_dma.c +++ b/drivers/video/tegra/host/pva/pva_dma.c @@ -263,6 +263,19 @@ out: return err; } +static uint16_t +get_sym_exe_id(struct pva_submit_task *task) +{ + u16 exe_id = NVPVA_NOOP_EXE_ID; + + if (task->exe_id2 != NVPVA_NOOP_EXE_ID) + exe_id = task->exe_id2; + if (task->exe_id1 != NVPVA_NOOP_EXE_ID) + exe_id = task->exe_id1; + + return exe_id; +} + static int32_t patch_dma_desc_address(struct pva_submit_task *task, struct nvpva_dma_descriptor *umd_dma_desc, @@ -271,11 +284,13 @@ patch_dma_desc_address(struct pva_submit_task *task, { int32_t err = 0; uint64_t addr_base = 0; + uint16_t exe_id = 0; struct pva_dma_task_buffer_info_s *buff_info = &task->task_buff_info[desc_id]; int hwgen = task->pva->version; nvpva_dbg_fn(task->pva, ""); + exe_id = get_sym_exe_id(task); switch (umd_dma_desc->srcTransferMode) { case DMA_DESC_SRC_XFER_L2RAM: /* @@ -329,7 +344,7 @@ patch_dma_desc_address(struct pva_submit_task *task, goto out; } - err = pva_get_sym_offset(&task->client->elf_ctx, task->exe_id1, + err = pva_get_sym_offset(&task->client->elf_ctx, exe_id, umd_dma_desc->srcPtr, &addr, &size); if (err) { err = -EINVAL; @@ -371,7 +386,7 @@ patch_dma_desc_address(struct pva_submit_task *task, /* calculate symbol address */ /* TODO: check VPUC handling in ELF segment */ - err = pva_get_sym_offset(&task->client->elf_ctx, task->exe_id1, + err = pva_get_sym_offset(&task->client->elf_ctx, exe_id, umd_dma_desc->srcPtr, &addr, &size); if (err) { task_err(task, "ERROR: Invalid offset or address"); @@ -516,7 +531,7 @@ patch_dma_desc_address(struct pva_submit_task *task, goto out; } - err = pva_get_sym_offset(&task->client->elf_ctx, task->exe_id1, + err = pva_get_sym_offset(&task->client->elf_ctx, exe_id, umd_dma_desc->dstPtr, &addr, &size); if (err) { err = -EINVAL; @@ -528,7 +543,7 @@ patch_dma_desc_address(struct pva_submit_task *task, if (umd_dma_desc->dst2Ptr != NVPVA_INVALID_SYMBOL_ID) { err = pva_get_sym_offset(&task->client->elf_ctx, - task->exe_id1, + exe_id, umd_dma_desc->dst2Ptr, &addr2, &size2); @@ -763,6 +778,8 @@ static int32_t nvpva_task_dma_desc_mapping(struct pva_submit_task *task, bool is_misr; u8 num_dma_descriptors = task->num_dma_descriptors; u8 *num_dma_desc_processed = &task->num_dma_desc_processed; + uint16_t exe_id = 0; + nvpva_dbg_fn(task->pva, ""); desc_num = *did; @@ -885,9 +902,10 @@ static int32_t nvpva_task_dma_desc_mapping(struct pva_submit_task *task, /* DMA_DESC_PY */ dma_desc->py = (uint8_t)umd_dma_desc->py; /* DMA_DESC_FRDA */ + exe_id = get_sym_exe_id(task); if (umd_dma_desc->dst2Ptr != NVPVA_INVALID_SYMBOL_ID) { err = pva_get_sym_offset(&task->client->elf_ctx, - task->exe_id1, + exe_id, umd_dma_desc->dst2Ptr, &addr, &size); diff --git a/drivers/video/tegra/host/pva/pva_ioctl.c b/drivers/video/tegra/host/pva/pva_ioctl.c index b252914b..4105c5bc 100644 --- a/drivers/video/tegra/host/pva/pva_ioctl.c +++ b/drivers/video/tegra/host/pva/pva_ioctl.c @@ -170,6 +170,7 @@ static int pva_copy_task(struct nvpva_ioctl_task *ioctl_task, * copy them. */ task->exe_id1 = ioctl_task->exe_id1; + task->exe_id2 = ioctl_task->exe_id2; task->stream_id = ioctl_task->stream_id; task->prog_id = ioctl_task->prog_id; task->l2_alloc_size = ioctl_task->l2_alloc_size; diff --git a/drivers/video/tegra/host/pva/pva_queue.c b/drivers/video/tegra/host/pva/pva_queue.c index 19aca391..f92f1c0e 100644 --- a/drivers/video/tegra/host/pva/pva_queue.c +++ b/drivers/video/tegra/host/pva/pva_queue.c @@ -87,6 +87,7 @@ static void pva_task_dump(struct pva_submit_task *task) int i; nvpva_dbg_info(task->pva, "task=%p, exe_id1=%u", task, task->exe_id1); + nvpva_dbg_info(task->pva, "task=%p, exe_id2=%u", task, task->exe_id2); for (i = 0; i < task->num_input_task_status; i++) nvpva_dbg_info(task->pva, "input task status %d: pin_id=%u, offset=%u", i, @@ -562,11 +563,19 @@ pva_task_write_vpu_parameter(struct pva_submit_task *task, u32 tail_count = 0U; struct pva_vpu_parameters_s *hw_task_param_list; - if ((task->exe_id1 == NVPVA_NOOP_EXE_ID) || (task->num_symbols == 0U)) + if (task->num_symbols == 0U) + goto out; + + if ((task->exe_id1 == NVPVA_NOOP_EXE_ID) && (task->exe_id2 == NVPVA_NOOP_EXE_ID)) goto out; tail_index = ((u32)task->num_symbols - 1U); - elf = get_elf_image(&task->client->elf_ctx, task->exe_id1); + + if (task->exe_id1 != NVPVA_NOOP_EXE_ID) { + elf = get_elf_image(&task->client->elf_ctx, task->exe_id1); + } else if (task->exe_id2 != NVPVA_NOOP_EXE_ID) + elf = get_elf_image(&task->client->elf_ctx, task->exe_id2); + if (task->num_symbols > elf->num_symbols) { task_err(task, "invalid number of symbols"); err = -EINVAL; @@ -706,12 +715,26 @@ pva_task_write_vpu_parameter(struct pva_submit_task *task, hw_task->task.parameter_info_base = task->dma_addr + offsetof(struct pva_hw_task, param_info); - err = pva_task_acquire_ref_vpu_app(&task->client->elf_ctx, - task->exe_id1); - if (err) { - task_err(task, - "unable to acquire ref count for app with id = %u", - task->exe_id1); + if (task->exe_id1 != NVPVA_NOOP_EXE_ID) { + + err = pva_task_acquire_ref_vpu_app(&task->client->elf_ctx, + task->exe_id1); + if (err) { + task_err(task, + "unable to acquire ref count for app with id = %u", + task->exe_id1); + } + } + + if (task->exe_id2 != NVPVA_NOOP_EXE_ID) { + + err = pva_task_acquire_ref_vpu_app(&task->client->elf_ctx, + task->exe_id2); + if (err) { + task_err(task, + "unable to acquire ref count for app with id = %u", + task->exe_id2); + } } task->pinned_app = true; @@ -760,7 +783,13 @@ static int pva_task_write(struct pva_submit_task *task) if (!pva_vpu_elf_is_registered(&task->client->elf_ctx, task->exe_id1) && (task->exe_id1 != NVPVA_NOOP_EXE_ID)) { - task_err(task, "invalid exe id: %d", task->exe_id1); + task_err(task, "invalid VPU exe id: %d", task->exe_id1); + return -EINVAL; + } + + if (!pva_vpu_elf_is_registered(&task->client->elf_ctx, task->exe_id2) && + (task->exe_id2 != NVPVA_NOOP_EXE_ID)) { + task_err(task, "invalid exe id: %d", task->exe_id2); return -EINVAL; } /* Task start from the memory base */ @@ -810,6 +839,9 @@ static int pva_task_write(struct pva_submit_task *task) hw_task->task.bin_info = phys_get_bin_info(&task->client->elf_ctx, task->exe_id1); + hw_task->task.bin_info2 = + phys_get_bin_info(&task->client->elf_ctx, task->exe_id2); + if (task->stdout) { hw_task->stdout_cb_info.buffer = task->stdout->buffer_addr; hw_task->stdout_cb_info.head = task->stdout->head_addr; @@ -927,9 +959,12 @@ void pva_task_free(struct kref *ref) mutex_unlock(&my_queue->tail_lock); pva_task_unpin_mem(task); - if (task->pinned_app) + if (task->pinned_app) { pva_task_release_ref_vpu_app(&task->client->elf_ctx, task->exe_id1); + pva_task_release_ref_vpu_app(&task->client->elf_ctx, + task->exe_id2); + } nvhost_module_idle(task->pva->pdev); nvpva_client_context_put(task->client); diff --git a/drivers/video/tegra/host/pva/pva_queue.h b/drivers/video/tegra/host/pva/pva_queue.h index 03ef6d60..a8b9f3b0 100644 --- a/drivers/video/tegra/host/pva/pva_queue.h +++ b/drivers/video/tegra/host/pva/pva_queue.h @@ -110,6 +110,7 @@ struct pva_submit_task { u32 exe_id1; u64 stream_id; u64 prog_id; + u32 exe_id2; u32 l2_alloc_size; /* Not applicable for Xavier */ struct pva_cb *stdout; diff --git a/drivers/video/tegra/host/pva/pva_vpu_exe.c b/drivers/video/tegra/host/pva/pva_vpu_exe.c index fe51c4de..a26d64c5 100644 --- a/drivers/video/tegra/host/pva/pva_vpu_exe.c +++ b/drivers/video/tegra/host/pva/pva_vpu_exe.c @@ -909,7 +909,7 @@ pva_get_sym_tab(struct nvpva_elf_context *d, return 0; } -int32_t pva_get_sym_info(struct nvpva_elf_context *d, uint16_t vpu_exe_id, +int32_t pva_get_sym_info(struct nvpva_elf_context *d, uint16_t exe_id, const char *sym_name, struct pva_elf_symbol *symbol) { struct pva_elf_image *elf; @@ -917,7 +917,7 @@ int32_t pva_get_sym_info(struct nvpva_elf_context *d, uint16_t vpu_exe_id, int32_t err = 0; size_t strSize = strnlen(sym_name, ELF_MAX_SYMBOL_LENGTH); - elf = get_elf_image(d, vpu_exe_id); + elf = get_elf_image(d, exe_id); for (i = 0; i < elf->num_symbols; i++) { if (strncmp(sym_name, elf->sym[i].symbol_name, strSize) == 0) { symbol->symbolID = elf->sym[i].symbolID; diff --git a/drivers/video/tegra/host/pva/pva_vpu_exe.h b/drivers/video/tegra/host/pva/pva_vpu_exe.h index 78ccf6f9..1c4e885d 100644 --- a/drivers/video/tegra/host/pva/pva_vpu_exe.h +++ b/drivers/video/tegra/host/pva/pva_vpu_exe.h @@ -151,7 +151,7 @@ struct nvpva_elf_context { * Get Symbol info given the symbol name from a vpu app * * @param d Pointer to Elf Context - * @param vpu_exe_id ID of the VPU app + * @param exe_id ID of the VPU app * @param *sym_name String containing Name of the symbol * @param *symbol symbol information @@ -159,7 +159,7 @@ struct nvpva_elf_context { * When -EINVAL is returned, ignore values in id and * sym_size */ -int32_t pva_get_sym_info(struct nvpva_elf_context *d, uint16_t vpu_exe_id, +int32_t pva_get_sym_info(struct nvpva_elf_context *d, uint16_t exe_id, const char *sym_name, struct pva_elf_symbol *symbol); /** diff --git a/include/uapi/linux/nvpva_ioctl.h b/include/uapi/linux/nvpva_ioctl.h index 79cb097b..4c2cfa0d 100644 --- a/include/uapi/linux/nvpva_ioctl.h +++ b/include/uapi/linux/nvpva_ioctl.h @@ -475,6 +475,7 @@ struct nvpva_ioctl_task { uint64_t prog_id; uint64_t stream_id; uint16_t exe_id1; + uint16_t exe_id2; uint32_t flags; uint32_t l2_alloc_size; /* Not applicable for Xavier */ struct nvpva_ioctl_part prefences;