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

Commit 45e43d3a authored by Gaurav Jindal's avatar Gaurav Jindal
Browse files

msm: camera: LDAR Dump NRT devices information



In case of LDAR triggered, NRT drivers are traversed to
detect the problematic request id. It dumps the information
for NRT devices; JPEG, LRME, FD and ICP.

Change-Id: I06f0b328bfaf47912214aee3ef967f94602386a5
Signed-off-by: default avatarGaurav Jindal <gjindal@codeaurora.org>
parent d181d1a2
Loading
Loading
Loading
Loading
+16 −0
Original line number Diff line number Diff line
@@ -25,6 +25,9 @@ struct cam_context;
/* max device name string length*/
#define CAM_CTX_DEV_NAME_MAX_LENGTH 20

/* max tag  dump header string length*/
#define CAM_CONTEXT_DUMP_TAG_MAX_LEN 32

/* max request number */
#define CAM_CTX_REQ_MAX              20
#define CAM_CTX_CFG_MAX              20
@@ -229,6 +232,19 @@ struct cam_context {
	uint32_t                     last_flush_req;
};

/**
 * struct cam_context_dump_header -  Function for context dump header
 *
 * @tag         :    Tag for context dump header
 * @size        :    Size of data
 * @word_size   :    Word size of data
 */
struct cam_context_dump_header {
	char      tag[CAM_CONTEXT_DUMP_TAG_MAX_LEN];
	uint64_t  size;
	uint32_t  word_size;
};

/**
 * cam_context_shutdown()
 *
+74 −5
Original line number Diff line number Diff line
@@ -1045,6 +1045,72 @@ int32_t cam_context_dump_pf_info_to_hw(struct cam_context *ctx,
	return rc;
}

static int cam_context_dump_context(struct cam_context *ctx,
	struct cam_hw_dump_args *dump_args)
{
	int rc = 0;
	struct cam_context_dump_header *hdr;
	char *dst;
	uint64_t *addr, *start;
	uintptr_t cpu_addr;
	size_t    buf_len;
	uint32_t min_len, remain_len;
	struct cam_ctx_request *req;
	int i;

	if (list_empty(&ctx->active_req_list)) {
		CAM_ERR(CAM_CTXT, "[%s][%d] no active request",
			ctx->dev_name, ctx->ctx_id);
		return -EIO;
	}
	rc  = cam_mem_get_cpu_buf(dump_args->buf_handle,
		&cpu_addr, &buf_len);
	if (!cpu_addr || !buf_len || rc) {
		CAM_ERR(CAM_CTXT,
			"lnvalid addr %u len %zu rc %d",
			dump_args->buf_handle, buf_len, rc);
		return rc;
	}
	remain_len = buf_len - dump_args->offset;
	min_len =  2 * (sizeof(struct cam_context_dump_header) +
		    CAM_CONTEXT_DUMP_TAG_MAX_LEN);
	if (remain_len < min_len) {
		CAM_ERR(CAM_CTXT, "dump buffer exhaust %d %d",
			remain_len, min_len);
		goto end;
	}
	dst = (char *)cpu_addr + dump_args->offset;
	hdr = (struct cam_context_dump_header *)dst;
	snprintf(hdr->tag, CAM_CONTEXT_DUMP_TAG_MAX_LEN,
		"%s_CTXT_DUMP:", ctx->dev_name);
	hdr->word_size = sizeof(uint64_t);
	addr = (uint64_t *)(dst + sizeof(struct cam_context_dump_header));
	start = addr;
	req = list_first_entry(&ctx->active_req_list,
		struct cam_ctx_request, list);
	*addr++ = ctx->ctx_id;
	*addr++ = refcount_read(&(ctx->refcount.refcount));
	*addr++ = ctx->last_flush_req;
	*addr++ = ctx->state;
	*addr++ = req->num_out_map_entries;
	for (i = 0; i < req->num_out_map_entries; i++)
		if (req->out_map_entries[i].sync_id != -1)
			*addr++ = req->out_map_entries[i].sync_id;
	for (i = 0; i < req->num_in_map_entries; i++)
		if (req->in_map_entries[i].sync_id != -1)
			*addr++ = req->in_map_entries[i].sync_id;
	*addr++ = req->num_in_map_entries;
	hdr->size = hdr->word_size * (addr - start);
	dump_args->offset += hdr->size +
		sizeof(struct cam_context_dump_header);
end:
	rc  = cam_mem_put_cpu_buf(dump_args->buf_handle);
	if (rc)
		CAM_ERR(CAM_CTXT, "Cpu put failed handle %u",
			dump_args->buf_handle);
	return rc;
}

int32_t cam_context_dump_dev_to_hw(struct cam_context *ctx,
	struct cam_dump_req_cmd *cmd)
{
@@ -1074,11 +1140,14 @@ int32_t cam_context_dump_dev_to_hw(struct cam_context *ctx,
			    ctx->dev_name, ctx->ctx_id, dump_args.buf_handle);
			return rc;
		}
		if (dump_args.offset != cmd->offset) {
			cam_context_dump_context(ctx, &dump_args);
			CAM_INFO(CAM_CTXT, "[%s] ctx: %d Filled Length %d",
				ctx->dev_name, ctx->ctx_id,
				dump_args.offset - cmd->offset);
		/* Drivers update offest upto which the buffer is written*/
			/* Drivers update the offest */
			cmd->offset  = dump_args.offset;
		}
	} else {
		CAM_INFO(CAM_CTXT, "%s hw dump not registered", ctx->dev_name);
	}
+13 −0
Original line number Diff line number Diff line
@@ -124,6 +124,18 @@ 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)
{
@@ -203,6 +215,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,
+106 −0
Original line number Diff line number Diff line
@@ -910,6 +910,7 @@ static int cam_fd_mgr_util_submit_frame(void *priv, void *data)
	hw_device->req_id = frame_req->request_id;
	mutex_unlock(&hw_device->lock);

	cam_common_util_get_curr_timestamp(&frame_req->submit_timestamp);
	rc = cam_fd_mgr_util_put_frame_req(
		&hw_mgr->frame_processing_list, &frame_req);
	if (rc) {
@@ -1530,6 +1531,110 @@ 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)
{
	struct cam_fd_hw_mgr *hw_mgr = (struct cam_fd_hw_mgr *)hw_mgr_priv;
	struct cam_hw_dump_args *dump_args = hw_dump_args;
	struct cam_fd_mgr_frame_request *frame_req, *req_temp;
	uint64_t diff;
	struct timeval cur_time;
	int rc = 0;
	struct cam_fd_hw_mgr_ctx *hw_ctx =
		(struct cam_fd_hw_mgr_ctx *)dump_args->ctxt_to_hw_map;
	struct cam_fd_device *hw_device;
	char *dst;
	struct cam_fd_hw_dump_args fd_dump_args;
	struct cam_fd_hw_dump_header *hdr;
	uint64_t *addr, *start;
	uint32_t min_len, remain_len;

	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;
	}
	return rc;
hw_dump:
	cam_common_util_get_curr_timestamp(&cur_time);
	diff = cam_common_util_get_time_diff(&cur_time,
		&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,
			frame_req->submit_timestamp.tv_sec,
			frame_req->submit_timestamp.tv_usec,
			cur_time.tv_sec,
			cur_time.tv_usec);
		return 0;
	}
	CAM_INFO(CAM_FD, "Error req %lld %ld:%06ld %ld:%06ld",
		dump_args->request_id,
		frame_req->submit_timestamp.tv_sec,
		frame_req->submit_timestamp.tv_usec,
		cur_time.tv_sec,
		cur_time.tv_usec);
	rc  = cam_mem_get_cpu_buf(dump_args->buf_handle,
		&fd_dump_args.cpu_addr, &fd_dump_args.buf_len);
	if (!fd_dump_args.cpu_addr || !fd_dump_args.buf_len || rc) {
		CAM_ERR(CAM_FD,
			"lnvalid addr %u len %zu rc %d",
			dump_args->buf_handle, fd_dump_args.buf_len, rc);
		return rc;
	}
	remain_len = fd_dump_args.buf_len - dump_args->offset;
	min_len =  2 * (sizeof(struct cam_fd_hw_dump_header) +
		    CAM_FD_HW_DUMP_TAG_MAX_LEN);
	if (remain_len < min_len) {
		CAM_ERR(CAM_FD, "dump buffer exhaust %d %d",
			remain_len, min_len);
		goto end;
	}
	dst = (char *)fd_dump_args.cpu_addr + dump_args->offset;
	hdr = (struct cam_fd_hw_dump_header *)dst;
	snprintf(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++ = frame_req->submit_timestamp.tv_sec;
	*addr++ = frame_req->submit_timestamp.tv_usec;
	*addr++ = cur_time.tv_sec;
	*addr++ = cur_time.tv_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);
			goto end;
		}
	}
	dump_args->offset = fd_dump_args.offset;
end:
	rc  = cam_mem_put_cpu_buf(dump_args->buf_handle);
	if (rc)
		CAM_ERR(CAM_FD, "Cpu put failed handle %u",
			dump_args->buf_handle);
	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;
@@ -1977,6 +2082,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;

+8 −1
Original line number Diff line number Diff line
/* Copyright (c) 2017-2018, The Linux Foundation. All rights reserved.
/* Copyright (c) 2017-2019, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -27,6 +27,11 @@

#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;

@@ -107,6 +112,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;
@@ -115,6 +121,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;
	struct timeval                 submit_timestamp;
};

/**
Loading