diff --git a/msm/vidc/hfi_common.c b/msm/vidc/hfi_common.c index bbb48a5120de..4282b249f3af 100644 --- a/msm/vidc/hfi_common.c +++ b/msm/vidc/hfi_common.c @@ -1780,7 +1780,8 @@ static int venus_hfi_core_release(void *dev) } static int venus_hfi_core_trigger_ssr(void *device, - enum hal_ssr_trigger_type type) + enum hal_ssr_trigger_type ssr_type, u32 sub_client_id, + u32 test_addr) { struct hfi_cmd_sys_test_ssr_packet pkt; int rc = 0; @@ -1794,7 +1795,8 @@ static int venus_hfi_core_trigger_ssr(void *device, dev = device; mutex_lock(&dev->lock); - rc = call_hfi_pkt_op(dev, ssr_cmd, type, &pkt); + rc = call_hfi_pkt_op(dev, ssr_cmd, &pkt, ssr_type, + sub_client_id, test_addr); if (rc) { d_vpr_e("core_ping: failed to create packet\n"); goto err_create_pkt; diff --git a/msm/vidc/hfi_packetization.c b/msm/vidc/hfi_packetization.c index 30623ff31d5e..8518dc27018e 100644 --- a/msm/vidc/hfi_packetization.c +++ b/msm/vidc/hfi_packetization.c @@ -626,7 +626,7 @@ int create_pkt_cmd_session_set_property( static int get_hfi_ssr_type(enum hal_ssr_trigger_type type) { - int rc = HFI_TEST_SSR_HW_WDOG_IRQ; + int rc = HFI_TEST_SSR_SW_ERR_FATAL; switch (type) { case SSR_ERR_FATAL: @@ -638,22 +638,37 @@ static int get_hfi_ssr_type(enum hal_ssr_trigger_type type) case SSR_HW_WDOG_IRQ: rc = HFI_TEST_SSR_HW_WDOG_IRQ; break; + case SSR_NOC_ERROR: + rc = HFI_TEST_SSR_NOC_ERROR; + break; + case SSR_VCODEC_HUNG: + rc = HFI_TEST_SSR_VCODEC_HUNG; + break; default: d_vpr_e("SSR trigger type not recognized, using WDOG.\n"); } return rc; } -int create_pkt_ssr_cmd(enum hal_ssr_trigger_type type, - struct hfi_cmd_sys_test_ssr_packet *pkt) +int create_pkt_ssr_cmd(struct hfi_cmd_sys_test_ssr_packet *pkt, + enum hal_ssr_trigger_type ssr_type, u32 sub_client_id, + u32 test_addr) { + struct hfi_ssr_payload payload; if (!pkt) { d_vpr_e("%s: invalid params\n", __func__); return -EINVAL; } - pkt->size = sizeof(struct hfi_cmd_sys_test_ssr_packet); + pkt->size = sizeof(struct hfi_cmd_sys_test_ssr_packet) - sizeof(u32); pkt->packet_type = HFI_CMD_SYS_TEST_SSR; - pkt->trigger_type = get_hfi_ssr_type(type); + pkt->trigger_type = get_hfi_ssr_type(ssr_type); + if (pkt->trigger_type == HFI_TEST_SSR_NOC_ERROR || + pkt->trigger_type == HFI_TEST_SSR_VCODEC_HUNG) { + pkt->size += sizeof(struct hfi_ssr_payload); + payload.sub_client_id = sub_client_id; + payload.test_addr = test_addr; + memcpy(&pkt->rg_data[0], &payload, sizeof(struct hfi_ssr_payload)); + } return 0; } diff --git a/msm/vidc/hfi_packetization.h b/msm/vidc/hfi_packetization.h index f77c4be243db..accce3144aa4 100644 --- a/msm/vidc/hfi_packetization.h +++ b/msm/vidc/hfi_packetization.h @@ -1,6 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ /* - * Copyright (c) 2012-2019, The Linux Foundation. All rights reserved. + * Copyright (c) 2012-2020, The Linux Foundation. All rights reserved. */ #ifndef __HFI_PACKETIZATION_H__ #define __HFI_PACKETIZATION_H__ @@ -36,8 +36,9 @@ struct hfi_packetization_ops { int (*sys_image_version)(struct hfi_cmd_sys_get_property_packet *pkt); int (*sys_ubwc_config)(struct hfi_cmd_sys_set_property_packet *pkt, struct msm_vidc_ubwc_config_data *ubwc_config); - int (*ssr_cmd)(enum hal_ssr_trigger_type type, - struct hfi_cmd_sys_test_ssr_packet *pkt); + int (*ssr_cmd)(struct hfi_cmd_sys_test_ssr_packet *pkt, + enum hal_ssr_trigger_type ssr_type, u32 sub_client_id, + u32 test_addr); int (*session_init)( struct hfi_cmd_sys_session_init_packet *pkt, u32 sid, u32 session_domain, u32 session_codec); diff --git a/msm/vidc/msm_vidc_common.c b/msm/vidc/msm_vidc_common.c index f85fe2017c4d..4c71d3512441 100644 --- a/msm/vidc/msm_vidc_common.c +++ b/msm/vidc/msm_vidc_common.c @@ -25,6 +25,12 @@ static void msm_vidc_print_running_insts(struct msm_vidc_core *core); #define V4L2_VP9_LEVEL_61 V4L2_MPEG_VIDC_VIDEO_VP9_LEVEL_61 #define TIMESTAMPS_WINDOW_SIZE 32 +#define SSR_TYPE 0x0000000F +#define SSR_TYPE_SHIFT 0 +#define SSR_SUB_CLIENT_ID 0x000000F0 +#define SSR_SUB_CLIENT_ID_SHIFT 4 +#define SSR_ADDR_ID 0xFFFFFFFF00000000 +#define SSR_ADDR_SHIFT 32 int msm_comm_g_ctrl_for_id(struct msm_vidc_inst *inst, int id) { @@ -5644,13 +5650,25 @@ int msm_vidc_noc_error_info(struct msm_vidc_core *core) } int msm_vidc_trigger_ssr(struct msm_vidc_core *core, - enum hal_ssr_trigger_type type) + u64 trigger_ssr_val) { + struct msm_vidc_ssr *ssr; if (!core) { d_vpr_e("%s: Invalid parameters\n", __func__); return -EINVAL; } - core->ssr_type = type; + ssr = &core->ssr; + /* + * ssr_type: 0-3 bits + * sub_client_id: 4-7 bits + * reserved: 8-31 bits + * test_addr: 32-63 bits */ + ssr->ssr_type = (trigger_ssr_val & + (unsigned long)SSR_TYPE) >> SSR_TYPE_SHIFT; + ssr->sub_client_id = (trigger_ssr_val & + (unsigned long)SSR_SUB_CLIENT_ID) >> SSR_SUB_CLIENT_ID_SHIFT; + ssr->test_addr = (trigger_ssr_val & + (unsigned long)SSR_ADDR_ID) >> SSR_ADDR_SHIFT; schedule_work(&core->ssr_work); return 0; } @@ -5660,6 +5678,7 @@ void msm_vidc_ssr_handler(struct work_struct *work) int rc; struct msm_vidc_core *core; struct hfi_device *hdev; + struct msm_vidc_ssr *ssr; core = container_of(work, struct msm_vidc_core, ssr_work); if (!core || !core->device) { @@ -5667,10 +5686,11 @@ void msm_vidc_ssr_handler(struct work_struct *work) return; } hdev = core->device; + ssr = &core->ssr; mutex_lock(&core->lock); if (core->state == VIDC_CORE_INIT_DONE) { - d_vpr_e("%s: ssr type %d\n", __func__, core->ssr_type); + d_vpr_e("%s: ssr type %d\n", __func__, ssr->ssr_type); /* * In current implementation user-initiated SSR triggers * a fatal error from hardware. However, there is no way @@ -5679,7 +5699,8 @@ void msm_vidc_ssr_handler(struct work_struct *work) */ core->trigger_ssr = true; rc = call_hfi_op(hdev, core_trigger_ssr, - hdev->hfi_device_data, core->ssr_type); + hdev->hfi_device_data, ssr->ssr_type, + ssr->sub_client_id, ssr->test_addr); if (rc) { d_vpr_e("%s: trigger_ssr failed\n", __func__); core->trigger_ssr = false; diff --git a/msm/vidc/msm_vidc_debug.c b/msm/vidc/msm_vidc_debug.c index 4b0f6090de40..cd69a2ae161a 100644 --- a/msm/vidc/msm_vidc_debug.c +++ b/msm/vidc/msm_vidc_debug.c @@ -4,7 +4,7 @@ */ #define CREATE_TRACE_POINTS -#define MAX_SSR_STRING_LEN 10 +#define MAX_SSR_STRING_LEN 64 #define MAX_DEBUG_LEVEL_STRING_LEN 15 #include "msm_vidc_debug.h" #include "vidc_hfi_api.h" diff --git a/msm/vidc/msm_vidc_internal.h b/msm/vidc/msm_vidc_internal.h index b54f981e6017..2c1d1c4c7d41 100644 --- a/msm/vidc/msm_vidc_internal.h +++ b/msm/vidc/msm_vidc_internal.h @@ -467,6 +467,12 @@ struct msm_vidc_core_ops { int (*calc_bw)(struct vidc_bus_vote_data *vidc_data); }; +struct msm_vidc_ssr { + enum hal_ssr_trigger_type ssr_type; + u32 sub_client_id; + u32 test_addr; +}; + struct msm_vidc_core { struct list_head list; struct mutex lock; @@ -485,7 +491,7 @@ struct msm_vidc_core { struct delayed_work fw_unload_work; struct work_struct ssr_work; struct workqueue_struct *vidc_core_workq; - enum hal_ssr_trigger_type ssr_type; + struct msm_vidc_ssr ssr; bool smmu_fault_handled; bool trigger_ssr; unsigned long min_freq; @@ -605,7 +611,7 @@ struct msm_vidc_ctrl { void handle_cmd_response(enum hal_command_response cmd, void *data); int msm_vidc_trigger_ssr(struct msm_vidc_core *core, - enum hal_ssr_trigger_type type); + u64 trigger_ssr_val); int msm_vidc_noc_error_info(struct msm_vidc_core *core); int msm_vidc_check_session_supported(struct msm_vidc_inst *inst); int msm_vidc_check_scaling_supported(struct msm_vidc_inst *inst); diff --git a/msm/vidc/vidc_hfi.h b/msm/vidc/vidc_hfi.h index 29c6c85b699c..9d2ab5d0dfe7 100644 --- a/msm/vidc/vidc_hfi.h +++ b/msm/vidc/vidc_hfi.h @@ -282,6 +282,11 @@ struct hfi_hybrid_hierp { u32 layers; }; +struct hfi_ssr_payload { + u32 sub_client_id; + u32 test_addr; +}; + #define HFI_PRIORITY_LOW 10 #define HFI_PRIOIRTY_MEDIUM 20 #define HFI_PRIORITY_HIGH 30 diff --git a/msm/vidc/vidc_hfi_api.h b/msm/vidc/vidc_hfi_api.h index 1193b227ca9f..ee86ad85f7be 100644 --- a/msm/vidc/vidc_hfi_api.h +++ b/msm/vidc/vidc_hfi_api.h @@ -133,6 +133,8 @@ enum hal_ssr_trigger_type { SSR_ERR_FATAL = 1, SSR_SW_DIV_BY_ZERO, SSR_HW_WDOG_IRQ, + SSR_NOC_ERROR, + SSR_VCODEC_HUNG, }; struct hal_profile_level { @@ -634,7 +636,9 @@ struct hfi_device { /*Add function pointers for all the hfi functions below*/ int (*core_init)(void *device); int (*core_release)(void *device); - int (*core_trigger_ssr)(void *device, enum hal_ssr_trigger_type); + int (*core_trigger_ssr)(void *device, + enum hal_ssr_trigger_type ssr_type, u32 sub_client_id, + u32 test_addr); int (*session_init)(void *device, void *inst_id, enum hal_domain session_type, enum hal_video_codec codec_type, void **new_session, u32 sid); diff --git a/msm/vidc/vidc_hfi_helper.h b/msm/vidc/vidc_hfi_helper.h index 7800ac795a6e..177069932797 100644 --- a/msm/vidc/vidc_hfi_helper.h +++ b/msm/vidc/vidc_hfi_helper.h @@ -833,6 +833,8 @@ struct hfi_aspect_ratio { #define HFI_TEST_SSR_SW_ERR_FATAL 0x1 #define HFI_TEST_SSR_SW_DIV_BY_ZERO 0x2 #define HFI_TEST_SSR_HW_WDOG_IRQ 0x3 +#define HFI_TEST_SSR_NOC_ERROR 0x4 +#define HFI_TEST_SSR_VCODEC_HUNG 0x5 struct vidc_hal_cmd_pkt_hdr { u32 size; @@ -1057,6 +1059,7 @@ struct hfi_cmd_sys_test_ssr_packet { u32 size; u32 packet_type; u32 trigger_type; + u32 rg_data[1]; }; struct hfi_hdr10_pq_sei {