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

Commit dac0b6c8 authored by Lakshmi Narayana Kalavala's avatar Lakshmi Narayana Kalavala Committed by Karthik Anantha Ram
Browse files

msm: camera: icp: Enable HFI debug queue



Enabled HFI debug queue which logs the result for every
transaction with firmware. Debug msg interrupt raised
when debug queue size drops below water mark value. This
helps with debugging firmware related transactions. Also
updated processing of the queues as chunks of messages
than a single message.

To enable debug messages from firmware
echo 1 > /sys/kernel/debug/camera_icp/a5_debug_q

To enable A5 Jtag debugging
echo 1 > /sys/kernel/debug/camera_icp/a5_jtag_debug

To set debug level mask
echo $masked_value > /sys/kernel/debug/camera_icp/a5_debug_lvl

To enable trace_event
echo 1 > /sys/kernel/debug/tracing/events/camera/cam_icp_fw_dbg/enable
echo 1 > /sys/kernel/debug/tracing/tracing_on

Change-Id: I86fd4b6d345f3cb02b30d56aedf4b512d6d269e8
Signed-off-by: default avatarLakshmi Narayana Kalavala <lkalaval@codeaurora.org>
Signed-off-by: default avatarKarthik Anantha Ram <kartanan@codeaurora.org>
parent 8c2eea77
Loading
Loading
Loading
Loading
+7 −2
Original line number Diff line number Diff line
@@ -61,9 +61,9 @@ int hfi_write_cmd(void *cmd_ptr);
 * @pmsg: buffer to place read message for hfi queue
 * @q_id: queue id
 *
 * Returns success(zero)/failure(non zero)
 * Returns size read in words/failure(negative value)
 */
int hfi_read_message(uint32_t *pmsg, uint8_t q_id);
int64_t hfi_read_message(uint32_t *pmsg, uint8_t q_id);

/**
 * hfi_init() - function initialize hfi after firmware download
@@ -109,6 +109,11 @@ void cam_hfi_disable_cpu(void __iomem *icp_base);
 * cam_hfi_deinit() - cleanup HFI
 */
void cam_hfi_deinit(void);
/**
 * hfi_set_debug_level() - set debug level
 * @lvl: FW debug message level
 */
int hfi_set_debug_level(uint32_t lvl);

/**
 * hfi_enable_ipe_bps_pc() - Enable interframe pc
+4 −3
Original line number Diff line number Diff line
@@ -60,11 +60,11 @@

#define ICP_CMD_Q_SIZE_IN_BYTES                 4096
#define ICP_MSG_Q_SIZE_IN_BYTES                 4096
#define ICP_DBG_Q_SIZE_IN_BYTES                 8192
#define ICP_DBG_Q_SIZE_IN_BYTES                 102400

#define ICP_SHARED_MEM_IN_BYTES                 (1024 * 1024)
#define ICP_UNCACHED_HEAP_SIZE_IN_BYTES         (2 * 1024 * 1024)
#define ICP_HFI_MAX_MSG_SIZE_IN_WORDS           128
#define ICP_HFI_MAX_PKT_SIZE_IN_WORDS           25600

#define ICP_HFI_QTBL_HOSTID1                    0x01000000
#define ICP_HFI_QTBL_STATUS_ENABLED             0x00000001
@@ -109,7 +109,8 @@ enum hfi_state {
 */
enum reg_settings {
	RESET,
	SET
	SET,
	SET_WM = 1024
};

/**
+62 −23
Original line number Diff line number Diff line
@@ -119,13 +119,13 @@ int hfi_write_cmd(void *cmd_ptr)
	return rc;
}

int hfi_read_message(uint32_t *pmsg, uint8_t q_id)
int64_t hfi_read_message(uint32_t *pmsg, uint8_t q_id)
{
	struct hfi_qtbl *q_tbl_ptr;
	struct hfi_q_hdr *q;
	uint32_t new_read_idx, size_in_words, temp;
	uint32_t *read_q, *read_ptr;
	int rc = 0;
	uint32_t new_read_idx, size_in_words, word_diff, temp;
	uint32_t *read_q, *read_ptr, *write_ptr;
	int64_t rc = 0;

	if (!pmsg) {
		CAM_ERR(CAM_HFI, "Invalid msg");
@@ -168,10 +168,23 @@ int hfi_read_message(uint32_t *pmsg, uint8_t q_id)
		read_q = (uint32_t *)g_hfi->map.dbg_q.kva;

	read_ptr = (uint32_t *)(read_q + q->qhdr_read_idx);
	write_ptr = (uint32_t *)(read_q + q->qhdr_write_idx);
	size_in_words = (*read_ptr) >> BYTE_WORD_SHIFT;

	if (write_ptr > read_ptr)
		size_in_words = write_ptr - read_ptr;
	else {
		word_diff = read_ptr - write_ptr;
		if (q_id == Q_MSG)
			size_in_words = (ICP_MSG_Q_SIZE_IN_BYTES >>
			BYTE_WORD_SHIFT) - word_diff;
		else
			size_in_words = (ICP_DBG_Q_SIZE_IN_BYTES >>
			BYTE_WORD_SHIFT) - word_diff;
	}

	if ((size_in_words == 0) ||
		(size_in_words > ICP_HFI_MAX_MSG_SIZE_IN_WORDS)) {
		(size_in_words > ICP_HFI_MAX_PKT_SIZE_IN_WORDS)) {
		CAM_ERR(CAM_HFI, "invalid HFI message packet size - 0x%08x",
			size_in_words << BYTE_WORD_SHIFT);
		q->qhdr_read_idx = q->qhdr_write_idx;
@@ -192,6 +205,7 @@ int hfi_read_message(uint32_t *pmsg, uint8_t q_id)
	}

	q->qhdr_read_idx = new_read_idx;
	rc = size_in_words;
err:
	mutex_unlock(&hfi_msg_q_mutex);
	return rc;
@@ -223,6 +237,45 @@ int hfi_enable_ipe_bps_pc(bool enable)
	return 0;
}

int hfi_set_debug_level(uint32_t lvl)
{
	uint8_t *prop;
	struct hfi_cmd_prop *dbg_prop;
	uint32_t size = 0, val;

	val = HFI_DEBUG_MSG_LOW |
		HFI_DEBUG_MSG_MEDIUM |
		HFI_DEBUG_MSG_HIGH |
		HFI_DEBUG_MSG_ERROR |
		HFI_DEBUG_MSG_FATAL |
		HFI_DEBUG_MSG_PERF |
		HFI_DEBUG_CFG_WFI |
		HFI_DEBUG_CFG_ARM9WD;

	if (lvl > val)
		return -EINVAL;

	size = sizeof(struct hfi_cmd_prop) +
		sizeof(struct hfi_debug);

	prop = kzalloc(size, GFP_KERNEL);
	if (!prop)
		return -ENOMEM;

	dbg_prop = (struct hfi_cmd_prop *)prop;
	dbg_prop->size = size;
	dbg_prop->pkt_type = HFI_CMD_SYS_SET_PROPERTY;
	dbg_prop->num_prop = 1;
	dbg_prop->prop_data[0] = HFI_PROP_SYS_DEBUG_CFG;
	dbg_prop->prop_data[1] = lvl;
	dbg_prop->prop_data[2] = HFI_DEBUG_MODE_QUEUE;

	hfi_write_cmd(prop);
	kfree(prop);

	return 0;
}

void hfi_send_system_cmd(uint32_t type, uint64_t data, uint32_t size)
{
	switch (type) {
@@ -456,8 +509,8 @@ int cam_hfi_init(uint8_t event_driven_mode, struct hfi_mem_info *hfi_mem,

		dbg_q_hdr->qhdr_type = Q_DBG;
		dbg_q_hdr->qhdr_rx_wm = SET;
		dbg_q_hdr->qhdr_tx_wm = SET;
		dbg_q_hdr->qhdr_rx_req = SET;
		dbg_q_hdr->qhdr_tx_wm = SET_WM;
		dbg_q_hdr->qhdr_rx_req = RESET;
		dbg_q_hdr->qhdr_tx_req = RESET;
		dbg_q_hdr->qhdr_rx_irq_status = RESET;
		dbg_q_hdr->qhdr_tx_irq_status = RESET;
@@ -495,8 +548,8 @@ int cam_hfi_init(uint8_t event_driven_mode, struct hfi_mem_info *hfi_mem,
		dbg_q_hdr->qhdr_type = Q_DBG | TX_EVENT_DRIVEN_MODE_2 |
			RX_EVENT_DRIVEN_MODE_2;
		dbg_q_hdr->qhdr_rx_wm = SET;
		dbg_q_hdr->qhdr_tx_wm = SET;
		dbg_q_hdr->qhdr_rx_req = SET;
		dbg_q_hdr->qhdr_tx_wm = SET_WM;
		dbg_q_hdr->qhdr_rx_req = RESET;
		dbg_q_hdr->qhdr_tx_req = RESET;
		dbg_q_hdr->qhdr_rx_irq_status = RESET;
		dbg_q_hdr->qhdr_tx_irq_status = RESET;
@@ -574,17 +627,3 @@ void cam_hfi_deinit(void)
	mutex_unlock(&hfi_cmd_q_mutex);
	mutex_unlock(&hfi_msg_q_mutex);
}

void icp_enable_fw_debug(void)
{
	hfi_send_system_cmd(HFI_CMD_SYS_SET_PROPERTY,
		(uint64_t)HFI_PROP_SYS_DEBUG_CFG, 0);
}

int icp_ping_fw(void)
{
	hfi_send_system_cmd(HFI_CMD_SYS_PING,
		(uint64_t)0x12123434, 0);

	return 0;
}
+139 −29
Original line number Diff line number Diff line
@@ -46,6 +46,7 @@
#include "hfi_sys_defs.h"
#include "cam_debug_util.h"
#include "cam_soc_util.h"
#include "cam_trace.h"

#define ICP_WORKQ_TASK_CMD_TYPE 1
#define ICP_WORKQ_TASK_MSG_TYPE 2
@@ -790,6 +791,21 @@ DEFINE_SIMPLE_ATTRIBUTE(cam_icp_debug_default_clk,
	cam_icp_get_dbg_default_clk,
	cam_icp_set_dbg_default_clk, "%16llu");

static int cam_icp_set_a5_dbg_lvl(void *data, u64 val)
{
	icp_hw_mgr.a5_dbg_lvl = val;
	return 0;
}

static int cam_icp_get_a5_dbg_lvl(void *data, u64 *val)
{
	*val = icp_hw_mgr.a5_dbg_lvl;
	return 0;
}

DEFINE_SIMPLE_ATTRIBUTE(cam_icp_debug_fs, cam_icp_get_a5_dbg_lvl,
	cam_icp_set_a5_dbg_lvl, "%08llu");

static int cam_icp_hw_mgr_create_debugfs_entry(void)
{
	int rc = 0;
@@ -798,15 +814,6 @@ static int cam_icp_hw_mgr_create_debugfs_entry(void)
	if (!icp_hw_mgr.dentry)
		return -ENOMEM;

	if (!debugfs_create_bool("a5_debug",
		0644,
		icp_hw_mgr.dentry,
		&icp_hw_mgr.a5_debug)) {
		debugfs_remove_recursive(icp_hw_mgr.dentry);
		rc = -ENOMEM;
		goto err;
	}

	if (!debugfs_create_bool("icp_pc",
		0644,
		icp_hw_mgr.dentry,
@@ -825,6 +832,32 @@ static int cam_icp_hw_mgr_create_debugfs_entry(void)
		goto err;
	}

	if (!debugfs_create_bool("a5_jtag_debug",
		0644,
		icp_hw_mgr.dentry,
		&icp_hw_mgr.a5_jtag_debug)) {
		rc = -ENOMEM;
		goto err;
	}

	if (!debugfs_create_bool("a5_debug_q",
		0644,
		icp_hw_mgr.dentry,
		&icp_hw_mgr.a5_debug_q)) {
		CAM_ERR(CAM_ICP, "failed to create a5_debug_q\n");
		rc = -ENOMEM;
		goto err;
	}

	if (!debugfs_create_file("a5_debug_lvl",
		0644,
		icp_hw_mgr.dentry,
		NULL, &cam_icp_debug_fs)) {
		CAM_ERR(CAM_ICP, "failed to create a5_dbg_lvl\n");
		rc = -ENOMEM;
		goto err;
	}

	return rc;
err:
	debugfs_remove_recursive(icp_hw_mgr.dentry);
@@ -1091,56 +1124,81 @@ static int cam_icp_mgr_process_direct_ack_msg(uint32_t *msg_ptr)
	return rc;
}

static int32_t cam_icp_mgr_process_msg(void *priv, void *data)
static void cam_icp_mgr_process_dbg_buf(void)
{
	int rc = 0;
	uint32_t *msg_ptr = NULL;
	struct hfi_msg_work_data *task_data;
	struct cam_icp_hw_mgr *hw_mgr;
	int read_len;
	uint32_t *msg_ptr = NULL, *pkt_ptr = NULL;
	struct hfi_msg_debug *dbg_msg;
	int64_t read_len, size_processed = 0;
	char *dbg_buf;

	if (!data || !priv) {
		CAM_ERR(CAM_ICP, "Invalid data");
		return -EINVAL;
	}

	task_data = data;
	hw_mgr = priv;
	read_len = hfi_read_message(icp_hw_mgr.dbg_buf, Q_DBG);
	if (read_len < 0)
		return;

	read_len = hfi_read_message(icp_hw_mgr.msg_buf, Q_MSG);
	if (read_len < 0) {
		CAM_DBG(CAM_ICP, "Unable to read msg q");
		return read_len;
	msg_ptr = (uint32_t *)icp_hw_mgr.dbg_buf;
	while (true) {
		pkt_ptr = msg_ptr;
		if (pkt_ptr[ICP_PACKET_TYPE] == HFI_MSG_SYS_DEBUG) {
			dbg_msg = (struct hfi_msg_debug *)pkt_ptr;
			dbg_buf = (char *)&dbg_msg->msg_data;
			trace_cam_icp_fw_dbg(dbg_buf);
		}
		size_processed += (pkt_ptr[ICP_PACKET_SIZE] >>
			BYTE_WORD_SHIFT);
		if (size_processed >= read_len)
			return;
		msg_ptr += (pkt_ptr[ICP_PACKET_SIZE] >>
		BYTE_WORD_SHIFT);
		pkt_ptr = NULL;
		dbg_msg = NULL;
		dbg_buf = NULL;
	}
}

	msg_ptr = (uint32_t *)icp_hw_mgr.msg_buf;
static int cam_icp_process_msg_pkt_type(
	struct cam_icp_hw_mgr *hw_mgr,
	uint32_t *msg_ptr)
{
	int rc = 0;
	int size_processed = 0;
	struct hfi_msg_ipebps_async_ack *async_ack = NULL;

	switch (msg_ptr[ICP_PACKET_TYPE]) {
	case HFI_MSG_SYS_INIT_DONE:
		CAM_DBG(CAM_ICP, "received SYS_INIT_DONE");
		complete(&hw_mgr->a5_complete);
		size_processed = sizeof(struct hfi_msg_init_done);
		break;

	case HFI_MSG_SYS_PING_ACK:
		CAM_DBG(CAM_ICP, "received SYS_PING_ACK");
		rc = cam_icp_mgr_process_msg_ping_ack(msg_ptr);
		size_processed = sizeof(struct hfi_msg_ping_ack);
		break;

	case HFI_MSG_IPEBPS_CREATE_HANDLE_ACK:
		CAM_DBG(CAM_ICP, "received IPEBPS_CREATE_HANDLE_ACK");
		rc = cam_icp_mgr_process_msg_create_handle(msg_ptr);
		size_processed = sizeof(struct hfi_msg_create_handle_ack);
		break;

	case HFI_MSG_IPEBPS_ASYNC_COMMAND_INDIRECT_ACK:
		CAM_DBG(CAM_ICP, "received ASYNC_INDIRECT_ACK");
		rc = cam_icp_mgr_process_indirect_ack_msg(msg_ptr);
		async_ack = (struct hfi_msg_ipebps_async_ack *)msg_ptr;
		size_processed = async_ack->size;
		async_ack = NULL;
		break;

	case  HFI_MSG_IPEBPS_ASYNC_COMMAND_DIRECT_ACK:
		CAM_DBG(CAM_ICP, "received ASYNC_DIRECT_ACK");
		rc = cam_icp_mgr_process_direct_ack_msg(msg_ptr);
		size_processed = sizeof(struct hfi_msg_ipebps_async_ack);
		break;

	case HFI_MSG_EVENT_NOTIFY:
		CAM_DBG(CAM_ICP, "received EVENT_NOTIFY");
		size_processed = sizeof(struct hfi_msg_event_notify);
		break;

	default:
@@ -1150,6 +1208,53 @@ static int32_t cam_icp_mgr_process_msg(void *priv, void *data)
		break;
	}

	if (rc)
		return rc;

	return size_processed;
}

static int32_t cam_icp_mgr_process_msg(void *priv, void *data)
{
	int64_t read_len, msg_processed_len;
	int rc = 0;
	uint32_t *msg_ptr = NULL;
	struct hfi_msg_work_data *task_data;
	struct cam_icp_hw_mgr *hw_mgr;

	if (!data || !priv) {
		CAM_ERR(CAM_ICP, "Invalid data");
		return -EINVAL;
	}

	task_data = data;
	hw_mgr = priv;

	read_len = hfi_read_message(icp_hw_mgr.msg_buf, Q_MSG);
	if (read_len < 0) {
		rc = read_len;
		CAM_DBG(CAM_ICP, "Unable to read msg q");
	} else {
		msg_ptr = (uint32_t *)icp_hw_mgr.msg_buf;
		while (true) {
			msg_processed_len = cam_icp_process_msg_pkt_type(
			hw_mgr, msg_ptr);
			if (msg_processed_len < 0) {
				rc = msg_processed_len;
				return rc;
			}

			read_len -= msg_processed_len;
			if (read_len > 0)
				msg_ptr += msg_processed_len;
			else
				break;
		}
	}

	if (icp_hw_mgr.a5_debug_q)
		cam_icp_mgr_process_dbg_buf();

	return rc;
}

@@ -1706,7 +1811,7 @@ static int cam_icp_mgr_hfi_init(struct cam_icp_hw_mgr *hw_mgr)

	return cam_hfi_init(0, &hfi_mem,
		a5_dev->soc_info.reg_map[A5_SIERRA_BASE].mem_base,
		hw_mgr->a5_debug);
		hw_mgr->a5_jtag_debug);
}

static int cam_icp_mgr_send_fw_init(struct cam_icp_hw_mgr *hw_mgr)
@@ -1804,10 +1909,15 @@ static int cam_icp_mgr_download_fw(void *hw_mgr_priv, void *download_fw_args)
		NULL, 0);
	hw_mgr->fw_download = true;
	hw_mgr->ctxt_cnt = 0;
	mutex_unlock(&hw_mgr->hw_mgr_mutex);
	CAM_DBG(CAM_ICP, "FW download done successfully");

	if (icp_hw_mgr.a5_debug_q)
		hfi_set_debug_level(icp_hw_mgr.a5_dbg_lvl);

	mutex_unlock(&hw_mgr->hw_mgr_mutex);
	if (!download_fw_args)
		cam_icp_mgr_hw_close(hw_mgr, NULL);

	return rc;

fw_init_failed:
+10 −2
Original line number Diff line number Diff line
@@ -44,6 +44,8 @@

#define ICP_FRAME_PROCESS_SUCCESS 0
#define ICP_FRAME_PROCESS_FAILURE 1
#define ICP_MSG_BUF_SIZE        256
#define ICP_DBG_BUF_SIZE        102400

#define ICP_CLK_HW_IPE          0x0
#define ICP_CLK_HW_BPS          0x1
@@ -230,6 +232,9 @@ struct cam_icp_clk_info {
 * @icp_default_clk: Set this clok if user doesn't supply
 * @clk_info: Clock info of hardware
 * @secure_mode: Flag to enable/disable secure camera
 * @a5_jtag_debug: entry to enable A5 JTAG debugging
 * @a5_debug_q : entry to enable FW debug message
 * @a5_dbg_lvl : debug level set to FW.
 */
struct cam_icp_hw_mgr {
	struct mutex hw_mgr_mutex;
@@ -245,8 +250,8 @@ struct cam_icp_hw_mgr {
	struct icp_hfi_mem_info hfi_mem;
	struct cam_req_mgr_core_workq *cmd_work;
	struct cam_req_mgr_core_workq *msg_work;
	uint32_t msg_buf[256];
	uint32_t dbg_buf[256];
	uint32_t msg_buf[ICP_MSG_BUF_SIZE];
	uint32_t dbg_buf[ICP_DBG_BUF_SIZE];
	struct completion a5_complete;
	struct hfi_cmd_work_data *cmd_work_data;
	struct hfi_msg_work_data *msg_work_data;
@@ -260,6 +265,9 @@ struct cam_icp_hw_mgr {
	uint64_t icp_default_clk;
	struct cam_icp_clk_info clk_info[ICP_CLK_HW_MAX];
	bool secure_mode;
	bool a5_jtag_debug;
	bool a5_debug_q;
	u64 a5_dbg_lvl;
};

static int cam_icp_mgr_hw_close(void *hw_priv, void *hw_close_args);
Loading