From e3da5c43e2948c721085f96c67c79e23838e7233 Mon Sep 17 00:00:00 2001 From: Vikash Garodia Date: Thu, 14 Apr 2022 18:39:35 +0530 Subject: [PATCH] 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 --- driver/platform/kalama/src/msm_vidc_kalama.c | 32 +++++++++++++ driver/platform/waipio/src/msm_vidc_waipio.c | 31 ++++++++++++ driver/vidc/inc/hfi_command.h | 6 +++ driver/vidc/inc/msm_vidc_control.h | 2 + driver/vidc/inc/msm_vidc_driver.h | 5 ++ driver/vidc/inc/msm_vidc_internal.h | 3 ++ driver/vidc/inc/venus_hfi.h | 1 + driver/vidc/src/msm_vidc_control.c | 45 ++++++++++++++++++ driver/vidc/src/msm_vidc_driver.c | 39 +++++++++++++++ driver/vidc/src/venus_hfi.c | 47 +++++++++++++++++++ .../uapi/vidc/media/v4l2_vidc_extensions.h | 5 ++ 11 files changed, 216 insertions(+) diff --git a/driver/platform/kalama/src/msm_vidc_kalama.c b/driver/platform/kalama/src/msm_vidc_kalama.c index c377b56bf2..c780926b85 100644 --- a/driver/platform/kalama/src/msm_vidc_kalama.c +++ b/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}, diff --git a/driver/platform/waipio/src/msm_vidc_waipio.c b/driver/platform/waipio/src/msm_vidc_waipio.c index b51e12c1b0..5691b68c80 100644 --- a/driver/platform/waipio/src/msm_vidc_waipio.c +++ b/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}, diff --git a/driver/vidc/inc/hfi_command.h b/driver/vidc/inc/hfi_command.h index b88f6571ae..c037e34595 100644 --- a/driver/vidc/inc/hfi_command.h +++ b/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 diff --git a/driver/vidc/inc/msm_vidc_control.h b/driver/vidc/inc/msm_vidc_control.h index a61762fb15..92d14e7c8b 100644 --- a/driver/vidc/inc/msm_vidc_control.h +++ b/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, diff --git a/driver/vidc/inc/msm_vidc_driver.h b/driver/vidc/inc/msm_vidc_driver.h index fac616bc4c..0523a6302f 100644 --- a/driver/vidc/inc/msm_vidc_driver.h +++ b/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); diff --git a/driver/vidc/inc/msm_vidc_internal.h b/driver/vidc/inc/msm_vidc_internal.h index 77f2cbccfd..cc04ae259f 100644 --- a/driver/vidc/inc/msm_vidc_internal.h +++ b/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, diff --git a/driver/vidc/inc/venus_hfi.h b/driver/vidc/inc/venus_hfi.h index cbbd4ec571..ba41ad24dc 100644 --- a/driver/vidc/inc/venus_hfi.h +++ b/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, diff --git a/driver/vidc/src/msm_vidc_control.c b/driver/vidc/src/msm_vidc_control.c index 0d2169f2bb..8e5a75167a 100644 --- a/driver/vidc/src/msm_vidc_control.c +++ b/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) { diff --git a/driver/vidc/src/msm_vidc_driver.c b/driver/vidc/src/msm_vidc_driver.c index 395dc4bab5..0514ea2010 100644 --- a/driver/vidc/src/msm_vidc_driver.c +++ b/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 */ diff --git a/driver/vidc/src/venus_hfi.c b/driver/vidc/src/venus_hfi.c index 5f55c0d9ec..551afdb0bc 100644 --- a/driver/vidc/src/venus_hfi.c +++ b/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; diff --git a/include/uapi/vidc/media/v4l2_vidc_extensions.h b/include/uapi/vidc/media/v4l2_vidc_extensions.h index 407a450e72..afc041b34e 100644 --- a/include/uapi/vidc/media/v4l2_vidc_extensions.h +++ b/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