ソースを参照

driver: video: Add critical priority and reserve duration

Critical priority - A video session which is prioritized above
all concurrent sessions. Such sessions have low latencies and
at the same time they cannot be rejected due to overload.
Reserve duration - Duration by which a session reserves the
video hardware for processing frames from that session.
Both the above aspects are implemented with these changes.

Change-Id: I58aef5f239e5ee106201d6819d2228784f0f0ad0
Signed-off-by: Vikash Garodia <[email protected]>
Vikash Garodia 3 年 前
コミット
e3da5c43e2

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

@@ -13,6 +13,7 @@
 #include "msm_vidc_control.h"
 #include "hfi_property.h"
 #include "msm_vidc_iris3.h"
+#include "hfi_command.h"
 
 #define DEFAULT_VIDEO_CONCEAL_COLOR_BLACK 0x8020010
 #define MAX_LTR_FRAME_COUNT     2
@@ -1386,6 +1387,19 @@ static struct msm_platform_inst_capability instance_cap_data_kalama[] = {
 		HFI_PROP_SESSION_PRIORITY,
 		CAP_FLAG_DYNAMIC_ALLOWED},
 
+	{FIRMWARE_PRIORITY_OFFSET, DEC | ENC, CODECS_ALL,
+		1, 1, 1, 1},
+
+	{CRITICAL_PRIORITY, ENC, CODECS_ALL,
+		0, 1, 1, 0,
+		V4L2_CID_MPEG_VIDC_CRITICAL_PRIORITY},
+
+	{RESERVE_DURATION, ENC, CODECS_ALL,
+		0, INT_MAX, 1, 0,
+		V4L2_CID_MPEG_VIDC_RESERVE_DURATION,
+		HFI_CMD_RESERVE,
+		CAP_FLAG_DYNAMIC_ALLOWED},
+
 	{ENC_IP_CR, ENC, CODECS_ALL,
 		0, S32_MAX, 1, 0,
 		V4L2_CID_MPEG_VIDC_ENC_INPUT_COMPRESSION_RATIO,
@@ -2266,6 +2280,24 @@ static struct msm_platform_inst_cap_dependency instance_cap_dependency_data_kala
 		msm_vidc_adjust_session_priority,
 		msm_vidc_set_session_priority},
 
+	{FIRMWARE_PRIORITY_OFFSET, DEC | ENC, CODECS_ALL,
+		{0},
+		{0},
+		NULL,
+		NULL},
+
+	{CRITICAL_PRIORITY, ENC, CODECS_ALL,
+		{0},
+		{0},
+		NULL,
+		NULL},
+
+	{RESERVE_DURATION, ENC, CODECS_ALL,
+		{0},
+		{0},
+		NULL,
+		msm_vidc_set_reserve_duration},
+
 	{DPB_LIST, DEC, CODECS_ALL,
 		{0},
 		{0},

+ 31 - 0
driver/platform/waipio/src/msm_vidc_waipio.c

@@ -1292,6 +1292,19 @@ static struct msm_platform_inst_capability instance_cap_data_waipio[] = {
 		HFI_PROP_SESSION_PRIORITY,
 		CAP_FLAG_DYNAMIC_ALLOWED},
 
+	{FIRMWARE_PRIORITY_OFFSET, DEC | ENC, CODECS_ALL,
+		1, 1, 1, 1},
+
+	{CRITICAL_PRIORITY, ENC, CODECS_ALL,
+		0, 1, 1, 0,
+		V4L2_CID_MPEG_VIDC_CRITICAL_PRIORITY},
+
+	{RESERVE_DURATION, ENC, CODECS_ALL,
+		0, INT_MAX, 1, 0,
+		V4L2_CID_MPEG_VIDC_RESERVE_DURATION,
+		HFI_CMD_RESERVE,
+		CAP_FLAG_DYNAMIC_ALLOWED},
+
 	{ENC_IP_CR, ENC, CODECS_ALL,
 		0, S32_MAX, 1, 0,
 		V4L2_CID_MPEG_VIDC_ENC_INPUT_COMPRESSION_RATIO,
@@ -2058,6 +2071,24 @@ static struct msm_platform_inst_cap_dependency instance_cap_dependency_data_waip
 		msm_vidc_adjust_session_priority,
 		msm_vidc_set_session_priority},
 
+	{FIRMWARE_PRIORITY_OFFSET, DEC | ENC, CODECS_ALL,
+		{0},
+		{0},
+		NULL,
+		NULL},
+
+	{CRITICAL_PRIORITY, ENC, CODECS_ALL,
+		{0},
+		{0},
+		NULL,
+		NULL},
+
+	{RESERVE_DURATION, ENC, CODECS_ALL,
+		{0},
+		{0},
+		NULL,
+		msm_vidc_set_reserve_duration},
+
 	{DPB_LIST, DEC, CODECS_ALL,
 		{0},
 		{0},

+ 6 - 0
driver/vidc/inc/hfi_command.h

@@ -147,6 +147,11 @@ enum hfi_property_mode_type {
 	HFI_MODE_METADATA             = 0x00000004,
 };
 
+enum hfi_reserve_type {
+	HFI_RESERVE_START = 0x1,
+	HFI_RESERVE_STOP  = 0x2,
+};
+
 #define HFI_CMD_BEGIN                                           0x01000000
 #define HFI_CMD_INIT                                            0x01000001
 #define HFI_CMD_POWER_COLLAPSE                                  0x01000002
@@ -160,6 +165,7 @@ enum hfi_property_mode_type {
 #define HFI_CMD_DELIVERY_MODE                                   0x0100000A
 #define HFI_CMD_SUBSCRIBE_MODE                                  0x0100000B
 #define HFI_CMD_SETTINGS_CHANGE                                 0x0100000C
+#define HFI_CMD_RESERVE                                         0x0100000F
 
 #define HFI_SSR_TYPE_SW_ERR_FATAL       0x1
 #define HFI_SSR_TYPE_SW_DIV_BY_ZERO     0x2

+ 2 - 0
driver/vidc/inc/msm_vidc_control.h

@@ -119,6 +119,8 @@ int msm_vidc_set_level(void *instance,
 	enum msm_vidc_inst_capability_type cap_id);
 int msm_vidc_set_preprocess(void *instance,
 	enum msm_vidc_inst_capability_type cap_id);
+int msm_vidc_set_reserve_duration(void *instance,
+	enum msm_vidc_inst_capability_type cap_id);
 int msm_vidc_set_u32_enum(void *instance,
 	enum msm_vidc_inst_capability_type cap_id);
 int msm_vidc_set_q16(void *instance,

+ 5 - 0
driver/vidc/inc/msm_vidc_driver.h

@@ -293,6 +293,11 @@ static inline bool is_realtime_session(struct msm_vidc_inst *inst)
 	return inst->capabilities->cap[PRIORITY].value == 0 ? true : false;
 }
 
+static inline bool is_critical_priority_session(struct msm_vidc_inst *inst)
+{
+	return !!(inst->capabilities->cap[CRITICAL_PRIORITY].value);
+}
+
 static inline bool is_lowlatency_session(struct msm_vidc_inst *inst)
 {
 	return !!(inst->capabilities->cap[LOWLATENCY_MODE].value);

+ 3 - 0
driver/vidc/inc/msm_vidc_internal.h

@@ -477,6 +477,9 @@ enum msm_vidc_inst_capability_type {
 	SEQ_CHANGE_AT_SYNC_FRAME,
 	QUALITY_MODE,
 	PRIORITY,
+	FIRMWARE_PRIORITY_OFFSET,
+	CRITICAL_PRIORITY,
+	RESERVE_DURATION,
 	DPB_LIST,
 	FILM_GRAIN,
 	SUPER_BLOCK,

+ 1 - 0
driver/vidc/inc/venus_hfi.h

@@ -59,6 +59,7 @@ int venus_hfi_trigger_ssr(struct msm_vidc_core *core, u32 type,
 	u32 client_id, u32 addr);
 int venus_hfi_trigger_stability(struct msm_vidc_inst *inst, u32 type,
 	u32 client_id, u32 val);
+int venus_hfi_reserve_hardware(struct msm_vidc_inst *inst, u32 duration);
 int venus_hfi_scale_clocks(struct msm_vidc_inst* inst, u64 freq);
 int venus_hfi_scale_buses(struct msm_vidc_inst* inst, u64 bw_ddr, u64 bw_llcc);
 int venus_hfi_set_ir_period(struct msm_vidc_inst *inst, u32 ir_type,

+ 45 - 0
driver/vidc/src/msm_vidc_control.c

@@ -1106,6 +1106,13 @@ static int msm_vidc_update_static_property(struct msm_vidc_inst *inst,
 		if (rc)
 			return rc;
 	}
+
+	if (ctrl->id == V4L2_CID_MPEG_VIDC_CRITICAL_PRIORITY) {
+		inst->decode_batch.enable = msm_vidc_allow_decode_batch(inst);
+		msm_vidc_allow_dcvs(inst);
+		msm_vidc_update_cap_value(inst, PRIORITY, 0, __func__);
+	}
+
 	if (ctrl->id == V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_LAYER) {
 		u32 enable;
 
@@ -3940,6 +3947,9 @@ int msm_vidc_set_session_priority(void *instance,
 	}
 
 	hfi_value = inst->capabilities->cap[cap_id].value;
+	if (!is_critical_priority_session(inst))
+		hfi_value = inst->capabilities->cap[cap_id].value +
+			inst->capabilities->cap[FIRMWARE_PRIORITY_OFFSET].value;
 
 	rc = msm_vidc_packetize_control(inst, cap_id, HFI_PAYLOAD_U32,
 		&hfi_value, sizeof(u32), __func__);
@@ -4202,6 +4212,41 @@ int msm_vidc_set_csc_custom_matrix(void *instance,
 	return rc;
 }
 
+int msm_vidc_set_reserve_duration(void *instance,
+	enum msm_vidc_inst_capability_type cap_id)
+{
+	int rc = 0;
+	u32 hfi_value = 0;
+	struct msm_vidc_inst *inst = (struct msm_vidc_inst *)instance;
+
+	if (!inst || !inst->capabilities) {
+		d_vpr_e("%s: invalid params\n", __func__);
+		return -EINVAL;
+	}
+
+	/* reserve hardware only when input port is streaming*/
+	if (!inst->bufq[INPUT_PORT].vb2q->streaming)
+		return 0;
+
+	if (!(inst->capabilities->cap[cap_id].flags & CAP_FLAG_CLIENT_SET))
+		return 0;
+
+	inst->capabilities->cap[cap_id].flags &= (~CAP_FLAG_CLIENT_SET);
+
+	if (!is_critical_priority_session(inst)) {
+		i_vpr_h(inst, "%s: reserve duration allowed only for critical session\n", __func__);
+		return 0;
+	}
+
+	hfi_value = inst->capabilities->cap[cap_id].value;
+
+	rc = venus_hfi_reserve_hardware(inst, hfi_value);
+	if (rc)
+		return rc;
+
+	return rc;
+}
+
 int msm_vidc_set_level(void *instance,
 	enum msm_vidc_inst_capability_type cap_id)
 {

+ 39 - 0
driver/vidc/src/msm_vidc_driver.c

@@ -177,6 +177,9 @@ static const struct msm_vidc_cap_name cap_name_arr[] = {
 	{SEQ_CHANGE_AT_SYNC_FRAME,       "SEQ_CHANGE_AT_SYNC_FRAME"   },
 	{QUALITY_MODE,                   "QUALITY_MODE"               },
 	{PRIORITY,                       "PRIORITY"                   },
+	{FIRMWARE_PRIORITY_OFFSET,       "FIRMWARE_PRIORITY_OFFSET"   },
+	{CRITICAL_PRIORITY,              "CRITICAL_PRIORITY"          },
+	{RESERVE_DURATION,               "RESERVE_DURATION"           },
 	{DPB_LIST,                       "DPB_LIST"                   },
 	{FILM_GRAIN,                     "FILM_GRAIN"                 },
 	{SUPER_BLOCK,                    "SUPER_BLOCK"                },
@@ -1376,6 +1379,7 @@ bool msm_vidc_allow_s_ctrl(struct msm_vidc_inst *inst, u32 id)
 			case V4L2_CID_MPEG_VIDC_PRIORITY:
 			case V4L2_CID_MPEG_VIDC_INPUT_METADATA_FD:
 			case V4L2_CID_MPEG_VIDC_INTRA_REFRESH_PERIOD:
+			case V4L2_CID_MPEG_VIDC_RESERVE_DURATION:
 				allow = true;
 				break;
 			default:
@@ -3086,6 +3090,12 @@ void msm_vidc_allow_dcvs(struct msm_vidc_inst *inst)
 		goto exit;
 	}
 
+	allow = !is_critical_priority_session(inst);
+	if (!allow) {
+		i_vpr_h(inst, "%s: critical priority session\n", __func__);
+		goto exit;
+	}
+
 	allow = !is_image_session(inst);
 	if (!allow) {
 		i_vpr_h(inst, "%s: image session\n", __func__);
@@ -5940,6 +5950,7 @@ bool msm_vidc_ignore_session_load(struct msm_vidc_inst *inst) {
 int msm_vidc_check_core_mbps(struct msm_vidc_inst *inst)
 {
 	u32 mbps = 0, total_mbps = 0, enc_mbps = 0;
+	u32 critical_mbps = 0;
 	struct msm_vidc_core *core;
 	struct msm_vidc_inst *instance;
 
@@ -5957,6 +5968,20 @@ int msm_vidc_check_core_mbps(struct msm_vidc_inst *inst)
 			is_image_session(inst));
 		return 0;
 	}
+
+	core_lock(core, __func__);
+	list_for_each_entry(instance, &core->instances, list) {
+		if (is_critical_priority_session(instance))
+			critical_mbps += msm_vidc_get_inst_load(instance);
+	}
+	core_unlock(core, __func__);
+
+	if (critical_mbps > core->capabilities[MAX_MBPS].value) {
+		i_vpr_e(inst, "%s: Hardware overloaded with critical sessions. needed %u, max %u",
+			__func__, critical_mbps, core->capabilities[MAX_MBPS].value);
+		return -ENOMEM;
+	}
+
 	core_lock(core, __func__);
 	list_for_each_entry(instance, &core->instances, list) {
 		/* ignore invalid/error session */
@@ -6014,6 +6039,7 @@ int msm_vidc_check_core_mbps(struct msm_vidc_inst *inst)
 int msm_vidc_check_core_mbpf(struct msm_vidc_inst *inst)
 {
 	u32 video_mbpf = 0, image_mbpf = 0, video_rt_mbpf = 0;
+	u32 critical_mbpf = 0;
 	struct msm_vidc_core *core;
 	struct msm_vidc_inst *instance;
 
@@ -6023,6 +6049,19 @@ int msm_vidc_check_core_mbpf(struct msm_vidc_inst *inst)
 	}
 	core = inst->core;
 
+	core_lock(core, __func__);
+	list_for_each_entry(instance, &core->instances, list) {
+		if (is_critical_priority_session(instance))
+			critical_mbpf += msm_vidc_get_mbs_per_frame(instance);
+	}
+	core_unlock(core, __func__);
+
+	if (critical_mbpf > core->capabilities[MAX_MBPF].value) {
+		i_vpr_e(inst, "%s: Hardware overloaded with critical sessions. needed %u, max %u",
+			__func__, critical_mbpf, core->capabilities[MAX_MBPF].value);
+		return -ENOMEM;
+	}
+
 	core_lock(core, __func__);
 	list_for_each_entry(instance, &core->instances, list) {
 		/* ignore thumbnail session */

+ 47 - 0
driver/vidc/src/venus_hfi.c

@@ -2922,6 +2922,53 @@ unlock:
 	return rc;
 }
 
+int venus_hfi_reserve_hardware(struct msm_vidc_inst *inst, u32 duration)
+{
+	struct msm_vidc_core *core;
+	enum hfi_reserve_type payload;
+	int rc = 0;
+
+	if (!inst || !inst->core || !inst->packet) {
+		d_vpr_e("%s: Invalid params\n", __func__);
+		return -EINVAL;
+	}
+	core = inst->core;
+	core_lock(core, __func__);
+
+	if (!__valdiate_session(core, inst, __func__)) {
+		rc = -EINVAL;
+		goto unlock;
+	}
+
+	if (duration)
+		payload = HFI_RESERVE_START;
+	else
+		payload = HFI_RESERVE_STOP;
+
+	rc = hfi_create_header(inst->packet, inst->packet_size,
+		inst->session_id, core->header_id++);
+	if (rc)
+		goto unlock;
+
+	rc = hfi_create_packet(inst->packet, inst->packet_size,
+		HFI_CMD_RESERVE,
+		HFI_HOST_FLAGS_NONE,
+		HFI_PAYLOAD_U32_ENUM,
+		HFI_PORT_NONE,
+		core->packet_id++,
+		&payload, sizeof(u32));
+	if (rc)
+		goto unlock;
+
+	rc = __iface_cmdq_write(core, inst->packet);
+	if (rc)
+		goto unlock;
+
+unlock:
+	core_unlock(core, __func__);
+	return rc;
+}
+
 int venus_hfi_session_open(struct msm_vidc_inst *inst)
 {
 	int rc = 0;

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

@@ -255,6 +255,11 @@ enum v4l2_h264_encode_delivery_mode {
 	V4L2_MPEG_VIDC_H264_ENCODE_DELIVERY_MODE_SLICE_BASED = 1,
 };
 
+#define V4L2_CID_MPEG_VIDC_CRITICAL_PRIORITY                                 \
+	(V4L2_CID_MPEG_VIDC_BASE + 0x3E)
+#define V4L2_CID_MPEG_VIDC_RESERVE_DURATION                                  \
+	(V4L2_CID_MPEG_VIDC_BASE + 0x3F)
+
 /* add new controls above this line */
 /* Deprecate below controls once availble in gki and gsi bionic header */
 #ifndef V4L2_CID_MPEG_VIDEO_BASELAYER_PRIORITY_ID