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

Commit 0cd43ce6 authored by Jilai Wang's avatar Jilai Wang
Browse files

msm: npu: Fix SSR issue due to race condition



NPU SSR is handled in worker thread, so race condition can happen
between SSR thread and user app threads when SSR is triggered which
will cause unpredictable stability issue. This change is to add a
mutex to serialize npu fw init/deinit and ipc operations to resolve
this issue.

Change-Id: Ib6dcde76995193a5586a2164c12f56f8cf95518f
Signed-off-by: default avatarJilai Wang <jilaiw@codeaurora.org>
parent a0b74a09
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -227,6 +227,6 @@ int npu_set_uc_power_level(struct npu_device *npu_dev,
	uint32_t pwr_level);

int fw_init(struct npu_device *npu_dev);
void fw_deinit(struct npu_device *npu_dev, bool fw_alive);
void fw_deinit(struct npu_device *npu_dev, bool fw_alive, bool ssr);

#endif /* _NPU_COMMON_H */
+1 −1
Original line number Diff line number Diff line
@@ -374,7 +374,7 @@ static ssize_t npu_debug_ctrl_write(struct file *file,
			pr_info("error in fw_init\n");
	} else if (strcmp(buf, "off") == 0) {
		pr_info("triggering fw_deinit\n");
		fw_deinit(npu_dev, true);
		fw_deinit(npu_dev, true, false);
	} else if (strcmp(buf, "ssr") == 0) {
		pr_info("trigger error irq\n");
		if (npu_enable_core_power(npu_dev))
+0 −13
Original line number Diff line number Diff line
@@ -33,9 +33,6 @@

#define QUEUE_TBL_VERSION 0x87654321

static DEFINE_SPINLOCK(hfi_rd_lock);
static DEFINE_SPINLOCK(hfi_wr_lock);

/* -------------------------------------------------------------------------
 * Data Structures
 * -------------------------------------------------------------------------
@@ -210,7 +207,6 @@ static int ipc_queue_read(struct npu_device *npu_dev,
	uint32_t packet_size, new_read_idx;
	size_t read_ptr;
	size_t offset = 0;
	unsigned long flags;

	offset = (size_t)IPC_ADDR + sizeof(struct hfi_queue_tbl_header) +
		target_que * sizeof(struct hfi_queue_header);
@@ -218,8 +214,6 @@ static int ipc_queue_read(struct npu_device *npu_dev,
	if ((packet == NULL) || (is_tx_req_set == NULL))
		return -EINVAL;

	spin_lock_irqsave(&hfi_rd_lock, flags);

	/* Read the queue */
	MEMR(npu_dev, (void *)((size_t)offset), (uint8_t *)&queue,
		HFI_QUEUE_HEADER_SIZE);
@@ -294,8 +288,6 @@ static int ipc_queue_read(struct npu_device *npu_dev,
		(size_t)&(queue.qhdr_read_idx) - (size_t)&queue)),
		(uint8_t *)&queue.qhdr_read_idx, sizeof(queue.qhdr_read_idx));

	spin_unlock_irqrestore(&hfi_rd_lock, flags);

	return status;
}

@@ -309,7 +301,6 @@ static int ipc_queue_write(struct npu_device *npu_dev,
	uint32_t empty_space;
	void *write_ptr;
	uint32_t read_idx;
	unsigned long flags;

	size_t offset = (size_t)IPC_ADDR +
		sizeof(struct hfi_queue_tbl_header) +
@@ -318,8 +309,6 @@ static int ipc_queue_write(struct npu_device *npu_dev,
	if ((packet == NULL) || (is_rx_req_set == NULL))
		return -EINVAL;

	spin_lock_irqsave(&hfi_wr_lock, flags);

	MEMR(npu_dev, (void *)((size_t)offset), (uint8_t *)&queue,
		HFI_QUEUE_HEADER_SIZE);
	packet_size = (*(uint32_t *)packet);
@@ -395,8 +384,6 @@ static int ipc_queue_write(struct npu_device *npu_dev,
		(size_t)&(queue.qhdr_write_idx) - (size_t)&queue))),
		&queue.qhdr_write_idx, sizeof(queue.qhdr_write_idx));

	spin_unlock_irqrestore(&hfi_wr_lock, flags);

	return status;
}

+2 −0
Original line number Diff line number Diff line
@@ -121,6 +121,7 @@ void npu_interrupt_ack(struct npu_device *npu_dev, uint32_t intr_num)
	if (wdg_irq_sts != 0) {
		pr_err("wdg irq %x\n", wdg_irq_sts);
		host_ctx->wdg_irq_sts |= wdg_irq_sts;
		host_ctx->fw_error = true;
	}

	error_irq_sts = REGR(npu_dev, NPU_MASTERn_ERROR_IRQ_STATUS(0));
@@ -129,6 +130,7 @@ void npu_interrupt_ack(struct npu_device *npu_dev, uint32_t intr_num)
		REGW(npu_dev, NPU_MASTERn_ERROR_IRQ_CLEAR(0), error_irq_sts);
		pr_err("error irq %x\n", error_irq_sts);
		host_ctx->err_irq_sts |= error_irq_sts;
		host_ctx->fw_error = true;
	}
}

+134 −94
Original line number Diff line number Diff line
@@ -53,6 +53,10 @@ static void log_msg_proc(struct npu_device *npu_dev, uint32_t *msg);
static void host_session_msg_hdlr(struct npu_device *npu_dev);
static void host_session_log_hdlr(struct npu_device *npu_dev);
static int host_error_hdlr(struct npu_device *npu_dev);
static int npu_send_network_cmd(struct npu_device *npu_dev,
	struct npu_network *network, void *cmd_ptr);
static int npu_send_misc_cmd(struct npu_device *npu_dev, uint32_t q_idx,
	void *cmd_ptr);

/* -------------------------------------------------------------------------
 * Function Definitions - Init / Deinit
@@ -61,24 +65,15 @@ static int host_error_hdlr(struct npu_device *npu_dev);
int fw_init(struct npu_device *npu_dev)
{
	uint32_t reg_val = 0;
	unsigned long flags;
	struct npu_host_ctx *host_ctx = &npu_dev->host_ctx;
	int ret = 0;

	spin_lock_irqsave(&host_ctx->lock, flags);
	mutex_lock(&host_ctx->lock);
	if (host_ctx->fw_state == FW_ENABLED) {
		host_ctx->fw_ref_cnt++;
		spin_unlock_irqrestore(&host_ctx->lock, flags);
		mutex_unlock(&host_ctx->lock);
		return 0;
	} else if (host_ctx->fw_state == FW_ENABLING ||
		host_ctx->fw_state == FW_DISABLING) {
		spin_unlock_irqrestore(&host_ctx->lock, flags);
		return -EAGAIN;
	}

	host_ctx->fw_state = FW_ENABLING;
	spin_unlock_irqrestore(&host_ctx->lock, flags);

	if (npu_enable_core_power(npu_dev)) {
		ret = -EPERM;
		goto enable_pw_fail;
@@ -148,18 +143,18 @@ int fw_init(struct npu_device *npu_dev)
		goto wait_fw_ready_fail;
	}

	host_ctx->fw_state = FW_ENABLED;
	host_ctx->fw_error = false;
	host_ctx->fw_ref_cnt++;
	mutex_unlock(&host_ctx->lock);
	pr_debug("firmware init complete\n");

	/* Set logging state */
	if (!npu_hw_log_enabled()) {
		pr_debug("fw logging disabled\n");
		turn_off_fw_logging(npu_dev);
	}

	spin_lock_irqsave(&host_ctx->lock, flags);
	host_ctx->fw_state = FW_ENABLED;
	host_ctx->fw_ref_cnt++;
	spin_unlock_irqrestore(&host_ctx->lock, flags);
	pr_debug("firmware init complete\n");

	return ret;

wait_fw_ready_fail:
@@ -172,26 +167,33 @@ int fw_init(struct npu_device *npu_dev)
	npu_disable_core_power(npu_dev);
enable_pw_fail:
	host_ctx->fw_state = FW_DISABLED;
	mutex_unlock(&host_ctx->lock);
	return ret;
}

void fw_deinit(struct npu_device *npu_dev, bool fw_alive)
void fw_deinit(struct npu_device *npu_dev, bool fw_alive, bool ssr)
{
	struct npu_host_ctx *host_ctx = &npu_dev->host_ctx;
	struct ipc_cmd_shutdown_pkt cmd_shutdown_pkt;
	unsigned long flags;
	int ret = 0;
	struct npu_network *network = NULL;
	int ret = 0, i;

	spin_lock_irqsave(&host_ctx->lock, flags);
	mutex_lock(&host_ctx->lock);
	if (!ssr && (host_ctx->fw_ref_cnt > 0))
		host_ctx->fw_ref_cnt--;

	pr_debug("fw_ref_cnt %d\n", host_ctx->fw_ref_cnt);
	if ((host_ctx->fw_state != FW_ENABLED) ||
		(host_ctx->fw_ref_cnt > 0 && fw_alive)) {
		spin_unlock_irqrestore(&host_ctx->lock, flags);

	if (host_ctx->fw_state != FW_ENABLED) {
		pr_err("fw is not enabled\n");
		mutex_unlock(&host_ctx->lock);
		return;
	}

	if ((host_ctx->fw_ref_cnt > 0) && !ssr) {
		mutex_unlock(&host_ctx->lock);
		return;
	}
	host_ctx->fw_state = FW_DISABLING;
	spin_unlock_irqrestore(&host_ctx->lock, flags);

	npu_disable_irq(npu_dev);

@@ -200,7 +202,8 @@ void fw_deinit(struct npu_device *npu_dev, bool fw_alive)
		cmd_shutdown_pkt.header.cmd_type = NPU_IPC_CMD_SHUTDOWN;
		cmd_shutdown_pkt.header.size =
			sizeof(struct ipc_cmd_shutdown_pkt);
		cmd_shutdown_pkt.header.trans_id = 1;
		cmd_shutdown_pkt.header.trans_id =
			atomic_add_return(1, &host_ctx->ipc_trans_id);
		cmd_shutdown_pkt.header.flags = 0xF;
		ret = npu_host_ipc_send_cmd(npu_dev,
			IPC_QUEUE_CMD_HIGH_PRIORITY, &cmd_shutdown_pkt);
@@ -226,6 +229,16 @@ void fw_deinit(struct npu_device *npu_dev, bool fw_alive)
	host_ctx->fw_state = FW_DISABLED;
	npu_disable_core_power(npu_dev);

	if (ssr) {
		/* mark all existing network to error state */
		for (i = 0; i < MAX_LOADED_NETWORK; i++) {
			network = &host_ctx->networks[i];
			if (network->is_valid)
				network->fw_error = true;
		}
	}

	mutex_unlock(&host_ctx->lock);
	pr_debug("firmware deinit complete\n");
	return;
}
@@ -235,14 +248,9 @@ int npu_host_init(struct npu_device *npu_dev)
	int sts = 0;
	struct npu_host_ctx *host_ctx = &npu_dev->host_ctx;

	memset(host_ctx, 0, sizeof(*host_ctx));
	init_completion(&host_ctx->loopback_done);

	host_ctx->sys_cache_disable = 0;
	spin_lock_init(&host_ctx->lock);
	host_ctx->fw_state = FW_DISABLED;
	host_ctx->fw_ref_cnt = 0;
	host_ctx->exec_flags_override = 0;
	host_ctx->fw_dbg_mode = 0;
	mutex_init(&host_ctx->lock);
	atomic_set(&host_ctx->ipc_trans_id, 1);

	host_ctx->wq = npu_create_wq(host_ctx, "irq_hdl", host_irq_wq,
@@ -258,6 +266,7 @@ void npu_host_deinit(struct npu_device *npu_dev)
	struct npu_host_ctx *host_ctx = &npu_dev->host_ctx;

	npu_destroy_wq(host_ctx->wq);
	mutex_destroy(&host_ctx->lock);
}

/* -------------------------------------------------------------------------
@@ -299,21 +308,19 @@ static int host_error_hdlr(struct npu_device *npu_dev)
		fw_alive = false;
	}

	fw_deinit(npu_dev, fw_alive);
	fw_init(npu_dev);

	fw_deinit(npu_dev, fw_alive, true);
	host_ctx->wdg_irq_sts = 0;
	host_ctx->err_irq_sts = 0;

	/* flush all pending npu cmds with error */
	/* flush all pending npu cmds */
	for (i = 0; i < MAX_LOADED_NETWORK; i++) {
		network = &host_ctx->networks[i];
		if (network->id != 0) {
			network->fw_error = true;
		if (network->is_valid && network->cmd_pending &&
			network->fw_error) {
			pr_debug("complete network %x\n", network->id);
			complete(&network->cmd_done);
		}
	}

	complete_all(&host_ctx->loopback_done);

	return 1;
@@ -337,15 +344,17 @@ static void host_irq_wq(struct work_struct *work)
static void turn_off_fw_logging(struct npu_device *npu_dev)
{
	struct ipc_cmd_log_state_pkt log_packet;
	struct npu_host_ctx *host_ctx = &npu_dev->host_ctx;
	int ret = 0;

	log_packet.header.cmd_type = NPU_IPC_CMD_CONFIG_LOG;
	log_packet.header.size = sizeof(struct ipc_cmd_log_state_pkt);
	log_packet.header.trans_id = 1;
	log_packet.header.trans_id =
		atomic_add_return(1, &host_ctx->ipc_trans_id);
	log_packet.header.flags = 0xF;
	log_packet.log_state.module_msk = 0;
	log_packet.log_state.level_msk = 0;
	ret = npu_host_ipc_send_cmd(npu_dev, IPC_QUEUE_CMD_HIGH_PRIORITY,
	ret = npu_send_misc_cmd(npu_dev, IPC_QUEUE_CMD_HIGH_PRIORITY,
		&log_packet);

	pr_debug("NPU_IPC_CMD_CONFIG_LOG sent status: %d\n", ret);
@@ -386,9 +395,8 @@ static struct npu_network *alloc_network(struct npu_host_ctx *ctx)
{
	int32_t i;
	struct npu_network *network = ctx->networks;
	unsigned long flags;

	spin_lock_irqsave(&ctx->lock, flags);
	mutex_lock(&ctx->lock);
	for (i = 0; i < MAX_LOADED_NETWORK; i++) {
		if (network->id == 0) {
			network->id = i + 1;
@@ -401,12 +409,13 @@ static struct npu_network *alloc_network(struct npu_host_ctx *ctx)
		network = NULL;
	else
		ctx->network_num++;
	spin_unlock_irqrestore(&ctx->lock, flags);
	mutex_unlock(&ctx->lock);

	if (network) {
		init_completion(&network->cmd_done);
		network->is_valid = true;
		network->fw_error = false;
		network->cmd_pending = false;
	}

	return network;
@@ -447,13 +456,12 @@ static struct npu_network *get_network_by_id(struct npu_host_ctx *ctx,
static void free_network(struct npu_host_ctx *ctx, int64_t id)
{
	struct npu_network *network = get_network_by_id(ctx, id);
	unsigned long flags;

	if (network) {
		spin_lock_irqsave(&ctx->lock, flags);
		mutex_lock(&ctx->lock);
		memset(network, 0, sizeof(struct npu_network));
		ctx->network_num--;
		spin_unlock_irqrestore(&ctx->lock, flags);
		mutex_unlock(&ctx->lock);
	}
}

@@ -492,7 +500,7 @@ static void app_msg_proc(struct npu_host_ctx *host_ctx, uint32_t *msg)
				exe_rsp_pkt->network_hdl);
			break;
		}

		network->cmd_pending = false;
		complete(&network->cmd_done);
		break;
	}
@@ -524,6 +532,7 @@ static void app_msg_proc(struct npu_host_ctx *host_ctx, uint32_t *msg)
			memcpy(network->stats_buf, exe_rsp_pkt->stats_data,
				stats_size);

		network->cmd_pending = false;
		complete(&network->cmd_done);
		break;
	}
@@ -549,6 +558,7 @@ static void app_msg_proc(struct npu_host_ctx *host_ctx, uint32_t *msg)
			break;
		}
		network->network_hdl = load_rsp_pkt->network_hdl;
		network->cmd_pending = false;
		complete(&network->cmd_done);
		break;
	}
@@ -569,6 +579,7 @@ static void app_msg_proc(struct npu_host_ctx *host_ctx, uint32_t *msg)
			break;
		}

		network->cmd_pending = false;
		complete(&network->cmd_done);
		break;
	}
@@ -667,6 +678,50 @@ int32_t npu_host_unmap_buf(struct npu_device *npu_dev,
	return 0;
}

static int npu_send_network_cmd(struct npu_device *npu_dev,
	struct npu_network *network, void *cmd_ptr)
{
	struct npu_host_ctx *host_ctx = &npu_dev->host_ctx;
	int ret = 0;

	mutex_lock(&host_ctx->lock);
	if (network->fw_error || host_ctx->fw_error ||
		(host_ctx->fw_state == FW_DISABLED)) {
		pr_err("fw is in error state or disabled, can't send network cmd\n");
		ret = -EIO;
	} else {
		pr_debug("Send cmd %d\n",
			((struct ipc_cmd_header_pkt *)cmd_ptr)->cmd_type);
		ret = npu_host_ipc_send_cmd(npu_dev,
			IPC_QUEUE_APPS_EXEC, cmd_ptr);
		if (!ret)
			network->cmd_pending = true;
	}
	mutex_unlock(&host_ctx->lock);

	return ret;
}

static int npu_send_misc_cmd(struct npu_device *npu_dev, uint32_t q_idx,
	void *cmd_ptr)
{
	struct npu_host_ctx *host_ctx = &npu_dev->host_ctx;
	int ret = 0;

	mutex_lock(&host_ctx->lock);
	if (host_ctx->fw_error || (host_ctx->fw_state == FW_DISABLED)) {
		pr_err("fw is in error state or disabled, can't send misc cmd\n");
		ret = -EIO;
	} else {
		pr_debug("Send cmd %d\n",
			((struct ipc_cmd_header_pkt *)cmd_ptr)->cmd_type);
		ret = npu_host_ipc_send_cmd(npu_dev, q_idx, cmd_ptr);
	}
	mutex_unlock(&host_ctx->lock);

	return ret;
}

static void host_copy_patch_data(struct npu_patch_tuple *param, uint32_t value,
		struct msm_npu_layer *layer_info)
{
@@ -775,13 +830,9 @@ int32_t npu_host_load_network(struct npu_device *npu_dev,

	/* NPU_IPC_CMD_LOAD will go onto IPC_QUEUE_APPS_EXEC */
	reinit_completion(&network->cmd_done);
	ret = npu_host_ipc_send_cmd(npu_dev,
		IPC_QUEUE_APPS_EXEC, &load_packet);

	pr_debug("NPU_IPC_CMD_LOAD sent status: %d\n", ret);

	ret = npu_send_network_cmd(npu_dev, network, &load_packet);
	if (ret) {
		ret = -EIO;
		pr_err("NPU_IPC_CMD_LOAD sent failed: %d\n", ret);
		goto error_free_network;
	}

@@ -805,7 +856,7 @@ int32_t npu_host_load_network(struct npu_device *npu_dev,
error_free_network:
	free_network(host_ctx, network->id);
err_deinit_fw:
	fw_deinit(npu_dev, true);
	fw_deinit(npu_dev, true, false);
	return ret;
}

@@ -875,13 +926,9 @@ int32_t npu_host_load_network_v2(struct npu_device *npu_dev,

	/* NPU_IPC_CMD_LOAD_V2 will go onto IPC_QUEUE_APPS_EXEC */
	reinit_completion(&network->cmd_done);
	ret = npu_host_ipc_send_cmd(npu_dev,
		IPC_QUEUE_APPS_EXEC, load_packet);

	pr_debug("NPU_IPC_CMD_LOAD_V2 sent status: %d\n", ret);

	ret = npu_send_network_cmd(npu_dev, network, load_packet);
	if (ret) {
		ret = -EIO;
		pr_debug("NPU_IPC_CMD_LOAD_V2 sent failed: %d\n", ret);
		goto error_free_network;
	}

@@ -906,7 +953,7 @@ int32_t npu_host_load_network_v2(struct npu_device *npu_dev,
	kfree(load_packet);
	free_network(host_ctx, network->id);
err_deinit_fw:
	fw_deinit(npu_dev, true);
	fw_deinit(npu_dev, true, false);
	return ret;
}

@@ -938,15 +985,12 @@ int32_t npu_host_unload_network(struct npu_device *npu_dev,

	/* NPU_IPC_CMD_UNLOAD will go onto IPC_QUEUE_APPS_EXEC */
	reinit_completion(&network->cmd_done);
	ret = npu_host_ipc_send_cmd(npu_dev, IPC_QUEUE_APPS_EXEC,
		&unload_packet);
	ret = npu_send_network_cmd(npu_dev, network, &unload_packet);

	if (ret) {
		pr_err("NPU_IPC_CMD_UNLOAD sent failed: %d\n", ret);
		return -EIO;
	}

	if (!wait_for_completion_interruptible_timeout(&network->cmd_done,
	} else if (!wait_for_completion_interruptible_timeout(
		&network->cmd_done,
		(host_ctx->fw_dbg_mode & FW_DBG_MODE_INC_TIMEOUT) ?
		NW_DEBUG_TIMEOUT : NW_CMD_TIMEOUT)) {
		pr_err_ratelimited("npu: NPU_IPC_CMD_UNLOAD time out\n");
@@ -962,8 +1006,7 @@ int32_t npu_host_unload_network(struct npu_device *npu_dev,
	 * handle is unloaded on the firmware side
	 */
	free_network(host_ctx, network->id);
	fw_deinit(npu_dev, true);

	fw_deinit(npu_dev, true, false);
	return ret;
}

@@ -1014,11 +1057,11 @@ int32_t npu_host_exec_network(struct npu_device *npu_dev,

	/* Send it on the high priority queue */
	reinit_completion(&network->cmd_done);
	ret = npu_host_ipc_send_cmd(npu_dev, IPC_QUEUE_APPS_EXEC, &exec_packet);

	pr_debug("NPU_IPC_CMD_EXECUTE sent status: %d\n", ret);
	ret = npu_send_network_cmd(npu_dev, network, &exec_packet);

	if (!wait_for_completion_interruptible_timeout(
	if (ret) {
		pr_err("NPU_IPC_CMD_EXECUTE sent failed: %d\n", ret);
	} else if (!wait_for_completion_interruptible_timeout(
		&network->cmd_done,
		(host_ctx->fw_dbg_mode & FW_DBG_MODE_INC_TIMEOUT) ?
		NW_DEBUG_TIMEOUT : NW_CMD_TIMEOUT)) {
@@ -1029,8 +1072,7 @@ int32_t npu_host_exec_network(struct npu_device *npu_dev,
	} else if (network->fw_error) {
		ret = -EIO;
		pr_err("execute cmd returns with error\n");
	}

	} else {
		/* Invalidate output buffers */
		for (i = 0; i < exec_ioctl->output_layer_num; i++) {
			if (exec_ioctl->output_layer_num == 1) {
@@ -1038,6 +1080,7 @@ int32_t npu_host_exec_network(struct npu_device *npu_dev,
					exec_ioctl->output_layers[i].buf_hdl);
			}
		}
	}

	return ret;
}
@@ -1100,11 +1143,11 @@ int32_t npu_host_exec_network_v2(struct npu_device *npu_dev,

	/* Send it on the high priority queue */
	reinit_completion(&network->cmd_done);
	ret = npu_host_ipc_send_cmd(npu_dev, IPC_QUEUE_APPS_EXEC, exec_packet);

	pr_debug("NPU_IPC_CMD_EXECUTE_V2 sent status: %d\n", ret);
	ret = npu_send_network_cmd(npu_dev, network, exec_packet);

	if (!wait_for_completion_interruptible_timeout(
	if (ret) {
		pr_err("NPU_IPC_CMD_EXECUTE_V2 sent failed: %d\n", ret);
	} else if (!wait_for_completion_interruptible_timeout(
		&network->cmd_done,
		(host_ctx->fw_dbg_mode & FW_DBG_MODE_INC_TIMEOUT) ?
		NW_DEBUG_TIMEOUT : NW_CMD_TIMEOUT)) {
@@ -1115,9 +1158,7 @@ int32_t npu_host_exec_network_v2(struct npu_device *npu_dev,
	} else if (network->fw_error) {
		ret = -EIO;
		pr_err("execute cmd returns with error\n");
	}

	if (!ret) {
	} else {
		exec_ioctl->stats_buf_size = network->stats_buf_size;
		if (exec_ioctl->stats_buf_size) {
			if (copy_to_user(
@@ -1150,8 +1191,7 @@ int32_t npu_host_loopback_test(struct npu_device *npu_dev)
	loopback_packet.loopbackParams = 15;

	reinit_completion(&host_ctx->loopback_done);
	ret = npu_host_ipc_send_cmd(npu_dev,
		 IPC_QUEUE_APPS_EXEC, &loopback_packet);
	ret = npu_send_misc_cmd(npu_dev, IPC_QUEUE_APPS_EXEC, &loopback_packet);

	if (ret) {
		pr_err("NPU_IPC_CMD_LOOPBACK sent failed: %d\n", ret);
@@ -1163,7 +1203,7 @@ int32_t npu_host_loopback_test(struct npu_device *npu_dev)
		ret = -ETIMEDOUT;
	}

	fw_deinit(npu_dev, true);
	fw_deinit(npu_dev, true, false);

	return ret;
}
Loading