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

Commit 49a213e5 authored by Jilai Wang's avatar Jilai Wang
Browse files

msm: npu: Dump debug information when IPC command times out



When IPC command times out, dump debug information including
IPC queue and GPR registers to help investigate the problem.

Change-Id: I304f6ff9e0649ef0c0c23dcbd148c3a889e1cc6b
Signed-off-by: default avatarJilai Wang <jilaiw@codeaurora.org>
parent f52b5e33
Loading
Loading
Loading
Loading
+80 −1
Original line number Diff line number Diff line
@@ -17,7 +17,7 @@
 * Function Definitions - Debug
 * -------------------------------------------------------------------------
 */
void npu_dump_debug_timeout_stats(struct npu_device *npu_dev)
static void npu_dump_debug_timeout_stats(struct npu_device *npu_dev)
{
	uint32_t reg_val;

@@ -28,3 +28,82 @@ void npu_dump_debug_timeout_stats(struct npu_device *npu_dev)
	reg_val = REGR(npu_dev, REG_NPU_FW_DEBUG_DATA);
	NPU_INFO("fw jobs aco parser debug = %d\n", reg_val);
}

void npu_dump_ipc_packet(struct npu_device *npu_dev, void *cmd_ptr)
{
	int32_t *ptr = (int32_t *)cmd_ptr;
	uint32_t cmd_pkt_size = 0;
	int i;

	cmd_pkt_size = (*(uint32_t *)cmd_ptr);

	NPU_ERR("IPC packet size %d content:\n", cmd_pkt_size);
	for (i = 0; i < cmd_pkt_size/4; i++)
		NPU_ERR("%x\n", ptr[i]);
}

static void npu_dump_ipc_queue(struct npu_device *npu_dev, uint32_t target_que)
{
	struct hfi_queue_header queue;
	size_t offset = (size_t)IPC_ADDR +
		sizeof(struct hfi_queue_tbl_header) +
		target_que * sizeof(struct hfi_queue_header);
	int32_t *ptr = (int32_t *)&queue;
	size_t content_off;
	uint32_t *content;
	int i;

	MEMR(npu_dev, (void *)((size_t)offset), (uint8_t *)&queue,
		HFI_QUEUE_HEADER_SIZE);

	NPU_ERR("DUMP IPC queue %d:\n", target_que);
	NPU_ERR("Header size %d:\n", HFI_QUEUE_HEADER_SIZE);
	NPU_ERR("Content size %d:\n", queue.qhdr_q_size);
	NPU_ERR("============QUEUE HEADER=============\n");
	for (i = 0; i < HFI_QUEUE_HEADER_SIZE/4; i++)
		NPU_ERR("%x\n", ptr[i]);

	content_off = (size_t)IPC_ADDR + queue.qhdr_start_offset;
	content = kzalloc(queue.qhdr_q_size, GFP_KERNEL);
	if (!content) {
		NPU_ERR("failed to allocate IPC queue content buffer\n");
		return;
	}

	MEMR(npu_dev, (void *)content_off, content, queue.qhdr_q_size);
	NPU_ERR("============QUEUE CONTENT=============\n");
	for (i = 0; i < queue.qhdr_q_size/4; i++)
		NPU_ERR("%x\n", content[i]);

	NPU_ERR("DUMP IPC queue %d END\n", target_que);
	kfree(content);
}

static void npu_dump_dbg_registers(struct npu_device *npu_dev)
{
	uint32_t reg_val, reg_addr;
	int i;

	NPU_ERR("============Debug Registers=============\n");
	reg_addr = NPU_GPR0;
	for (i = 0; i < 16; i++) {
		reg_val = REGR(npu_dev, reg_addr);
		NPU_ERR("npu dbg register %d : 0x%x\n", i, reg_val);
		reg_addr += 4;
	}
}

static void npu_dump_all_ipc_queue(struct npu_device *npu_dev)
{
	int i;

	for (i = 0; i < NPU_HFI_NUMBER_OF_QS; i++)
		npu_dump_ipc_queue(npu_dev, i);
}

void npu_dump_debug_info(struct npu_device *npu_dev)
{
	npu_dump_debug_timeout_stats(npu_dev);
	npu_dump_dbg_registers(npu_dev);
	npu_dump_all_ipc_queue(npu_dev);
}
+10 −6
Original line number Diff line number Diff line
@@ -1668,6 +1668,7 @@ int32_t npu_host_load_network(struct npu_client *client,
	mutex_lock(&host_ctx->lock);
	if (!ret) {
		NPU_ERR("NPU_IPC_CMD_LOAD time out\n");
		npu_dump_debug_info(npu_dev);
		ret = -ETIMEDOUT;
		goto error_free_network;
	} else if (ret < 0) {
@@ -1794,6 +1795,7 @@ int32_t npu_host_load_network_v2(struct npu_client *client,

	if (!ret) {
		NPU_ERR("npu: NPU_IPC_CMD_LOAD time out\n");
		npu_dump_debug_info(npu_dev);
		ret = -ETIMEDOUT;
		goto error_load_network;
	}
@@ -1908,6 +1910,7 @@ int32_t npu_host_unload_network(struct npu_client *client,

	if (!ret) {
		NPU_ERR("npu: NPU_IPC_CMD_UNLOAD time out\n");
		npu_dump_debug_info(npu_dev);
		network->cmd_pending = false;
		ret = -ETIMEDOUT;
		goto free_network;
@@ -2032,9 +2035,9 @@ int32_t npu_host_exec_network(struct npu_client *client,

	mutex_lock(&host_ctx->lock);
	if (!ret) {
		NPU_ERR("npu: NPU_IPC_CMD_EXECUTE time out\n");
		/* dump debug stats */
		npu_dump_debug_timeout_stats(npu_dev);
		NPU_ERR("npu: %x NPU_IPC_CMD_EXECUTE time out\n",
			network->id);
		npu_dump_debug_info(npu_dev);
		network->cmd_pending = false;
		ret = -ETIMEDOUT;
		goto exec_done;
@@ -2166,9 +2169,9 @@ int32_t npu_host_exec_network_v2(struct npu_client *client,

	mutex_lock(&host_ctx->lock);
	if (!ret) {
		NPU_ERR("npu: NPU_IPC_CMD_EXECUTE_V2 time out\n");
		/* dump debug stats */
		npu_dump_debug_timeout_stats(npu_dev);
		NPU_ERR("npu: %x NPU_IPC_CMD_EXECUTE_V2 time out\n",
			network->id);
		npu_dump_debug_info(npu_dev);
		network->cmd_pending = false;
		ret = -ETIMEDOUT;
		goto free_exec_packet;
@@ -2249,6 +2252,7 @@ int32_t npu_host_loopback_test(struct npu_device *npu_dev)

	if (!ret) {
		NPU_ERR("npu: NPU_IPC_CMD_LOOPBACK time out\n");
		npu_dump_debug_info(npu_dev);
		ret = -ETIMEDOUT;
	} else if (ret < 0) {
		NPU_ERR("Wait for loopback done interrupted by signal\n");
+2 −1
Original line number Diff line number Diff line
@@ -147,6 +147,7 @@ void npu_host_cleanup_networks(struct npu_client *client);
int npu_host_notify_fw_pwr_state(struct npu_device *npu_dev,
	uint32_t pwr_level, bool post);

void npu_dump_debug_timeout_stats(struct npu_device *npu_dev);
void npu_dump_debug_info(struct npu_device *npu_dev);
void npu_dump_ipc_packet(struct npu_device *npu_dev, void *cmd_ptr);

#endif /* _NPU_MGR_H */