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

Commit 1c4493f0 authored by Alok Chauhan's avatar Alok Chauhan
Browse files

msm: camera: ope: Add LDAR dump support



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 log about culprit information for OPE.

CRs-Fixed: 2669222
Change-Id: Ida5cbee7a36917f7276a0f9accf2c35f24bf69c9
Signed-off-by: default avatarAlok Chauhan <alokc@codeaurora.org>
parent 7ce0928a
Loading
Loading
Loading
Loading
+15 −1
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2019-2020, The Linux Foundation. All rights reserved.
 */

#include <linux/debugfs.h>
@@ -122,6 +122,18 @@ static int __cam_ope_flush_dev_in_ready(struct cam_context *ctx,
	return rc;
}

static int __cam_ope_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_OPE, "Failed to dump device");

	return rc;
}

static int __cam_ope_config_dev_in_ready(struct cam_context *ctx,
	struct cam_config_dev_cmd *cmd)
{
@@ -205,6 +217,7 @@ static struct cam_ctx_ops
			.start_dev = __cam_ope_start_dev_in_acquired,
			.config_dev = __cam_ope_config_dev_in_ready,
			.flush_dev = __cam_ope_flush_dev_in_ready,
			.dump_dev = __cam_ope_dump_dev_in_ready,
		},
		.crm_ops = {},
		.irq_ops = __cam_ope_handle_buf_done_in_ready,
@@ -217,6 +230,7 @@ static struct cam_ctx_ops
			.release_dev = __cam_ope_release_dev_in_ready,
			.config_dev = __cam_ope_config_dev_in_ready,
			.flush_dev = __cam_ope_flush_dev_in_ready,
			.dump_dev = __cam_ope_dump_dev_in_ready,
		},
		.crm_ops = {},
		.irq_ops = __cam_ope_handle_buf_done_in_ready,
+72 −0
Original line number Diff line number Diff line
@@ -3302,6 +3302,7 @@ static int cam_ope_mgr_config_hw(void *hw_priv, void *hw_config_args)
	cdm_cmd->cookie = ope_req->req_idx;

	cam_ope_mgr_ope_clk_update(hw_mgr, ctx_data, ope_req->req_idx);
	ctx_data->req_list[ope_req->req_idx]->submit_timestamp = ktime_get();

	if (ope_req->request_id <= ctx_data->last_flush_req)
		CAM_WARN(CAM_OPE,
@@ -3429,6 +3430,76 @@ static int cam_ope_mgr_flush_all(struct cam_ope_ctx *ctx_data,
	return rc;
}

static int cam_ope_mgr_hw_dump(void *hw_priv, void *hw_dump_args)
{
	struct cam_ope_ctx *ctx_data;
	struct cam_ope_hw_mgr *hw_mgr = hw_priv;
	struct cam_hw_dump_args  *dump_args;
	int idx;
	ktime_t cur_time;
	struct timespec64 cur_ts, req_ts;
	uint64_t diff;

	if ((!hw_priv) || (!hw_dump_args)) {
		CAM_ERR(CAM_OPE, "Invalid params %pK %pK",
			hw_priv, hw_dump_args);
		return -EINVAL;
	}

	dump_args = (struct cam_hw_dump_args *)hw_dump_args;
	ctx_data = dump_args->ctxt_to_hw_map;

	if (!ctx_data) {
		CAM_ERR(CAM_OPE, "Invalid context");
		return -EINVAL;
	}

	mutex_lock(&hw_mgr->hw_mgr_mutex);

	CAM_INFO(CAM_OPE, "Req %lld", dump_args->request_id);
	for (idx = 0; idx < CAM_CTX_REQ_MAX; idx++) {
		if (!ctx_data->req_list[idx])
			continue;

		if (ctx_data->req_list[idx]->request_id ==
			dump_args->request_id)
			break;
	}

	/* no matching request found */
	if (idx == CAM_CTX_REQ_MAX) {
		mutex_unlock(&hw_mgr->hw_mgr_mutex);
		return 0;
	}

	cur_time = ktime_get();
	diff = ktime_us_delta(ctx_data->req_list[idx]->submit_timestamp,
			cur_time);
	cur_ts = ktime_to_timespec64(cur_time);
	req_ts = ktime_to_timespec64(ctx_data->req_list[idx]->submit_timestamp);

	if (diff < (OPE_REQUEST_TIMEOUT * 1000)) {
		CAM_INFO(CAM_OPE, "No Error req %llu %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_ERR(CAM_OPE, "Error req %llu %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;
}

static int cam_ope_mgr_hw_flush(void *hw_priv, void *hw_flush_args)
{
	struct cam_hw_flush_args *flush_args = hw_flush_args;
@@ -3703,6 +3774,7 @@ int cam_ope_hw_mgr_init(struct device_node *of_node, uint64_t *hw_mgr_hdl,
	hw_mgr_intf->hw_open = cam_ope_mgr_hw_open_u;
	hw_mgr_intf->hw_close = cam_ope_mgr_hw_close_u;
	hw_mgr_intf->hw_flush = cam_ope_mgr_hw_flush;
	hw_mgr_intf->hw_dump = cam_ope_mgr_hw_dump;

	ope_hw_mgr->secure_mode = false;
	mutex_init(&ope_hw_mgr->hw_mgr_mutex);
+2 −2
Original line number Diff line number Diff line
@@ -62,8 +62,6 @@
#define OPE_DEVICE_IDLE_TIMEOUT    400
#define OPE_REQUEST_TIMEOUT        200



/**
 * struct cam_ope_clk_bw_request_v2
 * @budget_ns: Time required to process frame
@@ -390,6 +388,7 @@ struct ope_io_buf {
 * @clk_info:            Clock Info V1
 * @clk_info_v2:         Clock Info V2
 * @hang_data:           Debug data for HW error
 * @submit_timestamp:    Submit timestamp to hw
 */
struct cam_ope_request {
	uint64_t request_id;
@@ -410,6 +409,7 @@ struct cam_ope_request {
	struct cam_ope_clk_bw_request clk_info;
	struct cam_ope_clk_bw_req_internal_v2 clk_info_v2;
	struct cam_hw_mgr_dump_pf_data hang_data;
	ktime_t submit_timestamp;
};

/**