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

Commit 6c58ed29 authored by Camera Software Integration's avatar Camera Software Integration Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: camera: common: LDAR dump NRT devices information" into camera-kernel.lnx.3.1

parents 6d2eb031 e110aec0
Loading
Loading
Loading
Loading
+15 −1
Original line number Diff line number Diff line
// 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/module.h>
@@ -117,6 +117,19 @@ 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)
{
@@ -198,6 +211,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,
+134 −1
Original line number Diff line number Diff line
// 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/module.h>
@@ -883,6 +883,7 @@ static int cam_fd_mgr_util_submit_frame(void *priv, void *data)
	hw_device->cur_hw_ctx = hw_ctx;
	hw_device->req_id = frame_req->request_id;
	mutex_unlock(&hw_device->lock);
	frame_req->submit_timestamp = ktime_get();

	rc = cam_fd_mgr_util_put_frame_req(
		&hw_mgr->frame_processing_list, &frame_req);
@@ -1504,6 +1505,137 @@ 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)
{
	int                              rc;
	uint8_t                         *dst;
	ktime_t                          cur_time;
	size_t                           remain_len;
	uint32_t                         min_len;
	uint64_t                         diff;
	uint64_t                        *addr, *start;
	struct timespec64                cur_ts;
	struct timespec64                req_ts;
	struct cam_fd_hw_mgr            *hw_mgr;
	struct cam_hw_dump_args         *dump_args;
	struct cam_fd_hw_mgr_ctx        *hw_ctx;
	struct cam_fd_device            *hw_device;
	struct cam_fd_hw_dump_args       fd_dump_args;
	struct cam_fd_hw_dump_header    *hdr;
	struct cam_fd_mgr_frame_request *frame_req, *req_temp;

	hw_mgr = (struct cam_fd_hw_mgr *)hw_mgr_priv;
	dump_args = (struct cam_hw_dump_args *)hw_dump_args;
	if (!hw_mgr || !dump_args) {
		CAM_ERR(CAM_FD, "Invalid args %pK %pK",
			hw_mgr, dump_args);
		return -EINVAL;
	}

	hw_ctx = (struct cam_fd_hw_mgr_ctx *)dump_args->ctxt_to_hw_map;

	if (!hw_ctx) {
		CAM_ERR(CAM_FD, "Invalid ctx");
		return -EINVAL;
	}

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

	CAM_DBG(CAM_FD, "fd dump cannot find req %llu",
		dump_args->request_id);
	return rc;
hw_dump:
	cur_time = ktime_get();
	diff = ktime_us_delta(frame_req->submit_timestamp, cur_time);
	cur_ts = ktime_to_timespec64(cur_time);
	req_ts = ktime_to_timespec64(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,
			req_ts.tv_sec,
			req_ts.tv_nsec/NSEC_PER_USEC,
			cur_ts.tv_sec,
			cur_ts.tv_nsec/NSEC_PER_USEC);
		return 0;
	}
	CAM_INFO(CAM_FD, "Error req %lld %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);
	rc  = cam_mem_get_cpu_buf(dump_args->buf_handle,
		&fd_dump_args.cpu_addr, &fd_dump_args.buf_len);
	if (rc) {
		CAM_ERR(CAM_FD, "Invalid handle %u rc %d",
			dump_args->buf_handle, rc);
		return rc;
	}
	if (fd_dump_args.buf_len <= dump_args->offset) {
		CAM_WARN(CAM_FD, "dump offset overshoot len %zu offset %zu",
			fd_dump_args.buf_len, dump_args->offset);
		return -ENOSPC;
	}
	remain_len = fd_dump_args.buf_len - dump_args->offset;
	min_len =  sizeof(struct cam_fd_hw_dump_header) +
		(CAM_FD_HW_DUMP_NUM_WORDS * sizeof(uint64_t));

	if (remain_len < min_len) {
		CAM_WARN(CAM_FD, "dump buffer exhaust remain %zu min %u",
			remain_len, min_len);
		return -ENOSPC;
	}

	dst = (uint8_t *)fd_dump_args.cpu_addr + dump_args->offset;
	hdr = (struct cam_fd_hw_dump_header *)dst;
	scnprintf(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++ = req_ts.tv_sec;
	*addr++ = req_ts.tv_nsec/NSEC_PER_USEC;
	*addr++ = cur_ts.tv_sec;
	*addr++ = cur_ts.tv_nsec/NSEC_PER_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);
			return rc;
		}
	}
	CAM_DBG(CAM_FD, "Offset before %zu after %zu",
		dump_args->offset, fd_dump_args.offset);
	dump_args->offset = fd_dump_args.offset;
	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;
@@ -1944,6 +2076,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;

+9 −1
Original line number Diff line number Diff line
/* 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_FD_HW_MGR_H_
@@ -21,6 +21,12 @@
#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;

/**
@@ -100,6 +106,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;
@@ -108,6 +115,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;
	ktime_t                        submit_timestamp;
};

/**
+80 −1
Original line number Diff line number Diff line
// 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 "cam_fd_hw_core.h"
@@ -516,6 +516,80 @@ static int cam_fd_hw_util_processcmd_frame_done(struct cam_hw_info *fd_hw,
	return 0;
}

static int cam_fd_hw_util_processcmd_hw_dump(
	struct cam_hw_info *fd_hw,
	void               *args)
{
	int                            i, j;
	uint8_t                       *dst;
	uint32_t                      *addr, *start;
	uint32_t                       num_reg, min_len;
	uint64_t                       remain_len;
	struct cam_hw_soc_info        *soc_info;
	struct cam_fd_hw_dump_header  *hdr;
	struct cam_fd_hw_dump_args    *dump_args;

	if (!fd_hw || !args) {
		CAM_ERR(CAM_FD, "Invalid args %pK %pK",
			fd_hw, args);
		return -EINVAL;
	}

	mutex_lock(&fd_hw->hw_mutex);

	if (fd_hw->hw_state == CAM_HW_STATE_POWER_DOWN) {
		CAM_INFO(CAM_FD, "power off state");
		mutex_unlock(&fd_hw->hw_mutex);
		return 0;
	}

	dump_args = (struct cam_fd_hw_dump_args *)args;
	soc_info = &fd_hw->soc_info;

	if (dump_args->buf_len <= dump_args->offset) {
		CAM_WARN(CAM_FD, "dump offset overshoot len %zu offset %zu",
			dump_args->buf_len, dump_args->offset);
		mutex_unlock(&fd_hw->hw_mutex);
		return -ENOSPC;
	}

	remain_len = dump_args->buf_len - dump_args->offset;
	min_len =  sizeof(struct cam_fd_hw_dump_header) +
		    soc_info->reg_map[0].size + sizeof(uint32_t);

	if (remain_len < min_len) {
		CAM_WARN(CAM_FD, "dump buffer exhaust remain %zu min %u",
			remain_len, min_len);
		mutex_unlock(&fd_hw->hw_mutex);
		return -ENOSPC;
	}

	dst = (uint8_t *)dump_args->cpu_addr + dump_args->offset;
	hdr = (struct cam_fd_hw_dump_header *)dst;
	scnprintf(hdr->tag, CAM_FD_HW_DUMP_TAG_MAX_LEN,
		"FD_REG:");
	hdr->word_size = sizeof(uint32_t);
	addr = (uint32_t *)(dst + sizeof(struct cam_fd_hw_dump_header));
	start = addr;
	*addr++ = soc_info->index;

	for (j = 0; j < soc_info->num_reg_map; j++) {
		num_reg = soc_info->reg_map[j].size/4;
		for (i = 0; i < num_reg; i++) {
			*addr++ = soc_info->mem_block[j]->start + i*4;
			*addr++ = cam_io_r(soc_info->reg_map[j].mem_base +
				(i*4));
		}
	}

	mutex_unlock(&fd_hw->hw_mutex);
	hdr->size = hdr->word_size * (addr - start);
	dump_args->offset += hdr->size +
		sizeof(struct cam_fd_hw_dump_header);
	CAM_DBG(CAM_FD, "%zu", dump_args->offset);
	return 0;
}

irqreturn_t cam_fd_hw_irq(int irq_num, void *data)
{
	struct cam_hw_info *fd_hw = (struct cam_hw_info *)data;
@@ -1159,6 +1233,11 @@ int cam_fd_hw_process_cmd(void *hw_priv, uint32_t cmd_type,
			cmd_frame_results);
		break;
	}
	case CAM_FD_HW_CMD_HW_DUMP: {
		rc = cam_fd_hw_util_processcmd_hw_dump(fd_hw,
			cmd_args);
		break;
	}
	default:
		break;
	}
+33 −1
Original line number Diff line number Diff line
/* 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_FD_HW_INTF_H_
@@ -24,6 +24,8 @@

#define CAM_FD_MAX_IO_BUFFERS        5
#define CAM_FD_MAX_HW_ENTRIES        5
#define CAM_FD_HW_DUMP_TAG_MAX_LEN   32
#define CAM_FD_HW_DUMP_NUM_WORDS     5

/**
 * enum cam_fd_hw_type - Enum for FD HW type
@@ -81,12 +83,14 @@ enum cam_fd_hw_irq_type {
 * @CAM_FD_HW_CMD_UPDATE_SOC        : Command to process soc update
 * @CAM_FD_HW_CMD_REGISTER_CALLBACK : Command to set hw mgr callback
 * @CAM_FD_HW_CMD_MAX               : Indicates max cmd
 * @CAM_FD_HW_CMD_HW_DUMP           : Command to dump fd hw information
 */
enum cam_fd_hw_cmd_type {
	CAM_FD_HW_CMD_PRESTART,
	CAM_FD_HW_CMD_FRAME_DONE,
	CAM_FD_HW_CMD_UPDATE_SOC,
	CAM_FD_HW_CMD_REGISTER_CALLBACK,
	CAM_FD_HW_CMD_HW_DUMP,
	CAM_FD_HW_CMD_MAX,
};

@@ -279,4 +283,32 @@ struct cam_fd_hw_cmd_set_irq_cb {
	void *data;
};

/**
 * struct cam_fd_hw_dump_args : Args for dump request
 *
 * @request_id   : Issue request id
 * @offset       : offset of the buffer
 * @buf_len      : Length of target buffer
 * @cpu_addr     : start address of the target buffer
 */
struct cam_fd_hw_dump_args {
	uint64_t  request_id;
	size_t    offset;
	size_t    buf_len;
	uintptr_t cpu_addr;
};

/**
 * struct cam_fd_hw_dump_header : fd hw dump header
 *
 * @tag       : fd hw dump header tag
 * @size      : Size of data
 * @word_size : size of each word
 */
struct cam_fd_hw_dump_header {
	uint8_t  tag[CAM_FD_HW_DUMP_TAG_MAX_LEN];
	uint64_t size;
	uint32_t word_size;
};

#endif /* _CAM_FD_HW_INTF_H_ */
Loading