diff --git a/drivers/video/tegra/host/pva/fw_include/fw_config.h b/drivers/video/tegra/host/pva/fw_include/fw_config.h index 3d1163df..39d9a4c6 100644 --- a/drivers/video/tegra/host/pva/fw_include/fw_config.h +++ b/drivers/video/tegra/host/pva/fw_include/fw_config.h @@ -76,7 +76,7 @@ * @brief The first Reserved DMA descriptor. This is used as a * starting point to iterate over reserved DMA descriptors. */ -#define PVA_RESERVED_DESC_START PVA_NUM_DYNAMIC_DESCS +#define PVA_RESERVED_DESC_START (60U) /** * @brief The first Reserved AXI data buffers. This is used as a diff --git a/drivers/video/tegra/host/pva/fw_include/pva-sys-dma.h b/drivers/video/tegra/host/pva/fw_include/pva-sys-dma.h index 49f82a8e..2f629679 100644 --- a/drivers/video/tegra/host/pva/fw_include/pva-sys-dma.h +++ b/drivers/video/tegra/host/pva/fw_include/pva-sys-dma.h @@ -17,6 +17,10 @@ #include #include +#ifdef CONFIG_TEGRA_T26X_GRHOST_PVA +#include +#endif + /*** Version number of the current DMA info structure */ #define PVA_DMA_INFO_VERSION_ID (1U) @@ -45,8 +49,10 @@ struct PVA_PACKED pva_dma_ch_config_s { #define PVA_SYS_DMA_NUM_TRIGGERS (9U) /** Number of DMA channel configurations in DMA info structure. */ #define PVA_SYS_DMA_NUM_CHANNELS (15U) -/** Maximum number of DMA descriptors allowed. */ -#define PVA_SYS_DMA_MAX_DESCRIPTORS (60U) +/** Maximum number of DMA descriptors allowed in T19x. */ +#define PVA_SYS_DMA_MAX_DESCRIPTORS_T19X (60U) +/** Maximum number of DMA descriptors allowed in T23x. */ +#define PVA_SYS_DMA_MAX_DESCRIPTORS_T23X (60U) /** @brief DMA info for a VPU app. * diff --git a/drivers/video/tegra/host/pva/pva.h b/drivers/video/tegra/host/pva/pva.h index 090d0666..cb04fec6 100644 --- a/drivers/video/tegra/host/pva/pva.h +++ b/drivers/video/tegra/host/pva/pva.h @@ -336,7 +336,7 @@ struct nvpva_syncpts_desc { /** * @brief Driver private data, shared with all applications * - * version pva version; 1 or 2 + * version pva version; 1, 2 or 3 * pdev Pointer to the PVA device * pool Pointer to Queue table available for the PVA * fw_info firmware information struct @@ -368,7 +368,7 @@ struct nvpva_syncpts_desc { */ struct pva { - int version; + u32 version; struct pva_version_config *version_config; struct platform_device *pdev; struct platform_device *aux_pdev; diff --git a/drivers/video/tegra/host/pva/pva_dma.c b/drivers/video/tegra/host/pva/pva_dma.c index 3e0701d0..4d59d016 100644 --- a/drivers/video/tegra/host/pva/pva_dma.c +++ b/drivers/video/tegra/host/pva/pva_dma.c @@ -23,6 +23,13 @@ #define LOW_BITS (0xFFFFFFFFU >> (32U - 4U)) #define NVPVA_MAX_VALID_BLK_HGT_LG2 5U +static const u8 max_desc_id[4] = { + [0] = 0U, // dummy entry to simplify lookup + [PVA_HW_GEN1] = NVPVA_TASK_MAX_DMA_DESCRIPTORS_T19X, + [PVA_HW_GEN2] = NVPVA_TASK_MAX_DMA_DESCRIPTORS_T23X, + [PVA_HW_GEN3] = NVPVA_TASK_MAX_DMA_DESCRIPTOR_ID_T26X +}; + int pitch_linear_eq_offset(struct nvpva_dma_descriptor const *dma_desc, s64 *frame_buf_offset, @@ -779,6 +786,9 @@ static int32_t nvpva_task_dma_desc_mapping(struct pva_submit_task *task, u8 num_dma_descriptors = task->num_dma_descriptors; u8 *num_dma_desc_processed = &task->num_dma_desc_processed; uint16_t exe_id = 0; + const uint8_t resv_desc_start_idx = NVPVA_RESERVED_DESCRIPTORS_START_IDX; + const uint8_t resv_desc_end_idx = (NVPVA_RESERVED_DESCRIPTORS_START_IDX + + NVPVA_NUM_RESERVED_DESCRIPTORS - 1); nvpva_dbg_fn(task->pva, ""); @@ -788,8 +798,12 @@ static int32_t nvpva_task_dma_desc_mapping(struct pva_submit_task *task, if (task->desc_processed & (1LLU << desc_num)) continue; - task->desc_processed |= (1LLU << desc_num); - ++(*num_dma_desc_processed); + if (desc_num == resv_desc_start_idx) { + desc_num = resv_desc_end_idx; + i += (resv_desc_end_idx - resv_desc_start_idx + 1); + continue; + } + umd_dma_desc = &task->dma_descriptors[desc_num]; dma_desc = &hw_task->dma_desc[desc_num]; is_misr = !((task->dma_misr_config.descriptor_mask @@ -865,8 +879,10 @@ static int32_t nvpva_task_dma_desc_mapping(struct pva_submit_task *task, (u8)((task->dst_surf_base_addr & 0x3E00) >> 6U); } - if (umd_dma_desc->linkDescId > task->num_dma_descriptors) { - task_err(task, "invalid link ID"); + if ((umd_dma_desc->linkDescId > task->num_dma_descriptors) + || ((umd_dma_desc->linkDescId > resv_desc_start_idx) + && (umd_dma_desc->linkDescId <= resv_desc_end_idx + 1))) { + task_err(task, "invalid link ID %u", umd_dma_desc->linkDescId); return -EINVAL; } @@ -965,17 +981,20 @@ verify_dma_desc_hwseq(struct pva_submit_task *task, u64 *desc_hwseq_frm = &task->desc_hwseq_frm; struct nvpva_dma_descriptor *desc; - nvpva_dbg_fn(task->pva, ""); + const uint8_t resv_desc_start_idx = NVPVA_RESERVED_DESCRIPTORS_START_IDX; + const uint8_t resv_desc_end_idx = (NVPVA_RESERVED_DESCRIPTORS_START_IDX + + NVPVA_NUM_RESERVED_DESCRIPTORS - 1); if ((did == 0U) - || (did >= NVPVA_TASK_MAX_DMA_DESCRIPTORS)) { + || (did >= max_desc_id[task->pva->version]) + || (((did - 1) >= resv_desc_start_idx) && ((did - 1) <= resv_desc_end_idx))) { pr_err("invalid Descritor ID"); err = -EINVAL; goto out; } did = array_index_nospec((did - 1), - NVPVA_TASK_MAX_DMA_DESCRIPTORS); + max_desc_id[task->pva->version]); desc = &task->dma_descriptors[did]; /* return flag if block linear format is in use */ @@ -1869,7 +1888,7 @@ verify_hwseq_blob(struct pva_submit_task *task, } did = array_index_nospec((blob_desc->did1 - 1U), - NVPVA_TASK_MAX_DMA_DESCRIPTORS); + max_desc_id[task->pva->version]); desc_block_height_log2[did] = user_ch->blockHeight; if (!is_desc_mode(blob->f_header.fid)) { desc_entries[k].did = did; @@ -1899,7 +1918,7 @@ verify_hwseq_blob(struct pva_submit_task *task, } did = array_index_nospec((blob_desc->did2 - 1U), - NVPVA_TASK_MAX_DMA_DESCRIPTORS); + max_desc_id[task->pva->version]); desc_block_height_log2[did] = user_ch->blockHeight; if (!is_desc_mode(blob->f_header.fid)) { desc_entries[k].did = did; @@ -1971,12 +1990,16 @@ nvpva_task_dma_channel_mapping(struct pva_submit_task *task, u32 adb_limit; int err = 0; u8 bl_xfers_in_use = 0; + const u8 resv_desc_start = NVPVA_RESERVED_DESCRIPTORS_START_IDX; + const u8 resv_desc_end = NVPVA_RESERVED_DESCRIPTORS_START_IDX + + NVPVA_NUM_RESERVED_DESCRIPTORS - 1; nvpva_dbg_fn(task->pva, ""); - if (((user_ch->descIndex > PVA_NUM_DYNAMIC_DESCS) || - ((user_ch->vdbSize + user_ch->vdbOffset) > - PVA_NUM_DYNAMIC_VDB_BUFFS))) { + if ((((user_ch->descIndex > resv_desc_start) + && (user_ch->descIndex <= resv_desc_end)) + || ((user_ch->vdbSize + user_ch->vdbOffset) > + PVA_NUM_DYNAMIC_VDB_BUFFS))) { pr_err("ERR: Invalid Channel control data"); err = -EINVAL; goto out; diff --git a/drivers/video/tegra/host/pva/pva_queue.h b/drivers/video/tegra/host/pva/pva_queue.h index a8b9f3b0..313a01c1 100644 --- a/drivers/video/tegra/host/pva/pva_queue.h +++ b/drivers/video/tegra/host/pva/pva_queue.h @@ -14,9 +14,27 @@ #include "pva-task.h" #include "pva_hwseq.h" +#ifdef CONFIG_TEGRA_T26X_GRHOST_PVA +#include +#else +#define NVPVA_TASK_MAX_DMA_DESCRIPTOR_ID_T26X \ + NVPVA_TASK_MAX_DMA_DESCRIPTORS_T23X +#define NVPVA_TASK_MAX_DMA_CHANNELS_T26X \ + NVPVA_TASK_MAX_DMA_CHANNELS_T23X +#endif + #define task_err(task, fmt, ...) \ dev_err(&task->pva->pdev->dev, fmt, ##__VA_ARGS__) +#define MAX_VAL(x, y) (((x) > (y)) ? (x) : (y)) +#define MAX_NUM_DESCS MAX_VAL((MAX_VAL(NVPVA_TASK_MAX_DMA_DESCRIPTORS_T19X, \ + NVPVA_TASK_MAX_DMA_DESCRIPTORS_T23X)), \ + NVPVA_TASK_MAX_DMA_DESCRIPTOR_ID_T26X) + +#define MAX_NUM_CHANNELS MAX_VAL((MAX_VAL(NVPVA_TASK_MAX_DMA_CHANNELS_T19X, \ + NVPVA_TASK_MAX_DMA_CHANNELS_T23X)), \ + NVPVA_TASK_MAX_DMA_CHANNELS_T26X) + struct dma_buf; extern struct nvpva_queue_ops pva_queue_ops; @@ -145,9 +163,9 @@ struct pva_submit_task { struct nvpva_mem input_task_status[NVPVA_TASK_MAX_INPUT_STATUS]; struct nvpva_mem output_task_status[NVPVA_TASK_MAX_OUTPUT_STATUS]; struct nvpva_dma_descriptor - dma_descriptors[NVPVA_TASK_MAX_DMA_DESCRIPTORS]; + dma_descriptors[MAX_NUM_DESCS]; /* max of T19x, T23x & T26x */ struct nvpva_dma_channel dma_channels - [NVPVA_TASK_MAX_DMA_CHANNELS_T23X]; /* max of T19x & T23x */ + [MAX_NUM_CHANNELS]; /* max of T19x, T23x & T26x */ struct nvpva_dma_misr dma_misr_config; struct nvpva_hwseq_config hwseq_config; struct nvpva_symbol_param symbols[NVPVA_TASK_MAX_SYMBOLS]; @@ -162,11 +180,10 @@ struct pva_submit_task { u64 fence_act_serial_ids[NVPVA_MAX_FENCE_TYPES] [NVPVA_TASK_MAX_FENCEACTIONS]; u64 prefences_serial_ids[NVPVA_TASK_MAX_PREFENCES]; - struct pva_hwseq_priv_s hwseq_info[NVPVA_TASK_MAX_DMA_CHANNELS_T23X]; - u8 desc_block_height_log2[NVPVA_TASK_MAX_DMA_DESCRIPTORS]; - struct pva_dma_task_buffer_info_s task_buff_info[NVPVA_TASK_MAX_DMA_DESCRIPTORS]; - struct pva_dma_hwseq_desc_entry_s desc_entries[NVPVA_TASK_MAX_DMA_CHANNELS_T23X] - [PVA_HWSEQ_DESC_LIMIT]; + struct pva_hwseq_priv_s hwseq_info[MAX_NUM_CHANNELS]; + u8 desc_block_height_log2[MAX_NUM_DESCS]; + struct pva_dma_task_buffer_info_s task_buff_info[MAX_NUM_DESCS]; + struct pva_dma_hwseq_desc_entry_s desc_entries[MAX_NUM_CHANNELS][PVA_HWSEQ_DESC_LIMIT]; /** Store Suface base address */ u64 src_surf_base_addr; @@ -285,7 +302,7 @@ struct pva_hw_task { struct pva_task_action_s postactions[PVA_MAX_POSTACTION_LISTS]; struct pva_dma_info_and_params_list_s dma_info_and_params_list; struct pva_dma_misr_config_s dma_misr_config; - struct pva_dtd_s dma_desc[NVPVA_TASK_MAX_DMA_DESCRIPTORS]; + struct pva_dtd_s dma_desc[MAX_NUM_DESCS]; /* max of all gens */ struct pva_vpu_parameter_info_s param_info; struct pva_task_statistics_s statistics; struct pva_circular_buffer_info_s stdout_cb_info; diff --git a/include/uapi/linux/nvpva_ioctl.h b/include/uapi/linux/nvpva_ioctl.h index 4c2cfa0d..76cfb0ea 100644 --- a/include/uapi/linux/nvpva_ioctl.h +++ b/include/uapi/linux/nvpva_ioctl.h @@ -516,12 +516,31 @@ union nvpva_set_vpu_print_buffer_size_args { struct nvpva_set_vpu_print_buffer_size_in_arg in; }; -/* There are 64 DMA descriptors in T19x and T23x. But R5 FW reserves +/** + * There are 64 DMA descriptors in T19x. But R5 FW reserves * 4 DMA descriptors for internal use. */ -#define NVPVA_TASK_MAX_DMA_DESCRIPTORS (60U) +#define NVPVA_TASK_MAX_DMA_DESCRIPTORS_T19X (60U) +/** + * There are 64 DMA descriptors in T23x. But R5 FW reserves + * 4 DMA descriptors for internal use. + */ +#define NVPVA_TASK_MAX_DMA_DESCRIPTORS_T23X (60U) + +/** + * Number of DMA descriptors reserved for R5 FW's + * internal use + */ +#define NVPVA_NUM_RESERVED_DESCRIPTORS (4U) + +/** + * Index of the first reserved DMA descriptor + */ +#define NVPVA_RESERVED_DESCRIPTORS_START_IDX (60U) + /*TODO: Remove NVPVA_TASK_MAX_DMA_CHANNELS */ -/*There are 14 DMA channels in T19x and 16 DMA channels in T23X. +/** + * There are 14 DMA channels in T19x and 16 DMA channels in T23X. * R5 FW reserves one DMA channel for internal use. */ #define NVPVA_TASK_MAX_DMA_CHANNELS 16U @@ -597,7 +616,7 @@ union nvpva_set_vpu_print_buffer_size_args { NVPVA_MAX_FENCE_TYPES * sizeof(struct nvpva_fence_action) + \ NVPVA_TASK_MAX_INPUT_STATUS * sizeof(struct nvpva_mem) + \ NVPVA_TASK_MAX_OUTPUT_STATUS * sizeof(struct nvpva_mem) + \ - NVPVA_TASK_MAX_DMA_DESCRIPTORS * \ + NVPVA_TASK_MAX_DMA_DESCRIPTORS_T23X * \ sizeof(struct nvpva_dma_descriptor) + \ NVPVA_TASK_MAX_DMA_CHANNELS * sizeof(struct nvpva_dma_channel) + \ sizeof(struct nvpva_hwseq_config) + \