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

Commit 541ec94e authored by Jilai Wang's avatar Jilai Wang Committed by Gerrit - the friendly Code Review server
Browse files

msm: npu: Add support to get firmware capabilities



Add new property ID MSM_NPU_PROP_ID_FW_GETCAPS to retrieve firmware
capabilities. In order to allow get/set firmware property when no
network is loaded, firmware will be enabled before sending command
to firmware and disabled after.

Change-Id: I13846e087e5200fbb5402431ad61692faf97b141
Signed-off-by: default avatarJilai Wang <jilaiw@codeaurora.org>
parent b09ff0a7
Loading
Loading
Loading
Loading
+1 −10
Original line number Diff line number Diff line
@@ -1355,12 +1355,6 @@ static int npu_set_fw_state(struct npu_client *client, uint32_t enable)
	struct npu_host_ctx *host_ctx = &npu_dev->host_ctx;
	int rc = 0;

	if (host_ctx->network_num > 0) {
		NPU_ERR("Need to unload network first\n");
		mutex_unlock(&npu_dev->dev_lock);
		return -EINVAL;
	}

	if (enable) {
		NPU_DBG("enable fw\n");
		rc = enable_fw(npu_dev);
@@ -1370,9 +1364,6 @@ static int npu_set_fw_state(struct npu_client *client, uint32_t enable)
			host_ctx->npu_init_cnt++;
			NPU_DBG("npu_init_cnt %d\n",
				host_ctx->npu_init_cnt);
			/* set npu to lowest power level */
			if (npu_set_uc_power_level(npu_dev, 1))
				NPU_WARN("Failed to set uc power level\n");
		}
	} else if (host_ctx->npu_init_cnt > 0) {
		NPU_DBG("disable fw\n");
@@ -1469,7 +1460,7 @@ static int npu_get_property(struct npu_client *client,
	default:
		ret = npu_host_get_fw_property(client->npu_dev, &prop);
		if (ret) {
			NPU_ERR("npu_host_set_fw_property failed\n");
			NPU_ERR("npu_host_get_fw_property failed\n");
			return ret;
		}
		break;
+94 −11
Original line number Diff line number Diff line
@@ -85,6 +85,7 @@ static void npu_dequeue_misc_cmd(struct npu_host_ctx *ctx,
	struct npu_misc_cmd *cmd);
static struct npu_misc_cmd *npu_find_misc_cmd(struct npu_host_ctx *ctx,
	uint32_t trans_id);
static int npu_get_fw_caps(struct npu_device *npu_dev);

/* -------------------------------------------------------------------------
 * Function Definitions - Init / Deinit
@@ -211,6 +212,37 @@ static int load_fw_nolock(struct npu_device *npu_dev, bool enable)
	return ret;
}

static int npu_get_fw_caps(struct npu_device *npu_dev)
{
	int ret = 0, i;
	struct npu_host_ctx *host_ctx = &npu_dev->host_ctx;

	if (host_ctx->fw_caps_valid) {
		NPU_DBG("cached fw caps available\n");
		return ret;
	}

	memset(&host_ctx->fw_caps, 0, sizeof(host_ctx->fw_caps));
	host_ctx->fw_caps.prop_id = MSM_NPU_PROP_ID_FW_GETCAPS;
	host_ctx->fw_caps.num_of_params = PROP_PARAM_MAX_SIZE;

	ret = npu_host_get_fw_property(npu_dev, &host_ctx->fw_caps);
	if (!ret) {
		NPU_DBG("Get fw caps successfully\n");
		host_ctx->fw_caps_valid = true;

		for (i = 0; i < host_ctx->fw_caps.num_of_params; i++)
			NPU_INFO("fw caps %d:%x\n", i,
				host_ctx->fw_caps.prop_param[i]);
	} else {
		/* save the return code */
		host_ctx->fw_caps_err_code = ret;
		NPU_ERR("get fw caps failed %d\n", ret);
	}

	return ret;
}

static void npu_load_fw_work(struct work_struct *work)
{
	int ret;
@@ -224,8 +256,12 @@ static void npu_load_fw_work(struct work_struct *work)
	ret = load_fw_nolock(npu_dev, false);
	mutex_unlock(&host_ctx->lock);

	if (ret)
	if (ret) {
		NPU_ERR("load fw failed %d\n", ret);
		return;
	}

	npu_get_fw_caps(npu_dev);
}

int load_fw(struct npu_device *npu_dev)
@@ -265,6 +301,8 @@ int unload_fw(struct npu_device *npu_dev)

	subsystem_put_local(host_ctx->subsystem_handle);
	host_ctx->fw_state = FW_UNLOADED;
	host_ctx->fw_caps_valid = false;
	host_ctx->fw_caps_err_code = 0;
	NPU_DBG("fw is unloaded\n");
	mutex_unlock(&host_ctx->lock);

@@ -736,6 +774,8 @@ int npu_host_init(struct npu_device *npu_dev)

	INIT_LIST_HEAD(&host_ctx->misc_cmd_list);
	host_ctx->auto_pil_disable = false;
	host_ctx->fw_caps_valid = false;
	host_ctx->fw_caps_err_code = 0;

	return 0;

@@ -2125,7 +2165,13 @@ int32_t npu_host_set_fw_property(struct npu_device *npu_dev,
		break;
	default:
		NPU_ERR("unsupported property %d\n", property->prop_id);
		goto set_prop_exit;
		goto free_prop_packet;
	}

	ret = enable_fw(npu_dev);
	if (ret) {
		NPU_ERR("failed to enable fw\n");
		goto free_prop_packet;
	}

	prop_packet->header.cmd_type = NPU_IPC_CMD_SET_PROPERTY;
@@ -2140,16 +2186,17 @@ 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];

	mutex_lock(&host_ctx->lock);
	misc_cmd = npu_alloc_misc_cmd(host_ctx);
	if (!misc_cmd) {
		NPU_ERR("Can't allocate misc_cmd\n");
		ret = -ENOMEM;
		goto set_prop_exit;
		goto disable_fw;
	}

	misc_cmd->cmd_type = NPU_IPC_CMD_SET_PROPERTY;
	misc_cmd->trans_id = prop_packet->header.trans_id;

	mutex_lock(&host_ctx->lock);
	npu_queue_misc_cmd(host_ctx, misc_cmd);

	ret = npu_send_misc_cmd(npu_dev, IPC_QUEUE_APPS_EXEC,
@@ -2183,10 +2230,13 @@ int32_t npu_host_set_fw_property(struct npu_device *npu_dev,

free_misc_cmd:
	npu_dequeue_misc_cmd(host_ctx, misc_cmd);
	npu_free_misc_cmd(host_ctx, misc_cmd);
set_prop_exit:
	mutex_unlock(&host_ctx->lock);
	npu_free_misc_cmd(host_ctx, misc_cmd);
disable_fw:
	disable_fw(npu_dev);
free_prop_packet:
	kfree(prop_packet);

	return ret;
}

@@ -2204,6 +2254,15 @@ int32_t npu_host_get_fw_property(struct npu_device *npu_dev,
		NPU_ERR("Not supproted fw property id %x\n",
			property->prop_id);
		return -EINVAL;
	} else if (property->prop_id == MSM_NPU_PROP_ID_FW_GETCAPS) {
		if (host_ctx->fw_caps_valid) {
			NPU_DBG("return cached fw_caps\n");
			memcpy(property, &host_ctx->fw_caps, sizeof(*property));
			return 0;
		} else if (host_ctx->fw_caps_err_code) {
			NPU_DBG("return cached error code\n");
			return host_ctx->fw_caps_err_code;
		}
	}

	num_of_params = min_t(uint32_t, property->num_of_params,
@@ -2214,6 +2273,12 @@ int32_t npu_host_get_fw_property(struct npu_device *npu_dev,
	if (!prop_packet)
		return -ENOMEM;

	ret = enable_fw(npu_dev);
	if (ret) {
		NPU_ERR("failed to enable fw\n");
		goto free_prop_packet;
	}

	prop_packet->header.cmd_type = NPU_IPC_CMD_GET_PROPERTY;
	prop_packet->header.size = pkt_size;
	prop_packet->header.trans_id =
@@ -2226,16 +2291,17 @@ 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];

	mutex_lock(&host_ctx->lock);
	misc_cmd = npu_alloc_misc_cmd(host_ctx);
	if (!misc_cmd) {
		NPU_ERR("Can't allocate misc_cmd\n");
		ret = -ENOMEM;
		goto get_prop_exit;
		goto disable_fw;
	}

	misc_cmd->cmd_type = NPU_IPC_CMD_GET_PROPERTY;
	misc_cmd->trans_id = prop_packet->header.trans_id;

	mutex_lock(&host_ctx->lock);
	npu_queue_misc_cmd(host_ctx, misc_cmd);

	ret = npu_send_misc_cmd(npu_dev, IPC_QUEUE_APPS_EXEC,
@@ -2264,26 +2330,43 @@ int32_t npu_host_get_fw_property(struct npu_device *npu_dev,
	}

	ret = misc_cmd->ret_status;
	prop_from_fw = &misc_cmd->u.prop;
	if (!ret) {
		/* Return prop data retrieved from fw to user */
		prop_from_fw = &misc_cmd->u.prop;
		if (property->prop_id == prop_from_fw->prop_id &&
			property->network_hdl == prop_from_fw->network_hdl) {
			num_of_params = min_t(uint32_t,
				prop_from_fw->num_of_params,
				(uint32_t)PROP_PARAM_MAX_SIZE);
			property->num_of_params = num_of_params;
			for (i = 0; i < num_of_params; i++)
				property->prop_param[i] =
					prop_from_fw->prop_param[i];
		} else {
			NPU_WARN("Not Match: id %x:%x hdl %x:%x\n",
				property->prop_id, prop_from_fw->prop_id,
				property->network_hdl,
				prop_from_fw->network_hdl);
			property->num_of_params = 0;
		}
	} else {
		NPU_ERR("get fw property failed %d\n", ret);
		NPU_ERR("prop_id: %x\n", prop_from_fw->prop_id);
		NPU_ERR("network_hdl: %x\n", prop_from_fw->network_hdl);
		NPU_ERR("param_num: %x\n", prop_from_fw->num_of_params);
		for (i = 0; i < prop_from_fw->num_of_params; i++)
			NPU_ERR("%x\n", prop_from_fw->prop_param[i]);
	}

free_misc_cmd:
	npu_dequeue_misc_cmd(host_ctx, misc_cmd);
	npu_free_misc_cmd(host_ctx, misc_cmd);
get_prop_exit:
	mutex_unlock(&host_ctx->lock);
	npu_free_misc_cmd(host_ctx, misc_cmd);
disable_fw:
	disable_fw(npu_dev);
free_prop_packet:
	kfree(prop_packet);

	return ret;
}

+4 −0
Original line number Diff line number Diff line
@@ -138,6 +138,10 @@ struct npu_host_ctx {
	bool bridge_mbox_pwr_on;
	void *ipc_msg_buf;
	struct list_head misc_cmd_list;

	struct msm_npu_property fw_caps;
	bool fw_caps_valid;
	uint32_t fw_caps_err_code;
};

struct npu_device;
+2 −1
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0-only WITH Linux-syscall-note */
/*
 * Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
 * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
 */

#ifndef _UAPI_MSM_NPU_H_
@@ -87,6 +87,7 @@
#define MSM_NPU_PROP_ID_CLK_GATING_MODE (MSM_NPU_FW_PROP_ID_START + 2)
#define MSM_NPU_PROP_ID_HW_VERSION (MSM_NPU_FW_PROP_ID_START + 3)
#define MSM_NPU_PROP_ID_FW_VERSION (MSM_NPU_FW_PROP_ID_START + 4)
#define MSM_NPU_PROP_ID_FW_GETCAPS (MSM_NPU_FW_PROP_ID_START + 5)

/* features supported by driver */
#define MSM_NPU_FEATURE_MULTI_EXECUTE  0x1