浏览代码

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 <[email protected]>
Akshata Sahukar 3 年之前
父节点
当前提交
0a5549a6a9

+ 14 - 0
driver/platform/kalama/src/msm_vidc_kalama.c

@@ -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,

+ 6 - 4
driver/vidc/inc/msm_vidc_fence.h

@@ -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);
 

+ 2 - 1
driver/vidc/inc/msm_vidc_inst.h

@@ -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;

+ 10 - 6
driver/vidc/inc/msm_vidc_internal.h

@@ -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 {

+ 1 - 0
driver/vidc/src/msm_vidc.c

@@ -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]);
 

+ 19 - 8
driver/vidc/src/msm_vidc_driver.c

@@ -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);
 }

+ 87 - 39
driver/vidc/src/msm_vidc_fence.c

@@ -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)
+
+	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__, 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;
+	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", "");
 }

+ 6 - 1
driver/vidc/src/venus_hfi.c

@@ -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;

+ 15 - 3
driver/vidc/src/venus_hfi_response.c

@@ -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);

+ 12 - 0
include/uapi/vidc/media/v4l2_vidc_extensions.h

@@ -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 */