video: driver: buffer flow changes
When client queued a buffer, v4l2 framework compares the client Dmabuf with the existing dmabuf in the bufs array at the same index. If the dmabuf is different then v4l2 framework would call unmap_dmabuf, detach_dmabuf callbacks for the old buffer and then calls attach_dmabuf, map_dmabuf callbacks for the new buffer before qbuf callback is made to driver. If the dmabuf is same then qbuf callback will be made directly. V4l2 framework expects that clients recycles the same buffers in the same indices so that when v4l2 framework compares dmabuf it won't unmap or map buffers. If client recycle the buffers in different indices still usecase works but there will be unnecessary unmap, map overhead will be incurred. If client does not recycle the buffers at all, meaning every time client queues new buffers then special handling is required for decoder output buffers which are used for reference by video hardware.If any buffers are used by video hardware as reference buffers then firmware returns those buffers with READ_ONLY flag and they are kept in read_only list and when read_only grows beyond some limit then driver would ask firmware to release those READ_ONLY buffers and when firmware responds driver would delete these READ_ONLY buffers. Change-Id: I8a0b11c986dd0b9464895498efd8c1831a754198 Signed-off-by: Darshana Patil <quic_darshana@quicinc.com>
This commit is contained in:
@@ -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,7 +497,7 @@ 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,
|
||||
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);
|
||||
@@ -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_
|
||||
|
||||
|
@@ -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;
|
||||
|
@@ -21,6 +21,8 @@
|
||||
#include <media/videobuf2-core.h>
|
||||
#include <media/videobuf2-v4l2.h>
|
||||
|
||||
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;
|
||||
|
@@ -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_
|
@@ -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__
|
||||
|
@@ -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);
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
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;
|
||||
}
|
||||
|
||||
|
@@ -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);
|
||||
|
@@ -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)
|
||||
list_for_each_entry_safe(ro_buf, dummy, &inst->buffers.read_only.list, list) {
|
||||
if (ro_buf->attr & MSM_VIDC_ATTR_READ_ONLY)
|
||||
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);
|
||||
}
|
||||
}
|
||||
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);
|
||||
|
@@ -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;
|
||||
|
@@ -4,6 +4,8 @@
|
||||
*/
|
||||
/* Copyright (c) 2022. Qualcomm Innovation Center, Inc. All rights reserved. */
|
||||
|
||||
#include <linux/qcom-dma-mapping.h>
|
||||
|
||||
#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;
|
||||
}
|
||||
|
||||
|
@@ -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) {
|
||||
|
Reference in New Issue
Block a user