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 <quic_dmadival@quicinc.com>
This commit is contained in:
@@ -1379,7 +1379,7 @@ static struct msm_platform_inst_capability instance_cap_data_kalama[] = {
|
|||||||
CAP_FLAG_INPUT_PORT | CAP_FLAG_DYNAMIC_ALLOWED},
|
CAP_FLAG_INPUT_PORT | CAP_FLAG_DYNAMIC_ALLOWED},
|
||||||
|
|
||||||
{PRIORITY, DEC|ENC, CODECS_ALL,
|
{PRIORITY, DEC|ENC, CODECS_ALL,
|
||||||
0, 2, 1, 1,
|
0, 1 + NRT_PRIORITY_OFFSET, 1, 1 + NRT_PRIORITY_OFFSET,
|
||||||
V4L2_CID_MPEG_VIDC_PRIORITY,
|
V4L2_CID_MPEG_VIDC_PRIORITY,
|
||||||
HFI_PROP_SESSION_PRIORITY,
|
HFI_PROP_SESSION_PRIORITY,
|
||||||
CAP_FLAG_DYNAMIC_ALLOWED},
|
CAP_FLAG_DYNAMIC_ALLOWED},
|
||||||
|
@@ -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);
|
void msm_vidc_allow_dcvs(struct msm_vidc_inst *inst);
|
||||||
bool msm_vidc_allow_decode_batch(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);
|
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_mbps(struct msm_vidc_inst *inst);
|
||||||
int msm_vidc_check_core_mbpf(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);
|
int msm_vidc_check_scaling_supported(struct msm_vidc_inst *inst);
|
||||||
|
@@ -171,5 +171,6 @@ struct msm_vidc_inst {
|
|||||||
u32 max_rate;
|
u32 max_rate;
|
||||||
bool has_bframe;
|
bool has_bframe;
|
||||||
bool ir_enabled;
|
bool ir_enabled;
|
||||||
|
u32 adjust_priority;
|
||||||
};
|
};
|
||||||
#endif // _MSM_VIDC_INST_H_
|
#endif // _MSM_VIDC_INST_H_
|
||||||
|
@@ -31,6 +31,8 @@
|
|||||||
#define DEFAULT_WIDTH 320
|
#define DEFAULT_WIDTH 320
|
||||||
#define DEFAULT_FPS 30
|
#define DEFAULT_FPS 30
|
||||||
#define MAXIMUM_VP9_FPS 60
|
#define MAXIMUM_VP9_FPS 60
|
||||||
|
#define NRT_PRIORITY_OFFSET 2
|
||||||
|
#define RT_DEC_DOWN_PRORITY_OFFSET 1
|
||||||
#define MAX_SUPPORTED_INSTANCES 16
|
#define MAX_SUPPORTED_INSTANCES 16
|
||||||
#define DEFAULT_BSE_VPP_DELAY 2
|
#define DEFAULT_BSE_VPP_DELAY 2
|
||||||
#define MAX_CAP_PARENTS 20
|
#define MAX_CAP_PARENTS 20
|
||||||
|
@@ -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 */
|
/* batch decoder output & meta buffer only */
|
||||||
if (inst->decode_batch.enable && vb2->type == OUTPUT_MPLANE)
|
if (inst->decode_batch.enable && vb2->type == OUTPUT_MPLANE)
|
||||||
rc = msm_vdec_qbuf_batch(inst, vb2);
|
rc = msm_vdec_qbuf_batch(inst, vb2);
|
||||||
|
@@ -1085,21 +1085,11 @@ static int msm_vidc_update_static_property(struct msm_vidc_inst *inst,
|
|||||||
return rc;
|
return rc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* call this explicitly to adjust client priority */
|
||||||
if (ctrl->id == V4L2_CID_MPEG_VIDC_PRIORITY) {
|
if (ctrl->id == V4L2_CID_MPEG_VIDC_PRIORITY) {
|
||||||
rc = msm_vidc_adjust_session_priority(inst, ctrl);
|
rc = msm_vidc_adjust_session_priority(inst, ctrl);
|
||||||
if (rc)
|
if (rc)
|
||||||
return 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) {
|
if (ctrl->id == V4L2_CID_MPEG_VIDEO_HEVC_HIER_CODING_LAYER) {
|
||||||
u32 enable;
|
u32 enable;
|
||||||
@@ -2792,8 +2782,29 @@ int msm_vidc_adjust_session_priority(void *instance, struct v4l2_ctrl *ctrl)
|
|||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
}
|
}
|
||||||
capability = inst->capabilities;
|
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__);
|
msm_vidc_update_cap_value(inst, PRIORITY, adjusted_value, __func__);
|
||||||
|
|
||||||
|
@@ -5923,12 +5923,25 @@ static int msm_vidc_print_insts_info(struct msm_vidc_core *core)
|
|||||||
return 0;
|
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)
|
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_core *core;
|
||||||
struct msm_vidc_inst *instance;
|
struct msm_vidc_inst *instance;
|
||||||
int rc = 0;
|
|
||||||
|
|
||||||
if (!inst || !inst->core || !inst->capabilities) {
|
if (!inst || !inst->core || !inst->capabilities) {
|
||||||
d_vpr_e("%s: invalid params\n", __func__);
|
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;
|
core = inst->core;
|
||||||
|
|
||||||
if (!inst->capabilities->cap[CHECK_MBPS].value) {
|
/* skip mbps check for non-realtime, thumnail, image sessions */
|
||||||
i_vpr_h(inst, "%s: skip mbps check\n", __func__);
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
core_lock(core, __func__);
|
core_lock(core, __func__);
|
||||||
list_for_each_entry(instance, &core->instances, list) {
|
list_for_each_entry(instance, &core->instances, list) {
|
||||||
/* ignore invalid/error session */
|
/* ignore invalid/error session */
|
||||||
@@ -5948,25 +5964,50 @@ int msm_vidc_check_core_mbps(struct msm_vidc_inst *inst)
|
|||||||
continue;
|
continue;
|
||||||
|
|
||||||
/* ignore thumbnail, image, and non realtime sessions */
|
/* ignore thumbnail, image, and non realtime sessions */
|
||||||
if (is_thumbnail_session(instance) ||
|
if (msm_vidc_ignore_session_load(inst))
|
||||||
is_image_session(instance) ||
|
|
||||||
!is_realtime_session(instance))
|
|
||||||
continue;
|
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__);
|
core_unlock(core, __func__);
|
||||||
|
|
||||||
if (mbps > core->capabilities[MAX_MBPS].value) {
|
if (is_encode_session(inst)) {
|
||||||
rc = -ENOMEM;
|
/* reject encoder if all encoders mbps is greater than MAX_MBPS */
|
||||||
i_vpr_e(inst, "%s: Hardware overloaded. needed %u, max %u", __func__,
|
if (enc_mbps > core->capabilities[MAX_MBPS].value) {
|
||||||
mbps, core->capabilities[MAX_MBPS].value);
|
i_vpr_e(inst, "%s: Hardware overloaded. needed %u, max %u", __func__,
|
||||||
return rc;
|
mbps, core->capabilities[MAX_MBPS].value);
|
||||||
} else {
|
return -ENOMEM;
|
||||||
i_vpr_h(inst, "%s: HW load needed %u is within max %u", __func__,
|
}
|
||||||
mbps, core->capabilities[MAX_MBPS].value);
|
/*
|
||||||
|
* 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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -6010,9 +6051,7 @@ int msm_vidc_check_core_mbpf(struct msm_vidc_inst *inst)
|
|||||||
core_lock(core, __func__);
|
core_lock(core, __func__);
|
||||||
/* check real-time video sessions max limit */
|
/* check real-time video sessions max limit */
|
||||||
list_for_each_entry(instance, &core->instances, list) {
|
list_for_each_entry(instance, &core->instances, list) {
|
||||||
if (is_thumbnail_session(instance) ||
|
if (msm_vidc_ignore_session_load(inst))
|
||||||
is_image_session(instance) ||
|
|
||||||
!is_realtime_session(instance))
|
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
video_rt_mbpf += msm_vidc_get_mbs_per_frame(instance);
|
video_rt_mbpf += msm_vidc_get_mbs_per_frame(instance);
|
||||||
|
Reference in New Issue
Block a user