diff --git a/driver/vidc/inc/msm_vidc_debug.h b/driver/vidc/inc/msm_vidc_debug.h index 6858b7e653..392411d46e 100644 --- a/driver/vidc/inc/msm_vidc_debug.h +++ b/driver/vidc/inc/msm_vidc_debug.h @@ -33,6 +33,7 @@ extern unsigned int msm_vidc_debug; extern bool msm_vidc_lossless_encode; extern bool msm_vidc_syscache_disable; extern int msm_vidc_clock_voting; +extern bool msm_vidc_fw_dump; /* To enable messages OR these values and * echo the result to debugfs file. diff --git a/driver/vidc/src/msm_vidc_debug.c b/driver/vidc/src/msm_vidc_debug.c index 0a0c7f4868..df2c3ed954 100644 --- a/driver/vidc/src/msm_vidc_debug.c +++ b/driver/vidc/src/msm_vidc_debug.c @@ -83,6 +83,9 @@ EXPORT_SYMBOL(msm_vidc_syscache_disable); int msm_vidc_clock_voting = !1; +bool msm_vidc_fw_dump = !true; +EXPORT_SYMBOL(msm_vidc_fw_dump); + #define MAX_DBG_BUF_SIZE 4096 struct core_inst_pair { @@ -244,6 +247,8 @@ struct dentry* msm_vidc_debugfs_init_drv() &msm_vidc_syscache_disable); debugfs_create_bool("lossless_encoding", 0644, dir, &msm_vidc_lossless_encode); + debugfs_create_bool("msm_vidc_fw_dump", 0644, dir, + &msm_vidc_fw_dump); return dir; diff --git a/driver/vidc/src/venus_hfi_response.c b/driver/vidc/src/venus_hfi_response.c index b916a66794..734214593e 100644 --- a/driver/vidc/src/venus_hfi_response.c +++ b/driver/vidc/src/venus_hfi_response.c @@ -3,6 +3,8 @@ * Copyright (c) 2020-2021, The Linux Foundation. All rights reserved. */ +#include +#include #include "hfi_packet.h" #include "venus_hfi.h" #include "venus_hfi_response.h" @@ -372,13 +374,61 @@ static int handle_session_error(struct msm_vidc_inst *inst, return rc; } +static void fw_coredump(struct platform_device *pdev) +{ + int rc = 0; + struct device_node *node = NULL; + struct resource res = {0}; + phys_addr_t mem_phys = 0; + size_t res_size = 0; + void *mem_va = NULL; + void *data = NULL; + + node = of_parse_phandle(pdev->dev.of_node, "memory-region", 0); + if (!node) { + d_vpr_e("%s: DT error getting \"memory-region\" property\n", + __func__); + return; + } + + rc = of_address_to_resource(node, 0, &res); + if (rc) { + d_vpr_e("%s: error %d while getting \"memory-region\" resource\n", + __func__, rc); + return; + } + + mem_phys = res.start; + res_size = (size_t)resource_size(&res); + + mem_va = memremap(mem_phys, res_size, MEMREMAP_WC); + if (!mem_va) { + d_vpr_e("%s: unable to remap firmware memory\n", __func__); + return; + } + + data = vmalloc(res_size); + if (!data) { + memunmap(mem_va); + return; + } + + memcpy(data, mem_va, res_size); + memunmap(mem_va); + dev_coredumpv(&pdev->dev, data, res_size, GFP_KERNEL); +} + int handle_system_error(struct msm_vidc_core *core, struct hfi_packet *pkt) { d_vpr_e("%s: system error received\n", __func__); + print_sfr_message(core); venus_hfi_noc_error_info(core); msm_vidc_core_deinit(core, true); + if (msm_vidc_fw_dump) + fw_coredump(core->pdev); + return 0; }