Merge "msm: npu: fix network and misc commands race condition problem"

This commit is contained in:
qctecmdr 2021-12-19 03:19:35 -08:00 • committed by Gerrit - the friendly Code Review server
commit 7fbe930d38
2 changed files with 50 additions and 22 deletions

View file

@ -292,9 +292,8 @@ int npu_host_init(struct npu_device *npu_dev)
struct npu_host_ctx *host_ctx = &npu_dev->host_ctx;
memset(host_ctx, 0, sizeof(*host_ctx));
init_completion(&host_ctx->loopback_done);
init_completion(&host_ctx->misc_done);
init_completion(&host_ctx->fw_deinit_done);
init_completion(&host_ctx->property_done);
mutex_init(&host_ctx->lock);
atomic_set(&host_ctx->ipc_trans_id, 1);
host_ctx->npu_dev = npu_dev;
@ -308,6 +307,8 @@ int npu_host_init(struct npu_device *npu_dev)
if (!host_ctx->prop_buf)
return -ENOMEM;
host_ctx->misc_pending = false;
return 0;
}
@ -368,6 +369,7 @@ static int host_error_hdlr(struct npu_device *npu_dev, bool force)
network = &host_ctx->networks[i];
if (network->is_valid && network->cmd_pending &&
network->fw_error) {
network->cmd_pending = false;
if (network->cmd_async) {
pr_debug("async cmd, queue ssr event\n");
kevt.evt.type = MSM_NPU_EVENT_TYPE_SSR;
@ -382,7 +384,8 @@ static int host_error_hdlr(struct npu_device *npu_dev, bool force)
}
}
}
complete_all(&host_ctx->loopback_done);
host_ctx->misc_pending = false;
complete_all(&host_ctx->misc_done);
mutex_unlock(&host_ctx->lock);
return 1;
@ -927,7 +930,9 @@ static void app_msg_proc(struct npu_host_ctx *host_ctx, uint32_t *msg)
pr_debug("NPU_IPC_MSG_LOOPBACK_DONE loopbackParams: 0x%x\n",
lb_rsp_pkt->loopbackParams);
complete_all(&host_ctx->loopback_done);
host_ctx->misc_pending = false;
complete_all(&host_ctx->misc_done);
break;
}
case NPU_IPC_MSG_SET_PROPERTY_DONE:
@ -942,8 +947,9 @@ static void app_msg_proc(struct npu_host_ctx *host_ctx, uint32_t *msg)
param[0]);
host_ctx->cmd_ret_status = prop_rsp_pkt->header.status;
host_ctx->misc_pending = false;
complete_all(&host_ctx->property_done);
complete_all(&host_ctx->misc_done);
break;
}
case NPU_IPC_MSG_GET_PROPERTY_DONE:
@ -968,8 +974,9 @@ static void app_msg_proc(struct npu_host_ctx *host_ctx, uint32_t *msg)
sizeof(struct ipc_msg_header_pkt);
memcpy(host_ctx->prop_buf, prop_data, prop_size);
}
host_ctx->misc_pending = false;
complete_all(&host_ctx->property_done);
complete_all(&host_ctx->misc_done);
break;
}
case NPU_IPC_MSG_GENERAL_NOTIFY:
@ -1143,7 +1150,7 @@ static int npu_send_network_cmd(struct npu_device *npu_dev,
network->cmd_async = async;
network->cmd_ret_status = 0;
network->cmd_pending = true;
network->trans_id = atomic_read(&host_ctx->ipc_trans_id);
network->trans_id = ((struct ipc_cmd_header_pkt *)cmd_ptr)->trans_id;
ret = npu_host_ipc_send_cmd(npu_dev,
IPC_QUEUE_APPS_EXEC, cmd_ptr);
if (ret)
@ -1163,11 +1170,18 @@ static int npu_send_misc_cmd(struct npu_device *npu_dev, uint32_t q_idx,
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 if (host_ctx->misc_pending) {
pr_err("Another misc cmd is pending\n");
ret = -EBUSY;
} else {
pr_debug("Send cmd %d\n",
((struct ipc_cmd_header_pkt *)cmd_ptr)->cmd_type);
host_ctx->cmd_ret_status = 0;
reinit_completion(&host_ctx->misc_done);
host_ctx->misc_pending = true;
ret = npu_host_ipc_send_cmd(npu_dev, q_idx, cmd_ptr);
if (ret)
host_ctx->misc_pending = false;
}
mutex_unlock(&host_ctx->lock);
@ -1306,6 +1320,12 @@ int32_t npu_host_set_fw_property(struct npu_device *npu_dev,
goto set_prop_exit;
}
ret = fw_init(npu_dev);
if (ret) {
pr_err("fw_init fail\n");
goto set_prop_exit;
}
prop_packet->header.cmd_type = NPU_IPC_CMD_SET_PROPERTY;
prop_packet->header.size = pkt_size;
prop_packet->header.trans_id =
@ -1318,34 +1338,36 @@ int32_t npu_host_set_fw_property(struct npu_device *npu_dev,
for (i = 0; i < num_of_params; i++)
prop_packet->prop_param[i] = property->prop_param[i];
reinit_completion(&host_ctx->property_done);
ret = npu_send_misc_cmd(npu_dev, IPC_QUEUE_APPS_EXEC,
prop_packet);
pr_debug("NPU_IPC_CMD_SET_PROPERTY sent status: %d\n", ret);
if (ret) {
pr_err("NPU_IPC_CMD_SET_PROPERTY failed\n");
goto set_prop_exit;
goto deinit_fw;
}
ret = wait_for_completion_interruptible_timeout(
&host_ctx->property_done,
&host_ctx->misc_done,
(host_ctx->fw_dbg_mode & FW_DBG_MODE_INC_TIMEOUT) ?
NW_DEBUG_TIMEOUT : NW_CMD_TIMEOUT);
if (!ret) {
pr_err_ratelimited("npu: NPU_IPC_CMD_SET_PROPERTY time out\n");
ret = -ETIMEDOUT;
goto set_prop_exit;
goto deinit_fw;
} else if (ret < 0) {
pr_err("Wait for set_property done interrupted by signal\n");
goto set_prop_exit;
goto deinit_fw;
}
ret = host_ctx->cmd_ret_status;
if (ret)
pr_err("set fw property failed %d\n", ret);
deinit_fw:
fw_deinit(npu_dev, false, true);
set_prop_exit:
kfree(prop_packet);
return ret;
@ -1368,6 +1390,12 @@ int32_t npu_host_get_fw_property(struct npu_device *npu_dev,
if (!prop_packet)
return -ENOMEM;
ret = fw_init(npu_dev);
if (ret) {
pr_err("fw_init fail\n");
goto get_prop_exit;
}
prop_packet->header.cmd_type = NPU_IPC_CMD_GET_PROPERTY;
prop_packet->header.size = pkt_size;
prop_packet->header.trans_id =
@ -1380,28 +1408,27 @@ int32_t npu_host_get_fw_property(struct npu_device *npu_dev,
for (i = 0; i < num_of_params; i++)
prop_packet->prop_param[i] = property->prop_param[i];
reinit_completion(&host_ctx->property_done);
ret = npu_send_misc_cmd(npu_dev, IPC_QUEUE_APPS_EXEC,
prop_packet);
pr_debug("NPU_IPC_CMD_GET_PROPERTY sent status: %d\n", ret);
if (ret) {
pr_err("NPU_IPC_CMD_GET_PROPERTY failed\n");
goto get_prop_exit;
goto deinit_fw;
}
ret = wait_for_completion_interruptible_timeout(
&host_ctx->property_done,
&host_ctx->misc_done,
(host_ctx->fw_dbg_mode & FW_DBG_MODE_INC_TIMEOUT) ?
NW_DEBUG_TIMEOUT : NW_CMD_TIMEOUT);
if (!ret) {
pr_err_ratelimited("npu: NPU_IPC_CMD_GET_PROPERTY time out\n");
ret = -ETIMEDOUT;
goto get_prop_exit;
goto deinit_fw;
} else if (ret < 0) {
pr_err("Wait for get_property done interrupted by signal\n");
goto get_prop_exit;
goto deinit_fw;
}
ret = host_ctx->cmd_ret_status;
@ -1419,6 +1446,8 @@ int32_t npu_host_get_fw_property(struct npu_device *npu_dev,
pr_err("get fw property failed %d\n", ret);
}
deinit_fw:
fw_deinit(npu_dev, false, true);
get_prop_exit:
kfree(prop_packet);
return ret;
@ -1609,7 +1638,7 @@ int32_t npu_host_load_network_v2(struct npu_client *client,
mutex_lock(&host_ctx->lock);
if (!ret) {
pr_err_ratelimited("npu: NPU_IPC_CMD_LOAD time out\n");
pr_err_ratelimited("npu: NPU_IPC_CMD_LOAD_V2 time out\n");
ret = -ETIMEDOUT;
goto error_free_network;
}
@ -2052,7 +2081,6 @@ int32_t npu_host_loopback_test(struct npu_device *npu_dev)
loopback_packet.header.flags = 0;
loopback_packet.loopbackParams = 15;
reinit_completion(&host_ctx->loopback_done);
ret = npu_send_misc_cmd(npu_dev, IPC_QUEUE_APPS_EXEC, &loopback_packet);
if (ret) {
@ -2061,7 +2089,7 @@ int32_t npu_host_loopback_test(struct npu_device *npu_dev)
}
ret = wait_for_completion_interruptible_timeout(
&host_ctx->loopback_done,
&host_ctx->misc_done,
(host_ctx->fw_dbg_mode & FW_DBG_MODE_INC_TIMEOUT) ?
NW_DEBUG_TIMEOUT : NW_CMD_TIMEOUT);

View file

@ -77,9 +77,9 @@ struct npu_host_ctx {
struct delayed_work fw_deinit_work;
atomic_t fw_deinit_work_cnt;
struct workqueue_struct *wq;
struct completion loopback_done;
struct completion misc_done;
struct completion fw_deinit_done;
struct completion property_done;
bool misc_pending;
void *prop_buf;
int32_t network_num;
struct npu_network networks[MAX_LOADED_NETWORK];