From 659ec598884bd736da031500d5d1c913f85d4de7 Mon Sep 17 00:00:00 2001 From: Govindaraj Rajagopal Date: Tue, 15 Jun 2021 18:23:15 +0530 Subject: [PATCH] video: driver: dump queues for system error Add support to dump all queues(cmd, msg, dbg) as part of handle_system_error using devcoredump framework. Change-Id: Ia1b011a29e6bc657eb002dbba09deab62dc0b2b2 Signed-off-by: Govindaraj Rajagopal --- driver/vidc/inc/msm_vidc_internal.h | 1 + driver/vidc/inc/venus_hfi_response.h | 1 + driver/vidc/src/venus_hfi.c | 13 +++++++++---- driver/vidc/src/venus_hfi_response.c | 24 ++++++++++++++++++------ 4 files changed, 29 insertions(+), 10 deletions(-) diff --git a/driver/vidc/inc/msm_vidc_internal.h b/driver/vidc/inc/msm_vidc_internal.h index eddb52dfac..a0ebd13dd9 100644 --- a/driver/vidc/inc/msm_vidc_internal.h +++ b/driver/vidc/inc/msm_vidc_internal.h @@ -633,6 +633,7 @@ struct hfi_queue_header { #define ALIGNED_QUEUE_SIZE ALIGN(QUEUE_SIZE, SZ_4K) #define SHARED_QSIZE ALIGN(ALIGNED_SFR_SIZE + ALIGNED_QUEUE_SIZE + \ ALIGNED_QDSS_SIZE, SZ_1M) +#define TOTAL_QSIZE (SHARED_QSIZE - ALIGNED_SFR_SIZE - ALIGNED_QDSS_SIZE) struct buf_count { u32 etb; diff --git a/driver/vidc/inc/venus_hfi_response.h b/driver/vidc/inc/venus_hfi_response.h index f699022dfb..1a47d08e63 100644 --- a/driver/vidc/inc/venus_hfi_response.h +++ b/driver/vidc/inc/venus_hfi_response.h @@ -21,5 +21,6 @@ int handle_session_response_work(struct msm_vidc_inst *inst, struct response_work *work); int handle_system_error(struct msm_vidc_core *core, struct hfi_packet *pkt); +void fw_coredump(struct msm_vidc_core *core); #endif // __VENUS_HFI_RESPONSE_H__ diff --git a/driver/vidc/src/venus_hfi.c b/driver/vidc/src/venus_hfi.c index a01be84d70..70ceeeca4a 100644 --- a/driver/vidc/src/venus_hfi.c +++ b/driver/vidc/src/venus_hfi.c @@ -2356,16 +2356,14 @@ static int __interface_queues_init(struct msm_vidc_core *core) struct msm_vidc_alloc alloc; struct msm_vidc_map map; int offset = 0; - u32 q_size; u32 i; d_vpr_h("%s()\n", __func__); - q_size = SHARED_QSIZE - ALIGNED_SFR_SIZE - ALIGNED_QDSS_SIZE; memset(&alloc, 0, sizeof(alloc)); alloc.type = MSM_VIDC_BUF_QUEUE; alloc.region = MSM_VIDC_NON_SECURE; - alloc.size = q_size; + alloc.size = TOTAL_QSIZE; alloc.secure = false; alloc.map_kernel = true; rc = msm_vidc_memory_alloc(core, &alloc); @@ -2879,8 +2877,15 @@ int venus_hfi_core_deinit(struct msm_vidc_core *core) __resume(core); __flush_debug_queue(core, core->packet, core->packet_size); __disable_subcaches(core); - __interface_queues_deinit(core); __unload_fw(core); + /** + * coredump need to be called after firmware unload, coredump also + * copying queues memory. So need to be called before queues deinit. + */ + if (msm_vidc_fw_dump) + fw_coredump(core); + __interface_queues_deinit(core); + return 0; } diff --git a/driver/vidc/src/venus_hfi_response.c b/driver/vidc/src/venus_hfi_response.c index bdd6b3453b..1af365d46b 100644 --- a/driver/vidc/src/venus_hfi_response.c +++ b/driver/vidc/src/venus_hfi_response.c @@ -375,15 +375,23 @@ static int handle_session_error(struct msm_vidc_inst *inst, return rc; } -static void fw_coredump(struct platform_device *pdev) +void fw_coredump(struct msm_vidc_core *core) { int rc = 0; + struct platform_device *pdev; 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; + char *data = NULL; + u64 total_size; + + if (!core) { + d_vpr_e("%s: invalid params\n", __func__); + return; + } + pdev = core->pdev; node = of_parse_phandle(pdev->dev.of_node, "memory-region", 0); if (!node) { @@ -407,16 +415,22 @@ static void fw_coredump(struct platform_device *pdev) d_vpr_e("%s: unable to remap firmware memory\n", __func__); return; } + total_size = res_size + TOTAL_QSIZE; - data = vmalloc(res_size); + data = vmalloc(total_size); if (!data) { memunmap(mem_va); return; } + /* copy firmware dump */ memcpy(data, mem_va, res_size); memunmap(mem_va); - dev_coredumpv(&pdev->dev, data, res_size, GFP_KERNEL); + + /* copy queues(cmd, msg, dbg) dump(along with headers) */ + memcpy(data + res_size, (char *)core->iface_q_table.align_virtual_addr, TOTAL_QSIZE); + + dev_coredumpv(&pdev->dev, data, total_size, GFP_KERNEL); } int handle_system_error(struct msm_vidc_core *core, @@ -427,8 +441,6 @@ int handle_system_error(struct msm_vidc_core *core, 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; }