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 <quic_vgarodia@quicinc.com>
This commit is contained in:
Vikash Garodia
2022-04-14 18:39:35 +05:30
parent 91f3bc9ab7
commit e3da5c43e2
11 changed files with 216 additions and 0 deletions

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

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