Loading drivers/cam_fd/cam_fd_context.c +15 −1 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include <linux/module.h> Loading Loading @@ -117,6 +117,19 @@ static int __cam_fd_ctx_release_dev_in_activated(struct cam_context *ctx, return rc; } static int __cam_fd_ctx_dump_dev_in_activated( struct cam_context *ctx, struct cam_dump_req_cmd *cmd) { int rc; rc = cam_context_dump_dev_to_hw(ctx, cmd); if (rc) CAM_ERR(CAM_FD, "Failed to dump device, rc=%d", rc); return rc; } static int __cam_fd_ctx_flush_dev_in_activated(struct cam_context *ctx, struct cam_flush_dev_cmd *cmd) { Loading Loading @@ -198,6 +211,7 @@ static struct cam_ctx_ops .release_dev = __cam_fd_ctx_release_dev_in_activated, .config_dev = __cam_fd_ctx_config_dev_in_activated, .flush_dev = __cam_fd_ctx_flush_dev_in_activated, .dump_dev = __cam_fd_ctx_dump_dev_in_activated, }, .crm_ops = {}, .irq_ops = __cam_fd_ctx_handle_irq_in_activated, Loading drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c +134 −1 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include <linux/module.h> Loading Loading @@ -883,6 +883,7 @@ static int cam_fd_mgr_util_submit_frame(void *priv, void *data) hw_device->cur_hw_ctx = hw_ctx; hw_device->req_id = frame_req->request_id; mutex_unlock(&hw_device->lock); frame_req->submit_timestamp = ktime_get(); rc = cam_fd_mgr_util_put_frame_req( &hw_mgr->frame_processing_list, &frame_req); Loading Loading @@ -1504,6 +1505,137 @@ static int cam_fd_mgr_hw_flush(void *hw_mgr_priv, return rc; } static int cam_fd_mgr_hw_dump( void *hw_mgr_priv, void *hw_dump_args) { int rc; uint8_t *dst; ktime_t cur_time; size_t remain_len; uint32_t min_len; uint64_t diff; uint64_t *addr, *start; struct timespec64 cur_ts; struct timespec64 req_ts; struct cam_fd_hw_mgr *hw_mgr; struct cam_hw_dump_args *dump_args; struct cam_fd_hw_mgr_ctx *hw_ctx; struct cam_fd_device *hw_device; struct cam_fd_hw_dump_args fd_dump_args; struct cam_fd_hw_dump_header *hdr; struct cam_fd_mgr_frame_request *frame_req, *req_temp; hw_mgr = (struct cam_fd_hw_mgr *)hw_mgr_priv; dump_args = (struct cam_hw_dump_args *)hw_dump_args; if (!hw_mgr || !dump_args) { CAM_ERR(CAM_FD, "Invalid args %pK %pK", hw_mgr, dump_args); return -EINVAL; } hw_ctx = (struct cam_fd_hw_mgr_ctx *)dump_args->ctxt_to_hw_map; if (!hw_ctx) { CAM_ERR(CAM_FD, "Invalid ctx"); return -EINVAL; } rc = cam_fd_mgr_util_get_device(hw_mgr, hw_ctx, &hw_device); if (rc) { CAM_ERR(CAM_FD, "Error in getting device %d", rc); return rc; } list_for_each_entry_safe(frame_req, req_temp, &hw_mgr->frame_processing_list, list) { if (frame_req->request_id == dump_args->request_id) goto hw_dump; } CAM_DBG(CAM_FD, "fd dump cannot find req %llu", dump_args->request_id); return rc; hw_dump: cur_time = ktime_get(); diff = ktime_us_delta(frame_req->submit_timestamp, cur_time); cur_ts = ktime_to_timespec64(cur_time); req_ts = ktime_to_timespec64(frame_req->submit_timestamp); if (diff < CAM_FD_RESPONSE_TIME_THRESHOLD) { CAM_INFO(CAM_FD, "No Error req %lld %ld:%06ld %ld:%06ld", dump_args->request_id, req_ts.tv_sec, req_ts.tv_nsec/NSEC_PER_USEC, cur_ts.tv_sec, cur_ts.tv_nsec/NSEC_PER_USEC); return 0; } CAM_INFO(CAM_FD, "Error req %lld %ld:%06ld %ld:%06ld", dump_args->request_id, req_ts.tv_sec, req_ts.tv_nsec/NSEC_PER_USEC, cur_ts.tv_sec, cur_ts.tv_nsec/NSEC_PER_USEC); rc = cam_mem_get_cpu_buf(dump_args->buf_handle, &fd_dump_args.cpu_addr, &fd_dump_args.buf_len); if (rc) { CAM_ERR(CAM_FD, "Invalid handle %u rc %d", dump_args->buf_handle, rc); return rc; } if (fd_dump_args.buf_len <= dump_args->offset) { CAM_WARN(CAM_FD, "dump offset overshoot len %zu offset %zu", fd_dump_args.buf_len, dump_args->offset); return -ENOSPC; } remain_len = fd_dump_args.buf_len - dump_args->offset; min_len = sizeof(struct cam_fd_hw_dump_header) + (CAM_FD_HW_DUMP_NUM_WORDS * sizeof(uint64_t)); if (remain_len < min_len) { CAM_WARN(CAM_FD, "dump buffer exhaust remain %zu min %u", remain_len, min_len); return -ENOSPC; } dst = (uint8_t *)fd_dump_args.cpu_addr + dump_args->offset; hdr = (struct cam_fd_hw_dump_header *)dst; scnprintf(hdr->tag, CAM_FD_HW_DUMP_TAG_MAX_LEN, "FD_REQ:"); hdr->word_size = sizeof(uint64_t); addr = (uint64_t *)(dst + sizeof(struct cam_fd_hw_dump_header)); start = addr; *addr++ = frame_req->request_id; *addr++ = req_ts.tv_sec; *addr++ = req_ts.tv_nsec/NSEC_PER_USEC; *addr++ = cur_ts.tv_sec; *addr++ = cur_ts.tv_nsec/NSEC_PER_USEC; hdr->size = hdr->word_size * (addr - start); dump_args->offset += hdr->size + sizeof(struct cam_fd_hw_dump_header); fd_dump_args.request_id = dump_args->request_id; fd_dump_args.offset = dump_args->offset; if (hw_device->hw_intf->hw_ops.process_cmd) { rc = hw_device->hw_intf->hw_ops.process_cmd( hw_device->hw_intf->hw_priv, CAM_FD_HW_CMD_HW_DUMP, &fd_dump_args, sizeof(struct cam_fd_hw_dump_args)); if (rc) { CAM_ERR(CAM_FD, "Hw Dump cmd fails req %lld rc %d", frame_req->request_id, rc); return rc; } } CAM_DBG(CAM_FD, "Offset before %zu after %zu", dump_args->offset, fd_dump_args.offset); dump_args->offset = fd_dump_args.offset; return rc; } static int cam_fd_mgr_hw_stop(void *hw_mgr_priv, void *mgr_stop_args) { struct cam_fd_hw_mgr *hw_mgr = (struct cam_fd_hw_mgr *)hw_mgr_priv; Loading Loading @@ -1944,6 +2076,7 @@ int cam_fd_hw_mgr_init(struct device_node *of_node, hw_mgr_intf->hw_write = NULL; hw_mgr_intf->hw_close = NULL; hw_mgr_intf->hw_flush = cam_fd_mgr_hw_flush; hw_mgr_intf->hw_dump = cam_fd_mgr_hw_dump; return rc; Loading drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.h +9 −1 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_FD_HW_MGR_H_ Loading @@ -21,6 +21,12 @@ #define CAM_FD_HW_MAX 1 #define CAM_FD_WORKQ_NUM_TASK 10 /* * Response time threshold in ms beyond which a request is not expected to be * with FD hw */ #define CAM_FD_RESPONSE_TIME_THRESHOLD 100000 struct cam_fd_hw_mgr; /** Loading Loading @@ -100,6 +106,7 @@ struct cam_fd_device { * @hw_update_entries : HW update entries corresponding to this request * which needs to be submitted to HW through CDM * @num_hw_update_entries : Number of HW update entries * @submit_timestamp : Time stamp for submit req with hw */ struct cam_fd_mgr_frame_request { struct list_head list; Loading @@ -108,6 +115,7 @@ struct cam_fd_mgr_frame_request { struct cam_fd_hw_req_private hw_req_private; struct cam_hw_update_entry hw_update_entries[CAM_FD_MAX_HW_ENTRIES]; uint32_t num_hw_update_entries; ktime_t submit_timestamp; }; /** Loading drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c +80 −1 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include "cam_fd_hw_core.h" Loading Loading @@ -516,6 +516,80 @@ static int cam_fd_hw_util_processcmd_frame_done(struct cam_hw_info *fd_hw, return 0; } static int cam_fd_hw_util_processcmd_hw_dump( struct cam_hw_info *fd_hw, void *args) { int i, j; uint8_t *dst; uint32_t *addr, *start; uint32_t num_reg, min_len; uint64_t remain_len; struct cam_hw_soc_info *soc_info; struct cam_fd_hw_dump_header *hdr; struct cam_fd_hw_dump_args *dump_args; if (!fd_hw || !args) { CAM_ERR(CAM_FD, "Invalid args %pK %pK", fd_hw, args); return -EINVAL; } mutex_lock(&fd_hw->hw_mutex); if (fd_hw->hw_state == CAM_HW_STATE_POWER_DOWN) { CAM_INFO(CAM_FD, "power off state"); mutex_unlock(&fd_hw->hw_mutex); return 0; } dump_args = (struct cam_fd_hw_dump_args *)args; soc_info = &fd_hw->soc_info; if (dump_args->buf_len <= dump_args->offset) { CAM_WARN(CAM_FD, "dump offset overshoot len %zu offset %zu", dump_args->buf_len, dump_args->offset); mutex_unlock(&fd_hw->hw_mutex); return -ENOSPC; } remain_len = dump_args->buf_len - dump_args->offset; min_len = sizeof(struct cam_fd_hw_dump_header) + soc_info->reg_map[0].size + sizeof(uint32_t); if (remain_len < min_len) { CAM_WARN(CAM_FD, "dump buffer exhaust remain %zu min %u", remain_len, min_len); mutex_unlock(&fd_hw->hw_mutex); return -ENOSPC; } dst = (uint8_t *)dump_args->cpu_addr + dump_args->offset; hdr = (struct cam_fd_hw_dump_header *)dst; scnprintf(hdr->tag, CAM_FD_HW_DUMP_TAG_MAX_LEN, "FD_REG:"); hdr->word_size = sizeof(uint32_t); addr = (uint32_t *)(dst + sizeof(struct cam_fd_hw_dump_header)); start = addr; *addr++ = soc_info->index; for (j = 0; j < soc_info->num_reg_map; j++) { num_reg = soc_info->reg_map[j].size/4; for (i = 0; i < num_reg; i++) { *addr++ = soc_info->mem_block[j]->start + i*4; *addr++ = cam_io_r(soc_info->reg_map[j].mem_base + (i*4)); } } mutex_unlock(&fd_hw->hw_mutex); hdr->size = hdr->word_size * (addr - start); dump_args->offset += hdr->size + sizeof(struct cam_fd_hw_dump_header); CAM_DBG(CAM_FD, "%zu", dump_args->offset); return 0; } irqreturn_t cam_fd_hw_irq(int irq_num, void *data) { struct cam_hw_info *fd_hw = (struct cam_hw_info *)data; Loading Loading @@ -1159,6 +1233,11 @@ int cam_fd_hw_process_cmd(void *hw_priv, uint32_t cmd_type, cmd_frame_results); break; } case CAM_FD_HW_CMD_HW_DUMP: { rc = cam_fd_hw_util_processcmd_hw_dump(fd_hw, cmd_args); break; } default: break; } Loading drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_intf.h +33 −1 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_FD_HW_INTF_H_ Loading @@ -24,6 +24,8 @@ #define CAM_FD_MAX_IO_BUFFERS 5 #define CAM_FD_MAX_HW_ENTRIES 5 #define CAM_FD_HW_DUMP_TAG_MAX_LEN 32 #define CAM_FD_HW_DUMP_NUM_WORDS 5 /** * enum cam_fd_hw_type - Enum for FD HW type Loading Loading @@ -81,12 +83,14 @@ enum cam_fd_hw_irq_type { * @CAM_FD_HW_CMD_UPDATE_SOC : Command to process soc update * @CAM_FD_HW_CMD_REGISTER_CALLBACK : Command to set hw mgr callback * @CAM_FD_HW_CMD_MAX : Indicates max cmd * @CAM_FD_HW_CMD_HW_DUMP : Command to dump fd hw information */ enum cam_fd_hw_cmd_type { CAM_FD_HW_CMD_PRESTART, CAM_FD_HW_CMD_FRAME_DONE, CAM_FD_HW_CMD_UPDATE_SOC, CAM_FD_HW_CMD_REGISTER_CALLBACK, CAM_FD_HW_CMD_HW_DUMP, CAM_FD_HW_CMD_MAX, }; Loading Loading @@ -279,4 +283,32 @@ struct cam_fd_hw_cmd_set_irq_cb { void *data; }; /** * struct cam_fd_hw_dump_args : Args for dump request * * @request_id : Issue request id * @offset : offset of the buffer * @buf_len : Length of target buffer * @cpu_addr : start address of the target buffer */ struct cam_fd_hw_dump_args { uint64_t request_id; size_t offset; size_t buf_len; uintptr_t cpu_addr; }; /** * struct cam_fd_hw_dump_header : fd hw dump header * * @tag : fd hw dump header tag * @size : Size of data * @word_size : size of each word */ struct cam_fd_hw_dump_header { uint8_t tag[CAM_FD_HW_DUMP_TAG_MAX_LEN]; uint64_t size; uint32_t word_size; }; #endif /* _CAM_FD_HW_INTF_H_ */ Loading
drivers/cam_fd/cam_fd_context.c +15 −1 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include <linux/module.h> Loading Loading @@ -117,6 +117,19 @@ static int __cam_fd_ctx_release_dev_in_activated(struct cam_context *ctx, return rc; } static int __cam_fd_ctx_dump_dev_in_activated( struct cam_context *ctx, struct cam_dump_req_cmd *cmd) { int rc; rc = cam_context_dump_dev_to_hw(ctx, cmd); if (rc) CAM_ERR(CAM_FD, "Failed to dump device, rc=%d", rc); return rc; } static int __cam_fd_ctx_flush_dev_in_activated(struct cam_context *ctx, struct cam_flush_dev_cmd *cmd) { Loading Loading @@ -198,6 +211,7 @@ static struct cam_ctx_ops .release_dev = __cam_fd_ctx_release_dev_in_activated, .config_dev = __cam_fd_ctx_config_dev_in_activated, .flush_dev = __cam_fd_ctx_flush_dev_in_activated, .dump_dev = __cam_fd_ctx_dump_dev_in_activated, }, .crm_ops = {}, .irq_ops = __cam_fd_ctx_handle_irq_in_activated, Loading
drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.c +134 −1 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include <linux/module.h> Loading Loading @@ -883,6 +883,7 @@ static int cam_fd_mgr_util_submit_frame(void *priv, void *data) hw_device->cur_hw_ctx = hw_ctx; hw_device->req_id = frame_req->request_id; mutex_unlock(&hw_device->lock); frame_req->submit_timestamp = ktime_get(); rc = cam_fd_mgr_util_put_frame_req( &hw_mgr->frame_processing_list, &frame_req); Loading Loading @@ -1504,6 +1505,137 @@ static int cam_fd_mgr_hw_flush(void *hw_mgr_priv, return rc; } static int cam_fd_mgr_hw_dump( void *hw_mgr_priv, void *hw_dump_args) { int rc; uint8_t *dst; ktime_t cur_time; size_t remain_len; uint32_t min_len; uint64_t diff; uint64_t *addr, *start; struct timespec64 cur_ts; struct timespec64 req_ts; struct cam_fd_hw_mgr *hw_mgr; struct cam_hw_dump_args *dump_args; struct cam_fd_hw_mgr_ctx *hw_ctx; struct cam_fd_device *hw_device; struct cam_fd_hw_dump_args fd_dump_args; struct cam_fd_hw_dump_header *hdr; struct cam_fd_mgr_frame_request *frame_req, *req_temp; hw_mgr = (struct cam_fd_hw_mgr *)hw_mgr_priv; dump_args = (struct cam_hw_dump_args *)hw_dump_args; if (!hw_mgr || !dump_args) { CAM_ERR(CAM_FD, "Invalid args %pK %pK", hw_mgr, dump_args); return -EINVAL; } hw_ctx = (struct cam_fd_hw_mgr_ctx *)dump_args->ctxt_to_hw_map; if (!hw_ctx) { CAM_ERR(CAM_FD, "Invalid ctx"); return -EINVAL; } rc = cam_fd_mgr_util_get_device(hw_mgr, hw_ctx, &hw_device); if (rc) { CAM_ERR(CAM_FD, "Error in getting device %d", rc); return rc; } list_for_each_entry_safe(frame_req, req_temp, &hw_mgr->frame_processing_list, list) { if (frame_req->request_id == dump_args->request_id) goto hw_dump; } CAM_DBG(CAM_FD, "fd dump cannot find req %llu", dump_args->request_id); return rc; hw_dump: cur_time = ktime_get(); diff = ktime_us_delta(frame_req->submit_timestamp, cur_time); cur_ts = ktime_to_timespec64(cur_time); req_ts = ktime_to_timespec64(frame_req->submit_timestamp); if (diff < CAM_FD_RESPONSE_TIME_THRESHOLD) { CAM_INFO(CAM_FD, "No Error req %lld %ld:%06ld %ld:%06ld", dump_args->request_id, req_ts.tv_sec, req_ts.tv_nsec/NSEC_PER_USEC, cur_ts.tv_sec, cur_ts.tv_nsec/NSEC_PER_USEC); return 0; } CAM_INFO(CAM_FD, "Error req %lld %ld:%06ld %ld:%06ld", dump_args->request_id, req_ts.tv_sec, req_ts.tv_nsec/NSEC_PER_USEC, cur_ts.tv_sec, cur_ts.tv_nsec/NSEC_PER_USEC); rc = cam_mem_get_cpu_buf(dump_args->buf_handle, &fd_dump_args.cpu_addr, &fd_dump_args.buf_len); if (rc) { CAM_ERR(CAM_FD, "Invalid handle %u rc %d", dump_args->buf_handle, rc); return rc; } if (fd_dump_args.buf_len <= dump_args->offset) { CAM_WARN(CAM_FD, "dump offset overshoot len %zu offset %zu", fd_dump_args.buf_len, dump_args->offset); return -ENOSPC; } remain_len = fd_dump_args.buf_len - dump_args->offset; min_len = sizeof(struct cam_fd_hw_dump_header) + (CAM_FD_HW_DUMP_NUM_WORDS * sizeof(uint64_t)); if (remain_len < min_len) { CAM_WARN(CAM_FD, "dump buffer exhaust remain %zu min %u", remain_len, min_len); return -ENOSPC; } dst = (uint8_t *)fd_dump_args.cpu_addr + dump_args->offset; hdr = (struct cam_fd_hw_dump_header *)dst; scnprintf(hdr->tag, CAM_FD_HW_DUMP_TAG_MAX_LEN, "FD_REQ:"); hdr->word_size = sizeof(uint64_t); addr = (uint64_t *)(dst + sizeof(struct cam_fd_hw_dump_header)); start = addr; *addr++ = frame_req->request_id; *addr++ = req_ts.tv_sec; *addr++ = req_ts.tv_nsec/NSEC_PER_USEC; *addr++ = cur_ts.tv_sec; *addr++ = cur_ts.tv_nsec/NSEC_PER_USEC; hdr->size = hdr->word_size * (addr - start); dump_args->offset += hdr->size + sizeof(struct cam_fd_hw_dump_header); fd_dump_args.request_id = dump_args->request_id; fd_dump_args.offset = dump_args->offset; if (hw_device->hw_intf->hw_ops.process_cmd) { rc = hw_device->hw_intf->hw_ops.process_cmd( hw_device->hw_intf->hw_priv, CAM_FD_HW_CMD_HW_DUMP, &fd_dump_args, sizeof(struct cam_fd_hw_dump_args)); if (rc) { CAM_ERR(CAM_FD, "Hw Dump cmd fails req %lld rc %d", frame_req->request_id, rc); return rc; } } CAM_DBG(CAM_FD, "Offset before %zu after %zu", dump_args->offset, fd_dump_args.offset); dump_args->offset = fd_dump_args.offset; return rc; } static int cam_fd_mgr_hw_stop(void *hw_mgr_priv, void *mgr_stop_args) { struct cam_fd_hw_mgr *hw_mgr = (struct cam_fd_hw_mgr *)hw_mgr_priv; Loading Loading @@ -1944,6 +2076,7 @@ int cam_fd_hw_mgr_init(struct device_node *of_node, hw_mgr_intf->hw_write = NULL; hw_mgr_intf->hw_close = NULL; hw_mgr_intf->hw_flush = cam_fd_mgr_hw_flush; hw_mgr_intf->hw_dump = cam_fd_mgr_hw_dump; return rc; Loading
drivers/cam_fd/fd_hw_mgr/cam_fd_hw_mgr.h +9 −1 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_FD_HW_MGR_H_ Loading @@ -21,6 +21,12 @@ #define CAM_FD_HW_MAX 1 #define CAM_FD_WORKQ_NUM_TASK 10 /* * Response time threshold in ms beyond which a request is not expected to be * with FD hw */ #define CAM_FD_RESPONSE_TIME_THRESHOLD 100000 struct cam_fd_hw_mgr; /** Loading Loading @@ -100,6 +106,7 @@ struct cam_fd_device { * @hw_update_entries : HW update entries corresponding to this request * which needs to be submitted to HW through CDM * @num_hw_update_entries : Number of HW update entries * @submit_timestamp : Time stamp for submit req with hw */ struct cam_fd_mgr_frame_request { struct list_head list; Loading @@ -108,6 +115,7 @@ struct cam_fd_mgr_frame_request { struct cam_fd_hw_req_private hw_req_private; struct cam_hw_update_entry hw_update_entries[CAM_FD_MAX_HW_ENTRIES]; uint32_t num_hw_update_entries; ktime_t submit_timestamp; }; /** Loading
drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_core.c +80 −1 Original line number Diff line number Diff line // SPDX-License-Identifier: GPL-2.0-only /* * Copyright (c) 2017-2019, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #include "cam_fd_hw_core.h" Loading Loading @@ -516,6 +516,80 @@ static int cam_fd_hw_util_processcmd_frame_done(struct cam_hw_info *fd_hw, return 0; } static int cam_fd_hw_util_processcmd_hw_dump( struct cam_hw_info *fd_hw, void *args) { int i, j; uint8_t *dst; uint32_t *addr, *start; uint32_t num_reg, min_len; uint64_t remain_len; struct cam_hw_soc_info *soc_info; struct cam_fd_hw_dump_header *hdr; struct cam_fd_hw_dump_args *dump_args; if (!fd_hw || !args) { CAM_ERR(CAM_FD, "Invalid args %pK %pK", fd_hw, args); return -EINVAL; } mutex_lock(&fd_hw->hw_mutex); if (fd_hw->hw_state == CAM_HW_STATE_POWER_DOWN) { CAM_INFO(CAM_FD, "power off state"); mutex_unlock(&fd_hw->hw_mutex); return 0; } dump_args = (struct cam_fd_hw_dump_args *)args; soc_info = &fd_hw->soc_info; if (dump_args->buf_len <= dump_args->offset) { CAM_WARN(CAM_FD, "dump offset overshoot len %zu offset %zu", dump_args->buf_len, dump_args->offset); mutex_unlock(&fd_hw->hw_mutex); return -ENOSPC; } remain_len = dump_args->buf_len - dump_args->offset; min_len = sizeof(struct cam_fd_hw_dump_header) + soc_info->reg_map[0].size + sizeof(uint32_t); if (remain_len < min_len) { CAM_WARN(CAM_FD, "dump buffer exhaust remain %zu min %u", remain_len, min_len); mutex_unlock(&fd_hw->hw_mutex); return -ENOSPC; } dst = (uint8_t *)dump_args->cpu_addr + dump_args->offset; hdr = (struct cam_fd_hw_dump_header *)dst; scnprintf(hdr->tag, CAM_FD_HW_DUMP_TAG_MAX_LEN, "FD_REG:"); hdr->word_size = sizeof(uint32_t); addr = (uint32_t *)(dst + sizeof(struct cam_fd_hw_dump_header)); start = addr; *addr++ = soc_info->index; for (j = 0; j < soc_info->num_reg_map; j++) { num_reg = soc_info->reg_map[j].size/4; for (i = 0; i < num_reg; i++) { *addr++ = soc_info->mem_block[j]->start + i*4; *addr++ = cam_io_r(soc_info->reg_map[j].mem_base + (i*4)); } } mutex_unlock(&fd_hw->hw_mutex); hdr->size = hdr->word_size * (addr - start); dump_args->offset += hdr->size + sizeof(struct cam_fd_hw_dump_header); CAM_DBG(CAM_FD, "%zu", dump_args->offset); return 0; } irqreturn_t cam_fd_hw_irq(int irq_num, void *data) { struct cam_hw_info *fd_hw = (struct cam_hw_info *)data; Loading Loading @@ -1159,6 +1233,11 @@ int cam_fd_hw_process_cmd(void *hw_priv, uint32_t cmd_type, cmd_frame_results); break; } case CAM_FD_HW_CMD_HW_DUMP: { rc = cam_fd_hw_util_processcmd_hw_dump(fd_hw, cmd_args); break; } default: break; } Loading
drivers/cam_fd/fd_hw_mgr/fd_hw/cam_fd_hw_intf.h +33 −1 Original line number Diff line number Diff line /* SPDX-License-Identifier: GPL-2.0-only */ /* * Copyright (c) 2017-2018, The Linux Foundation. All rights reserved. * Copyright (c) 2017-2020, The Linux Foundation. All rights reserved. */ #ifndef _CAM_FD_HW_INTF_H_ Loading @@ -24,6 +24,8 @@ #define CAM_FD_MAX_IO_BUFFERS 5 #define CAM_FD_MAX_HW_ENTRIES 5 #define CAM_FD_HW_DUMP_TAG_MAX_LEN 32 #define CAM_FD_HW_DUMP_NUM_WORDS 5 /** * enum cam_fd_hw_type - Enum for FD HW type Loading Loading @@ -81,12 +83,14 @@ enum cam_fd_hw_irq_type { * @CAM_FD_HW_CMD_UPDATE_SOC : Command to process soc update * @CAM_FD_HW_CMD_REGISTER_CALLBACK : Command to set hw mgr callback * @CAM_FD_HW_CMD_MAX : Indicates max cmd * @CAM_FD_HW_CMD_HW_DUMP : Command to dump fd hw information */ enum cam_fd_hw_cmd_type { CAM_FD_HW_CMD_PRESTART, CAM_FD_HW_CMD_FRAME_DONE, CAM_FD_HW_CMD_UPDATE_SOC, CAM_FD_HW_CMD_REGISTER_CALLBACK, CAM_FD_HW_CMD_HW_DUMP, CAM_FD_HW_CMD_MAX, }; Loading Loading @@ -279,4 +283,32 @@ struct cam_fd_hw_cmd_set_irq_cb { void *data; }; /** * struct cam_fd_hw_dump_args : Args for dump request * * @request_id : Issue request id * @offset : offset of the buffer * @buf_len : Length of target buffer * @cpu_addr : start address of the target buffer */ struct cam_fd_hw_dump_args { uint64_t request_id; size_t offset; size_t buf_len; uintptr_t cpu_addr; }; /** * struct cam_fd_hw_dump_header : fd hw dump header * * @tag : fd hw dump header tag * @size : Size of data * @word_size : size of each word */ struct cam_fd_hw_dump_header { uint8_t tag[CAM_FD_HW_DUMP_TAG_MAX_LEN]; uint64_t size; uint32_t word_size; }; #endif /* _CAM_FD_HW_INTF_H_ */