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

Commit d181d1a2 authored by Jeyaprakash Soundrapandian's avatar Jeyaprakash Soundrapandian Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: camera: isp: LDAR Dump ISP information" into dev/msm-4.14-camx

parents a581a6e1 1382b19f
Loading
Loading
Loading
Loading
+148 −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
@@ -714,3 +714,150 @@ void cam_cdm_util_dump_cmd_buf(
		}
	} while (buf_now <= cmd_buf_end);
}

static long cam_cdm_util_dump_reg_cont_cmd_v2(
	uint32_t *cmd_buf_addr,
	struct cam_cdm_cmd_buf_dump_info *dump_info)
{
	long ret = 0;
	struct cdm_regcontinuous_cmd *p_regcont_cmd;
	uint32_t *temp_ptr = cmd_buf_addr;
	int i = 0;
	struct cam_cdm_cmd_dump_header *hdr;
	uint32_t *addr, *start;
	uint8_t *dst;
	uint32_t min_len, remain_len;

	p_regcont_cmd = (struct cdm_regcontinuous_cmd *)temp_ptr;
	temp_ptr += CDMCmdHeaderSizes[CAM_CDM_CMD_REG_CONT];
	ret += CDMCmdHeaderSizes[CAM_CDM_CMD_REG_CONT];
	CAM_DBG(CAM_CDM, "REG_CONT: COUNT: %u OFFSET: 0x%X",
		p_regcont_cmd->count, p_regcont_cmd->offset);

	min_len = (sizeof(uint32_t) * p_regcont_cmd->count) +
		sizeof(struct cam_cdm_cmd_dump_header);
	remain_len = dump_info->dst_max_size - dump_info->dst_offset;
	if (remain_len < min_len) {
		CAM_ERR_RATE_LIMIT(CAM_CDM, "Dump buffer exhaust %d %d",
			remain_len, min_len);
		return ret;
	}
	dst = (char *)dump_info->dst_start + dump_info->dst_offset;
	hdr = (struct cam_cdm_cmd_dump_header *)dst;
	snprintf(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 long cam_cdm_util_dump_reg_random_cmd_v2(
	uint32_t *cmd_buf_addr,
	struct cam_cdm_cmd_buf_dump_info *dump_info)
{
	struct cdm_regrandom_cmd *p_regrand_cmd;
	uint32_t *temp_ptr = cmd_buf_addr;
	long ret = 0;
	int i = 0;
	uint32_t *addr, *start;
	struct cam_cdm_cmd_dump_header *hdr;
	uint8_t *dst;
	uint32_t min_len, remain_len;

	p_regrand_cmd = (struct cdm_regrandom_cmd *)temp_ptr;
	temp_ptr += CDMCmdHeaderSizes[CAM_CDM_CMD_REG_RANDOM];
	ret += CDMCmdHeaderSizes[CAM_CDM_CMD_REG_RANDOM];

	min_len = (2 * sizeof(uint32_t) * p_regrand_cmd->count) +
		sizeof(struct cam_cdm_cmd_dump_header);
	remain_len = dump_info->dst_max_size - dump_info->dst_offset;
	if (remain_len < min_len) {
		CAM_ERR_RATE_LIMIT(CAM_CDM, "Dump buffer exhaust %d %d",
			remain_len, min_len);
		return ret;
	}
	dst = (char *)dump_info->dst_start + dump_info->dst_offset;
	hdr = (struct cam_cdm_cmd_dump_header *)dst;
	snprintf(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;
}

void cam_cdm_util_dump_cmd_bufs_v2(
	struct cam_cdm_cmd_buf_dump_info *dump_info)
{
	uint32_t cmd = 0;
	uint32_t *buf_now;

	if (!dump_info || !dump_info->src_start || !dump_info->src_end ||
			!dump_info->dst_start) {
		CAM_INFO(CAM_CDM, "Invalid args");
		return;
	}
	buf_now = dump_info->src_start;
	do {
		cmd = *dump_info->src_start;
		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 += CDMCmdHeaderSizes[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 += CDMCmdHeaderSizes[CAM_CDM_CMD_BUFF_INDIRECT];
			break;
		case CAM_CDM_CMD_GEN_IRQ:
			buf_now += CDMCmdHeaderSizes[CAM_CDM_CMD_GEN_IRQ];
			break;
		case CAM_CDM_CMD_WAIT_EVENT:
			buf_now += CDMCmdHeaderSizes[CAM_CDM_CMD_WAIT_EVENT];
			break;
		case CAM_CDM_CMD_CHANGE_BASE:
			buf_now += CDMCmdHeaderSizes[CAM_CDM_CMD_CHANGE_BASE];
			break;
		case CAM_CDM_CMD_PERF_CTRL:
			buf_now += CDMCmdHeaderSizes[CAM_CDM_CMD_PERF_CTRL];
			break;
		default:
			CAM_INFO(CAM_CDM, "Invalid CMD: 0x%x buf 0x%x",
				cmd, *buf_now);
			buf_now++;
			break;
		}
	} while (buf_now <= dump_info->src_end);

}
+43 −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
@@ -13,6 +13,9 @@
#ifndef _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 {
	CAM_CDM_CMD_UNUSED = 0x0,
	CAM_CDM_CMD_DMI = 0x1,
@@ -151,6 +154,34 @@ void (*cdm_write_genirq)(
	uint32_t  userdata);
};

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

/**
 * 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 {
	char      tag[CAM_CDM_CMD_TAG_MAX_LEN];
	uint64_t  size;
	uint32_t  word_size;
};

/**
 * cam_cdm_util_log_cmd_bufs()
 *
@@ -163,6 +194,17 @@ void (*cdm_write_genirq)(
void cam_cdm_util_dump_cmd_buf(
	uint32_t *cmd_buffer_start, uint32_t *cmd_buffer_end);

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


#endif /* _CAM_CDM_UTIL_H_ */
+331 −13
Original line number Diff line number Diff line
@@ -29,13 +29,123 @@

static const char isp_dev_name[] = "cam-isp";

#define INC_STATE_MONITOR_HEAD(head) \
#define INC_HEAD(head, max_entries) \
	(atomic64_add_return(1, head) % \
	CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES)
	max_entries)

static int cam_isp_context_dump_active_request(void *data, unsigned long iova,
	uint32_t buf_info);

static const char *__cam_isp_evt_val_to_type(
	uint32_t evt_id)
{
	switch (evt_id) {
	case CAM_ISP_CTX_EVENT_SUBMIT:
		return "SUBMIT";
	case CAM_ISP_CTX_EVENT_APPLY:
		return "APPLY";
	case CAM_ISP_CTX_EVENT_EPOCH:
		return "EPOCH";
	case CAM_ISP_CTX_EVENT_RUP:
		return "RUP";
	case CAM_ISP_CTX_EVENT_BUFDONE:
		return "BUFDONE";
	default:
		return "CAM_ISP_EVENT_INVALID";
	}
}

static void __cam_isp_ctx_update_event_record(
	struct cam_isp_context *ctx_isp,
	enum cam_isp_ctx_event event,
	struct cam_ctx_request *req)
{
	int iterator = 0;
	struct cam_isp_ctx_req  *req_isp;
	struct timeval cur_time;

	switch (event) {
	case CAM_ISP_CTX_EVENT_EPOCH:
	case CAM_ISP_CTX_EVENT_RUP:
	case CAM_ISP_CTX_EVENT_BUFDONE:
		break;
	case CAM_ISP_CTX_EVENT_SUBMIT:
	case CAM_ISP_CTX_EVENT_APPLY:
		if (!req) {
			CAM_ERR(CAM_ISP, "Invalid arg for event %d", event);
			return;
		}
		break;
	default:
		break;
	}

	iterator = INC_HEAD(&ctx_isp->event_record_head[event],
		CAM_ISP_CTX_EVENT_RECORD_MAX_ENTRIES);
	cam_common_util_get_curr_timestamp(&cur_time);

	if (req) {
		req_isp = (struct cam_isp_ctx_req *) req->req_priv;
		ctx_isp->event_record[event][iterator].req_id =
			req->request_id;
		req_isp->event_timestamp[event].tv_sec =
			cur_time.tv_sec;
		req_isp->event_timestamp[event].tv_usec =
			cur_time.tv_usec;
	} else {
		ctx_isp->event_record[event][iterator].req_id = 0;
	}
	ctx_isp->event_record[event][iterator].timestamp.tv_sec =
		cur_time.tv_sec;
	ctx_isp->event_record[event][iterator].timestamp.tv_usec =
		cur_time.tv_usec;
}

static void __cam_isp_ctx_dump_event_record(
	struct cam_isp_context *ctx_isp,
	uintptr_t cpu_addr,
	size_t buf_len,
	uint32_t *offset)
{
	int i, j;
	struct cam_isp_context_event_record *record;
	int index;
	uint64_t state_head;
	struct cam_isp_context_dump_header *hdr;
	uint64_t *addr, *start;
	uint8_t *dst;

	if (!cpu_addr || !buf_len || !offset) {
		CAM_ERR(CAM_ISP, "Invalid args");
		return;
	}
	for (i = 0; i < CAM_ISP_CTX_EVENT_MAX; i++) {
		state_head = atomic64_read(&ctx_isp->event_record_head[i]);
		dst = (char *)cpu_addr + *offset;
		hdr = (struct cam_isp_context_dump_header *)dst;
		snprintf(hdr->tag,
			CAM_ISP_CONTEXT_DUMP_TAG_MAX_LEN, "ISP_EVT_%s:",
			__cam_isp_evt_val_to_type(i));
		hdr->word_size = sizeof(uint64_t);
		addr = (uint64_t *)(dst +
			sizeof(struct cam_isp_context_dump_header));
		start = addr;
		for (j = CAM_ISP_CTX_EVENT_RECORD_MAX_ENTRIES - 1; j >= 0;
			j--) {
			index = (((state_head - j) +
				CAM_ISP_CTX_EVENT_RECORD_MAX_ENTRIES) %
				CAM_ISP_CTX_EVENT_RECORD_MAX_ENTRIES);
			record  = &ctx_isp->event_record[i][index];
			*addr++ = record->req_id;
			*addr++ = record->timestamp.tv_sec;
			*addr++ = record->timestamp.tv_usec;
		}
		hdr->size = hdr->word_size * (addr - start);
		*offset += hdr->size +
			sizeof(struct cam_isp_context_dump_header);
	}
}

static void __cam_isp_ctx_update_state_monitor_array(
	struct cam_isp_context *ctx_isp,
	enum cam_isp_hw_event_type    hw_event,
@@ -44,7 +154,8 @@ static void __cam_isp_ctx_update_state_monitor_array(
{
	int iterator = 0;

	iterator = INC_STATE_MONITOR_HEAD(&ctx_isp->state_monitor_head);
	iterator = INC_HEAD(&ctx_isp->state_monitor_head,
		CAM_ISP_CTX_STATE_MONITOR_MAX_ENTRIES);
	ctx_isp->cam_isp_ctx_state_monitor[iterator].curr_state =
		curr_state;
	ctx_isp->cam_isp_ctx_state_monitor[iterator].next_state =
@@ -160,7 +271,11 @@ static void __cam_isp_ctx_dump_state_monitor_array(
	}
}

static void cam_isp_ctx_dump_req(struct cam_isp_ctx_req *req_isp)
static void cam_isp_ctx_dump_req(struct cam_isp_ctx_req *req_isp,
	uintptr_t cpu_addr,
	size_t buf_len,
	uint32_t *offset,
	bool dump_to_buff)
{
	int i = 0, rc = 0;
	size_t len = 0;
@@ -168,6 +283,7 @@ static void cam_isp_ctx_dump_req(struct cam_isp_ctx_req *req_isp)
	uint32_t *buf_start, *buf_end;
	size_t   remain_len = 0;
	bool     need_put = false;
	struct cam_cdm_cmd_buf_dump_info dump_info;

	for (i = 0; i < req_isp->num_cfg; i++) {
		rc = cam_packet_util_get_cmd_mem_addr(
@@ -202,7 +318,21 @@ static void cam_isp_ctx_dump_req(struct cam_isp_ctx_req *req_isp)
				req_isp->cfg[i].offset);
			buf_end = (uint32_t *)((uint8_t *) buf_start +
				req_isp->cfg[i].len - 1);
			if (dump_to_buff) {
				if (!cpu_addr || !offset || !buf_len) {
					CAM_ERR(CAM_ISP, "Invalid args");
					break;
				}
				dump_info.src_start = buf_start;
				dump_info.src_end =   buf_end;
				dump_info.dst_start = cpu_addr;
				dump_info.dst_offset = *offset;
				dump_info.dst_max_size = buf_len;
				cam_cdm_util_dump_cmd_bufs_v2(&dump_info);
				*offset = dump_info.dst_offset;
			} else {
				cam_cdm_util_dump_cmd_buf(buf_start, buf_end);
			}
			if (cam_mem_put_cpu_buf(req_isp->cfg[i].handle))
				CAM_WARN(CAM_ISP, "Failed to put cpu buf: 0x%x",
					req_isp->cfg[i].handle);
@@ -216,6 +346,7 @@ static int __cam_isp_ctx_enqueue_request_in_order(
	struct cam_ctx_request           *req_current;
	struct cam_ctx_request           *req_prev;
	struct list_head                  temp_list;
	struct cam_isp_context *ctx_isp;

	INIT_LIST_HEAD(&temp_list);
	spin_lock_bh(&ctx->lock);
@@ -246,6 +377,9 @@ static int __cam_isp_ctx_enqueue_request_in_order(
			}
		}
	}
	ctx_isp = (struct cam_isp_context *) ctx->ctx_priv;
	__cam_isp_ctx_update_event_record(ctx_isp,
		CAM_ISP_CTX_EVENT_SUBMIT, req);
	spin_unlock_bh(&ctx->lock);
	return 0;
}
@@ -490,7 +624,6 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state(
				req_isp->fence_map_out[j].resource_handle,
				req_isp->fence_map_out[j].sync_id,
				ctx->ctx_id);

			rc = cam_sync_signal(req_isp->fence_map_out[j].sync_id,
				CAM_SYNC_STATE_SIGNALED_SUCCESS);
			if (rc)
@@ -560,6 +693,8 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state(
			CAM_ISP_HW_EVENT_DONE,
			ctx_isp->substate_activated,
			ctx_isp->substate_activated);
		__cam_isp_ctx_update_event_record(ctx_isp,
			CAM_ISP_CTX_EVENT_BUFDONE, req);
	} else {
		list_del_init(&req->list);
		list_add_tail(&req->list, &ctx->free_req_list);
@@ -574,6 +709,8 @@ static int __cam_isp_ctx_handle_buf_done_in_activated_state(
			CAM_ISP_HW_EVENT_DONE,
			ctx_isp->substate_activated,
			ctx_isp->substate_activated);
		__cam_isp_ctx_update_event_record(ctx_isp,
			CAM_ISP_CTX_EVENT_BUFDONE, req);
	}

	if (ctx_isp->active_req_cnt && ctx_isp->irq_delay_detect) {
@@ -742,6 +879,10 @@ static int __cam_isp_ctx_reg_upd_in_activated_state(
		CAM_DBG(CAM_REQ,
			"move request %lld to active list(cnt = %d), ctx %u",
			req->request_id, ctx_isp->active_req_cnt, ctx->ctx_id);

		__cam_isp_ctx_update_event_record(ctx_isp,
			CAM_ISP_CTX_EVENT_RUP, req);

	} else {
		/* no io config, so the request is completed. */
		list_add_tail(&req->list, &ctx->free_req_list);
@@ -776,7 +917,7 @@ static int __cam_isp_ctx_notify_sof_in_activated_state(
	int rc = 0;
	struct cam_req_mgr_trigger_notify  notify;
	struct cam_context *ctx = ctx_isp->base;
	struct cam_ctx_request  *req;
	struct cam_ctx_request  *req = NULL;
	uint64_t  request_id  = 0;

	/*
@@ -807,6 +948,8 @@ static int __cam_isp_ctx_notify_sof_in_activated_state(
				ctx_isp->req_info.reported_req_id = request_id;
				ctx_isp->req_info.last_reported_id_time_stamp =
					jiffies_to_msecs(jiffies);
				__cam_isp_ctx_update_event_record(ctx_isp,
					CAM_ISP_CTX_EVENT_EPOCH, req);
				break;
			}
		}
@@ -973,6 +1116,8 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp,
		__cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
			CAM_REQ_MGR_SOF_EVENT_SUCCESS);

		__cam_isp_ctx_update_event_record(ctx_isp,
			CAM_ISP_CTX_EVENT_EPOCH, NULL);
		goto end;
	}

@@ -1018,6 +1163,8 @@ static int __cam_isp_ctx_epoch_in_applied(struct cam_isp_context *ctx_isp,
	}
	__cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
		CAM_REQ_MGR_SOF_EVENT_ERROR);
	__cam_isp_ctx_update_event_record(ctx_isp,
		CAM_ISP_CTX_EVENT_EPOCH, req);

	ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_BUBBLE;
	CAM_DBG(CAM_ISP, "next substate %d",
@@ -1128,7 +1275,8 @@ static int __cam_isp_ctx_epoch_in_bubble_applied(
		__cam_isp_ctx_dump_state_monitor_array(ctx_isp, true);
		__cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
			CAM_REQ_MGR_SOF_EVENT_SUCCESS);

		__cam_isp_ctx_update_event_record(ctx_isp,
			CAM_ISP_CTX_EVENT_EPOCH, NULL);
		ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_BUBBLE;
		goto end;
	}
@@ -1175,13 +1323,20 @@ static int __cam_isp_ctx_epoch_in_bubble_applied(
			jiffies_to_msecs(jiffies);
			__cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
			CAM_REQ_MGR_SOF_EVENT_ERROR);
		} else
			__cam_isp_ctx_update_event_record(ctx_isp,
				CAM_ISP_CTX_EVENT_EPOCH, req);
		} else {
			__cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
				CAM_REQ_MGR_SOF_EVENT_SUCCESS);
	} else
			__cam_isp_ctx_update_event_record(ctx_isp,
				CAM_ISP_CTX_EVENT_EPOCH, NULL);
		}
	} else {
		__cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
			CAM_REQ_MGR_SOF_EVENT_SUCCESS);

		__cam_isp_ctx_update_event_record(ctx_isp,
			CAM_ISP_CTX_EVENT_EPOCH, NULL);
	}
	ctx_isp->substate_activated = CAM_ISP_CTX_ACTIVATED_BUBBLE;
	CAM_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated);
end:
@@ -1253,7 +1408,7 @@ static int __cam_isp_ctx_handle_error(struct cam_isp_context *ctx_isp,
	req_isp = (struct cam_isp_ctx_req *) req_to_dump->req_priv;

	if (error_event_data->enable_reg_dump)
		cam_isp_ctx_dump_req(req_isp);
		cam_isp_ctx_dump_req(req_isp, 0, 0, NULL, false);

	list_for_each_entry_safe(req, req_temp,
		&ctx->active_req_list, list) {
@@ -1916,6 +2071,8 @@ static int __cam_isp_ctx_apply_req_in_activated_state(
		CAM_DBG(CAM_ISP, "new substate state %d, applied req %lld",
			next_state,
			ctx_isp->req_info.last_applied_req_id);
		__cam_isp_ctx_update_event_record(ctx_isp,
			CAM_ISP_CTX_EVENT_APPLY, req);
		spin_unlock_bh(&ctx->lock);
	}
end:
@@ -1971,6 +2128,160 @@ static int __cam_isp_ctx_apply_req_in_bubble(
	return rc;
}

static int __cam_isp_ctx_dump_req_info(struct cam_context *ctx,
	struct cam_ctx_request *req,
	uintptr_t cpu_addr,
	size_t buf_len,
	uint32_t *offset)
{
	int rc = 0;
	struct cam_isp_ctx_req *req_isp;
	struct cam_isp_context *ctx_isp;
	int i;
	struct cam_isp_context_dump_header *hdr;
	int32_t *addr, *start;
	uint8_t *dst;

	if (!req || !ctx || !offset || !cpu_addr || !buf_len) {
		CAM_ERR(CAM_ISP, "Invalid parameters %pK %pK %u %pK %pK %pK ",
			req, ctx, offset, cpu_addr, buf_len);
		return -EINVAL;
	}
	req_isp = (struct cam_isp_ctx_req *)req->req_priv;
	ctx_isp = (struct cam_isp_context *)ctx->ctx_priv;
	dst = (char *)cpu_addr + *offset;
	hdr = (struct cam_isp_context_dump_header *)dst;
	hdr->word_size = sizeof(int32_t);
	snprintf(hdr->tag, CAM_ISP_CONTEXT_DUMP_TAG_MAX_LEN,
		"ISP_OUT_FENCE:");
	addr = (int32_t *)(dst + sizeof(struct cam_isp_context_dump_header));
	start = addr;
	for (i = 0; i < req_isp->num_fence_map_out; i++) {
		if (req_isp->fence_map_out[i].sync_id != -1) {
			*addr++ = req_isp->fence_map_out[i].resource_handle;
			*addr++ = req_isp->fence_map_out[i].sync_id;
		}
	}
	hdr->size = hdr->word_size * (addr - start);
	*offset += hdr->size + sizeof(struct cam_isp_context_dump_header);
	cam_isp_ctx_dump_req(req_isp, cpu_addr, buf_len,
		offset, true);
	return rc;
}

static int __cam_isp_ctx_dump_in_top_state(struct cam_context *ctx,
	struct cam_req_mgr_dump_info *dump_info)
{
	struct cam_ctx_request           *req = NULL;
	struct cam_isp_ctx_req           *req_isp;
	struct cam_ctx_request           *req_temp;
	struct cam_hw_dump_args dump_args;
	struct cam_isp_context *ctx_isp;
	uint64_t diff = 0;
	struct timeval cur_time;
	int rc = 0;
	uintptr_t cpu_addr;
	size_t buf_len;
	struct cam_isp_context_dump_header *hdr;
	uint64_t *addr, *start;
	uint8_t *dst;
	bool is_dump_only_event_record = false;

	list_for_each_entry_safe(req, req_temp,
		&ctx->active_req_list, list) {
		if (req->request_id == dump_info->req_id) {
			CAM_DBG(CAM_ISP, "isp active dumping req: %lld",
			    dump_info->req_id);
			goto hw_dump;
		}
	}
	list_for_each_entry_safe(req, req_temp,
		&ctx->wait_req_list, list) {
		if (req->request_id == dump_info->req_id) {
			CAM_ERR(CAM_ISP, "isp dumping wait req: %lld",
			    dump_info->req_id);
			goto hw_dump;
		}
	}
	return rc;
hw_dump:
	if (req) {
		req_isp = (struct cam_isp_ctx_req *) req->req_priv;
		cam_common_util_get_curr_timestamp(&cur_time);
		diff = cam_common_util_get_time_diff(&cur_time,
			&req_isp->event_timestamp[CAM_ISP_CTX_EVENT_APPLY]);
		if (diff < CAM_ISP_CTX_RESPONSE_TIME_THRESHOLD) {
			CAM_INFO(CAM_ISP, "req %lld found no error",
				req->request_id);
			is_dump_only_event_record = true;
		}
		ctx_isp = (struct cam_isp_context *) ctx->ctx_priv;
		rc  = cam_mem_get_cpu_buf(dump_info->buf_handle,
			&cpu_addr, &buf_len);
		if (!cpu_addr || !buf_len || rc) {
			CAM_ERR(CAM_ISP,
				"lnvalid addr %u len %zu rc %d",
				dump_info->buf_handle, buf_len, rc);
			return rc;
		}
		/* we take for isp sw information to be max as 2048*/
		if ((buf_len - dump_info->offset) <
			CAM_ISP_CTX_DUMP_MIN_LENGTH) {
			CAM_ERR(CAM_ISP, "Dump buffer exhaust %u %u",
				buf_len, dump_info->offset);
			goto end;
		}
		dst = (char *)cpu_addr + dump_info->offset;
		hdr = (struct cam_isp_context_dump_header *)dst;
		snprintf(hdr->tag, CAM_ISP_CONTEXT_DUMP_TAG_MAX_LEN,
			"ISP_CTX_DUMP:");
		hdr->word_size = sizeof(uint64_t);
		addr = (uint64_t *)(dst +
			sizeof(struct cam_isp_context_dump_header));
		start = addr;
		*addr++ = req->request_id;
		*addr++ = req_isp->event_timestamp
			[CAM_ISP_CTX_EVENT_APPLY].tv_sec;
		*addr++ = req_isp->event_timestamp
			[CAM_ISP_CTX_EVENT_APPLY].tv_usec;
		*addr++ = cur_time.tv_sec;
		*addr++ = cur_time.tv_usec;
		hdr->size = hdr->word_size * (addr - start);
		dump_info->offset += hdr->size +
			sizeof(struct cam_isp_context_dump_header);

		spin_lock_bh(&ctx->lock);
		__cam_isp_ctx_dump_event_record(ctx_isp, cpu_addr,
			buf_len, &dump_info->offset);
		spin_unlock_bh(&ctx->lock);
		if (is_dump_only_event_record)
			goto end;
		rc = __cam_isp_ctx_dump_req_info(ctx, req, cpu_addr,
			buf_len, &dump_info->offset);
		if (rc) {
			CAM_ERR(CAM_ISP, "Dump Req info fail %lld",
				req->request_id);
			goto end;
		}
		if (ctx->hw_mgr_intf->hw_dump) {
			dump_args.offset = dump_info->offset;
			dump_args.request_id = dump_info->req_id;
			dump_args.buf_handle = dump_info->buf_handle;
			dump_args.ctxt_to_hw_map = ctx_isp->hw_ctx;
			rc = ctx->hw_mgr_intf->hw_dump(
				ctx->hw_mgr_intf->hw_mgr_priv,
				&dump_args);
			dump_info->offset = dump_args.offset;
		}
end:
		rc  = cam_mem_put_cpu_buf(dump_info->buf_handle);
		if (rc)
			CAM_ERR(CAM_ISP, "Cpu put failed handle %u",
				dump_info->buf_handle);
	}
	return rc;
}

static int __cam_isp_ctx_flush_req(struct cam_context *ctx,
	struct list_head *req_list, struct cam_req_mgr_flush_request *flush_req)
{
@@ -2510,7 +2821,7 @@ static int __cam_isp_ctx_rdi_only_sof_in_bubble_state(
static int __cam_isp_ctx_rdi_only_reg_upd_in_bubble_applied_state(
	struct cam_isp_context *ctx_isp, void *evt_data)
{
	struct cam_ctx_request  *req;
	struct cam_ctx_request  *req = NULL;
	struct cam_context      *ctx = ctx_isp->base;
	struct cam_isp_ctx_req  *req_isp = NULL;
	struct cam_req_mgr_trigger_notify  notify;
@@ -2572,6 +2883,8 @@ static int __cam_isp_ctx_rdi_only_reg_upd_in_bubble_applied_state(

	__cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
		CAM_REQ_MGR_SOF_EVENT_SUCCESS);
	__cam_isp_ctx_update_event_record(ctx_isp,
		CAM_ISP_CTX_EVENT_RUP, req);
	CAM_DBG(CAM_ISP, "next substate %d", ctx_isp->substate_activated);

	return 0;
@@ -2579,6 +2892,8 @@ static int __cam_isp_ctx_rdi_only_reg_upd_in_bubble_applied_state(
	/* Send SOF event as idle frame*/
	__cam_isp_ctx_send_sof_timestamp(ctx_isp, request_id,
		CAM_REQ_MGR_SOF_EVENT_SUCCESS);
	__cam_isp_ctx_update_event_record(ctx_isp,
		CAM_ISP_CTX_EVENT_RUP, NULL);

	/*
	 * There is no request in the pending list, move the sub state machine
@@ -3839,6 +4154,7 @@ static struct cam_ctx_ops
			.unlink = __cam_isp_ctx_unlink_in_acquired,
			.get_dev_info = __cam_isp_ctx_get_dev_info_in_acquired,
			.flush_req = __cam_isp_ctx_flush_req_in_top_state,
			.dump_req = __cam_isp_ctx_dump_in_top_state,
		},
		.irq_ops = NULL,
		.pagefault_ops = cam_isp_context_dump_active_request,
@@ -3854,6 +4170,7 @@ static struct cam_ctx_ops
		.crm_ops = {
			.unlink = __cam_isp_ctx_unlink_in_ready,
			.flush_req = __cam_isp_ctx_flush_req_in_ready,
			.dump_req = __cam_isp_ctx_dump_in_top_state,
		},
		.irq_ops = NULL,
		.pagefault_ops = cam_isp_context_dump_active_request,
@@ -3871,6 +4188,7 @@ static struct cam_ctx_ops
			.apply_req = __cam_isp_ctx_apply_req,
			.flush_req = __cam_isp_ctx_flush_req_in_top_state,
			.process_evt = __cam_isp_ctx_process_evt,
			.dump_req = __cam_isp_ctx_dump_in_top_state,
		},
		.irq_ops = __cam_isp_ctx_handle_irq_in_activated,
		.pagefault_ops = cam_isp_context_dump_active_request,
+66 −0

File changed.

Preview size limit exceeded, changes collapsed.

+109 −0
Original line number Diff line number Diff line
@@ -4576,6 +4576,114 @@ static int cam_ife_mgr_cmd(void *hw_mgr_priv, void *cmd_args)
	return rc;
}

static int cam_ife_mgr_dump(void *hw_mgr_priv, void *args)
{
	struct cam_isp_hw_dump_args isp_hw_dump_args;
	struct cam_hw_dump_args *dump_args = (struct cam_hw_dump_args *)args;
	struct cam_ife_hw_mgr_res            *hw_mgr_res;
	struct cam_hw_intf                   *hw_intf;
	struct cam_ife_hw_mgr_ctx *ife_ctx = (struct cam_ife_hw_mgr_ctx *)
						dump_args->ctxt_to_hw_map;
	int i;
	int rc = 0;

	rc  = cam_mem_get_cpu_buf(dump_args->buf_handle,
		&isp_hw_dump_args.cpu_addr,
		&isp_hw_dump_args.buf_len);
	if (!isp_hw_dump_args.cpu_addr ||
		!isp_hw_dump_args.buf_len || rc) {
		CAM_ERR(CAM_ISP,
		    "lnvalid addr %u len %zu rc %d",
		    dump_args->buf_handle,
		    isp_hw_dump_args.buf_len,
		    rc);
		return rc;
	}
	isp_hw_dump_args.offset = dump_args->offset;
	isp_hw_dump_args.req_id = dump_args->request_id;

	list_for_each_entry(hw_mgr_res, &ife_ctx->res_list_ife_csid, list) {
		for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
			if (!hw_mgr_res->hw_res[i])
				continue;
			hw_intf = hw_mgr_res->hw_res[i]->hw_intf;
			switch (hw_mgr_res->hw_res[i]->res_id) {
			case CAM_IFE_PIX_PATH_RES_RDI_0:
			case CAM_IFE_PIX_PATH_RES_RDI_1:
			case CAM_IFE_PIX_PATH_RES_RDI_2:
			case CAM_IFE_PIX_PATH_RES_RDI_3:
				if (ife_ctx->is_rdi_only_context &&
					hw_intf->hw_ops.process_cmd) {
					rc = hw_intf->hw_ops.process_cmd(
						hw_intf->hw_priv,
						CAM_ISP_HW_CMD_DUMP_HW,
						&isp_hw_dump_args,
						sizeof(struct
						    cam_isp_hw_dump_args));
				}
				break;
			case CAM_IFE_PIX_PATH_RES_IPP:
				if (hw_intf->hw_ops.process_cmd) {
					rc = hw_intf->hw_ops.process_cmd(
						hw_intf->hw_priv,
						CAM_ISP_HW_CMD_DUMP_HW,
						&isp_hw_dump_args,
						sizeof(struct
						    cam_isp_hw_dump_args));
				}
				break;
			default:
				CAM_DBG(CAM_ISP, "not a valid res %d",
				hw_mgr_res->res_id);
				break;
			}
		}
	}
	list_for_each_entry(hw_mgr_res, &ife_ctx->res_list_ife_src, list) {
		for (i = 0; i < CAM_ISP_HW_SPLIT_MAX; i++) {
			if (!hw_mgr_res->hw_res[i])
				continue;
			hw_intf = hw_mgr_res->hw_res[i]->hw_intf;
			switch (hw_mgr_res->res_id) {
			case CAM_ISP_HW_VFE_IN_RDI0:
			case CAM_ISP_HW_VFE_IN_RDI1:
			case CAM_ISP_HW_VFE_IN_RDI2:
			case CAM_ISP_HW_VFE_IN_RDI3:
				if (ife_ctx->is_rdi_only_context &&
					hw_intf->hw_ops.process_cmd) {
					rc = hw_intf->hw_ops.process_cmd(
						hw_intf->hw_priv,
						CAM_ISP_HW_CMD_DUMP_HW,
						&isp_hw_dump_args,
						sizeof(struct
						    cam_isp_hw_dump_args));
				}
				break;
			case CAM_ISP_HW_VFE_IN_CAMIF:
				if (hw_intf->hw_ops.process_cmd) {
					rc = hw_intf->hw_ops.process_cmd(
						hw_intf->hw_priv,
						CAM_ISP_HW_CMD_DUMP_HW,
						&isp_hw_dump_args,
						sizeof(struct
						    cam_isp_hw_dump_args));
				}
				break;
			default:
				CAM_DBG(CAM_ISP, "not a valid res %d",
					hw_mgr_res->res_id);
				break;
			}
		}
	}
	dump_args->offset = isp_hw_dump_args.offset;
	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_ife_mgr_cmd_get_sof_timestamp(
	struct cam_ife_hw_mgr_ctx      *ife_ctx,
	uint64_t                       *time_stamp,
@@ -6190,6 +6298,7 @@ int cam_ife_hw_mgr_init(struct cam_hw_mgr_intf *hw_mgr_intf, int *iommu_hdl)
	hw_mgr_intf->hw_config = cam_ife_mgr_config_hw;
	hw_mgr_intf->hw_cmd = cam_ife_mgr_cmd;
	hw_mgr_intf->hw_reset = cam_ife_mgr_reset;
	hw_mgr_intf->hw_dump = cam_ife_mgr_dump;

	if (iommu_hdl)
		*iommu_hdl = g_ife_hw_mgr.mgr_common.img_iommu_hdl;
Loading