video: driver: decouple fence structure from video buffer

Decouple fence structure from video buffer. Also add some
misc fence flow setup support.

Change-Id: Ia4e223a3a288f0dae3238850685f3a73d4b9400a
Signed-off-by: Akshata Sahukar <quic_asahukar@quicinc.com>
This commit is contained in:
Akshata Sahukar
2022-02-09 14:04:30 -08:00
committed by Gerrit - the friendly Code Review server
parent d10f2f9108
commit 0a5549a6a9
10 changed files with 173 additions and 63 deletions

View File

@@ -273,6 +273,20 @@ static struct msm_platform_inst_capability instance_data_kalama[] = {
{0},
NULL, msm_vidc_set_u32},
{SW_FENCE_ENABLE, DEC, CODECS_ALL,
V4L2_MPEG_MSM_VIDC_DISABLE, V4L2_MPEG_MSM_VIDC_ENABLE,
1, V4L2_MPEG_MSM_VIDC_DISABLE,
V4L2_CID_MPEG_VIDC_SW_FENCE_ENABLE,
HFI_PROP_FENCE},
{FENCE_ID, DEC, CODECS_ALL,
0, INT_MAX, 1, 0,
V4L2_CID_MPEG_VIDC_SW_FENCE_ID},
{FENCE_FD, DEC, CODECS_ALL,
0, INT_MAX, 1, 0,
V4L2_CID_MPEG_VIDC_SW_FENCE_FD},
{TS_REORDER, DEC, H264|HEVC,
V4L2_MPEG_MSM_VIDC_DISABLE, V4L2_MPEG_MSM_VIDC_ENABLE,
1, V4L2_MPEG_MSM_VIDC_DISABLE,

View File

@@ -9,12 +9,14 @@
#include "msm_vidc_inst.h"
#include "msm_vidc_buffer.h"
int msm_vidc_fence_create(struct msm_vidc_inst *inst,
struct msm_vidc_buffer *buf);
struct msm_vidc_fence *msm_vidc_fence_create(
struct msm_vidc_inst *inst);
int msm_vidc_create_fence_fd(struct msm_vidc_inst *inst,
struct msm_vidc_fence *fence);
int msm_vidc_fence_signal(struct msm_vidc_inst *inst,
struct msm_vidc_buffer *buf);
u32 fence_id);
void msm_vidc_fence_destroy(struct msm_vidc_inst *inst,
struct msm_vidc_buffer *buf);
struct msm_vidc_fence *fence);
int msm_vidc_fence_init(struct msm_vidc_inst *inst);
void msm_vidc_fence_deinit(struct msm_vidc_inst *inst);

View File

@@ -145,6 +145,7 @@ struct msm_vidc_inst {
struct list_head children_list;
struct list_head firmware_list;
struct list_head pending_pkts; /* list of struct hfi_pending_packet */
struct list_head fence_list; /* list of struct msm_vidc_fence */
bool once_per_session_set;
bool ipsc_properties_set;
bool opsc_properties_set;
@@ -154,7 +155,7 @@ struct msm_vidc_inst {
struct msm_vidc_statistics stats;
struct msm_vidc_inst_capability *capabilities;
struct completion completions[MAX_SIGNAL];
struct msm_vidc_fence_context fence;
struct msm_vidc_fence_context fence_context;
enum priority_level priority_level;
u32 firmware_priority;
bool active;

View File

@@ -367,6 +367,9 @@ enum msm_vidc_inst_capability_type {
MB_CYCLES_FW,
MB_CYCLES_FW_VPP,
SECURE_MODE,
SW_FENCE_ENABLE,
FENCE_ID,
FENCE_FD,
TS_REORDER,
SLICE_INTERFACE,
HFLIP,
@@ -790,11 +793,12 @@ struct msm_vidc_fence_context {
};
struct msm_vidc_fence {
struct dma_fence dma_fence;
char name[MAX_NAME_LENGTH];
spinlock_t lock;
struct sync_file *sync_file;
int fd;
struct list_head list;
struct dma_fence dma_fence;
char name[MAX_NAME_LENGTH];
spinlock_t lock;
struct sync_file *sync_file;
int fd;
};
struct msm_vidc_alloc {
@@ -844,7 +848,7 @@ struct msm_vidc_buffer {
u32 flags;
u64 timestamp;
enum msm_vidc_buffer_attributes attr;
struct msm_vidc_fence *fence;
u64 fence_id;
};
struct msm_vidc_buffers {

View File

@@ -951,6 +951,7 @@ void *msm_vidc_open(void *vidc_core, u32 session_type)
INIT_LIST_HEAD(&inst->enc_input_crs);
INIT_LIST_HEAD(&inst->dmabuf_tracker);
INIT_LIST_HEAD(&inst->pending_pkts);
INIT_LIST_HEAD(&inst->fence_list);
for (i = 0; i < MAX_SIGNAL; i++)
init_completion(&inst->completions[i]);

View File

@@ -82,6 +82,9 @@ static const struct msm_vidc_cap_name cap_name_arr[] = {
{MB_CYCLES_FW, "MB_CYCLES_FW" },
{MB_CYCLES_FW_VPP, "MB_CYCLES_FW_VPP" },
{SECURE_MODE, "SECURE_MODE" },
{SW_FENCE_ENABLE, "SW_FENCE_ENABLE" },
{FENCE_ID, "FENCE_ID" },
{FENCE_FD, "FENCE_FD" },
{TS_REORDER, "TS_REORDER" },
{SLICE_INTERFACE, "SLICE_INTERFACE" },
{HFLIP, "HFLIP" },
@@ -3257,10 +3260,10 @@ int msm_vidc_queue_buffer_single(struct msm_vidc_inst *inst, struct vb2_buffer *
{
int rc = 0;
struct msm_vidc_buffer *buf;
struct msm_vidc_fence *fence;
enum msm_vidc_allow allow;
const int fence_enabled = 0;
if (!inst || !vb2) {
if (!inst || !vb2 || !inst->capabilities) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
@@ -3269,11 +3272,12 @@ int msm_vidc_queue_buffer_single(struct msm_vidc_inst *inst, struct vb2_buffer *
if (!buf)
return -EINVAL;
if (fence_enabled && is_decode_session(inst) &&
is_output_buffer(buf->type)) {
rc = msm_vidc_fence_create(inst, buf);
if (rc)
if (inst->capabilities->cap[SW_FENCE_ENABLE].value &&
is_output_buffer(buf->type)) {
fence = msm_vidc_fence_create(inst);
if (!fence)
return rc;
buf->fence_id = fence->dma_fence.seqno;
}
allow = msm_vidc_allow_qbuf(inst, vb2->type);
@@ -3296,7 +3300,7 @@ int msm_vidc_queue_buffer_single(struct msm_vidc_inst *inst, struct vb2_buffer *
exit:
if (rc) {
i_vpr_e(inst, "%s: qbuf failed\n", __func__);
msm_vidc_fence_destroy(inst, buf);
msm_vidc_fence_destroy(inst, fence);
}
return rc;
}
@@ -5164,6 +5168,8 @@ void msm_vidc_destroy_buffers(struct msm_vidc_inst *inst)
struct msm_memory_dmabuf *dbuf, *dummy_dbuf;
struct response_work *work, *dummy_work = NULL;
struct msm_vidc_inst_cap_entry *entry, *dummy_entry;
struct msm_vidc_fence *fence, *dummy_fence;
static const enum msm_vidc_buffer_type ext_buf_types[] = {
MSM_VIDC_BUF_INPUT,
MSM_VIDC_BUF_OUTPUT,
@@ -5222,7 +5228,6 @@ void msm_vidc_destroy_buffers(struct msm_vidc_inst *inst)
list_for_each_entry_safe(buf, dummy, &buffers->list, list) {
print_vidc_buffer(VIDC_ERR, "err ", "destroying ", inst, buf);
msm_vidc_fence_destroy(inst, buf);
if (!(buf->attr & MSM_VIDC_ATTR_BUFFER_DONE))
msm_vidc_vb2_buffer_done(inst, buf);
msm_vidc_put_driver_buf(inst, buf);
@@ -5261,6 +5266,12 @@ void msm_vidc_destroy_buffers(struct msm_vidc_inst *inst)
kfree(entry);
}
list_for_each_entry_safe(fence, dummy_fence, &inst->fence_list, list) {
i_vpr_e(inst, "%s: destroying fence id: %llu",
__func__, fence->dma_fence.seqno);
msm_vidc_fence_destroy(inst, fence);
}
/* destroy buffers from pool */
msm_memory_pools_deinit(inst);
}

View File

@@ -47,26 +47,49 @@ static const struct dma_fence_ops msm_vidc_dma_fence_ops = {
.release = msm_vidc_dma_fence_release,
};
int msm_vidc_fence_create(struct msm_vidc_inst *inst,
struct msm_vidc_buffer *buf)
struct msm_vidc_fence *msm_vidc_fence_create(struct msm_vidc_inst *inst)
{
int rc = 0;
struct msm_vidc_fence *fence;
if (!inst) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
return NULL;
}
fence = kzalloc(sizeof(*fence), GFP_KERNEL);
if (!fence)
return -ENOMEM;
if (!fence) {
i_vpr_e(inst, "%s: failed to allocate memory for fence\n",
__func__);
return NULL;
}
spin_lock_init(&fence->lock);
dma_fence_init(&fence->dma_fence, &msm_vidc_dma_fence_ops,
&fence->lock, inst->fence.ctx_num, inst->fence.seq_num++);
&fence->lock, inst->fence_context.ctx_num,
++inst->fence_context.seq_num);
snprintf(fence->name, sizeof(fence->name), "%s: %llu",
inst->fence.name, inst->fence.seq_num);
inst->fence_context.name, inst->fence_context.seq_num);
/* reset seqno to avoid going beyond INT_MAX */
if (inst->fence_context.seq_num >= INT_MAX)
inst->fence_context.seq_num = 0;
INIT_LIST_HEAD(&fence->list);
list_add_tail(&fence->list, &inst->fence_list);
i_vpr_l(inst, "%s: created %s\n", __func__, fence->name);
return fence;
}
int msm_vidc_create_fence_fd(struct msm_vidc_inst *inst,
struct msm_vidc_fence *fence)
{
int rc = 0;
if (!inst || !fence) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
fence->fd = get_unused_fd_flags(0);
if (fence->fd < 0) {
@@ -82,54 +105,78 @@ int msm_vidc_fence_create(struct msm_vidc_inst *inst,
goto err_sync_file;
}
fd_install(fence->fd, fence->sync_file->file);
buf->fence = fence;
i_vpr_h(inst, "%s: created %s\n", __func__, fence->name);
return 0;
i_vpr_l(inst, "%s: created fd %d for fence %s id: %llu\n", __func__,
fence->fd, fence->name, fence->dma_fence.seqno);
err_sync_file:
put_unused_fd(fence->fd);
err_fd:
dma_fence_put(&fence->dma_fence);
buf->fence = NULL;
return rc;
}
int msm_vidc_fence_signal(struct msm_vidc_inst *inst,
struct msm_vidc_buffer *buf)
int msm_vidc_fence_signal(struct msm_vidc_inst *inst, u32 fence_id)
{
int rc = 0;
struct msm_vidc_fence *fence, *dummy_fence;
bool found = false;
if (!inst || !buf) {
if (!inst) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
if (!buf->fence)
return 0;
i_vpr_l(inst, "%s: fence %s\n", __func__, buf->fence->name);
dma_fence_signal(&buf->fence->dma_fence);
dma_fence_put(&buf->fence->dma_fence);
buf->fence = NULL;
list_for_each_entry_safe(fence, dummy_fence, &inst->fence_list, list) {
if (fence->dma_fence.seqno == (u64)fence_id) {
found = true;
break;
}
}
if (!found) {
i_vpr_e(inst, "%s: no fence available to signal with id: %u",
__func__, fence_id);
rc = -EINVAL;
goto exit;
}
i_vpr_l(inst, "%s: fence %s\n", __func__, fence->name);
dma_fence_signal(&fence->dma_fence);
dma_fence_put(&fence->dma_fence);
list_del_init(&fence->list);
exit:
return rc;
}
void msm_vidc_fence_destroy(struct msm_vidc_inst *inst,
struct msm_vidc_buffer *buf)
struct msm_vidc_fence *fence_to_destroy)
{
if (!inst || !buf) {
struct msm_vidc_fence *fence, *dummy_fence;
bool found = false;
if (!inst || !fence_to_destroy) {
d_vpr_e("%s: invalid params\n", __func__);
return;
}
if (!buf->fence)
return;
i_vpr_e(inst, "%s: fence %s\n", __func__, buf->fence->name);
dma_fence_set_error(&buf->fence->dma_fence, -EINVAL);
dma_fence_signal(&buf->fence->dma_fence);
dma_fence_put(&buf->fence->dma_fence);
buf->fence = NULL;
list_for_each_entry_safe(fence, dummy_fence, &inst->fence_list, list) {
if (fence->dma_fence.seqno ==
fence_to_destroy->dma_fence.seqno) {
found = true;
break;
}
}
if (!found) {
i_vpr_e(inst, "%s: no fence available to destroy with id: %llu",
__func__, fence_to_destroy->dma_fence.seqno);
return;
}
i_vpr_e(inst, "%s: fence %s\n", __func__, fence->name);
dma_fence_set_error(&fence->dma_fence, -EINVAL);
dma_fence_signal(&fence->dma_fence);
dma_fence_put(&fence->dma_fence);
list_del_init(&fence->list);
}
int msm_vidc_fence_init(struct msm_vidc_inst *inst)
@@ -141,13 +188,13 @@ int msm_vidc_fence_init(struct msm_vidc_inst *inst)
return -EINVAL;
}
inst->fence.ctx_num = dma_fence_context_alloc(1);
snprintf(inst->fence.name, sizeof(inst->fence.name),
inst->fence_context.ctx_num = dma_fence_context_alloc(1);
snprintf(inst->fence_context.name, sizeof(inst->fence_context.name),
"msm_vidc_fence: %s: %llu", inst->debug_str,
inst->fence.ctx_num);
i_vpr_h(inst, "%s: %s\n", __func__, inst->fence.name);
inst->fence_context.ctx_num);
i_vpr_h(inst, "%s: %s\n", __func__, inst->fence_context.name);
return rc;
return rc;
}
void msm_vidc_fence_deinit(struct msm_vidc_inst *inst)
@@ -156,7 +203,8 @@ void msm_vidc_fence_deinit(struct msm_vidc_inst *inst)
d_vpr_e("%s: invalid params\n", __func__);
return;
}
i_vpr_h(inst, "%s: %s\n", __func__, inst->fence.name);
inst->fence.ctx_num = 0;
snprintf(inst->fence.name, sizeof(inst->fence.name), "%s", "");
i_vpr_h(inst, "%s: %s\n", __func__, inst->fence_context.name);
inst->fence_context.ctx_num = 0;
snprintf(inst->fence_context.name, sizeof(inst->fence_context.name),
"%s", "");
}

View File

@@ -3473,7 +3473,7 @@ int venus_hfi_queue_buffer(struct msm_vidc_inst *inst,
struct msm_vidc_core *core;
struct hfi_buffer hfi_buffer;
if (!inst || !inst->core || !inst->packet) {
if (!inst || !inst->core || !inst->packet || !inst->capabilities) {
d_vpr_e("%s: invalid params\n", __func__);
return -EINVAL;
}
@@ -3523,6 +3523,11 @@ int venus_hfi_queue_buffer(struct msm_vidc_inst *inst,
goto unlock;
}
if (inst->capabilities->cap[SW_FENCE_ENABLE].value &&
is_output_buffer(buffer->type)) {
/* TODO(AS): create fence property packet to send to fw */
}
rc = venus_hfi_add_pending_packets(inst);
if (rc)
goto unlock;

View File

@@ -824,9 +824,6 @@ static int handle_output_buffer(struct msm_vidc_inst *inst,
return 0;
}
/* signal the fence asap */
msm_vidc_fence_signal(inst, buf);
buf->data_offset = buffer->data_offset;
buf->data_size = buffer->data_size;
buf->timestamp = buffer->timestamp;
@@ -1424,6 +1421,7 @@ static int handle_session_property(struct msm_vidc_inst *inst,
int rc = 0;
u32 port;
u32 *payload_ptr = NULL;
u32 fence_id = 0;
if (!inst || !inst->capabilities) {
d_vpr_e("%s: Invalid params\n", __func__);
@@ -1558,6 +1556,20 @@ static int handle_session_property(struct msm_vidc_inst *inst,
"%s: fw pipe mode(%d) not matching the capability value(%d)\n",
__func__, payload_ptr[0], inst->capabilities->cap[PIPE].value);
break;
case HFI_PROP_FENCE:
if (inst->capabilities->cap[SW_FENCE_ENABLE].value) {
if (payload_ptr) {
fence_id = payload_ptr[0];
rc = msm_vidc_fence_signal(inst, fence_id);
} else {
i_vpr_e(inst, "%s: fence payload is null\n", __func__);
rc = -EINVAL;
}
} else {
i_vpr_e(inst, "%s: fence is not enabled for this session\n",
__func__);
}
break;
default:
i_vpr_e(inst, "%s: invalid property %#x\n",
__func__, pkt->type);

View File

@@ -200,6 +200,18 @@ enum v4l2_mpeg_video_av1_tier {
/* Control to enable input metadata via request api */
#define V4L2_CID_MPEG_VIDC_INPUT_METADATA_VIA_REQUEST_ENABLE \
(V4L2_CID_MPEG_VIDC_BASE + 0x37)
/* Control to enable software fence feature */
#define V4L2_CID_MPEG_VIDC_SW_FENCE_ENABLE \
(V4L2_CID_MPEG_VIDC_BASE + 0x38)
/* Control to set fence id to driver in order get corresponding fence fd */
#define V4L2_CID_MPEG_VIDC_SW_FENCE_ID \
(V4L2_CID_MPEG_VIDC_BASE + 0x39)
/*
* Control to get fence fd from driver for the fence id
* set via V4L2_CID_MPEG_VIDC_SW_FENCE_ID
*/
#define V4L2_CID_MPEG_VIDC_SW_FENCE_FD \
(V4L2_CID_MPEG_VIDC_BASE + 0x3A)
/* add new controls above this line */
/* Deprecate below controls once availble in gki and gsi bionic header */