diff --git a/driver/vidc/inc/msm_vidc_driver.h b/driver/vidc/inc/msm_vidc_driver.h index d6ee13e9d9..687b34ea8d 100644 --- a/driver/vidc/inc/msm_vidc_driver.h +++ b/driver/vidc/inc/msm_vidc_driver.h @@ -468,12 +468,14 @@ struct msm_vidc_allocations *msm_vidc_get_allocations( const char *func); struct msm_vidc_buffer *msm_vidc_get_driver_buf(struct msm_vidc_inst *inst, struct vb2_buffer *vb2); +int msm_vidc_allocate_buffers(struct msm_vidc_inst *inst, + enum msm_vidc_buffer_type buf_type, u32 num_buffers); +int msm_vidc_free_buffers(struct msm_vidc_inst *inst, + enum msm_vidc_buffer_type buf_type); int msm_vidc_unmap_driver_buf(struct msm_vidc_inst *inst, struct msm_vidc_buffer *buf); int msm_vidc_map_driver_buf(struct msm_vidc_inst *inst, struct msm_vidc_buffer *buf); -int msm_vidc_put_driver_buf(struct msm_vidc_inst *inst, - struct msm_vidc_buffer *buf); int msm_vidc_get_delayed_unmap(struct msm_vidc_inst *inst, struct msm_vidc_map *map); int msm_vidc_put_delayed_unmap(struct msm_vidc_inst *inst, @@ -495,8 +497,8 @@ int msm_vidc_destroy_internal_buffer(struct msm_vidc_inst *inst, void msm_vidc_destroy_buffers(struct msm_vidc_inst *inst); int msm_vidc_flush_buffers(struct msm_vidc_inst* inst, enum msm_vidc_buffer_type type); -int msm_vidc_flush_delayed_unmap_buffers(struct msm_vidc_inst *inst, - enum msm_vidc_buffer_type type); +int msm_vidc_flush_read_only_buffers(struct msm_vidc_inst *inst, + enum msm_vidc_buffer_type type); struct msm_vidc_buffer *get_meta_buffer(struct msm_vidc_inst *inst, struct msm_vidc_buffer *vbuf); struct msm_vidc_inst *get_inst_ref(struct msm_vidc_core *core, @@ -598,5 +600,8 @@ int msm_vidc_get_input_rate(struct msm_vidc_inst *inst); int msm_vidc_get_frame_rate(struct msm_vidc_inst *inst); int msm_vidc_get_operating_rate(struct msm_vidc_inst *inst); int msm_vidc_alloc_and_queue_input_internal_buffers(struct msm_vidc_inst *inst); +int vb2_buffer_to_driver(struct vb2_buffer *vb2, struct msm_vidc_buffer *buf); +struct msm_vidc_buffer *msm_vidc_fetch_buffer(struct msm_vidc_inst *inst, + struct vb2_buffer *vb2); #endif // _MSM_VIDC_DRIVER_H_ diff --git a/driver/vidc/inc/msm_vidc_inst.h b/driver/vidc/inc/msm_vidc_inst.h index befd855b29..71d674433e 100644 --- a/driver/vidc/inc/msm_vidc_inst.h +++ b/driver/vidc/inc/msm_vidc_inst.h @@ -42,10 +42,6 @@ struct msm_vidc_allocations_info { }; struct msm_vidc_mappings_info { - struct msm_vidc_mappings input; - struct msm_vidc_mappings output; - struct msm_vidc_mappings input_meta; - struct msm_vidc_mappings output_meta; struct msm_vidc_mappings bin; struct msm_vidc_mappings arp; struct msm_vidc_mappings comv; @@ -61,7 +57,6 @@ struct msm_vidc_buffers_info { struct msm_vidc_buffers input; struct msm_vidc_buffers output; struct msm_vidc_buffers read_only; - struct msm_vidc_buffers release; struct msm_vidc_buffers input_meta; struct msm_vidc_buffers output_meta; struct msm_vidc_buffers bin; diff --git a/driver/vidc/inc/msm_vidc_internal.h b/driver/vidc/inc/msm_vidc_internal.h index 533a6b6387..f8fb7bc9f9 100644 --- a/driver/vidc/inc/msm_vidc_internal.h +++ b/driver/vidc/inc/msm_vidc_internal.h @@ -21,6 +21,8 @@ #include #include +struct msm_vidc_inst; + /* TODO : remove once available in mainline kernel */ #ifndef V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10_STILL_PICTURE #define V4L2_MPEG_VIDEO_HEVC_PROFILE_MAIN_10_STILL_PICTURE (3) @@ -220,7 +222,9 @@ enum msm_vidc_buffer_flags { MSM_VIDC_BUF_FLAG_BFRAME = 0x00000020, MSM_VIDC_BUF_FLAG_ERROR = 0x00000040, MSM_VIDC_BUF_FLAG_LAST = 0x00100000, + /* codec config is a vendor specific flag */ MSM_VIDC_BUF_FLAG_CODECCONFIG = 0x01000000, + /* sub frame is a vendor specific flag */ MSM_VIDC_BUF_FLAG_SUBFRAME = 0x02000000, }; @@ -858,6 +862,7 @@ struct msm_vidc_mappings { struct msm_vidc_buffer { struct list_head list; + struct msm_vidc_inst *inst; enum msm_vidc_buffer_type type; u32 index; int fd; @@ -865,10 +870,13 @@ struct msm_vidc_buffer { u32 data_offset; u32 data_size; u64 device_addr; - void *dmabuf; u32 flags; u64 timestamp; enum msm_vidc_buffer_attributes attr; + void *dmabuf; + struct sg_table *sg_table; + struct dma_buf_attachment *attach; + u32 dbuf_get:1; u64 fence_id; u32 start_time_ms; u32 end_time_ms; diff --git a/driver/vidc/inc/msm_vidc_memory.h b/driver/vidc/inc/msm_vidc_memory.h index 11105260b6..2ee8517aed 100644 --- a/driver/vidc/inc/msm_vidc_memory.h +++ b/driver/vidc/inc/msm_vidc_memory.h @@ -7,6 +7,7 @@ #define _MSM_VIDC_MEMORY_H_ #include "msm_vidc_internal.h" +#include "msm_vidc_dt.h" struct msm_vidc_core; struct msm_vidc_inst; @@ -66,4 +67,15 @@ void *msm_memory_pool_alloc(struct msm_vidc_inst *inst, void msm_memory_pool_free(struct msm_vidc_inst *inst, void *vidc_buf); int msm_vidc_vmem_alloc(unsigned long size, void **mem, const char *msg); void msm_vidc_vmem_free(void **addr); +struct context_bank_info *msm_vidc_get_context_bank(struct msm_vidc_core *core, + enum msm_vidc_buffer_region region); +struct dma_buf_attachment *msm_vidc_dma_buf_attach(struct dma_buf *dbuf, + struct device *dev); +int msm_vidc_dma_buf_detach(struct dma_buf *dbuf, + struct dma_buf_attachment *attach); +struct sg_table *msm_vidc_dma_buf_map_attachment( + struct dma_buf_attachment *attach); +int msm_vidc_dma_buf_unmap_attachment(struct dma_buf_attachment *attach, + struct sg_table *table); + #endif // _MSM_VIDC_MEMORY_H_ \ No newline at end of file diff --git a/driver/vidc/inc/venus_hfi_response.h b/driver/vidc/inc/venus_hfi_response.h index ebd19e9d68..776164a8e8 100644 --- a/driver/vidc/inc/venus_hfi_response.h +++ b/driver/vidc/inc/venus_hfi_response.h @@ -19,5 +19,7 @@ bool is_valid_hfi_buffer_type(struct msm_vidc_inst *inst, int handle_system_error(struct msm_vidc_core *core, struct hfi_packet *pkt); void fw_coredump(struct msm_vidc_core *core); +int handle_release_output_buffer(struct msm_vidc_inst *inst, + struct hfi_buffer *buffer); #endif // __VENUS_HFI_RESPONSE_H__ diff --git a/driver/vidc/src/msm_vdec.c b/driver/vidc/src/msm_vdec.c index 5ae47f2161..01747454a5 100644 --- a/driver/vidc/src/msm_vdec.c +++ b/driver/vidc/src/msm_vdec.c @@ -1861,7 +1861,7 @@ static inline enum msm_vidc_allow msm_vdec_allow_queue_deferred_buffers( static int msm_vdec_qbuf_batch(struct msm_vidc_inst *inst, struct vb2_buffer *vb2) { - struct msm_vidc_buffer *buf; + struct msm_vidc_buffer *buf = NULL; enum msm_vidc_allow allow; int rc; @@ -1874,8 +1874,6 @@ static int msm_vdec_qbuf_batch(struct msm_vidc_inst *inst, if (!buf) return -EINVAL; - msm_vidc_add_buffer_stats(inst, buf); - allow = msm_vidc_allow_qbuf(inst, vb2->type); if (allow == MSM_VIDC_DISALLOW) { i_vpr_e(inst, "%s: qbuf not allowed\n", __func__); @@ -1907,7 +1905,7 @@ static int msm_vdec_release_nonref_buffers(struct msm_vidc_inst *inst) { int rc = 0; u32 fw_ro_count = 0, nonref_ro_count = 0; - struct msm_vidc_buffer *ro_buf, *rel_buf, *dummy; + struct msm_vidc_buffer *ro_buf; int i = 0; bool found = false; @@ -1916,17 +1914,22 @@ static int msm_vdec_release_nonref_buffers(struct msm_vidc_inst *inst) return -EINVAL; } - /* count num buffers in read_only list */ - list_for_each_entry(ro_buf, &inst->buffers.read_only.list, list) + /* count read_only buffers which are not pending release in read_only list */ + list_for_each_entry(ro_buf, &inst->buffers.read_only.list, list) { + if (!(ro_buf->attr & MSM_VIDC_ATTR_READ_ONLY)) + continue; + if (ro_buf->attr & MSM_VIDC_ATTR_PENDING_RELEASE) + continue; fw_ro_count++; + } if (fw_ro_count <= MAX_DPB_COUNT) return 0; /* - * Mark those buffers present in read_only list as non-reference - * if that buffer is not part of dpb_list_payload - * count such non-ref read only buffers as nonref_ro_count + * Mark those read only buffers present in read_only list as + * non-reference if that buffer is not part of dpb_list_payload. + * count such non-ref read only buffers as nonref_ro_count. * dpb_list_payload details: * payload[0-1] : 64 bits base_address of DPB-1 * payload[2] : 32 bits addr_offset of DPB-1 @@ -1934,6 +1937,35 @@ static int msm_vdec_release_nonref_buffers(struct msm_vidc_inst *inst) */ list_for_each_entry(ro_buf, &inst->buffers.read_only.list, list) { found = false; + if (!(ro_buf->attr & MSM_VIDC_ATTR_READ_ONLY)) + continue; + if (ro_buf->attr & MSM_VIDC_ATTR_PENDING_RELEASE) + continue; + for (i = 0; (i + 3) < MAX_DPB_LIST_ARRAY_SIZE; i = i + 4) { + if (ro_buf->device_addr == inst->dpb_list_payload[i] && + ro_buf->data_offset == inst->dpb_list_payload[i + 3]) { + found = true; + break; + } + } + if (!found) + nonref_ro_count++; + } + + + if (nonref_ro_count <= inst->buffers.output.min_count) + return 0; + + i_vpr_l(inst, "%s: fw ro buf count %d, non-ref ro count %d\n", + __func__, fw_ro_count, nonref_ro_count); + + /* release the eligible buffers as per above condition */ + list_for_each_entry(ro_buf, &inst->buffers.read_only.list, list) { + found = false; + if (!(ro_buf->attr & MSM_VIDC_ATTR_READ_ONLY)) + continue; + if (ro_buf->attr & MSM_VIDC_ATTR_PENDING_RELEASE) + continue; for (i = 0; (i + 3) < MAX_DPB_LIST_ARRAY_SIZE; i = i + 4) { if (ro_buf->device_addr == inst->dpb_list_payload[i] && ro_buf->data_offset == inst->dpb_list_payload[i + 3]) { @@ -1942,146 +1974,14 @@ static int msm_vdec_release_nonref_buffers(struct msm_vidc_inst *inst) } } if (!found) { - ro_buf->attr &= ~MSM_VIDC_ATTR_READ_ONLY; - nonref_ro_count++; - } - } - - if (nonref_ro_count <= inst->buffers.output.min_count) - return 0; - - i_vpr_l(inst, "%s: fw ro buf count %d, non-ref ro count %d\n", - __func__, fw_ro_count, nonref_ro_count); - /* - * move non-ref read only buffers from read_only list to - * release list - */ - list_for_each_entry_safe(ro_buf, dummy, &inst->buffers.read_only.list, list) { - if (!(ro_buf->attr & MSM_VIDC_ATTR_READ_ONLY)) { - list_del(&ro_buf->list); - INIT_LIST_HEAD(&ro_buf->list); - list_add_tail(&ro_buf->list, &inst->buffers.release.list); - } - } - - /* send release flag along with read only flag for release list bufs*/ - list_for_each_entry(rel_buf, &inst->buffers.release.list, list) { - /* fw needs RO flag for FTB release buffer */ - rel_buf->attr |= MSM_VIDC_ATTR_READ_ONLY; - print_vidc_buffer(VIDC_LOW, "low ", "release buf", inst, rel_buf); - rc = venus_hfi_release_buffer(inst, rel_buf); - if (rc) - return rc; - } - - return rc; -} - -int msm_vdec_handle_release_buffer(struct msm_vidc_inst *inst, - struct msm_vidc_buffer *buf) -{ - int rc = 0; - - if (!inst || !buf) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - /** - * RO & release list doesnot take dma ref_count using dma_buf_get(). - * Dmabuf ptr willbe obsolete when its last ref was last. - * Use direct api to print logs instead of calling print_vidc_buffer() - * api, which will attempt to dereferrence dmabuf ptr. - */ - i_vpr_l(inst, - "release done: %s: idx %2d fd %3d off %d daddr %#llx size %8d filled %8d flags %#x ts %8lld attr %#x counts(etb ebd ftb fbd) %4llu %4llu %4llu %4llu\n", - buf_name(buf->type), - buf->index, buf->fd, buf->data_offset, - buf->device_addr, buf->buffer_size, buf->data_size, - buf->flags, buf->timestamp, buf->attr, inst->debug_count.etb, - inst->debug_count.ebd, inst->debug_count.ftb, inst->debug_count.fbd); - /* delete the buffer from release list */ - list_del(&buf->list); - msm_memory_pool_free(inst, buf); - - return rc; -} - -static bool is_valid_removable_buffer(struct msm_vidc_inst *inst, - struct msm_vidc_map *map) -{ - bool found = false; - struct msm_vidc_buffer *buf; - - if (!inst || !map) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - - if (map->refcount != 1) - return false; - - list_for_each_entry(buf, &inst->buffers.read_only.list, list) { - if (map->device_addr == buf->device_addr) { - found = true; - break; - } - } - - list_for_each_entry(buf, &inst->buffers.release.list, list) { - if (map->device_addr == buf->device_addr) { - found = true; - break; - } - } - - if (!found) - return true; - - return false; -} - -static int msm_vidc_unmap_excessive_mappings(struct msm_vidc_inst *inst) -{ - int rc = 0; - struct msm_vidc_map *map, *temp; - u32 refcount_one_bufs_count = 0; - - if (!inst) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - - /* - * count entries from map list which are not present in - * read_only buffers list, not present in release list - * and whose refcount is 1.these are excess mappings - * present due to delayed unmap feature. - */ - list_for_each_entry(map, &inst->mappings.output.list, list) { - if (is_valid_removable_buffer(inst, map)) - refcount_one_bufs_count++; - } - - if (refcount_one_bufs_count <= inst->max_map_output_count) - return 0; - - /* unmap these buffers as they are stale entries */ - list_for_each_entry_safe(map, temp, &inst->mappings.output.list, list) { - if (is_valid_removable_buffer(inst, map)) { - i_vpr_l(inst, - "%s: type %11s, device_addr %#x, refcount %d, region %d\n", - __func__, buf_name(map->type), map->device_addr, - map->refcount, map->region); - rc = msm_vidc_put_delayed_unmap(inst, map); + ro_buf->attr |= MSM_VIDC_ATTR_PENDING_RELEASE; + print_vidc_buffer(VIDC_LOW, "low ", "release buf", inst, ro_buf); + rc = venus_hfi_release_buffer(inst, ro_buf); if (rc) return rc; - if (!map->refcount) { - list_del_init(&map->list); - msm_vidc_memory_put_dmabuf(inst, map->dmabuf); - msm_memory_pool_free(inst, map); - } } } + return rc; } @@ -2119,12 +2019,6 @@ int msm_vdec_qbuf(struct msm_vidc_inst *inst, struct vb2_buffer *vb2) if (rc) return rc; - if (vb2->type == OUTPUT_MPLANE) { - rc = msm_vidc_unmap_excessive_mappings(inst); - if (rc) - return rc; - } - return rc; } diff --git a/driver/vidc/src/msm_vidc.c b/driver/vidc/src/msm_vidc.c index 70c2aa449a..406389e814 100644 --- a/driver/vidc/src/msm_vidc.c +++ b/driver/vidc/src/msm_vidc.c @@ -893,7 +893,7 @@ void *msm_vidc_open(void *vidc_core, u32 session_type) inst->core = core; inst->domain = session_type; inst->session_id = hash32_ptr(inst); - inst->state = MSM_VIDC_OPEN; + msm_vidc_change_state(inst, MSM_VIDC_OPEN, __func__); inst->sub_state = MSM_VIDC_SUB_STATE_NONE; strlcpy(inst->sub_state_name, "SUB_STATE_NONE", sizeof(inst->sub_state_name)); inst->active = true; @@ -924,7 +924,6 @@ void *msm_vidc_open(void *vidc_core, u32 session_type) INIT_LIST_HEAD(&inst->buffers.output.list); INIT_LIST_HEAD(&inst->buffers.output_meta.list); INIT_LIST_HEAD(&inst->buffers.read_only.list); - INIT_LIST_HEAD(&inst->buffers.release.list); INIT_LIST_HEAD(&inst->buffers.bin.list); INIT_LIST_HEAD(&inst->buffers.arp.list); INIT_LIST_HEAD(&inst->buffers.comv.list); @@ -943,10 +942,6 @@ void *msm_vidc_open(void *vidc_core, u32 session_type) INIT_LIST_HEAD(&inst->allocations.persist.list); INIT_LIST_HEAD(&inst->allocations.vpss.list); INIT_LIST_HEAD(&inst->allocations.partial_data.list); - INIT_LIST_HEAD(&inst->mappings.input.list); - INIT_LIST_HEAD(&inst->mappings.input_meta.list); - INIT_LIST_HEAD(&inst->mappings.output.list); - INIT_LIST_HEAD(&inst->mappings.output_meta.list); INIT_LIST_HEAD(&inst->mappings.bin.list); INIT_LIST_HEAD(&inst->mappings.arp.list); INIT_LIST_HEAD(&inst->mappings.comv.list); @@ -1045,8 +1040,9 @@ int msm_vidc_close(void *instance) /* print final stats */ msm_vidc_print_stats(inst); msm_vidc_session_close(inst); + msm_vidc_event_queue_deinit(inst); + msm_vidc_vb2_queue_deinit(inst); msm_vidc_remove_session(inst); - msm_vidc_destroy_buffers(inst); inst_unlock(inst, __func__); client_unlock(inst, __func__); cancel_stability_work_sync(inst); diff --git a/driver/vidc/src/msm_vidc_driver.c b/driver/vidc/src/msm_vidc_driver.c index 9d332b8413..d6c9fbb491 100644 --- a/driver/vidc/src/msm_vidc_driver.c +++ b/driver/vidc/src/msm_vidc_driver.c @@ -455,17 +455,17 @@ void print_vidc_buffer(u32 tag, const char *tag_str, const char *str, struct msm } dprintk_inst(tag, tag_str, inst, - "%s: %s: idx %2d fd %3d off %d daddr %#llx inode %8lu ref %2ld size %8d filled %8d flags %#x ts %8lld attr %#x counts(etb ebd ftb fbd) %4llu %4llu %4llu %4llu\n", + "%s: %s: idx %2d fd %3d off %d daddr %#llx inode %8lu ref %2ld size %8d filled %8d flags %#x ts %8lld attr %#x dbuf_get %d attach %d map %d counts(etb ebd ftb fbd) %4llu %4llu %4llu %4llu\n", str, buf_name(vbuf->type), vbuf->index, vbuf->fd, vbuf->data_offset, - vbuf->device_addr, inode_num, ref_count, vbuf->buffer_size, vbuf->data_size, - vbuf->flags, vbuf->timestamp, vbuf->attr, inst->debug_count.etb, - inst->debug_count.ebd, inst->debug_count.ftb, inst->debug_count.fbd); + vbuf->device_addr, inode_num, ref_count, vbuf->buffer_size, + vbuf->data_size, vbuf->flags, vbuf->timestamp, vbuf->attr, + vbuf->dbuf_get, vbuf->attach ? 1 : 0, vbuf->sg_table ? 1 : 0, + inst->debug_count.etb, inst->debug_count.ebd, + inst->debug_count.ftb, inst->debug_count.fbd); trace_msm_v4l2_vidc_buffer_event_log(inst, str, buf_name(vbuf->type), vbuf, inode_num, ref_count); - - } void print_vb2_buffer(const char *str, struct msm_vidc_inst *inst, @@ -1171,14 +1171,6 @@ struct msm_vidc_mappings *msm_vidc_get_mappings( const char *func) { switch (buffer_type) { - case MSM_VIDC_BUF_INPUT: - return &inst->mappings.input; - case MSM_VIDC_BUF_INPUT_META: - return &inst->mappings.input_meta; - case MSM_VIDC_BUF_OUTPUT: - return &inst->mappings.output; - case MSM_VIDC_BUF_OUTPUT_META: - return &inst->mappings.output_meta; case MSM_VIDC_BUF_BIN: return &inst->mappings.bin; case MSM_VIDC_BUF_ARP: @@ -2469,25 +2461,26 @@ int msm_vidc_num_buffers(struct msm_vidc_inst *inst, return count; } -static int vb2_buffer_to_driver(struct vb2_buffer *vb2, +int vb2_buffer_to_driver(struct vb2_buffer *vb2, struct msm_vidc_buffer *buf) { int rc = 0; + struct vb2_v4l2_buffer *vbuf; if (!vb2 || !buf) { d_vpr_e("%s: invalid params\n", __func__); return -EINVAL; } + vbuf = to_vb2_v4l2_buffer(vb2); - buf->type = v4l2_type_to_driver(vb2->type, __func__); - if (!buf->type) - return -EINVAL; - buf->index = vb2->index; buf->fd = vb2->planes[0].m.fd; buf->data_offset = vb2->planes[0].data_offset; buf->data_size = vb2->planes[0].bytesused - vb2->planes[0].data_offset; buf->buffer_size = vb2->planes[0].length; buf->timestamp = vb2->timestamp; + buf->flags = vbuf->flags; + buf->attr = 0; + buf->fence_id = 0; return rc; } @@ -2497,7 +2490,6 @@ int msm_vidc_process_readonly_buffers(struct msm_vidc_inst *inst, { int rc = 0; struct msm_vidc_buffer *ro_buf, *dummy; - struct msm_vidc_buffers *ro_buffers; if (!inst || !buf) { d_vpr_e("%s: invalid params\n", __func__); @@ -2507,24 +2499,34 @@ int msm_vidc_process_readonly_buffers(struct msm_vidc_inst *inst, if (!is_decode_session(inst) || !is_output_buffer(buf->type)) return 0; - ro_buffers = msm_vidc_get_buffers(inst, MSM_VIDC_BUF_READ_ONLY, __func__); - if (!ro_buffers) - return -EINVAL; - /* - * check if buffer present in ro_buffers list - * if present: add ro flag to buf and remove from ro_buffers list - * if not present: do nothing + * check if read_only buffer is present in read_only list + * if present: add ro flag to buf */ - list_for_each_entry_safe(ro_buf, dummy, &ro_buffers->list, list) { - if (ro_buf->device_addr == buf->device_addr) { + list_for_each_entry_safe(ro_buf, dummy, &inst->buffers.read_only.list, list) { + if (ro_buf->device_addr == buf->device_addr && + ro_buf->attr & MSM_VIDC_ATTR_READ_ONLY) { buf->attr |= MSM_VIDC_ATTR_READ_ONLY; - print_vidc_buffer(VIDC_LOW, "low ", "ro buf removed", inst, ro_buf); - list_del(&ro_buf->list); - msm_memory_pool_free(inst, ro_buf); break; } } + + /* remove ro buffers if not required anymore */ + list_for_each_entry_safe(ro_buf, dummy, &inst->buffers.read_only.list, list) { + /* if read only buffer do not remove */ + if (ro_buf->attr & MSM_VIDC_ATTR_READ_ONLY) + continue; + /* if v4l2 did not ask for unmap/detach then do not remove */ + if (!ro_buf->sg_table || !ro_buf->attach || !ro_buf->dbuf_get) + continue; + print_vidc_buffer(VIDC_LOW, "low ", "ro buf removed", inst, ro_buf); + msm_vidc_dma_buf_unmap_attachment(ro_buf->attach, ro_buf->sg_table); + msm_vidc_dma_buf_detach(ro_buf->dmabuf, ro_buf->attach); + msm_vidc_memory_put_dmabuf(inst, ro_buf->dmabuf); + list_del_init(&ro_buf->list); + msm_memory_pool_free(inst, ro_buf); + } + return rc; } @@ -2999,29 +3001,6 @@ int msm_vidc_put_delayed_unmap(struct msm_vidc_inst *inst, struct msm_vidc_map * return rc; } -int msm_vidc_unmap_buffers(struct msm_vidc_inst *inst, - enum msm_vidc_buffer_type type) -{ - int rc = 0; - struct msm_vidc_mappings *mappings; - struct msm_vidc_map *map, *dummy; - - if (!inst) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - - mappings = msm_vidc_get_mappings(inst, type, __func__); - if (!mappings) - return -EINVAL; - - list_for_each_entry_safe(map, dummy, &mappings->list, list) { - msm_vidc_memory_unmap_completely(inst, map); - } - - return rc; -} - int msm_vidc_unmap_driver_buf(struct msm_vidc_inst *inst, struct msm_vidc_buffer *buf) { @@ -3135,34 +3114,116 @@ error: return rc; } -int msm_vidc_put_driver_buf(struct msm_vidc_inst *inst, - struct msm_vidc_buffer *buf) -{ - int rc = 0; - - if (!inst || !buf) { - d_vpr_e("%s: invalid params\n", __func__); - return -EINVAL; - } - - msm_vidc_unmap_driver_buf(inst, buf); - - msm_vidc_memory_put_dmabuf(inst, buf->dmabuf); - - /* delete the buffer from buffers->list */ - list_del(&buf->list); - msm_memory_pool_free(inst, buf); - - return rc; -} - struct msm_vidc_buffer *msm_vidc_get_driver_buf(struct msm_vidc_inst *inst, struct vb2_buffer *vb2) { int rc = 0; + struct msm_vidc_buffer *buf; + + if (!inst || !vb2) { + d_vpr_e("%s: invalid params\n", __func__); + return NULL; + } + + buf = msm_vidc_fetch_buffer(inst, vb2); + if (!buf) { + i_vpr_e(inst, "%s: failed to fetch buffer\n", __func__); + return NULL; + } + + rc = vb2_buffer_to_driver(vb2, buf); + if (rc) + return NULL; + + /* treat every buffer as deferred buffer initially */ + buf->attr |= MSM_VIDC_ATTR_DEFERRED; + + if (is_decode_session(inst) && is_output_buffer(buf->type)) { + /* get a reference */ + if (!buf->dbuf_get) { + buf->dmabuf = msm_vidc_memory_get_dmabuf(inst, buf->fd); + if (!buf->dmabuf) + return NULL; + buf->dbuf_get = 1; + } + } + + /* update start timestamp */ + msm_vidc_add_buffer_stats(inst, buf); + + return buf; +} + +int msm_vidc_allocate_buffers(struct msm_vidc_inst *inst, + enum msm_vidc_buffer_type buf_type, u32 num_buffers) +{ + int rc = 0; + int idx = 0; + struct msm_vidc_buffer *buf = NULL; + struct msm_vidc_buffers *buffers; + + if (!inst) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + + buffers = msm_vidc_get_buffers(inst, buf_type, __func__); + if (!buffers) + return -EINVAL; + + for (idx = 0; idx < num_buffers; idx++) { + buf = msm_memory_pool_alloc(inst, MSM_MEM_POOL_BUFFER); + if (!buf) { + i_vpr_e(inst, "%s: alloc failed\n", __func__); + return -EINVAL; + } + INIT_LIST_HEAD(&buf->list); + list_add_tail(&buf->list, &buffers->list); + buf->type = buf_type; + buf->index = idx; + } + i_vpr_h(inst, "%s: allocated %d buffers for type %s\n", + __func__, num_buffers, buf_name(buf_type)); + + return rc; +} + +int msm_vidc_free_buffers(struct msm_vidc_inst *inst, + enum msm_vidc_buffer_type buf_type) +{ + int rc = 0; + int buf_count = 0; + struct msm_vidc_buffer *buf, *dummy; + struct msm_vidc_buffers *buffers; + + if (!inst) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + + buffers = msm_vidc_get_buffers(inst, buf_type, __func__); + if (!buffers) + return -EINVAL; + + list_for_each_entry_safe(buf, dummy, &buffers->list, list) { + buf_count++; + print_vidc_buffer(VIDC_LOW, "low ", "free buffer", inst, buf); + list_del_init(&buf->list); + msm_memory_pool_free(inst, buf); + } + i_vpr_h(inst, "%s: freed %d buffers for type %s\n", + __func__, buf_count, buf_name(buf_type)); + + return rc; +} + +struct msm_vidc_buffer *msm_vidc_fetch_buffer(struct msm_vidc_inst *inst, + struct vb2_buffer *vb2) +{ struct msm_vidc_buffer *buf = NULL; struct msm_vidc_buffers *buffers; enum msm_vidc_buffer_type buf_type; + bool found = false; if (!inst || !vb2) { d_vpr_e("%s: invalid params\n", __func__); @@ -3177,36 +3238,20 @@ struct msm_vidc_buffer *msm_vidc_get_driver_buf(struct msm_vidc_inst *inst, if (!buffers) return NULL; - buf = msm_memory_pool_alloc(inst, MSM_MEM_POOL_BUFFER); - if (!buf) { - i_vpr_e(inst, "%s: alloc failed\n", __func__); + list_for_each_entry(buf, &buffers->list, list) { + if (buf->index == vb2->index) { + found = true; + break; + } + } + + if (!found) { + i_vpr_e(inst, "%s: buffer not found for index %d for vb2 buffer type %s\n", + __func__, vb2->index, v4l2_type_name(vb2->type)); return NULL; } - INIT_LIST_HEAD(&buf->list); - list_add_tail(&buf->list, &buffers->list); - - rc = vb2_buffer_to_driver(vb2, buf); - if (rc) - goto error; - - buf->dmabuf = msm_vidc_memory_get_dmabuf(inst, buf->fd); - if (!buf->dmabuf) - goto error; - - /* treat every buffer as deferred buffer initially */ - buf->attr |= MSM_VIDC_ATTR_DEFERRED; - - rc = msm_vidc_map_driver_buf(inst, buf); - if (rc) - goto error; return buf; - -error: - msm_vidc_memory_put_dmabuf(inst, buf->dmabuf); - list_del(&buf->list); - msm_memory_pool_free(inst, buf); - return NULL; } struct msm_vidc_buffer *get_meta_buffer(struct msm_vidc_inst *inst, @@ -3609,8 +3654,10 @@ static int msm_vidc_queue_buffer(struct msm_vidc_inst *inst, struct msm_vidc_buf print_vidc_buffer(VIDC_HIGH, "high", "qbuf", inst, buf); meta = get_meta_buffer(inst, buf); - if (meta) + if (meta && meta->attr & MSM_VIDC_ATTR_DEFERRED) print_vidc_buffer(VIDC_LOW, "low ", "qbuf", inst, meta); + else + meta = NULL; if (!meta && is_meta_enabled(inst, buf->type)) { print_vidc_buffer(VIDC_ERR, "err ", "missing meta for", inst, buf); @@ -3710,7 +3757,7 @@ int msm_vidc_queue_deferred_buffers(struct msm_vidc_inst *inst, enum msm_vidc_bu int msm_vidc_queue_buffer_single(struct msm_vidc_inst *inst, struct vb2_buffer *vb2) { int rc = 0; - struct msm_vidc_buffer *buf; + struct msm_vidc_buffer *buf = NULL; struct msm_vidc_fence *fence = NULL; enum msm_vidc_allow allow; @@ -3723,9 +3770,6 @@ int msm_vidc_queue_buffer_single(struct msm_vidc_inst *inst, struct vb2_buffer * if (!buf) return -EINVAL; - /* update start timestamp */ - msm_vidc_add_buffer_stats(inst, buf); - if (is_meta_rx_inp_enabled(inst, META_OUTBUF_FENCE) && is_output_buffer(buf->type)) { fence = msm_vidc_fence_create(inst); @@ -4638,12 +4682,13 @@ int msm_vidc_session_streamoff(struct msm_vidc_inst *inst, /* flush deferred buffers */ msm_vidc_flush_buffers(inst, buffer_type); - msm_vidc_flush_delayed_unmap_buffers(inst, buffer_type); + msm_vidc_flush_read_only_buffers(inst, buffer_type); return 0; error: msm_vidc_kill_session(inst); msm_vidc_flush_buffers(inst, buffer_type); + msm_vidc_flush_read_only_buffers(inst, buffer_type); return rc; } @@ -4684,10 +4729,9 @@ int msm_vidc_session_close(struct msm_vidc_inst *inst) } inst_lock(inst, __func__); - inst->state = MSM_VIDC_CLOSE; + msm_vidc_change_state(inst, MSM_VIDC_CLOSE, __func__); inst->sub_state = MSM_VIDC_SUB_STATE_NONE; strlcpy(inst->sub_state_name, "SUB_STATE_NONE", sizeof(inst->sub_state_name)); - msm_vidc_remove_session(inst); return rc; } @@ -5555,10 +5599,15 @@ int msm_vidc_flush_buffers(struct msm_vidc_inst *inst, buf->attr & MSM_VIDC_ATTR_DEFERRED) { print_vidc_buffer(VIDC_HIGH, "high", "flushing buffer", inst, buf); if (!(buf->attr & MSM_VIDC_ATTR_BUFFER_DONE)) { + if (is_decode_session(inst) && is_output_buffer(buf->type)) { + if (buf->dbuf_get) { + msm_vidc_memory_put_dmabuf(inst, buf->dmabuf); + buf->dbuf_get = 0; + } + } buf->data_size = 0; msm_vidc_vb2_buffer_done(inst, buf); } - msm_vidc_put_driver_buf(inst, buf); } } } @@ -5566,66 +5615,37 @@ int msm_vidc_flush_buffers(struct msm_vidc_inst *inst, return rc; } -int msm_vidc_flush_delayed_unmap_buffers(struct msm_vidc_inst *inst, +int msm_vidc_flush_read_only_buffers(struct msm_vidc_inst *inst, enum msm_vidc_buffer_type type) { int rc = 0; - struct msm_vidc_mappings *maps; - struct msm_vidc_map *map, *dummy; - struct msm_vidc_buffer *ro_buf, *ro_dummy; - enum msm_vidc_buffer_type buffer_type[2]; - int i; - bool found = false; + struct msm_vidc_buffer *ro_buf, *dummy; if (!inst) { d_vpr_e("%s: invalid params\n", __func__); return -EINVAL; } - if (type == MSM_VIDC_BUF_INPUT) { - buffer_type[0] = MSM_VIDC_BUF_INPUT_META; - buffer_type[1] = MSM_VIDC_BUF_INPUT; - } else if (type == MSM_VIDC_BUF_OUTPUT) { - buffer_type[0] = MSM_VIDC_BUF_OUTPUT_META; - buffer_type[1] = MSM_VIDC_BUF_OUTPUT; - } else { - i_vpr_h(inst, "%s: invalid buffer type %d\n", - __func__, type); - return -EINVAL; - } + if (!is_decode_session(inst) || !is_output_buffer(type)) + return 0; - for (i = 0; i < ARRAY_SIZE(buffer_type); i++) { - maps = msm_vidc_get_mappings(inst, buffer_type[i], __func__); - if (!maps) - return -EINVAL; - - list_for_each_entry_safe(map, dummy, &maps->list, list) { - /* - * decoder output bufs will have skip_delayed_unmap = true - * unmap all decoder output buffers except those present in - * read_only buffers list - */ - if (!map->skip_delayed_unmap) - continue; - found = false; - list_for_each_entry_safe(ro_buf, ro_dummy, - &inst->buffers.read_only.list, list) { - if (map->dmabuf == ro_buf->dmabuf) { - found = true; - break; - } - } - /* completely unmap */ - if (!found) { - if (map->refcount > 1) { - i_vpr_e(inst, - "%s: unexpected map refcount: %u device addr %#x\n", - __func__, map->refcount, map->device_addr); - msm_vidc_change_state(inst, MSM_VIDC_ERROR, __func__); - } - msm_vidc_memory_unmap_completely(inst, map); - } - } + list_for_each_entry_safe(ro_buf, dummy, &inst->buffers.read_only.list, list) { + if (ro_buf->attr & MSM_VIDC_ATTR_READ_ONLY) + continue; + print_vidc_buffer(VIDC_ERR, "high", "flush ro buf", inst, ro_buf); + if (ro_buf->attach && ro_buf->sg_table) + msm_vidc_dma_buf_unmap_attachment(ro_buf->attach, ro_buf->sg_table); + if (ro_buf->attach && ro_buf->dmabuf) + msm_vidc_dma_buf_detach(ro_buf->dmabuf, ro_buf->attach); + if (ro_buf->dbuf_get) + msm_vidc_memory_put_dmabuf(inst, ro_buf->dmabuf); + ro_buf->attach = NULL; + ro_buf->sg_table = NULL; + ro_buf->dmabuf = NULL; + ro_buf->dbuf_get = 0; + ro_buf->device_addr = 0x0; + list_del_init(&ro_buf->list); + msm_memory_pool_free(inst, ro_buf); } return rc; @@ -5678,19 +5698,20 @@ void msm_vidc_destroy_buffers(struct msm_vidc_inst *inst) } } - /* read_only and release list does not take dma ref_count using dma_buf_get(). - dma_buf ptr will be obselete when its ref_count reaches zero. Hence print - the dma_buf info before releasing the ref count. - */ + /* + * read_only list does not take dma ref_count using dma_buf_get(). + * dma_buf ptr will be obselete when its ref_count reaches zero. + * Hence printthe dma_buf info before releasing the ref count. + */ list_for_each_entry_safe(buf, dummy, &inst->buffers.read_only.list, list) { - print_vidc_buffer(VIDC_ERR, "err ", "destroying ro buffer", inst, buf); - list_del(&buf->list); - msm_memory_pool_free(inst, buf); - } - - list_for_each_entry_safe(buf, dummy, &inst->buffers.release.list, list) { - print_vidc_buffer(VIDC_ERR, "err ", "destroying release buffer", inst, buf); - list_del(&buf->list); + print_vidc_buffer(VIDC_ERR, "err ", "destroying ro buf", inst, buf); + if (buf->attach && buf->sg_table) + msm_vidc_dma_buf_unmap_attachment(buf->attach, buf->sg_table); + if (buf->attach && buf->dmabuf) + msm_vidc_dma_buf_detach(buf->dmabuf, buf->attach); + if (buf->dbuf_get) + msm_vidc_memory_put_dmabuf(inst, buf->dmabuf); + list_del_init(&buf->list); msm_memory_pool_free(inst, buf); } @@ -5700,12 +5721,17 @@ void msm_vidc_destroy_buffers(struct msm_vidc_inst *inst) continue; list_for_each_entry_safe(buf, dummy, &buffers->list, list) { - print_vidc_buffer(VIDC_ERR, "err ", "destroying ", inst, buf); - if (!(buf->attr & MSM_VIDC_ATTR_BUFFER_DONE)) - msm_vidc_vb2_buffer_done(inst, buf); - msm_vidc_put_driver_buf(inst, buf); + if (buf->attach && buf->sg_table) + msm_vidc_dma_buf_unmap_attachment(buf->attach, buf->sg_table); + if (buf->attach && buf->dmabuf) + msm_vidc_dma_buf_detach(buf->dmabuf, buf->attach); + if (buf->dbuf_get) { + print_vidc_buffer(VIDC_ERR, "err ", "destroying: put dmabuf", inst, buf); + msm_vidc_memory_put_dmabuf(inst, buf->dmabuf); + } + list_del_init(&buf->list); + msm_memory_pool_free(inst, buf); } - msm_vidc_unmap_buffers(inst, ext_buf_types[i]); } list_for_each_entry_safe(ts, dummy_ts, &inst->timestamps.list, sort.list) { @@ -5736,8 +5762,19 @@ void msm_vidc_destroy_buffers(struct msm_vidc_inst *inst) } list_for_each_entry_safe(dbuf, dummy_dbuf, &inst->dmabuf_tracker, list) { - i_vpr_e(inst, "%s: removing dma_buf %#x, refcount %u\n", - __func__, dbuf->dmabuf, dbuf->refcount); + struct dma_buf *dmabuf; + struct inode *f_inode; + unsigned long inode_num = 0; + + dmabuf = dbuf->dmabuf; + if (dmabuf && dmabuf->file) { + f_inode = file_inode(dmabuf->file); + if (f_inode) { + inode_num = f_inode->i_ino; + } + } + i_vpr_e(inst, "%s: removing dma_buf %#lx, inode %lu, refcount %u\n", + __func__, dbuf->dmabuf, inode_num, dbuf->refcount); msm_vidc_memory_put_dmabuf_completely(inst, dbuf); } @@ -5774,8 +5811,6 @@ static void msm_vidc_close_helper(struct kref *kref) i_vpr_h(inst, "%s()\n", __func__); msm_vidc_fence_deinit(inst); - msm_vidc_event_queue_deinit(inst); - msm_vidc_vb2_queue_deinit(inst); msm_vidc_debugfs_deinit_inst(inst); if (is_decode_session(inst)) msm_vdec_inst_deinit(inst); @@ -5784,6 +5819,7 @@ static void msm_vidc_close_helper(struct kref *kref) msm_vidc_free_input_cr_list(inst); if (inst->workq) destroy_workqueue(inst->workq); + msm_vidc_destroy_buffers(inst); msm_vidc_remove_dangling_session(inst); mutex_destroy(&inst->client_lock); mutex_destroy(&inst->request_lock); diff --git a/driver/vidc/src/msm_vidc_memory.c b/driver/vidc/src/msm_vidc_memory.c index 936fa8185e..b1dd7d0a00 100644 --- a/driver/vidc/src/msm_vidc_memory.c +++ b/driver/vidc/src/msm_vidc_memory.c @@ -14,7 +14,6 @@ #include "msm_vidc_debug.h" #include "msm_vidc_internal.h" #include "msm_vidc_driver.h" -#include "msm_vidc_dt.h" #include "msm_vidc_core.h" #include "msm_vidc_events.h" #include "venus_hfi.h" @@ -28,7 +27,7 @@ struct msm_vidc_buf_region_name { char *name; }; -struct context_bank_info *get_context_bank(struct msm_vidc_core *core, +struct context_bank_info *msm_vidc_get_context_bank(struct msm_vidc_core *core, enum msm_vidc_buffer_region region) { const char *name; @@ -215,7 +214,7 @@ int msm_vidc_memory_map(struct msm_vidc_core *core, struct msm_vidc_map *map) } } - cb = get_context_bank(core, map->region); + cb = msm_vidc_get_context_bank(core, map->region); if (!cb) { d_vpr_e("%s: Failed to get context bank device\n", __func__); @@ -318,6 +317,78 @@ exit: return rc; } +struct dma_buf_attachment *msm_vidc_dma_buf_attach(struct dma_buf *dbuf, + struct device *dev) +{ + int rc = 0; + struct dma_buf_attachment *attach = NULL; + + if (!dbuf || !dev) { + d_vpr_e("%s: invalid params\n", __func__); + return NULL; + } + + attach = dma_buf_attach(dbuf, dev); + if (IS_ERR_OR_NULL(attach)) { + rc = PTR_ERR(attach) ? PTR_ERR(attach) : -1; + d_vpr_e("Failed to attach dmabuf, error %d\n", rc); + return NULL;; + } + + return attach; +} + +int msm_vidc_dma_buf_detach(struct dma_buf *dbuf, + struct dma_buf_attachment *attach) +{ + int rc = 0; + + if (!dbuf || !attach) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + + dma_buf_detach(dbuf, attach); + + return rc; +} + +struct sg_table *msm_vidc_dma_buf_map_attachment( + struct dma_buf_attachment *attach) +{ + int rc = 0; + struct sg_table *table = NULL; + + if (!attach) { + d_vpr_e("%s: invalid params\n", __func__); + return NULL; + } + + table = dma_buf_map_attachment(attach, DMA_BIDIRECTIONAL); + if (IS_ERR_OR_NULL(table)) { + rc = PTR_ERR(table) ? PTR_ERR(table) : -1; + d_vpr_e("Failed to map table, error %d\n", rc); + return NULL; + } + + return table; +} + +int msm_vidc_dma_buf_unmap_attachment(struct dma_buf_attachment *attach, + struct sg_table *table) +{ + int rc = 0; + + if (!attach || !table) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + + dma_buf_unmap_attachment(attach, table, DMA_BIDIRECTIONAL); + + return rc; +} + int msm_vidc_vmem_alloc(unsigned long size, void **mem, const char *msg) { int rc = 0; diff --git a/driver/vidc/src/msm_vidc_vb2.c b/driver/vidc/src/msm_vidc_vb2.c index 7aaad7ad96..ae51df02d0 100644 --- a/driver/vidc/src/msm_vidc_vb2.c +++ b/driver/vidc/src/msm_vidc_vb2.c @@ -4,6 +4,8 @@ */ /* Copyright (c) 2022. Qualcomm Innovation Center, Inc. All rights reserved. */ +#include + #include "msm_vidc_vb2.h" #include "msm_vidc_core.h" #include "msm_vidc_inst.h" @@ -14,6 +16,7 @@ #include "msm_venc.h" #include "msm_vidc_debug.h" #include "msm_vidc_control.h" +#include "msm_vidc_dt.h" extern struct msm_vidc_core *g_core; @@ -65,7 +68,52 @@ void *msm_vb2_alloc(struct vb2_buffer *vb, struct device *dev, void *msm_vb2_attach_dmabuf(struct vb2_buffer *vb, struct device *dev, struct dma_buf *dbuf, unsigned long size) { - return (void *)0xdeadbeef; + struct msm_vidc_inst *inst; + struct msm_vidc_core *core; + struct msm_vidc_buffer *buf = NULL; + + if (!vb || !dev || !dbuf || !vb->vb2_queue) { + d_vpr_e("%s: invalid params\n", __func__); + return NULL; + } + inst = vb->vb2_queue->drv_priv; + inst = get_inst_ref(g_core, inst); + if (!inst || !inst->core) { + d_vpr_e("%s: invalid params %pK\n", __func__, inst); + return NULL; + } + core = inst->core; + + buf = msm_vidc_fetch_buffer(inst, vb); + if (!buf) { + i_vpr_e(inst, "%s: failed to fetch buffer\n", __func__); + buf = NULL; + goto exit; + } + buf->inst = inst; + + buf->attach = msm_vidc_dma_buf_attach(dbuf, dev); + if (!buf->attach) { + buf->attach = NULL; + buf = NULL; + goto exit; + } + + buf->attach->dma_map_attrs |= DMA_ATTR_SKIP_CPU_SYNC; + /* remove below flag when userspace recycles buffers in same index */ + buf->attach->dma_map_attrs |= DMA_ATTR_DELAYED_UNMAP; + if (core->dt->sys_cache_present) + buf->attach->dma_map_attrs |= + DMA_ATTR_IOMMU_USE_UPSTREAM_HINT; + + buf->dmabuf = dbuf; + print_vidc_buffer(VIDC_LOW, "low ", "attach", inst, buf); + +exit: + if (!buf) + msm_vidc_change_state(inst, MSM_VIDC_ERROR, __func__); + put_inst(inst); + return buf; } #endif @@ -80,15 +128,126 @@ int msm_vb2_mmap(void *buf_priv, struct vm_area_struct *vma) void msm_vb2_detach_dmabuf(void *buf_priv) { + struct msm_vidc_buffer *vbuf = buf_priv; + struct msm_vidc_buffer *ro_buf, *dummy; + struct msm_vidc_inst *inst; + + if (!vbuf || !vbuf->inst) { + d_vpr_e("%s: invalid params\n", __func__); + return; + } + inst = vbuf->inst; + inst = get_inst_ref(g_core, inst); + if (!inst || !inst->core) { + d_vpr_e("%s: invalid params %pK\n", __func__, inst); + return; + } + + if (is_decode_session(inst) && is_output_buffer(vbuf->type)) { + list_for_each_entry_safe(ro_buf, dummy, &inst->buffers.read_only.list, list) { + if (ro_buf->dmabuf == vbuf->dmabuf) { + print_vidc_buffer(VIDC_LOW, "low ", "detach: found ro buf", inst, ro_buf); + ro_buf->attach = vbuf->attach; + vbuf->attach = NULL; + goto exit; + } + } + } + + print_vidc_buffer(VIDC_LOW, "low ", "detach", inst, vbuf); + if (vbuf->attach && vbuf->dmabuf) { + msm_vidc_dma_buf_detach(vbuf->dmabuf, vbuf->attach); + vbuf->attach = NULL; + vbuf->dmabuf = NULL; + vbuf->inst = NULL; + } + vbuf->inst = NULL; + +exit: + put_inst(inst); + return; } int msm_vb2_map_dmabuf(void *buf_priv) { - return 0; + int rc = 0; + struct msm_vidc_buffer *buf = buf_priv; + struct msm_vidc_inst *inst; + + if (!buf || !buf->inst) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + inst = buf->inst; + inst = get_inst_ref(g_core, inst); + if (!inst || !inst->core) { + d_vpr_e("%s: invalid params\n", __func__); + return -EINVAL; + } + + buf->sg_table = msm_vidc_dma_buf_map_attachment(buf->attach); + if (!buf->sg_table) { + buf->sg_table = NULL; + rc = -ENOMEM; + goto exit; + } + + if (!buf->sg_table->sgl) { + i_vpr_e(inst, "%s: sgl is NULL\n", __func__); + rc = -ENOMEM; + goto exit; + } + + buf->device_addr = buf->sg_table->sgl->dma_address; + print_vidc_buffer(VIDC_HIGH, "high", "map", inst, buf); + +exit: + if (rc) + msm_vidc_change_state(inst, MSM_VIDC_ERROR, __func__); + put_inst(inst); + return rc; } void msm_vb2_unmap_dmabuf(void *buf_priv) { + struct msm_vidc_buffer *vbuf = buf_priv; + struct msm_vidc_buffer *ro_buf, *dummy; + struct msm_vidc_inst *inst; + + if (!vbuf || !vbuf->inst) { + d_vpr_e("%s: invalid params\n", __func__); + return; + } + inst = vbuf->inst; + inst = get_inst_ref(g_core, inst); + if (!inst || !inst->core) { + d_vpr_e("%s: invalid params %pK\n", __func__, inst); + return; + } + + if (is_decode_session(inst) && is_output_buffer(vbuf->type)) { + list_for_each_entry_safe(ro_buf, dummy, &inst->buffers.read_only.list, list) { + if (ro_buf->dmabuf == vbuf->dmabuf) { + print_vidc_buffer(VIDC_LOW, "low ", "unmap: found ro buf", inst, ro_buf); + ro_buf->sg_table = vbuf->sg_table; + ro_buf->attach = vbuf->attach; + vbuf->sg_table = NULL; + vbuf->device_addr = 0x0; + goto exit; + } + } + } + + print_vidc_buffer(VIDC_HIGH, "high", "unmap", inst, vbuf); + if (vbuf->attach && vbuf->sg_table) { + msm_vidc_dma_buf_unmap_attachment(vbuf->attach, vbuf->sg_table); + vbuf->sg_table = NULL; + vbuf->device_addr = 0x0; + } + +exit: + put_inst(inst); + return; } int msm_vidc_queue_setup(struct vb2_queue *q, @@ -97,8 +256,12 @@ int msm_vidc_queue_setup(struct vb2_queue *q, { int rc = 0; struct msm_vidc_inst *inst; + struct msm_vidc_core *core; int port; struct v4l2_format *f; + enum msm_vidc_buffer_type buffer_type = 0; + enum msm_vidc_buffer_region region = MSM_VIDC_REGION_NONE; + struct context_bank_info *cb = NULL; if (!q || !num_buffers || !num_planes || !sizes || !q->drv_priv) { @@ -111,6 +274,7 @@ int msm_vidc_queue_setup(struct vb2_queue *q, d_vpr_e("%s: invalid params %pK\n", __func__, inst); return -EINVAL; } + core = inst->core; if (is_state(inst, MSM_VIDC_STREAMING)) { i_vpr_e(inst, "%s: invalid state %d\n", __func__, inst->state); @@ -135,6 +299,16 @@ int msm_vidc_queue_setup(struct vb2_queue *q, } } + buffer_type = v4l2_type_to_driver(q->type, __func__); + if (!buffer_type) + return -EINVAL; + + rc = msm_vidc_free_buffers(inst, buffer_type); + if (rc) { + i_vpr_e(inst, "%s: failed to free buffers, type %s\n", + __func__, v4l2_type_name(q->type)); + return rc; + } if (port == INPUT_PORT) { *num_planes = 1; @@ -181,9 +355,25 @@ int msm_vidc_queue_setup(struct vb2_queue *q, sizes[0] = inst->fmts[port].fmt.meta.buffersize; } + rc = msm_vidc_allocate_buffers(inst, buffer_type, *num_buffers); + if (rc) { + i_vpr_e(inst, "%s: failed to allocate buffers, type %s\n", + __func__, v4l2_type_name(q->type)); + return rc; + } + + region = msm_vidc_get_buffer_region(inst, buffer_type, __func__); + cb = msm_vidc_get_context_bank(core, region); + if (!cb) { + d_vpr_e("%s: Failed to get context bank device\n", + __func__); + return -EIO; + } + q->dev = cb->dev; + i_vpr_h(inst, - "queue_setup: type %s num_buffers %d sizes[0] %d\n", - v4l2_type_name(q->type), *num_buffers, sizes[0]); + "queue_setup: type %s num_buffers %d sizes[0] %d cb %s\n", + v4l2_type_name(q->type), *num_buffers, sizes[0], cb->name); return rc; } diff --git a/driver/vidc/src/venus_hfi_response.c b/driver/vidc/src/venus_hfi_response.c index 5eb8aaa6b6..c37ad90a66 100644 --- a/driver/vidc/src/venus_hfi_response.c +++ b/driver/vidc/src/venus_hfi_response.c @@ -657,7 +657,6 @@ static int handle_read_only_buffer(struct msm_vidc_inst *inst, struct msm_vidc_buffer *buf) { struct msm_vidc_buffer *ro_buf; - struct msm_vidc_buffers *ro_buffers; bool found = false; if (!inst || !buf) { @@ -671,11 +670,7 @@ static int handle_read_only_buffer(struct msm_vidc_inst *inst, if (!(buf->attr & MSM_VIDC_ATTR_READ_ONLY)) return 0; - ro_buffers = msm_vidc_get_buffers(inst, MSM_VIDC_BUF_READ_ONLY, __func__); - if (!ro_buffers) - return -EINVAL; - - list_for_each_entry(ro_buf, &ro_buffers->list, list) { + list_for_each_entry(ro_buf, &inst->buffers.read_only.list, list) { if (ro_buf->device_addr == buf->device_addr) { found = true; break; @@ -691,10 +686,20 @@ static int handle_read_only_buffer(struct msm_vidc_inst *inst, i_vpr_e(inst, "%s: buffer alloc failed\n", __func__); return -ENOMEM; } - memcpy(ro_buf, buf, sizeof(struct msm_vidc_buffer)); + ro_buf->index = -1; + ro_buf->inst = inst; + ro_buf->type = buf->type; + ro_buf->fd = buf->fd; + ro_buf->dmabuf = buf->dmabuf; + ro_buf->device_addr = buf->device_addr; + ro_buf->data_offset = buf->data_offset; + ro_buf->dbuf_get = buf->dbuf_get; + buf->dbuf_get = 0; INIT_LIST_HEAD(&ro_buf->list); - list_add_tail(&ro_buf->list, &ro_buffers->list); + list_add_tail(&ro_buf->list, &inst->buffers.read_only.list); print_vidc_buffer(VIDC_LOW, "low ", "ro buf added", inst, ro_buf); + } else { + print_vidc_buffer(VIDC_LOW, "low ", "ro buf found", inst, ro_buf); } ro_buf->attr |= MSM_VIDC_ATTR_READ_ONLY; @@ -705,8 +710,6 @@ static int handle_non_read_only_buffer(struct msm_vidc_inst *inst, struct hfi_buffer *buffer) { struct msm_vidc_buffer *ro_buf; - struct msm_vidc_buffers *ro_buffers; - bool found = false; if (!inst || !buffer) { d_vpr_e("%s: invalid params\n", __func__); @@ -719,27 +722,13 @@ static int handle_non_read_only_buffer(struct msm_vidc_inst *inst, if (buffer->flags & HFI_BUF_FW_FLAG_READONLY) return 0; - ro_buffers = msm_vidc_get_buffers(inst, MSM_VIDC_BUF_READ_ONLY, __func__); - if (!ro_buffers) - return -EINVAL; - - list_for_each_entry(ro_buf, &ro_buffers->list, list) { + list_for_each_entry(ro_buf, &inst->buffers.read_only.list, list) { if (ro_buf->device_addr == buffer->base_address) { - found = true; + ro_buf->attr &= ~MSM_VIDC_ATTR_READ_ONLY; break; } } - /* - * Without RO flag: remove buffer from read_only list if present - * if not present, do not error out - */ - if (found) { - print_vidc_buffer(VIDC_LOW, "low ", "ro buf deleted", inst, ro_buf); - list_del(&ro_buf->list); - msm_memory_pool_free(inst, ro_buf); - } - return 0; } @@ -883,6 +872,9 @@ static int handle_output_buffer(struct msm_vidc_inst *inst, } if (is_decode_session(inst)) { + /* handle release response for decoder output buffer */ + if (buffer->flags & HFI_BUF_FW_FLAG_RELEASE_DONE) + return handle_release_output_buffer(inst, buffer); /* handle psc last flag buffer */ if (buffer->flags & HFI_BUF_FW_FLAG_PSC_LAST) { rc = handle_psc_last_flag_buffer(inst, buffer); @@ -903,8 +895,11 @@ static int handle_output_buffer(struct msm_vidc_inst *inst, found = false; list_for_each_entry(buf, &buffers->list, list) { + if (!(buf->attr & MSM_VIDC_ATTR_QUEUED)) + continue; if (is_decode_session(inst)) - found = (buf->device_addr == buffer->base_address && + found = (buf->index == buffer->index && + buf->device_addr == buffer->base_address && buf->data_offset == buffer->data_offset); else found = (buf->index == buffer->index); @@ -912,11 +907,9 @@ static int handle_output_buffer(struct msm_vidc_inst *inst, if (found) break; } - if (!found) - return 0; - - if (!(buf->attr & MSM_VIDC_ATTR_QUEUED)) { - print_vidc_buffer(VIDC_ERR, "err ", "not queued", inst, buf); + if (!found) { + i_vpr_l(inst, "%s: invalid idx %d daddr %#x\n", + __func__, buffer->index, buffer->base_address); return 0; } @@ -987,6 +980,11 @@ static int handle_output_buffer(struct msm_vidc_inst *inst, } else { buf->attr &= ~MSM_VIDC_ATTR_READ_ONLY; } + + if (buf->dbuf_get) { + msm_vidc_memory_put_dmabuf(inst, buf->dmabuf); + buf->dbuf_get = 0; + } } buf->flags = 0; @@ -1259,7 +1257,6 @@ static int handle_dequeue_buffers(struct msm_vidc_inst *inst) rc = 0; } } - msm_vidc_put_driver_buf(inst, buf); } } } @@ -1303,15 +1300,16 @@ static int handle_release_internal_buffer(struct msm_vidc_inst *inst, return rc; } -static int handle_release_output_buffer(struct msm_vidc_inst *inst, - struct hfi_buffer *buffer, enum hfi_packet_port_type port_type) +int handle_release_output_buffer(struct msm_vidc_inst *inst, + struct hfi_buffer *buffer) { int rc = 0; struct msm_vidc_buffer *buf; bool found = false; - list_for_each_entry(buf, &inst->buffers.release.list, list) { - if (buf->device_addr == buffer->base_address) { + list_for_each_entry(buf, &inst->buffers.read_only.list, list) { + if (buf->device_addr == buffer->base_address && + buf->attr & MSM_VIDC_ATTR_PENDING_RELEASE) { found = true; break; } @@ -1322,9 +1320,8 @@ static int handle_release_output_buffer(struct msm_vidc_inst *inst, return -EINVAL; } - rc = msm_vdec_handle_release_buffer(inst, buf); - if (rc) - return rc; + buf->attr &= ~MSM_VIDC_ATTR_READ_ONLY; + print_vidc_buffer(VIDC_LOW, "low ", "release done", inst, buf); return rc; } @@ -1388,9 +1385,6 @@ static int handle_session_buffer(struct msm_vidc_inst *inst, msm_vidc_change_state(inst, MSM_VIDC_ERROR, __func__); return 0; } - if (is_decode_session(inst) && buffer->type == HFI_BUFFER_RAW && - buffer->flags & HFI_BUF_FW_FLAG_RELEASE_DONE) - return handle_release_output_buffer(inst, buffer, pkt->port); if (is_encode_session(inst)) { if (pkt->port == HFI_PORT_RAW) {