msm: camera: isp: LDAR Dump ISP information

When user space detects an error or does not receive
response for a request, Lets do a reset(LDAR) is triggered.
Before LDAR, user space sends flush command to the
kernel space.
In order to debug the cause for this situation and to dump
the information, user space sends a dump command to
kernel space before sending flush.
As a part of this command, it passes the culprit request id
and the buffer into which the information can be dumped.
Kernel space traverses across the drivers and find the culprit hw
and dumps the relevant information in the buffer.
This data is written to a file for offline processing.
This commit dumps the IFE, CSID registers, LUT tables and context
information, cmd buffers, timestamps information for
submit, apply, RUP, epoch and buffdones of the last 20
requests.

CRs-Fixed: 2612116
Change-Id: If83db59458c1e5ad778f3fa90cbc730122491c54
Signed-off-by: Gaurav Jindal <gjindal@codeaurora.org>
This commit is contained in:
Gaurav Jindal
2019-10-14 17:09:54 +05:30
committed by Gerrit - the friendly Code Review server
parent 2460a8e82a
commit e3f5738e43
17 changed files with 1568 additions and 46 deletions

View File

@@ -823,3 +823,171 @@ void cam_cdm_util_dump_cmd_buf(
}
} while (buf_now <= cmd_buf_end);
}
static uint32_t cam_cdm_util_dump_reg_cont_cmd_v2(
uint32_t *cmd_buf_addr,
struct cam_cdm_cmd_buf_dump_info *dump_info)
{
int i;
long ret;
uint8_t *dst;
size_t remain_len;
uint32_t *temp_ptr = cmd_buf_addr;
uint32_t *addr, *start;
uint32_t min_len;
struct cdm_regcontinuous_cmd *p_regcont_cmd;
struct cam_cdm_cmd_dump_header *hdr;
p_regcont_cmd = (struct cdm_regcontinuous_cmd *)temp_ptr;
temp_ptr += cdm_get_cmd_header_size(CAM_CDM_CMD_REG_CONT);
ret = cdm_get_cmd_header_size(CAM_CDM_CMD_REG_CONT);
min_len = (sizeof(uint32_t) * p_regcont_cmd->count) +
sizeof(struct cam_cdm_cmd_dump_header) +
(2 * sizeof(uint32_t));
remain_len = dump_info->dst_max_size - dump_info->dst_offset;
if (remain_len < min_len) {
CAM_WARN_RATE_LIMIT(CAM_CDM,
"Dump buffer exhaust remain %zu min %u",
remain_len, min_len);
return ret;
}
dst = (char *)dump_info->dst_start + dump_info->dst_offset;
hdr = (struct cam_cdm_cmd_dump_header *)dst;
scnprintf(hdr->tag, CAM_CDM_CMD_TAG_MAX_LEN, "CDM_REG_CONT:");
hdr->word_size = sizeof(uint32_t);
addr = (uint32_t *)(dst + sizeof(struct cam_cdm_cmd_dump_header));
start = addr;
*addr++ = p_regcont_cmd->offset;
*addr++ = p_regcont_cmd->count;
for (i = 0; i < p_regcont_cmd->count; i++) {
*addr = *temp_ptr;
temp_ptr++;
addr++;
ret++;
}
hdr->size = hdr->word_size * (addr - start);
dump_info->dst_offset += hdr->size +
sizeof(struct cam_cdm_cmd_dump_header);
return ret;
}
static uint32_t cam_cdm_util_dump_reg_random_cmd_v2(
uint32_t *cmd_buf_addr,
struct cam_cdm_cmd_buf_dump_info *dump_info)
{
int i;
long ret;
uint8_t *dst;
uint32_t *temp_ptr = cmd_buf_addr;
uint32_t *addr, *start;
size_t remain_len;
uint32_t min_len;
struct cdm_regrandom_cmd *p_regrand_cmd;
struct cam_cdm_cmd_dump_header *hdr;
p_regrand_cmd = (struct cdm_regrandom_cmd *)temp_ptr;
temp_ptr += cdm_get_cmd_header_size(CAM_CDM_CMD_REG_RANDOM);
ret = cdm_get_cmd_header_size(CAM_CDM_CMD_REG_RANDOM);
min_len = (2 * sizeof(uint32_t) * p_regrand_cmd->count) +
sizeof(struct cam_cdm_cmd_dump_header) + sizeof(uint32_t);
remain_len = dump_info->dst_max_size - dump_info->dst_offset;
if (remain_len < min_len) {
CAM_WARN_RATE_LIMIT(CAM_CDM,
"Dump buffer exhaust remain %zu min %u",
remain_len, min_len);
return ret;
}
dst = (char *)dump_info->dst_start + dump_info->dst_offset;
hdr = (struct cam_cdm_cmd_dump_header *)dst;
scnprintf(hdr->tag, CAM_CDM_CMD_TAG_MAX_LEN, "CDM_REG_RANDOM:");
hdr->word_size = sizeof(uint32_t);
addr = (uint32_t *)(dst + sizeof(struct cam_cdm_cmd_dump_header));
start = addr;
*addr++ = p_regrand_cmd->count;
for (i = 0; i < p_regrand_cmd->count; i++) {
addr[0] = temp_ptr[0] & CAM_CDM_REG_OFFSET_MASK;
addr[1] = temp_ptr[1];
temp_ptr += 2;
addr += 2;
ret += 2;
}
hdr->size = hdr->word_size * (addr - start);
dump_info->dst_offset += hdr->size +
sizeof(struct cam_cdm_cmd_dump_header);
return ret;
}
int cam_cdm_util_dump_cmd_bufs_v2(
struct cam_cdm_cmd_buf_dump_info *dump_info)
{
uint32_t cmd;
uint32_t *buf_now;
int rc = 0;
if (!dump_info || !dump_info->src_start || !dump_info->src_end ||
!dump_info->dst_start) {
CAM_INFO(CAM_CDM, "Invalid args");
return -EINVAL;
}
buf_now = dump_info->src_start;
do {
if (dump_info->dst_offset >= dump_info->dst_max_size) {
CAM_WARN(CAM_CDM,
"Dump overshoot offset %zu size %zu",
dump_info->dst_offset,
dump_info->dst_max_size);
return -ENOSPC;
}
cmd = *buf_now;
cmd = cmd >> CAM_CDM_COMMAND_OFFSET;
switch (cmd) {
case CAM_CDM_CMD_DMI:
case CAM_CDM_CMD_DMI_32:
case CAM_CDM_CMD_DMI_64:
buf_now += cdm_get_cmd_header_size(CAM_CDM_CMD_DMI);
break;
case CAM_CDM_CMD_REG_CONT:
buf_now += cam_cdm_util_dump_reg_cont_cmd_v2(buf_now,
dump_info);
break;
case CAM_CDM_CMD_REG_RANDOM:
buf_now += cam_cdm_util_dump_reg_random_cmd_v2(buf_now,
dump_info);
break;
case CAM_CDM_CMD_BUFF_INDIRECT:
buf_now += cdm_get_cmd_header_size(
CAM_CDM_CMD_BUFF_INDIRECT);
break;
case CAM_CDM_CMD_GEN_IRQ:
buf_now += cdm_get_cmd_header_size(
CAM_CDM_CMD_GEN_IRQ);
break;
case CAM_CDM_CMD_WAIT_EVENT:
buf_now += cdm_get_cmd_header_size(
CAM_CDM_CMD_WAIT_EVENT);
break;
case CAM_CDM_CMD_CHANGE_BASE:
buf_now += cdm_get_cmd_header_size(
CAM_CDM_CMD_CHANGE_BASE);
break;
case CAM_CDM_CMD_PERF_CTRL:
buf_now += cdm_get_cmd_header_size(
CAM_CDM_CMD_PERF_CTRL);
break;
default:
CAM_ERR(CAM_CDM, "Invalid CMD: 0x%x", cmd);
buf_now++;
break;
}
} while (buf_now <= dump_info->src_end);
return rc;
}