Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 88b74d63 authored by Gaurav Jindal's avatar Gaurav Jindal
Browse files

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 the
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: 2602180
Change-Id: If83db59458c1e5ad778f3fa90cbc730122491c54
Signed-off-by: default avatarGaurav Jindal <gjindal@codeaurora.org>
parent 299c1a13
Loading
Loading
Loading
Loading
+169 −1
Original line number Original line Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
// 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/types.h>
#include <linux/types.h>
@@ -715,3 +715,171 @@ void cam_cdm_util_dump_cmd_buf(
		}
		}
	} while (buf_now <= cmd_buf_end);
	} 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;
}
+44 −1
Original line number Original line Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only */
/* 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_CDM_UTIL_H_
#ifndef _CAM_CDM_UTIL_H_
#define _CAM_CDM_UTIL_H_
#define _CAM_CDM_UTIL_H_


/* Max len for tag name for header while dumping cmd buffer*/
#define CAM_CDM_CMD_TAG_MAX_LEN 32

enum cam_cdm_command {
enum cam_cdm_command {
	CAM_CDM_CMD_UNUSED = 0x0,
	CAM_CDM_CMD_UNUSED = 0x0,
	CAM_CDM_CMD_DMI = 0x1,
	CAM_CDM_CMD_DMI = 0x1,
@@ -144,6 +147,34 @@ void (*cdm_write_genirq)(
	uint32_t  userdata);
	uint32_t  userdata);
};
};


/**
 * struct cam_cdm_cmd_buf_dump_info; - Camera CDM dump info
 * @dst_offset:      dst offset
 * @dst_max_size     max size of destination buffer
 * @src_start:       source start address
 * @src_end:         source end   address
 * @dst_start:       dst start address
 */
struct cam_cdm_cmd_buf_dump_info {
	size_t    dst_offset;
	size_t    dst_max_size;
	uint32_t *src_start;
	uint32_t *src_end;
	uintptr_t dst_start;
};

/**
 * struct cam_cdm_cmd_dump_header- Camera CDM dump header
 * @tag:       tag name for header
 * @size:      size of data
 * @word_size: size of each word
 */
struct cam_cdm_cmd_dump_header {
	uint8_t   tag[CAM_CDM_CMD_TAG_MAX_LEN];
	uint64_t  size;
	uint32_t  word_size;
};

/**
/**
 * cam_cdm_util_log_cmd_bufs()
 * cam_cdm_util_log_cmd_bufs()
 *
 *
@@ -156,6 +187,18 @@ void (*cdm_write_genirq)(
void cam_cdm_util_dump_cmd_buf(
void cam_cdm_util_dump_cmd_buf(
	uint32_t *cmd_buffer_start, uint32_t *cmd_buffer_end);
	uint32_t *cmd_buffer_start, uint32_t *cmd_buffer_end);


/**
 * cam_cdm_util_dump_cmd_bufs_v2()
 *
 * @brief:        Util function to cdm command buffers
 *                to a buffer
 *
 * @dump_info:    Information about source and destination buffers
 *
 * return SUCCESS/FAILURE
 */
int cam_cdm_util_dump_cmd_bufs_v2(
	struct cam_cdm_cmd_buf_dump_info *dump_info);




#endif /* _CAM_CDM_UTIL_H_ */
#endif /* _CAM_CDM_UTIL_H_ */
Loading