video: driver: Enable Subsystem Restart (SSR) testing
Enable Subsystem Restart test support. Clients can trigger SSR through debugfs as follows: echo <trigger_val> > /d/msm_vidc/core/trigger_ssr u64 trigger_val provides: /* <test_addr><sub_client_id><ssr_type> * ssr_type: 0-3 bits * sub_client_id: 4-7 bits * reserved: 8-31 bits * test_addr: 32-63 bits */ Change-Id: If23fce3084de00461f1e5cc57884e10d15ad66a9 Signed-off-by: Mihir Ganu <mganu@codeaurora.org>
This commit is contained in:
@@ -276,7 +276,7 @@ void msm_vidc_print_core_info(struct msm_vidc_core *core);
|
||||
int msm_vidc_smmu_fault_handler(struct iommu_domain *domain,
|
||||
struct device *dev, unsigned long iova, int flags, void *data);
|
||||
int msm_vidc_trigger_ssr(struct msm_vidc_core *core,
|
||||
enum msm_vidc_ssr_trigger_type type);
|
||||
u64 trigger_ssr_val);
|
||||
void msm_vidc_ssr_handler(struct work_struct *work);
|
||||
void msm_vidc_pm_work_handler(struct work_struct *work);
|
||||
void msm_vidc_fw_unload_handler(struct work_struct *work);
|
||||
|
@@ -815,6 +815,8 @@ struct response_work {
|
||||
struct msm_vidc_ssr {
|
||||
bool trigger;
|
||||
enum msm_vidc_ssr_trigger_type ssr_type;
|
||||
u32 sub_client_id;
|
||||
u32 test_addr;
|
||||
};
|
||||
|
||||
struct msm_vidc_sfr {
|
||||
|
@@ -48,6 +48,8 @@ int venus_hfi_core_init(struct msm_vidc_core *core);
|
||||
int venus_hfi_core_deinit(struct msm_vidc_core *core);
|
||||
int venus_hfi_noc_error_info(struct msm_vidc_core *core);
|
||||
int venus_hfi_suspend(struct msm_vidc_core *core);
|
||||
int venus_hfi_trigger_ssr(struct msm_vidc_core *core, u32 type,
|
||||
u32 client_id, u32 addr);
|
||||
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);
|
||||
|
||||
|
@@ -11,7 +11,7 @@
|
||||
#include "msm_vidc_inst.h"
|
||||
#include "msm_vidc_internal.h"
|
||||
|
||||
#define MAX_SSR_STRING_LEN 10
|
||||
#define MAX_SSR_STRING_LEN 64
|
||||
#define MAX_DEBUG_LEVEL_STRING_LEN 15
|
||||
|
||||
int msm_vidc_debug = VIDC_ERR | VIDC_PRINTK | FW_ERROR | FW_FATAL;
|
||||
|
@@ -30,6 +30,13 @@ extern struct msm_vidc_core *g_core;
|
||||
} \
|
||||
}
|
||||
|
||||
#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
|
||||
|
||||
struct msm_vidc_buf_type_name {
|
||||
enum msm_vidc_buffer_type type;
|
||||
char *name;
|
||||
@@ -3463,13 +3470,64 @@ int msm_vidc_smmu_fault_handler(struct iommu_domain *domain,
|
||||
}
|
||||
|
||||
int msm_vidc_trigger_ssr(struct msm_vidc_core *core,
|
||||
enum msm_vidc_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;
|
||||
}
|
||||
ssr = &core->ssr;
|
||||
/*
|
||||
* <test_addr><sub_client_id><ssr_type>
|
||||
* 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;
|
||||
}
|
||||
|
||||
void msm_vidc_ssr_handler(struct work_struct *work)
|
||||
{
|
||||
int rc;
|
||||
struct msm_vidc_core *core;
|
||||
struct msm_vidc_ssr *ssr;
|
||||
|
||||
core = container_of(work, struct msm_vidc_core, ssr_work);
|
||||
if (!core) {
|
||||
d_vpr_e("%s: invalid params %pK\n", __func__, core);
|
||||
return;
|
||||
}
|
||||
ssr = &core->ssr;
|
||||
|
||||
core_lock(core, __func__);
|
||||
if (core->state == MSM_VIDC_CORE_INIT) {
|
||||
/*
|
||||
* In current implementation, user-initiated SSR triggers
|
||||
* a fatal error from hardware. However, there is no way
|
||||
* to know if fatal error is due to SSR or not. Handle
|
||||
* user SSR as non-fatal.
|
||||
*/
|
||||
core->ssr.trigger = true;
|
||||
rc = venus_hfi_trigger_ssr(core, ssr->ssr_type,
|
||||
ssr->sub_client_id, ssr->test_addr);
|
||||
if (rc) {
|
||||
d_vpr_e("%s: trigger_ssr failed\n", __func__);
|
||||
core->ssr.trigger = false;
|
||||
}
|
||||
} else {
|
||||
d_vpr_e("%s: video core not initialized\n", __func__);
|
||||
}
|
||||
core_unlock(core, __func__);
|
||||
}
|
||||
|
||||
void msm_vidc_pm_work_handler(struct work_struct *work)
|
||||
|
@@ -2897,6 +2897,49 @@ int venus_hfi_suspend(struct msm_vidc_core *core)
|
||||
return rc;
|
||||
}
|
||||
|
||||
int venus_hfi_trigger_ssr(struct msm_vidc_core *core, u32 type,
|
||||
u32 client_id, u32 addr)
|
||||
{
|
||||
int rc = 0;
|
||||
u32 payload[2];
|
||||
|
||||
if (!core || !core->packet) {
|
||||
d_vpr_e("%s: Invalid params\n", __func__);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
payload[0] = client_id << 4 | type;
|
||||
payload[1] = addr;
|
||||
|
||||
rc = hfi_create_header(core->packet, core->packet_size,
|
||||
0 /*session_id*/,
|
||||
core->header_id++);
|
||||
if (rc)
|
||||
goto err_ssr_pkt;
|
||||
|
||||
/* HFI_CMD_SSR */
|
||||
rc = hfi_create_packet(core->packet, core->packet_size,
|
||||
HFI_CMD_SSR,
|
||||
HFI_HOST_FLAGS_RESPONSE_REQUIRED |
|
||||
HFI_HOST_FLAGS_INTR_REQUIRED,
|
||||
HFI_PAYLOAD_U64,
|
||||
HFI_PORT_NONE,
|
||||
core->packet_id++,
|
||||
&payload, sizeof(u64));
|
||||
if (rc)
|
||||
goto err_ssr_pkt;
|
||||
|
||||
rc = __iface_cmdq_write(core, core->packet);
|
||||
if (rc)
|
||||
return rc;
|
||||
|
||||
return 0;
|
||||
|
||||
err_ssr_pkt:
|
||||
d_vpr_e("%s: create packet failed\n", __func__);
|
||||
return rc;
|
||||
}
|
||||
|
||||
int venus_hfi_session_open(struct msm_vidc_inst *inst)
|
||||
{
|
||||
int rc = 0;
|
||||
|
Reference in New Issue
Block a user