Browse Source

video: driver: amend priorities to allow more sessions

1. adjust client set non-realtime priroty with NRT_PRIORITY_OFFSET (2)
2. if total mbps is more than max_mbps
    a. allow encode session by reducing decoder sessions priority by 1
    b. allow decode session by moving it to non-realtime session
        in order to not disturb the ongoing sessions

Change-Id: I96fd2ac75c123d681982fb9a2c06ac51d15bd59a
Signed-off-by: Deepa Guthyappa Madivalara <[email protected]>
Deepa Guthyappa Madivalara 3 năm trước cách đây
mục cha
commit
59b8019b9d

+ 1 - 1
driver/platform/kalama/src/msm_vidc_kalama.c

@@ -1379,7 +1379,7 @@ static struct msm_platform_inst_capability instance_cap_data_kalama[] = {
 		CAP_FLAG_INPUT_PORT | CAP_FLAG_DYNAMIC_ALLOWED},
 
 	{PRIORITY, DEC|ENC, CODECS_ALL,
-		0, 2, 1, 1,
+		0, 1 + NRT_PRIORITY_OFFSET, 1, 1 + NRT_PRIORITY_OFFSET,
 		V4L2_CID_MPEG_VIDC_PRIORITY,
 		HFI_PROP_SESSION_PRIORITY,
 		CAP_FLAG_DYNAMIC_ALLOWED},

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

@@ -477,6 +477,7 @@ int msm_vidc_update_debug_str(struct msm_vidc_inst *inst);
 void msm_vidc_allow_dcvs(struct msm_vidc_inst *inst);
 bool msm_vidc_allow_decode_batch(struct msm_vidc_inst *inst);
 int msm_vidc_check_session_supported(struct msm_vidc_inst *inst);
+bool msm_vidc_ignore_session_load(struct msm_vidc_inst *inst);
 int msm_vidc_check_core_mbps(struct msm_vidc_inst *inst);
 int msm_vidc_check_core_mbpf(struct msm_vidc_inst *inst);
 int msm_vidc_check_scaling_supported(struct msm_vidc_inst *inst);

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

@@ -171,5 +171,6 @@ struct msm_vidc_inst {
 	u32                                max_rate;
 	bool                               has_bframe;
 	bool                               ir_enabled;
+	u32                                adjust_priority;
 };
 #endif // _MSM_VIDC_INST_H_

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

@@ -31,6 +31,8 @@
 #define DEFAULT_WIDTH     320
 #define DEFAULT_FPS       30
 #define MAXIMUM_VP9_FPS   60
+#define NRT_PRIORITY_OFFSET        2
+#define RT_DEC_DOWN_PRORITY_OFFSET 1
 #define MAX_SUPPORTED_INSTANCES  16
 #define DEFAULT_BSE_VPP_DELAY    2
 #define MAX_CAP_PARENTS          20

+ 9 - 0
driver/vidc/src/msm_vdec.c

@@ -2054,6 +2054,15 @@ int msm_vdec_qbuf(struct msm_vidc_inst *inst, struct vb2_buffer *vb2)
 		}
 	}
 
+	if (inst->adjust_priority) {
+		s32 priority = inst->capabilities->cap[PRIORITY].value;
+
+		priority += inst->adjust_priority;
+		inst->adjust_priority = 0;
+		msm_vidc_update_cap_value(inst, PRIORITY, priority, __func__);
+		msm_vidc_set_session_priority(inst, PRIORITY);
+	}
+
 	/* batch decoder output & meta buffer only */
 	if (inst->decode_batch.enable && vb2->type == OUTPUT_MPLANE)
 		rc = msm_vdec_qbuf_batch(inst, vb2);

+ 24 - 13
driver/vidc/src/msm_vidc_control.c

@@ -1085,21 +1085,11 @@ static int msm_vidc_update_static_property(struct msm_vidc_inst *inst,
 			return rc;
 	}
 
+	/* call this explicitly to adjust client priority */
 	if (ctrl->id == V4L2_CID_MPEG_VIDC_PRIORITY) {
 		rc = msm_vidc_adjust_session_priority(inst, ctrl);
 		if (rc)
 			return rc;
-
-		/**
-		 * This is the last static s_ctrl from client(commit point). So update
-		 * input & output counts to reflect final buffer counts based on dcvs
-		 * & decoder_batching enable/disable. So client is expected to query
-		 * for final counts after setting priority control.
-		 */
-		if (is_decode_session(inst))
-			inst->decode_batch.enable = msm_vidc_allow_decode_batch(inst);
-
-		msm_vidc_allow_dcvs(inst);
 	}
 	if (ctrl->id == V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_LAYER) {
 		u32 enable;
@@ -2792,8 +2782,29 @@ int msm_vidc_adjust_session_priority(void *instance, struct v4l2_ctrl *ctrl)
 		return -EINVAL;
 	}
 	capability = inst->capabilities;
-	adjusted_value = ctrl ? ctrl->val :
-		capability->cap[PRIORITY].value;
+	/*
+	 * Priority handling
+	 * Client will set 0 (realtime), 1+ (non-realtime)
+	 * Driver adds NRT_PRIORITY_OFFSET (2) to clients non-realtime priority
+	 * and hence PRIORITY values in the driver become 0, 3+.
+	 * Driver may move decode realtime sessions to non-realtime by
+	 * increasing priority by 1 to RT sessions in HW overloaded cases.
+	 * So driver PRIORITY values can be 0, 1, 3+.
+	 * When driver setting priority to firmware, driver adds
+	 * FIRMWARE_PRIORITY_OFFSET (1) for all sessions except
+	 * non-critical sessions. So finally firmware priority values ranges
+	 * from 0 (Critical session), 1 (realtime session),
+	 * 2+ (non-realtime session)
+	 */
+	if (ctrl) {
+		/* add offset when client sets non-realtime */
+		if (ctrl->val)
+			adjusted_value = ctrl->val + NRT_PRIORITY_OFFSET;
+		else
+			adjusted_value = ctrl->val;
+	} else {
+		adjusted_value = capability->cap[PRIORITY].value;
+	}
 
 	msm_vidc_update_cap_value(inst, PRIORITY, adjusted_value, __func__);
 

+ 59 - 20
driver/vidc/src/msm_vidc_driver.c

@@ -5923,12 +5923,25 @@ static int msm_vidc_print_insts_info(struct msm_vidc_core *core)
 	return 0;
 }
 
+bool msm_vidc_ignore_session_load(struct msm_vidc_inst *inst) {
+
+	if (!inst) {
+		d_vpr_e("%s: invalid params\n", __func__);
+		return -EINVAL;
+	}
+
+	if (!is_realtime_session(inst) || is_thumbnail_session(inst) ||
+			is_image_session(inst))
+		return true;
+
+	return false;
+}
+
 int msm_vidc_check_core_mbps(struct msm_vidc_inst *inst)
 {
-	u32 mbps = 0;
+	u32 mbps = 0, total_mbps = 0, enc_mbps = 0;
 	struct msm_vidc_core *core;
 	struct msm_vidc_inst *instance;
-	int rc = 0;
 
 	if (!inst || !inst->core || !inst->capabilities) {
 		d_vpr_e("%s: invalid params\n", __func__);
@@ -5936,11 +5949,14 @@ int msm_vidc_check_core_mbps(struct msm_vidc_inst *inst)
 	}
 	core = inst->core;
 
-	if (!inst->capabilities->cap[CHECK_MBPS].value) {
-		i_vpr_h(inst, "%s: skip mbps check\n", __func__);
+	/* skip mbps check for non-realtime, thumnail, image sessions */
+	if (msm_vidc_ignore_session_load(inst)) {
+		i_vpr_h(inst,
+			"%s: skip mbps check due to NRT %d, TH %d, IMG %d\n", __func__,
+			!is_realtime_session(inst), is_thumbnail_session(inst),
+			is_image_session(inst));
 		return 0;
 	}
-
 	core_lock(core, __func__);
 	list_for_each_entry(instance, &core->instances, list) {
 		/* ignore invalid/error session */
@@ -5948,25 +5964,50 @@ int msm_vidc_check_core_mbps(struct msm_vidc_inst *inst)
 			continue;
 
 		/* ignore thumbnail, image, and non realtime sessions */
-		if (is_thumbnail_session(instance) ||
-			is_image_session(instance) ||
-			!is_realtime_session(instance))
+		if (msm_vidc_ignore_session_load(inst))
 			continue;
 
-		mbps += msm_vidc_get_inst_load(instance);
+		mbps = msm_vidc_get_inst_load(instance);
+		total_mbps += mbps;
+		if (is_encode_session(instance))
+			enc_mbps += mbps;
 	}
 	core_unlock(core, __func__);
 
-	if (mbps > core->capabilities[MAX_MBPS].value) {
-		rc = -ENOMEM;
-		i_vpr_e(inst, "%s: Hardware overloaded. needed %u, max %u", __func__,
-			mbps, core->capabilities[MAX_MBPS].value);
-		return rc;
-	} else {
-		i_vpr_h(inst, "%s: HW load needed %u is within max %u", __func__,
-			mbps, core->capabilities[MAX_MBPS].value);
+	if (is_encode_session(inst)) {
+		/* reject encoder if all encoders mbps is greater than MAX_MBPS */
+		if (enc_mbps > core->capabilities[MAX_MBPS].value) {
+			i_vpr_e(inst, "%s: Hardware overloaded. needed %u, max %u", __func__,
+				mbps, core->capabilities[MAX_MBPS].value);
+			return -ENOMEM;
+		}
+		/*
+		 * if total_mbps is greater than max_mbps then reduce all decoders
+		 * priority by 1 to allow this encoder
+		 */
+		if (total_mbps > core->capabilities[MAX_MBPS].value) {
+			core_lock(core, __func__);
+			list_for_each_entry(instance, &core->instances, list) {
+				/* reduce realtime decode sessions priority */
+				if (is_decode_session(inst) && is_realtime_session(inst)) {
+					instance->adjust_priority = RT_DEC_DOWN_PRORITY_OFFSET;
+					i_vpr_h(inst, "%s: pending adjust priority by %d\n",
+						__func__, inst->adjust_priority);
+				}
+			}
+			core_unlock(core, __func__);
+		}
+	} else if (is_decode_session(inst)){
+		if (total_mbps > core->capabilities[MAX_MBPS].value) {
+			inst->adjust_priority = RT_DEC_DOWN_PRORITY_OFFSET;
+			i_vpr_h(inst, "%s: pending adjust priority by %d\n",
+				__func__, inst->adjust_priority);
+		}
 	}
 
+	i_vpr_h(inst, "%s: HW load needed %u is within max %u", __func__,
+			total_mbps, core->capabilities[MAX_MBPS].value);
+
 	return 0;
 }
 
@@ -6010,9 +6051,7 @@ int msm_vidc_check_core_mbpf(struct msm_vidc_inst *inst)
 	core_lock(core, __func__);
 	/* check real-time video sessions max limit */
 	list_for_each_entry(instance, &core->instances, list) {
-		if (is_thumbnail_session(instance) ||
-			is_image_session(instance) ||
-			!is_realtime_session(instance))
+		if (msm_vidc_ignore_session_load(inst))
 			continue;
 
 		video_rt_mbpf += msm_vidc_get_mbs_per_frame(instance);