Merge "msm: camera: common: LDAR dump NRT devices information" into camera-kernel.lnx.4.0
Dieser Commit ist enthalten in:

committet von
Gerrit - the friendly Code Review server

Commit
23372b610f
@@ -1,6 +1,6 @@
|
||||
// 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>
|
||||
@@ -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)
|
||||
{
|
||||
@@ -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,
|
||||
|
@@ -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);
|
||||
@@ -1514,6 +1515,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;
|
||||
@@ -1954,6 +2086,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;
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/* 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_
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
@@ -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;
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@@ -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;
|
||||
@@ -1161,6 +1235,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;
|
||||
}
|
||||
|
@@ -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
|
||||
@@ -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,
|
||||
};
|
||||
|
||||
@@ -281,6 +285,34 @@ 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;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief : API to register FD Hw to platform framework.
|
||||
* @return struct platform_device pointer on on success, or ERR_PTR() on error.
|
||||
@@ -293,3 +325,4 @@ int cam_fd_hw_init_module(void);
|
||||
void cam_fd_hw_exit_module(void);
|
||||
|
||||
#endif /* _CAM_FD_HW_INTF_H_ */
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
// 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/debugfs.h>
|
||||
@@ -107,6 +107,19 @@ static int __cam_icp_start_dev_in_acquired(struct cam_context *ctx,
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int __cam_icp_dump_dev_in_ready(
|
||||
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_ICP, "Failed to dump device");
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int __cam_icp_flush_dev_in_ready(struct cam_context *ctx,
|
||||
struct cam_flush_dev_cmd *cmd)
|
||||
{
|
||||
@@ -230,6 +243,7 @@ static struct cam_ctx_ops
|
||||
.start_dev = __cam_icp_start_dev_in_acquired,
|
||||
.config_dev = __cam_icp_config_dev_in_ready,
|
||||
.flush_dev = __cam_icp_flush_dev_in_ready,
|
||||
.dump_dev = __cam_icp_dump_dev_in_ready,
|
||||
},
|
||||
.crm_ops = {},
|
||||
.irq_ops = __cam_icp_handle_buf_done_in_ready,
|
||||
@@ -242,6 +256,7 @@ static struct cam_ctx_ops
|
||||
.release_dev = __cam_icp_release_dev_in_ready,
|
||||
.config_dev = __cam_icp_config_dev_in_ready,
|
||||
.flush_dev = __cam_icp_flush_dev_in_ready,
|
||||
.dump_dev = __cam_icp_dump_dev_in_ready,
|
||||
},
|
||||
.crm_ops = {},
|
||||
.irq_ops = __cam_icp_handle_buf_done_in_ready,
|
||||
|
@@ -1,6 +1,6 @@
|
||||
// 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/slab.h>
|
||||
@@ -235,6 +235,53 @@ fw_download_failed:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_a5_fw_dump(
|
||||
struct cam_icp_hw_dump_args *dump_args,
|
||||
struct cam_a5_device_core_info *core_info)
|
||||
{
|
||||
u8 *dest;
|
||||
u8 *src;
|
||||
uint64_t size_required;
|
||||
struct cam_icp_dump_header *hdr;
|
||||
|
||||
if (!core_info || !dump_args) {
|
||||
CAM_ERR(CAM_ICP, "invalid params %pK %pK",
|
||||
core_info, dump_args);
|
||||
return -EINVAL;
|
||||
}
|
||||
if (!core_info->fw_kva_addr || !dump_args->cpu_addr) {
|
||||
CAM_ERR(CAM_ICP, "invalid params %pK, 0x%zx",
|
||||
core_info->fw_kva_addr, dump_args->cpu_addr);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
size_required = core_info->fw_buf_len +
|
||||
sizeof(struct cam_icp_dump_header);
|
||||
|
||||
if (dump_args->buf_len <= dump_args->offset) {
|
||||
CAM_WARN(CAM_ICP, "Dump offset overshoot len %zu offset %zu",
|
||||
dump_args->buf_len, dump_args->offset);
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
if ((dump_args->buf_len - dump_args->offset) < size_required) {
|
||||
CAM_WARN(CAM_ICP, "Dump buffer exhaust required %llu len %llu",
|
||||
size_required, core_info->fw_buf_len);
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
dest = (u8 *)dump_args->cpu_addr + dump_args->offset;
|
||||
hdr = (struct cam_icp_dump_header *)dest;
|
||||
scnprintf(hdr->tag, CAM_ICP_DUMP_TAG_MAX_LEN, "ICP_FW:");
|
||||
hdr->word_size = sizeof(u8);
|
||||
hdr->size = core_info->fw_buf_len;
|
||||
src = (u8 *)core_info->fw_kva_addr;
|
||||
dest = (u8 *)dest + sizeof(struct cam_icp_dump_header);
|
||||
memcpy_fromio(dest, src, core_info->fw_buf_len);
|
||||
dump_args->offset += hdr->size + sizeof(struct cam_icp_dump_header);
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cam_a5_init_hw(void *device_priv,
|
||||
void *init_hw_args, uint32_t arg_size)
|
||||
{
|
||||
@@ -543,6 +590,12 @@ int cam_a5_process_cmd(void *device_priv, uint32_t cmd_type,
|
||||
core_info->cpas_handle, &ahb_vote);
|
||||
break;
|
||||
}
|
||||
case CAM_ICP_A5_CMD_HW_DUMP: {
|
||||
struct cam_icp_hw_dump_args *dump_args = cmd_args;
|
||||
|
||||
rc = cam_a5_fw_dump(dump_args, core_info);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@@ -3930,6 +3930,7 @@ static int cam_icp_mgr_config_hw(void *hw_mgr_priv, void *config_hw_args)
|
||||
|
||||
cam_icp_mgr_ipe_bps_clk_update(hw_mgr, ctx_data, idx);
|
||||
ctx_data->hfi_frame_process.fw_process_flag[idx] = true;
|
||||
ctx_data->hfi_frame_process.submit_timestamp[idx] = ktime_get();
|
||||
|
||||
CAM_DBG(CAM_ICP, "req_id %llu, io config %llu", req_id,
|
||||
frame_info->io_config);
|
||||
@@ -5038,6 +5039,115 @@ static int cam_icp_mgr_enqueue_abort(
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cam_icp_mgr_hw_dump(void *hw_priv, void *hw_dump_args)
|
||||
{
|
||||
int rc;
|
||||
int i;
|
||||
size_t remain_len;
|
||||
uint8_t *dst;
|
||||
uint32_t min_len;
|
||||
uint64_t diff;
|
||||
uint64_t *addr, *start;
|
||||
struct timespec64 cur_ts;
|
||||
struct timespec64 req_ts;
|
||||
ktime_t cur_time;
|
||||
struct cam_hw_intf *a5_dev_intf;
|
||||
struct cam_icp_hw_mgr *hw_mgr;
|
||||
struct cam_hw_dump_args *dump_args;
|
||||
struct cam_icp_hw_ctx_data *ctx_data;
|
||||
struct cam_icp_dump_header *hdr;
|
||||
struct cam_icp_hw_dump_args icp_dump_args;
|
||||
struct hfi_frame_process_info *frm_process;
|
||||
|
||||
if ((!hw_priv) || (!hw_dump_args)) {
|
||||
CAM_ERR(CAM_ICP, "Invalid params %pK %pK",
|
||||
hw_priv, hw_dump_args);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dump_args = (struct cam_hw_dump_args *)hw_dump_args;
|
||||
hw_mgr = hw_priv;
|
||||
ctx_data = dump_args->ctxt_to_hw_map;
|
||||
CAM_DBG(CAM_ICP, "Req %lld", dump_args->request_id);
|
||||
frm_process = &ctx_data->hfi_frame_process;
|
||||
for (i = 0; i < CAM_FRAME_CMD_MAX; i++) {
|
||||
if ((frm_process->request_id[i] ==
|
||||
dump_args->request_id) &&
|
||||
frm_process->fw_process_flag[i])
|
||||
goto hw_dump;
|
||||
}
|
||||
return 0;
|
||||
hw_dump:
|
||||
cur_time = ktime_get();
|
||||
diff = ktime_us_delta(frm_process->submit_timestamp[i], cur_time);
|
||||
cur_ts = ktime_to_timespec64(cur_time);
|
||||
req_ts = ktime_to_timespec64(frm_process->submit_timestamp[i]);
|
||||
|
||||
if (diff < CAM_ICP_CTX_RESPONSE_TIME_THRESHOLD) {
|
||||
CAM_INFO(CAM_ICP, "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_ICP, "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,
|
||||
&icp_dump_args.cpu_addr, &icp_dump_args.buf_len);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_ICP, "Invalid addr %u rc %d",
|
||||
dump_args->buf_handle, rc);
|
||||
return rc;
|
||||
}
|
||||
if (icp_dump_args.buf_len <= dump_args->offset) {
|
||||
CAM_WARN(CAM_ICP, "dump buffer overshoot len %zu offset %zu",
|
||||
icp_dump_args.buf_len, dump_args->offset);
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
remain_len = icp_dump_args.buf_len - dump_args->offset;
|
||||
min_len = sizeof(struct cam_icp_dump_header) +
|
||||
(CAM_ICP_DUMP_NUM_WORDS * sizeof(uint64_t));
|
||||
|
||||
if (remain_len < min_len) {
|
||||
CAM_WARN(CAM_ICP, "dump buffer exhaust remain %zu min %u",
|
||||
remain_len, min_len);
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
dst = (uint8_t *)icp_dump_args.cpu_addr + dump_args->offset;
|
||||
hdr = (struct cam_icp_dump_header *)dst;
|
||||
scnprintf(hdr->tag, CAM_ICP_DUMP_TAG_MAX_LEN, "ICP_REQ:");
|
||||
hdr->word_size = sizeof(uint64_t);
|
||||
addr = (uint64_t *)(dst + sizeof(struct cam_icp_dump_header));
|
||||
start = addr;
|
||||
*addr++ = frm_process->request_id[i];
|
||||
*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_icp_dump_header));
|
||||
/* Dumping the fw image*/
|
||||
icp_dump_args.offset = dump_args->offset;
|
||||
a5_dev_intf = hw_mgr->a5_dev_intf;
|
||||
rc = a5_dev_intf->hw_ops.process_cmd(
|
||||
a5_dev_intf->hw_priv,
|
||||
CAM_ICP_A5_CMD_HW_DUMP, &icp_dump_args,
|
||||
sizeof(struct cam_icp_hw_dump_args));
|
||||
CAM_DBG(CAM_ICP, "Offset before %zu after %zu",
|
||||
dump_args->offset, icp_dump_args.offset);
|
||||
dump_args->offset = icp_dump_args.offset;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_icp_mgr_hw_flush(void *hw_priv, void *hw_flush_args)
|
||||
{
|
||||
struct cam_hw_flush_args *flush_args = hw_flush_args;
|
||||
@@ -5850,6 +5960,7 @@ int cam_icp_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl,
|
||||
hw_mgr_intf->hw_close = cam_icp_mgr_hw_close_u;
|
||||
hw_mgr_intf->hw_flush = cam_icp_mgr_hw_flush;
|
||||
hw_mgr_intf->hw_cmd = cam_icp_mgr_cmd;
|
||||
hw_mgr_intf->hw_dump = cam_icp_mgr_hw_dump;
|
||||
|
||||
icp_hw_mgr.secure_mode = CAM_SECURE_MODE_NON_SECURE;
|
||||
mutex_init(&icp_hw_mgr.hw_mgr_mutex);
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
#ifndef CAM_ICP_HW_MGR_H
|
||||
@@ -67,6 +67,12 @@
|
||||
/* Current appliacble vote paths, based on number of UAPI definitions */
|
||||
#define CAM_ICP_MAX_PER_PATH_VOTES 6
|
||||
|
||||
/*
|
||||
* Response time threshold in ms beyond which a request is not expected
|
||||
* to be with ICP hw
|
||||
*/
|
||||
#define CAM_ICP_CTX_RESPONSE_TIME_THRESHOLD 300000
|
||||
|
||||
/**
|
||||
* struct icp_hfi_mem_info
|
||||
* @qtbl: Memory info of queue table
|
||||
@@ -171,6 +177,7 @@ struct cam_icp_clk_bw_req_internal_v2 {
|
||||
* @clk_info: Clock information for a request
|
||||
* @clk_info_v2: Clock info for AXI bw voting v2
|
||||
* @frame_info: information needed to process request
|
||||
* @submit_timestamp: Submit timestamp to hw
|
||||
*/
|
||||
struct hfi_frame_process_info {
|
||||
struct hfi_cmd_ipebps_async hfi_frame_cmd[CAM_FRAME_CMD_MAX];
|
||||
@@ -186,6 +193,7 @@ struct hfi_frame_process_info {
|
||||
struct cam_icp_clk_bw_request clk_info[CAM_FRAME_CMD_MAX];
|
||||
struct cam_icp_clk_bw_req_internal_v2 clk_info_v2[CAM_FRAME_CMD_MAX];
|
||||
struct icp_frame_info frame_info[CAM_FRAME_CMD_MAX];
|
||||
ktime_t submit_timestamp[CAM_FRAME_CMD_MAX];
|
||||
};
|
||||
|
||||
/**
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
#ifndef CAM_A5_HW_INTF_H
|
||||
@@ -27,6 +27,7 @@ enum cam_icp_a5_cmd_type {
|
||||
CAM_ICP_A5_CMD_UBWC_CFG,
|
||||
CAM_ICP_A5_CMD_PC_PREP,
|
||||
CAM_ICP_A5_CMD_CLK_UPDATE,
|
||||
CAM_ICP_A5_CMD_HW_DUMP,
|
||||
CAM_ICP_A5_CMD_MAX,
|
||||
};
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
#ifndef CAM_ICP_HW_MGR_INTF_H
|
||||
@@ -27,6 +27,9 @@
|
||||
#define CAM_ICP_DEFAULT_AXI_PATH CAM_AXI_PATH_DATA_ALL
|
||||
#define CAM_ICP_DEFAULT_AXI_TRANSAC CAM_AXI_TRANSACTION_READ
|
||||
|
||||
#define CAM_ICP_DUMP_TAG_MAX_LEN 32
|
||||
#define CAM_ICP_DUMP_NUM_WORDS 5
|
||||
|
||||
int cam_icp_hw_mgr_init(struct device_node *of_node,
|
||||
uint64_t *hw_mgr_hdl, int *iommu_hdl);
|
||||
|
||||
@@ -44,4 +47,28 @@ struct cam_icp_cpas_vote {
|
||||
uint32_t axi_vote_valid;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_icp_hw_dump_args
|
||||
* @cpu_addr: kernel vaddr
|
||||
* @buf_len: buffer length
|
||||
* @offset: offset
|
||||
*/
|
||||
struct cam_icp_hw_dump_args {
|
||||
uintptr_t cpu_addr;
|
||||
size_t buf_len;
|
||||
size_t offset;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_icp_dump_header
|
||||
* @tag: tag of the packet
|
||||
* @size: size of data in packet
|
||||
* @word_size: size of each word in packet
|
||||
*/
|
||||
struct cam_icp_dump_header {
|
||||
uint8_t tag[CAM_ICP_DUMP_TAG_MAX_LEN];
|
||||
uint64_t size;
|
||||
int32_t word_size;
|
||||
};
|
||||
|
||||
#endif /* CAM_ICP_HW_MGR_INTF_H */
|
||||
|
@@ -1,6 +1,6 @@
|
||||
// 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/debugfs.h>
|
||||
@@ -83,6 +83,19 @@ static int __cam_jpeg_ctx_release_dev_in_acquired(struct cam_context *ctx,
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int __cam_jpeg_ctx_dump_dev_in_acquired(
|
||||
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_JPEG, "Failed to dump device, rc=%d", rc);
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int __cam_jpeg_ctx_flush_dev_in_acquired(struct cam_context *ctx,
|
||||
struct cam_flush_dev_cmd *cmd)
|
||||
{
|
||||
@@ -145,6 +158,7 @@ static struct cam_ctx_ops
|
||||
.config_dev = __cam_jpeg_ctx_config_dev_in_acquired,
|
||||
.stop_dev = __cam_jpeg_ctx_stop_dev_in_acquired,
|
||||
.flush_dev = __cam_jpeg_ctx_flush_dev_in_acquired,
|
||||
.dump_dev = __cam_jpeg_ctx_dump_dev_in_acquired,
|
||||
},
|
||||
.crm_ops = { },
|
||||
.irq_ops = __cam_jpeg_ctx_handle_buf_done_in_acquired,
|
||||
|
@@ -488,6 +488,7 @@ static int cam_jpeg_mgr_process_cmd(void *priv, void *data)
|
||||
rc);
|
||||
goto end_callcb;
|
||||
}
|
||||
p_cfg_req->submit_timestamp = ktime_get();
|
||||
|
||||
mutex_unlock(&hw_mgr->hw_mgr_mutex);
|
||||
return rc;
|
||||
@@ -1491,6 +1492,143 @@ num_dev_failed:
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_jpeg_mgr_hw_dump(void *hw_mgr_priv, void *dump_hw_args)
|
||||
{
|
||||
int rc;
|
||||
uint8_t *dst;
|
||||
ktime_t cur_time;
|
||||
size_t remain_len;
|
||||
uint32_t min_len;
|
||||
uint32_t dev_type;
|
||||
uint64_t diff;
|
||||
uint64_t *addr, *start;
|
||||
struct timespec64 cur_ts;
|
||||
struct timespec64 req_ts;
|
||||
struct cam_jpeg_hw_mgr *hw_mgr;
|
||||
struct cam_hw_dump_args *dump_args;
|
||||
struct cam_jpeg_hw_cfg_req *p_cfg_req;
|
||||
struct cam_jpeg_hw_ctx_data *ctx_data;
|
||||
struct cam_jpeg_hw_dump_args jpeg_dump_args;
|
||||
struct cam_jpeg_hw_dump_header *hdr;
|
||||
|
||||
if (!hw_mgr_priv || !dump_hw_args) {
|
||||
CAM_ERR(CAM_JPEG, "Invalid args %pK %pK",
|
||||
hw_mgr_priv, dump_hw_args);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
hw_mgr = hw_mgr_priv;
|
||||
dump_args = (struct cam_hw_dump_args *)dump_hw_args;
|
||||
ctx_data = (struct cam_jpeg_hw_ctx_data *)dump_args->ctxt_to_hw_map;
|
||||
|
||||
if (!ctx_data) {
|
||||
CAM_ERR(CAM_JPEG, "Invalid context");
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
mutex_lock(&hw_mgr->hw_mgr_mutex);
|
||||
|
||||
if (!ctx_data->in_use) {
|
||||
CAM_ERR(CAM_JPEG, "ctx is not in use");
|
||||
mutex_unlock(&hw_mgr->hw_mgr_mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
dev_type = ctx_data->jpeg_dev_acquire_info.dev_type;
|
||||
|
||||
if (true == hw_mgr->device_in_use[dev_type][0]) {
|
||||
p_cfg_req = hw_mgr->dev_hw_cfg_args[dev_type][0];
|
||||
if (p_cfg_req && p_cfg_req->req_id ==
|
||||
(uintptr_t)dump_args->request_id)
|
||||
goto hw_dump;
|
||||
}
|
||||
|
||||
mutex_unlock(&hw_mgr->hw_mgr_mutex);
|
||||
return 0;
|
||||
|
||||
hw_dump:
|
||||
cur_time = ktime_get();
|
||||
diff = ktime_us_delta(p_cfg_req->submit_timestamp, cur_time);
|
||||
cur_ts = ktime_to_timespec64(cur_time);
|
||||
req_ts = ktime_to_timespec64(p_cfg_req->submit_timestamp);
|
||||
|
||||
if (diff < CAM_JPEG_RESPONSE_TIME_THRESHOLD) {
|
||||
CAM_INFO(CAM_JPEG,
|
||||
"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);
|
||||
mutex_unlock(&hw_mgr->hw_mgr_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
CAM_INFO(CAM_JPEG,
|
||||
"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,
|
||||
&jpeg_dump_args.cpu_addr, &jpeg_dump_args.buf_len);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_JPEG, "Invalid handle %u rc %d",
|
||||
dump_args->buf_handle, rc);
|
||||
mutex_unlock(&hw_mgr->hw_mgr_mutex);
|
||||
return -rc;
|
||||
}
|
||||
|
||||
if (jpeg_dump_args.buf_len <= dump_args->offset) {
|
||||
CAM_WARN(CAM_JPEG, "dump offset overshoot len %zu offset %zu",
|
||||
jpeg_dump_args.buf_len, dump_args->offset);
|
||||
mutex_unlock(&hw_mgr->hw_mgr_mutex);
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
remain_len = jpeg_dump_args.buf_len - dump_args->offset;
|
||||
min_len = sizeof(struct cam_jpeg_hw_dump_header) +
|
||||
(CAM_JPEG_HW_DUMP_NUM_WORDS * sizeof(uint64_t));
|
||||
if (remain_len < min_len) {
|
||||
CAM_WARN(CAM_JPEG, "dump buffer exhaust remain %zu min %u",
|
||||
remain_len, min_len);
|
||||
mutex_unlock(&hw_mgr->hw_mgr_mutex);
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
dst = (uint8_t *)jpeg_dump_args.cpu_addr + dump_args->offset;
|
||||
hdr = (struct cam_jpeg_hw_dump_header *)dst;
|
||||
scnprintf(hdr->tag, CAM_JPEG_HW_DUMP_TAG_MAX_LEN,
|
||||
"JPEG_REQ:");
|
||||
hdr->word_size = sizeof(uint64_t);
|
||||
addr = (uint64_t *)(dst + sizeof(struct cam_jpeg_hw_dump_header));
|
||||
start = addr;
|
||||
*addr++ = dump_args->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_jpeg_hw_dump_header);
|
||||
jpeg_dump_args.request_id = dump_args->request_id;
|
||||
jpeg_dump_args.offset = dump_args->offset;
|
||||
|
||||
if (hw_mgr->devices[dev_type][0]->hw_ops.process_cmd) {
|
||||
rc = hw_mgr->devices[dev_type][0]->hw_ops.process_cmd(
|
||||
hw_mgr->devices[dev_type][0]->hw_priv,
|
||||
CAM_JPEG_CMD_HW_DUMP,
|
||||
&jpeg_dump_args, sizeof(jpeg_dump_args));
|
||||
}
|
||||
|
||||
mutex_unlock(&hw_mgr->hw_mgr_mutex);
|
||||
CAM_DBG(CAM_JPEG, "Offset before %u after %u",
|
||||
dump_args->offset, jpeg_dump_args.offset);
|
||||
dump_args->offset = jpeg_dump_args.offset;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_jpeg_mgr_cmd(void *hw_mgr_priv, void *cmd_args)
|
||||
{
|
||||
int rc = 0;
|
||||
@@ -1544,6 +1682,7 @@ int cam_jpeg_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl,
|
||||
hw_mgr_intf->hw_flush = cam_jpeg_mgr_hw_flush;
|
||||
hw_mgr_intf->hw_stop = cam_jpeg_mgr_hw_stop;
|
||||
hw_mgr_intf->hw_cmd = cam_jpeg_mgr_cmd;
|
||||
hw_mgr_intf->hw_dump = cam_jpeg_mgr_hw_dump;
|
||||
|
||||
mutex_init(&g_jpeg_hw_mgr.hw_mgr_mutex);
|
||||
spin_lock_init(&g_jpeg_hw_mgr.hw_mgr_lock);
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/* 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_JPEG_HW_MGR_H
|
||||
@@ -21,6 +21,12 @@
|
||||
#define CAM_JPEG_WORKQ_TASK_MSG_TYPE 2
|
||||
#define CAM_JPEG_HW_CFG_Q_MAX 50
|
||||
|
||||
/*
|
||||
* Response time threshold in ms beyond which a request is not expected
|
||||
* to be with JPEG hw
|
||||
*/
|
||||
#define CAM_JPEG_RESPONSE_TIME_THRESHOLD 100000
|
||||
|
||||
/**
|
||||
* struct cam_jpeg_process_frame_work_data_t
|
||||
*
|
||||
@@ -69,12 +75,14 @@ struct cam_jpeg_hw_cdm_info_t {
|
||||
* @hw_cfg_args: Hw config args
|
||||
* @dev_type: Dev type for cfg request
|
||||
* @req_id: Request Id
|
||||
* @submit_timestamp: Timestamp of submitting request
|
||||
*/
|
||||
struct cam_jpeg_hw_cfg_req {
|
||||
struct list_head list;
|
||||
struct cam_hw_config_args hw_cfg_args;
|
||||
uint32_t dev_type;
|
||||
uintptr_t req_id;
|
||||
ktime_t submit_timestamp;
|
||||
};
|
||||
|
||||
/**
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
#ifndef CAM_JPEG_HW_INTF_H
|
||||
@@ -15,6 +15,9 @@
|
||||
|
||||
#define JPEG_VOTE 640000000
|
||||
|
||||
#define CAM_JPEG_HW_DUMP_TAG_MAX_LEN 32
|
||||
#define CAM_JPEG_HW_DUMP_NUM_WORDS 5
|
||||
|
||||
enum cam_jpeg_hw_type {
|
||||
CAM_JPEG_DEV_ENC,
|
||||
CAM_JPEG_DEV_DMA,
|
||||
@@ -27,9 +30,23 @@ struct cam_jpeg_set_irq_cb {
|
||||
uint32_t b_set_cb;
|
||||
};
|
||||
|
||||
struct cam_jpeg_hw_dump_args {
|
||||
uint64_t request_id;
|
||||
uintptr_t cpu_addr;
|
||||
size_t offset;
|
||||
size_t buf_len;
|
||||
};
|
||||
|
||||
struct cam_jpeg_hw_dump_header {
|
||||
uint8_t tag[CAM_JPEG_HW_DUMP_TAG_MAX_LEN];
|
||||
uint64_t size;
|
||||
uint32_t word_size;
|
||||
};
|
||||
|
||||
enum cam_jpeg_cmd_type {
|
||||
CAM_JPEG_CMD_CDM_CFG,
|
||||
CAM_JPEG_CMD_SET_IRQ_CB,
|
||||
CAM_JPEG_CMD_HW_DUMP,
|
||||
CAM_JPEG_CMD_MAX,
|
||||
};
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
#ifndef CAM_JPEG_ENC_HW_INFO_TITAN170_H
|
||||
@@ -66,6 +66,10 @@ static struct cam_jpeg_enc_device_hw_info cam_jpeg_enc_hw_info = {
|
||||
.resetdone = CAM_JPEG_HW_MASK_COMP_RESET_ACK,
|
||||
.iserror = CAM_JPEG_HW_MASK_COMP_ERR,
|
||||
.stopdone = CAM_JPEG_HW_IRQ_STATUS_STOP_DONE_MASK,
|
||||
},
|
||||
.reg_dump = {
|
||||
.start_offset = 0x0,
|
||||
.end_offset = 0x33C,
|
||||
}
|
||||
};
|
||||
|
||||
|
@@ -1,6 +1,6 @@
|
||||
// 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/of.h>
|
||||
@@ -378,6 +378,81 @@ int cam_jpeg_enc_stop_hw(void *data,
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cam_jpeg_enc_hw_dump(
|
||||
struct cam_hw_info *jpeg_enc_dev,
|
||||
struct cam_jpeg_hw_dump_args *dump_args)
|
||||
{
|
||||
|
||||
int i;
|
||||
uint8_t *dst;
|
||||
uint32_t *addr, *start;
|
||||
uint32_t num_reg, min_len;
|
||||
uint32_t reg_start_offset;
|
||||
size_t remain_len;
|
||||
struct cam_hw_soc_info *soc_info;
|
||||
struct cam_jpeg_hw_dump_header *hdr;
|
||||
struct cam_jpeg_enc_device_hw_info *hw_info;
|
||||
struct cam_jpeg_enc_device_core_info *core_info;
|
||||
|
||||
soc_info = &jpeg_enc_dev->soc_info;
|
||||
core_info = (struct cam_jpeg_enc_device_core_info *)
|
||||
jpeg_enc_dev->core_info;
|
||||
hw_info = core_info->jpeg_enc_hw_info;
|
||||
mutex_lock(&core_info->core_mutex);
|
||||
spin_lock(&jpeg_enc_dev->hw_lock);
|
||||
|
||||
if (jpeg_enc_dev->hw_state == CAM_HW_STATE_POWER_DOWN) {
|
||||
CAM_ERR(CAM_JPEG, "JPEG HW is in off state");
|
||||
spin_unlock(&jpeg_enc_dev->hw_lock);
|
||||
mutex_unlock(&core_info->core_mutex);
|
||||
return -EINVAL;
|
||||
}
|
||||
|
||||
spin_unlock(&jpeg_enc_dev->hw_lock);
|
||||
|
||||
if (dump_args->buf_len <= dump_args->offset) {
|
||||
CAM_WARN(CAM_JPEG, "dump buffer overshoot %zu %zu",
|
||||
dump_args->buf_len, dump_args->offset);
|
||||
mutex_unlock(&core_info->core_mutex);
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
remain_len = dump_args->buf_len - dump_args->offset;
|
||||
min_len = sizeof(struct cam_jpeg_hw_dump_header) +
|
||||
soc_info->reg_map[0].size + sizeof(uint32_t);
|
||||
if (remain_len < min_len) {
|
||||
CAM_WARN(CAM_JPEG, "dump buffer exhaust %zu %u",
|
||||
remain_len, min_len);
|
||||
mutex_unlock(&core_info->core_mutex);
|
||||
return -ENOSPC;
|
||||
}
|
||||
|
||||
dst = (uint8_t *)dump_args->cpu_addr + dump_args->offset;
|
||||
hdr = (struct cam_jpeg_hw_dump_header *)dst;
|
||||
snprintf(hdr->tag, CAM_JPEG_HW_DUMP_TAG_MAX_LEN,
|
||||
"JPEG_REG:");
|
||||
hdr->word_size = sizeof(uint32_t);
|
||||
addr = (uint32_t *)(dst + sizeof(struct cam_jpeg_hw_dump_header));
|
||||
start = addr;
|
||||
*addr++ = soc_info->index;
|
||||
num_reg = (hw_info->reg_dump.end_offset -
|
||||
hw_info->reg_dump.start_offset)/4;
|
||||
reg_start_offset = hw_info->reg_dump.start_offset;
|
||||
for (i = 0; i < num_reg; i++) {
|
||||
*addr++ = soc_info->mem_block[0]->start +
|
||||
reg_start_offset + i*4;
|
||||
*addr++ = cam_io_r(soc_info->reg_map[0].mem_base + (i*4));
|
||||
}
|
||||
|
||||
mutex_unlock(&core_info->core_mutex);
|
||||
hdr->size = hdr->word_size * (addr - start);
|
||||
dump_args->offset += hdr->size +
|
||||
sizeof(struct cam_jpeg_hw_dump_header);
|
||||
CAM_DBG(CAM_JPEG, "offset %zu", dump_args->offset);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int cam_jpeg_enc_process_cmd(void *device_priv, uint32_t cmd_type,
|
||||
void *cmd_args, uint32_t arg_size)
|
||||
{
|
||||
@@ -418,6 +493,12 @@ int cam_jpeg_enc_process_cmd(void *device_priv, uint32_t cmd_type,
|
||||
rc = 0;
|
||||
break;
|
||||
}
|
||||
case CAM_JPEG_CMD_HW_DUMP:
|
||||
{
|
||||
rc = cam_jpeg_enc_hw_dump(jpeg_enc_dev,
|
||||
cmd_args);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
rc = -EINVAL;
|
||||
break;
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
#ifndef CAM_JPEG_ENC_CORE_H
|
||||
@@ -39,10 +39,16 @@ struct cam_jpeg_enc_int_status {
|
||||
uint32_t stopdone;
|
||||
};
|
||||
|
||||
struct cam_jpeg_enc_reg_dump {
|
||||
uint32_t start_offset;
|
||||
uint32_t end_offset;
|
||||
};
|
||||
|
||||
struct cam_jpeg_enc_device_hw_info {
|
||||
struct cam_jpeg_enc_reg_offsets reg_offset;
|
||||
struct cam_jpeg_enc_regval reg_val;
|
||||
struct cam_jpeg_enc_int_status int_status;
|
||||
struct cam_jpeg_enc_reg_dump reg_dump;
|
||||
};
|
||||
|
||||
enum cam_jpeg_enc_core_state {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
// 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>
|
||||
@@ -86,6 +86,21 @@ static int __cam_lrme_ctx_config_dev_in_activated(struct cam_context *ctx,
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int __cam_lrme_ctx_dump_dev_in_activated(
|
||||
struct cam_context *ctx,
|
||||
struct cam_dump_req_cmd *cmd)
|
||||
{
|
||||
int rc = 0;
|
||||
|
||||
CAM_DBG(CAM_LRME, "Enter ctx %d", ctx->ctx_id);
|
||||
|
||||
rc = cam_context_dump_dev_to_hw(ctx, cmd);
|
||||
if (rc)
|
||||
CAM_ERR(CAM_LRME, "Failed to dump device");
|
||||
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int __cam_lrme_ctx_flush_dev_in_activated(struct cam_context *ctx,
|
||||
struct cam_flush_dev_cmd *cmd)
|
||||
{
|
||||
@@ -199,6 +214,7 @@ static struct cam_ctx_ops
|
||||
.release_dev = __cam_lrme_ctx_release_dev_in_activated,
|
||||
.stop_dev = __cam_lrme_ctx_stop_dev_in_activated,
|
||||
.flush_dev = __cam_lrme_ctx_flush_dev_in_activated,
|
||||
.dump_dev = __cam_lrme_ctx_dump_dev_in_activated,
|
||||
},
|
||||
.crm_ops = {},
|
||||
.irq_ops = __cam_lrme_ctx_handle_irq_in_activated,
|
||||
|
@@ -1,6 +1,6 @@
|
||||
// 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>
|
||||
@@ -649,6 +649,50 @@ static int cam_lrme_mgr_hw_release(void *hw_mgr_priv, void *hw_release_args)
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_lrme_mgr_hw_dump(void *hw_mgr_priv, void *hw_dump_args)
|
||||
{
|
||||
struct cam_hw_dump_args *dump_args = hw_dump_args;
|
||||
struct cam_lrme_hw_mgr *hw_mgr = hw_mgr_priv;
|
||||
struct cam_lrme_device *hw_device;
|
||||
int rc = 0;
|
||||
uint32_t device_index;
|
||||
struct cam_lrme_hw_dump_args lrme_dump_args;
|
||||
|
||||
device_index = CAM_LRME_DECODE_DEVICE_INDEX(dump_args->ctxt_to_hw_map);
|
||||
if (device_index >= hw_mgr->device_count) {
|
||||
CAM_ERR(CAM_LRME, "Invalid device index %d", device_index);
|
||||
return -EPERM;
|
||||
}
|
||||
|
||||
CAM_DBG(CAM_LRME, "Start device index %d", device_index);
|
||||
|
||||
rc = cam_lrme_mgr_util_get_device(hw_mgr, device_index, &hw_device);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_LRME, "Failed to get hw device");
|
||||
return rc;
|
||||
}
|
||||
rc = cam_mem_get_cpu_buf(dump_args->buf_handle,
|
||||
&lrme_dump_args.cpu_addr,
|
||||
&lrme_dump_args.buf_len);
|
||||
if (rc) {
|
||||
CAM_ERR(CAM_LRME, "Invalid handle %u rc %d",
|
||||
dump_args->buf_handle, rc);
|
||||
return rc;
|
||||
}
|
||||
lrme_dump_args.offset = dump_args->offset;
|
||||
lrme_dump_args.request_id = dump_args->request_id;
|
||||
|
||||
rc = hw_device->hw_intf.hw_ops.process_cmd(
|
||||
hw_device->hw_intf.hw_priv,
|
||||
CAM_LRME_HW_CMD_DUMP,
|
||||
&lrme_dump_args,
|
||||
sizeof(struct cam_lrme_hw_dump_args));
|
||||
CAM_DBG(CAM_LRME, "Offset before %zu after %zu",
|
||||
dump_args->offset, lrme_dump_args.offset);
|
||||
dump_args->offset = lrme_dump_args.offset;
|
||||
return rc;
|
||||
}
|
||||
|
||||
static int cam_lrme_mgr_hw_flush(void *hw_mgr_priv, void *hw_flush_args)
|
||||
{ int rc = 0, i;
|
||||
struct cam_lrme_hw_mgr *hw_mgr = hw_mgr_priv;
|
||||
@@ -1147,6 +1191,7 @@ int cam_lrme_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf,
|
||||
hw_mgr_intf->hw_flush = cam_lrme_mgr_hw_flush;
|
||||
|
||||
g_lrme_hw_mgr.event_cb = cam_lrme_dev_buf_done_cb;
|
||||
hw_mgr_intf->hw_dump = cam_lrme_mgr_hw_dump;
|
||||
|
||||
cam_lrme_mgr_create_debugfs_entry();
|
||||
|
||||
|
@@ -3,6 +3,7 @@
|
||||
* Copyright (c) 2017-2020, The Linux Foundation. All rights reserved.
|
||||
*/
|
||||
|
||||
#include <linux/timer.h>
|
||||
#include "cam_lrme_hw_core.h"
|
||||
#include "cam_lrme_hw_soc.h"
|
||||
#include "cam_smmu_api.h"
|
||||
@@ -21,6 +22,159 @@ static void cam_lrme_dump_registers(void __iomem *base)
|
||||
cam_io_dump(base, 0x900, (0x928 - 0x900) / 0x4);
|
||||
}
|
||||
|
||||
static int cam_lrme_dump_regs_to_buf(
|
||||
struct cam_lrme_frame_request *req,
|
||||
struct cam_hw_info *lrme_hw,
|
||||
struct cam_lrme_hw_dump_args *dump_args)
|
||||
{
|
||||
int i;
|
||||
uint8_t *dst;
|
||||
uint32_t *addr, *start;
|
||||
uint32_t num_reg, min_len;
|
||||
size_t remain_len;
|
||||
struct cam_hw_soc_info *soc_info;
|
||||
struct cam_lrme_hw_dump_header *hdr;
|
||||
|
||||
if (!lrme_hw || !req || !dump_args) {
|
||||
CAM_ERR(CAM_LRME, "Invalid params %pK, %pK, %pK",
|
||||
lrme_hw, req, dump_args);
|
||||
return -EINVAL;
|
||||
}
|
||||
soc_info = &lrme_hw->soc_info;
|
||||
if (dump_args->buf_len <= dump_args->offset) {
|
||||
CAM_WARN(CAM_LRME, "dump buffer overshoot len %zu offset %zu",
|
||||
dump_args->buf_len, dump_args->offset);
|
||||
return -ENOSPC;
|
||||
}
|
||||
remain_len = dump_args->buf_len - dump_args->offset;
|
||||
min_len = sizeof(struct cam_lrme_hw_dump_header) +
|
||||
soc_info->reg_map[0].size + sizeof(uint32_t);
|
||||
|
||||
if (remain_len < min_len) {
|
||||
CAM_WARN(CAM_LRME, "dump buffer exhaust remain %zu min %u",
|
||||
remain_len, min_len);
|
||||
return -ENOSPC;
|
||||
}
|
||||
dst = (uint8_t *)dump_args->cpu_addr + dump_args->offset;
|
||||
hdr = (struct cam_lrme_hw_dump_header *)dst;
|
||||
scnprintf(hdr->tag, CAM_LRME_HW_DUMP_TAG_MAX_LEN,
|
||||
"LRME_REG:");
|
||||
hdr->word_size = sizeof(uint32_t);
|
||||
addr = (uint32_t *)(dst + sizeof(struct cam_lrme_hw_dump_header));
|
||||
start = addr;
|
||||
*addr++ = soc_info->index;
|
||||
num_reg = soc_info->reg_map[0].size/4;
|
||||
for (i = 0; i < num_reg; i++) {
|
||||
*addr++ = soc_info->mem_block[0]->start + (i*4);
|
||||
*addr++ = cam_io_r(soc_info->reg_map[0].mem_base + (i*4));
|
||||
}
|
||||
hdr->size = hdr->word_size * (addr - start);
|
||||
dump_args->offset += hdr->size +
|
||||
sizeof(struct cam_lrme_hw_dump_header);
|
||||
CAM_DBG(CAM_LRME, "offset %zu", dump_args->offset);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int cam_lrme_hw_dump(
|
||||
struct cam_hw_info *lrme_hw,
|
||||
struct cam_lrme_hw_dump_args *dump_args)
|
||||
{
|
||||
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_lrme_core *lrme_core;
|
||||
struct cam_lrme_frame_request *req = NULL;
|
||||
struct cam_lrme_hw_dump_header *hdr;
|
||||
|
||||
mutex_lock(&lrme_hw->hw_mutex);
|
||||
if (lrme_hw->hw_state == CAM_HW_STATE_POWER_DOWN) {
|
||||
CAM_DBG(CAM_LRME, "LRME HW is in off state");
|
||||
mutex_unlock(&lrme_hw->hw_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
lrme_core = (struct cam_lrme_core *)lrme_hw->core_info;
|
||||
|
||||
if (lrme_core->req_submit &&
|
||||
lrme_core->req_submit->req_id == dump_args->request_id)
|
||||
req = lrme_core->req_submit;
|
||||
else if (lrme_core->req_proc &&
|
||||
lrme_core->req_proc->req_id == dump_args->request_id)
|
||||
req = lrme_core->req_proc;
|
||||
|
||||
if (!req) {
|
||||
CAM_DBG(CAM_LRME, "LRME req %lld not with hw",
|
||||
dump_args->request_id);
|
||||
mutex_unlock(&lrme_hw->hw_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
cur_time = ktime_get();
|
||||
diff = ktime_us_delta(req->submit_timestamp, cur_time);
|
||||
cur_ts = ktime_to_timespec64(cur_time);
|
||||
req_ts = ktime_to_timespec64(req->submit_timestamp);
|
||||
|
||||
if (diff < CAM_LRME_RESPONSE_TIME_THRESHOLD) {
|
||||
CAM_INFO(CAM_LRME, "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);
|
||||
mutex_unlock(&lrme_hw->hw_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
CAM_INFO(CAM_LRME, "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);
|
||||
|
||||
if (dump_args->buf_len <= dump_args->offset) {
|
||||
CAM_WARN(CAM_LRME, "dump buffer overshoot len %zu offset %zu",
|
||||
dump_args->buf_len, dump_args->offset);
|
||||
mutex_unlock(&lrme_hw->hw_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
remain_len = dump_args->buf_len - dump_args->offset;
|
||||
min_len = sizeof(struct cam_lrme_hw_dump_header) +
|
||||
(CAM_LRME_HW_DUMP_NUM_WORDS * sizeof(uint64_t));
|
||||
|
||||
if (remain_len < min_len) {
|
||||
CAM_WARN(CAM_LRME, "dump buffer exhaust remain %zu min %u",
|
||||
remain_len, min_len);
|
||||
mutex_unlock(&lrme_hw->hw_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
dst = (uint8_t *)dump_args->cpu_addr + dump_args->offset;
|
||||
hdr = (struct cam_lrme_hw_dump_header *)dst;
|
||||
scnprintf(hdr->tag, CAM_LRME_HW_DUMP_TAG_MAX_LEN,
|
||||
"LRME_REQ:");
|
||||
hdr->word_size = sizeof(uint64_t);
|
||||
addr = (uint64_t *)(dst + sizeof(struct cam_lrme_hw_dump_header));
|
||||
start = addr;
|
||||
*addr++ = req->req_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_lrme_hw_dump_header);
|
||||
cam_lrme_dump_regs_to_buf(req, lrme_hw, dump_args);
|
||||
mutex_unlock(&lrme_hw->hw_mutex);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void cam_lrme_cdm_write_reg_val_pair(uint32_t *buffer,
|
||||
uint32_t *index, uint32_t reg_offset, uint32_t reg_value)
|
||||
{
|
||||
@@ -959,6 +1113,8 @@ int cam_lrme_hw_submit_req(void *hw_priv, void *hw_submit_args,
|
||||
goto error;
|
||||
}
|
||||
|
||||
frame_req->submit_timestamp = ktime_get();
|
||||
|
||||
switch (lrme_core->state) {
|
||||
case CAM_LRME_CORE_STATE_PROCESSING:
|
||||
lrme_core->state = CAM_LRME_CORE_STATE_REQ_PROC_PEND;
|
||||
@@ -1268,6 +1424,12 @@ int cam_lrme_hw_process_cmd(void *hw_priv, uint32_t cmd_type,
|
||||
break;
|
||||
}
|
||||
|
||||
case CAM_LRME_HW_CMD_DUMP: {
|
||||
struct cam_lrme_hw_dump_args *dump_args =
|
||||
(struct cam_lrme_hw_dump_args *)cmd_args;
|
||||
rc = cam_lrme_hw_dump(lrme_hw, dump_args);
|
||||
break;
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/* 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_LRME_HW_CORE_H_
|
||||
@@ -35,6 +35,10 @@
|
||||
|
||||
#define CAM_LRME_MAX_REG_PAIR_NUM 60
|
||||
|
||||
#define CAM_LRME_RESPONSE_TIME_THRESHOLD 100000
|
||||
#define CAM_LRME_HW_DUMP_TAG_MAX_LEN 32
|
||||
#define CAM_LRME_HW_DUMP_NUM_WORDS 5
|
||||
|
||||
/**
|
||||
* enum cam_lrme_irq_set
|
||||
*
|
||||
@@ -432,6 +436,20 @@ struct cam_lrme_hw_info {
|
||||
struct cam_lrme_titan_reg titan_reg;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_lrme_hw_dump_header : LRME hw dump header
|
||||
*
|
||||
* @tag : LRME hw dump header tag
|
||||
* @size : Size of data
|
||||
* @word_size : size of each word
|
||||
*/
|
||||
|
||||
struct cam_lrme_hw_dump_header {
|
||||
uint8_t tag[CAM_LRME_HW_DUMP_TAG_MAX_LEN];
|
||||
uint64_t size;
|
||||
uint32_t word_size;
|
||||
};
|
||||
|
||||
int cam_lrme_hw_process_irq(void *priv, void *data);
|
||||
int cam_lrme_hw_submit_req(void *hw_priv, void *hw_submit_args,
|
||||
uint32_t arg_size);
|
||||
|
@@ -1,6 +1,6 @@
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
#ifndef _CAM_LRME_HW_INTF_H_
|
||||
@@ -59,12 +59,14 @@ enum cam_lrme_cb_type {
|
||||
* @CAM_LRME_HW_CMD_REGISTER_CB : register HW manager callback
|
||||
* @CAM_LRME_HW_CMD_SUBMIT : Submit frame to HW
|
||||
* @CAM_LRME_HW_CMD_DUMP_REGISTER : dump register values
|
||||
* @CAM_LRME_HW_CMD_DUMP : dump register values to buffer
|
||||
*/
|
||||
enum cam_lrme_hw_cmd_type {
|
||||
CAM_LRME_HW_CMD_PREPARE_HW_UPDATE,
|
||||
CAM_LRME_HW_CMD_REGISTER_CB,
|
||||
CAM_LRME_HW_CMD_SUBMIT,
|
||||
CAM_LRME_HW_CMD_DUMP_REGISTER,
|
||||
CAM_LRME_HW_CMD_DUMP,
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -87,6 +89,7 @@ enum cam_lrme_hw_reset_type {
|
||||
* @hw_device : Pointer to HW device
|
||||
* @hw_update_entries : List of hw_update_entries
|
||||
* @num_hw_update_entries : number of hw_update_entries
|
||||
* @submit_timestamp : timestamp of submitting request with hw
|
||||
*/
|
||||
struct cam_lrme_frame_request {
|
||||
struct list_head frame_list;
|
||||
@@ -95,6 +98,7 @@ struct cam_lrme_frame_request {
|
||||
struct cam_lrme_device *hw_device;
|
||||
struct cam_hw_update_entry hw_update_entries[CAM_LRME_MAX_HW_ENTRIES];
|
||||
uint32_t num_hw_update_entries;
|
||||
ktime_t submit_timestamp;
|
||||
};
|
||||
|
||||
/**
|
||||
@@ -192,6 +196,21 @@ struct cam_lrme_hw_submit_args {
|
||||
struct cam_lrme_frame_request *frame_req;
|
||||
};
|
||||
|
||||
/**
|
||||
* struct cam_lrme_hw_dump_args : Args for dump request
|
||||
*
|
||||
* @request_id : Issue request id
|
||||
* @cpu_addr : start address of the target buffer
|
||||
* @offset : offset of the buffer
|
||||
* @buf_len : Length of target buffer
|
||||
*/
|
||||
struct cam_lrme_hw_dump_args {
|
||||
uint64_t request_id;
|
||||
uintptr_t cpu_addr;
|
||||
size_t offset;
|
||||
size_t buf_len;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief : API to register LRME hw to platform framework.
|
||||
* @return struct platform_device pointer on on success, or ERR_PTR() on error.
|
||||
@@ -202,4 +221,6 @@ int cam_lrme_hw_init_module(void);
|
||||
* @brief : API to remove LRME Hw from platform framework.
|
||||
*/
|
||||
void cam_lrme_hw_exit_module(void);
|
||||
|
||||
#endif /* _CAM_LRME_HW_INTF_H_ */
|
||||
|
||||
|
In neuem Issue referenzieren
Einen Benutzer sperren