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

Commit a02daa97 authored by qctecmdr's avatar qctecmdr Committed by Gerrit - the friendly Code Review server
Browse files

Merge "msm: npu: Support MSM_NPU_GET_PROP and update DCVS mode"

parents dbed0d4b cda7a344
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
@@ -51,7 +51,7 @@
#define NPU_MAX_STATS_BUF_SIZE 16384
#define NPU_MAX_PATCH_NUM		160

#define DCVS_MODE_MAX 100
#define PERF_MODE_DEFAULT 0

enum npu_power_level {
	NPU_PWRLEVEL_MINSVS = 0,
+61 −18
Original line number Diff line number Diff line
@@ -40,7 +40,6 @@
#define DDR_MAPPED_START_ADDR   0x80000000
#define DDR_MAPPED_SIZE         0x60000000

#define PERF_MODE_DEFAULT 0
#define MBOX_OP_TIMEOUTMS 1000

/* -------------------------------------------------------------------------
@@ -117,6 +116,8 @@ static int npu_receive_event(struct npu_client *client,
static int npu_set_fw_state(struct npu_client *client, uint32_t enable);
static int npu_set_property(struct npu_client *client,
	unsigned long arg);
static int npu_get_property(struct npu_client *client,
	unsigned long arg);
static long npu_ioctl(struct file *file, unsigned int cmd,
					unsigned long arg);
static unsigned int npu_poll(struct file *filp, struct poll_table_struct *p);
@@ -318,6 +319,7 @@ static ssize_t npu_store_perf_mode_override(struct device *dev,
					  struct device_attribute *attr,
					  const char *buf, size_t count)
{
	struct npu_client client;
	struct npu_device *npu_dev = dev_get_drvdata(dev);
	uint32_t val;
	int rc;
@@ -331,7 +333,9 @@ static ssize_t npu_store_perf_mode_override(struct device *dev,
	val = min(val, npu_dev->pwrctrl.num_pwrlevels);
	npu_dev->pwrctrl.perf_mode_override = val;
	pr_info("setting uc_pwrlevel_override to %d\n", val);
	npu_set_power_level(npu_dev, true);

	client.npu_dev = npu_dev;
	npu_host_set_perf_mode(&client, 0, val);

	return count;
}
@@ -361,7 +365,7 @@ static ssize_t npu_store_dcvs_mode(struct device *dev,
		return -EINVAL;
	}

	val = min(val, (uint32_t)DCVS_MODE_MAX);
	val = min(val, (uint32_t)(npu_dev->pwrctrl.num_pwrlevels - 1));
	pr_debug("sysfs: setting dcvs_mode to %d\n", val);

	prop.prop_id = MSM_NPU_PROP_ID_DCVS_MODE;
@@ -638,7 +642,6 @@ int npu_enable_core_power(struct npu_device *npu_dev)
			pwr->pwr_vote_num = 0;
			return ret;
		}
		pwr->cur_dcvs_activity = DCVS_MODE_MAX;
		npu_resume_devbw(npu_dev);
	}
	pwr->pwr_vote_num++;
@@ -665,7 +668,7 @@ void npu_disable_core_power(struct npu_device *npu_dev)
		pwr->active_pwrlevel = pwr->default_pwrlevel;
		pwr->uc_pwrlevel = pwr->max_pwrlevel;
		pwr->cdsprm_pwrlevel = pwr->max_pwrlevel;
		pwr->cur_dcvs_activity = 0;
		pwr->cur_dcvs_activity = pwr->num_pwrlevels;
		pr_debug("setting back to power level=%d\n",
			pwr->active_pwrlevel);
	}
@@ -725,14 +728,6 @@ static uint32_t npu_calc_power_level(struct npu_device *npu_dev)
	uint32_t active_pwr_level = npu_dev->pwrctrl.active_pwrlevel;
	uint32_t uc_pwr_level = npu_dev->pwrctrl.uc_pwrlevel;

	/*
	 * if perf_mode_override is not 0, use it to override
	 * uc_pwrlevel
	 */
	if (npu_dev->pwrctrl.perf_mode_override > 0)
		uc_pwr_level = npu_power_level_from_index(npu_dev,
			npu_dev->pwrctrl.perf_mode_override - 1);

	/*
	 * pick the lowese power level between thermal power and usecase power
	 * settings
@@ -821,9 +816,6 @@ int npu_set_uc_power_level(struct npu_device *npu_dev,
	struct npu_pwrctrl *pwr = &npu_dev->pwrctrl;
	uint32_t uc_pwrlevel_to_set;

	if (perf_mode == PERF_MODE_DEFAULT)
		uc_pwrlevel_to_set = pwr->default_pwrlevel;
	else
	uc_pwrlevel_to_set = npu_power_level_from_index(npu_dev,
		perf_mode - 1);

@@ -1671,6 +1663,53 @@ static int npu_set_property(struct npu_client *client,
	return ret;
}

static int npu_get_property(struct npu_client *client,
	unsigned long arg)
{
	struct msm_npu_property prop;
	void __user *argp = (void __user *)arg;
	int ret = -EINVAL;
	struct npu_device *npu_dev = client->npu_dev;
	struct npu_host_ctx *host_ctx = &npu_dev->host_ctx;

	ret = copy_from_user(&prop, argp, sizeof(prop));
	if (ret) {
		pr_err("fail to copy from user\n");
		return -EFAULT;
	}

	switch (prop.prop_id) {
	case MSM_NPU_PROP_ID_FW_STATE:
		prop.prop_param[0] = host_ctx->fw_state;
		break;
	case MSM_NPU_PROP_ID_PERF_MODE:
		prop.prop_param[0] = npu_host_get_perf_mode(client,
			(uint32_t)prop.network_hdl);
		break;
	case MSM_NPU_PROP_ID_PERF_MODE_MAX:
		prop.prop_param[0] = npu_dev->pwrctrl.num_pwrlevels;
		break;
	case MSM_NPU_PROP_ID_DRV_VERSION:
		prop.prop_param[0] = 0;
		break;
	default:
		ret = npu_host_get_fw_property(client->npu_dev, &prop);
		if (ret) {
			pr_err("npu_host_set_fw_property failed\n");
			return ret;
		}
		break;
	}

	ret = copy_to_user(argp, &prop, sizeof(prop));
	if (ret) {
		pr_err("fail to copy to user\n");
		return -EFAULT;
	}

	return ret;
}

static long npu_ioctl(struct file *file, unsigned int cmd,
						 unsigned long arg)
{
@@ -1708,6 +1747,9 @@ static long npu_ioctl(struct file *file, unsigned int cmd,
	case MSM_NPU_SET_PROP:
		ret = npu_set_property(client, arg);
		break;
	case MSM_NPU_GET_PROP:
		ret = npu_get_property(client, arg);
		break;
	default:
		pr_err("unexpected IOCTL %x\n", cmd);
	}
@@ -1926,6 +1968,7 @@ static int npu_of_parse_pwrlevels(struct npu_device *npu_dev,
	pwr->uc_pwrlevel = pwr->max_pwrlevel;
	pwr->perf_mode_override = 0;
	pwr->cdsprm_pwrlevel = pwr->max_pwrlevel;
	pwr->cur_dcvs_activity = pwr->num_pwrlevels;

	return 0;
}
+29 −20
Original line number Diff line number Diff line
@@ -40,6 +40,8 @@
#define NPU_IPC_CMD_EXECUTE_V2          0x0000000A
/* ipc_cmd_set_property_packet */
#define NPU_IPC_CMD_SET_PROPERTY        0x0000000B
/* ipc_cmd_get_property_packet */
#define NPU_IPC_CMD_GET_PROPERTY        0x0000000C

/* Messages sent **from** NPU */
/* IPC Message Response -- uint32_t */
@@ -59,8 +61,13 @@
#define NPU_IPC_MSG_EXECUTE_V2_DONE     0x00010006
/* ipc_msg_set_property_packet */
#define NPU_IPC_MSG_SET_PROPERTY_DONE   0x00010007
/* ipc_msg_set_power_mode */
#define NPU_IPC_MSG_DCVS_NOTIFY         0x00010010
/* ipc_msg_get_property_packet */
#define NPU_IPC_MSG_GET_PROPERTY_DONE   0x00010008
/* ipc_msg_general_notify_pkt */
#define NPU_IPC_MSG_GENERAL_NOTIFY      0x00010010

/* IPC Notify Message Type -- uint32_t */
#define NPU_NOTIFY_DCVS_MODE            0x00002000

/* Logging message size */
/* Number 32-bit elements for the maximum log message size */
@@ -109,10 +116,8 @@
/* Debug stats */
#define NUM_LAYER_STATS_PER_EXE_MSG_MAX 110

enum npu_fw_property_id {
	NPU_FW_PROP_ID_DCVS_MODE = 0,
	NPU_FW_PROP_ID_INVALID = 0xFFFFFFFF,
};
/* DCVS */
#define NPU_DCVS_ACTIVITY_MAX_PERF 0x100

/* -------------------------------------------------------------------------
 * Data Structures
@@ -283,9 +288,9 @@ struct ipc_cmd_loopback_pkt {
};

/*
 * Set property packet definition
 * Generic property definition
 */
struct ipc_cmd_set_prop_pkt {
struct ipc_cmd_prop_pkt {
	struct ipc_cmd_header_pkt header;
	uint32_t prop_id;
	uint32_t num_params;
@@ -294,15 +299,28 @@ struct ipc_cmd_set_prop_pkt {
};

/*
 * Set property response packet definition
 * Generic property response packet definition
 */
struct ipc_msg_set_prop_pkt {
struct ipc_msg_prop_pkt {
	struct ipc_msg_header_pkt header;
	uint32_t prop_id;
	uint32_t num_params;
	uint32_t network_hdl;
	uint32_t prop_value;
	uint32_t prop_param[0];
};

/*
 * Generic notify message packet definition
 */
struct ipc_msg_general_notify_pkt {
	struct ipc_msg_header_pkt header;
	uint32_t notify_id;
	uint32_t num_params;
	uint32_t network_hdl;
	uint32_t notify_param[0];
};


/*
 * LOAD response packet definition
 */
@@ -449,13 +467,4 @@ struct ipc_cmd_shutdown_pkt {
	uint32_t shutdown_flags;
};

/*
 * Notify driver to set power mode (a value from 0 to 100)
 */
struct ipc_msg_set_dcvs_mode {
	struct ipc_msg_header_pkt header;
	/* activity level from 0-100 */
	uint32_t activity;
};

#endif /* NPU_HOST_IPC_H */
+190 −59
Original line number Diff line number Diff line
@@ -294,28 +294,33 @@ void fw_deinit(struct npu_device *npu_dev, bool ssr, bool fw_alive)

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);
	init_completion(&host_ctx->fw_deinit_done);
	init_completion(&host_ctx->property_set_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;

	host_ctx->wq = npu_create_wq(host_ctx, "npu_wq");
	if (!host_ctx->wq)
		sts = -EPERM;
		return -EPERM;

	host_ctx->prop_buf = kzalloc(sizeof(struct msm_npu_property),
		GFP_KERNEL);
	if (!host_ctx->prop_buf)
		return -ENOMEM;

	return sts;
	return 0;
}

void npu_host_deinit(struct npu_device *npu_dev)
{
	struct npu_host_ctx *host_ctx = &npu_dev->host_ctx;

	kfree(host_ctx->prop_buf);
	npu_destroy_wq(host_ctx);
	mutex_destroy(&host_ctx->lock);
}
@@ -914,25 +919,65 @@ static void app_msg_proc(struct npu_host_ctx *host_ctx, uint32_t *msg)
	}
	case NPU_IPC_MSG_SET_PROPERTY_DONE:
	{
		struct ipc_msg_set_prop_pkt *set_prop_rsp_pkt =
			(struct ipc_msg_set_prop_pkt *)msg;

		struct ipc_msg_prop_pkt *prop_rsp_pkt =
			(struct ipc_msg_prop_pkt *)msg;
		uint32_t *param = (uint32_t *)((uint8_t *)prop_rsp_pkt +
			sizeof(struct ipc_msg_prop_pkt));
		pr_debug("NPU_IPC_MSG_SET_PROPERTY_DONE %d:0x%x:%d\n",
			set_prop_rsp_pkt->network_hdl,
			set_prop_rsp_pkt->prop_id,
			set_prop_rsp_pkt->prop_value);
		complete_all(&host_ctx->property_set_done);
			prop_rsp_pkt->network_hdl,
			prop_rsp_pkt->prop_id,
			param[0]);

		complete_all(&host_ctx->property_done);
		break;
	}
	case NPU_IPC_MSG_DCVS_NOTIFY:
	case NPU_IPC_MSG_GET_PROPERTY_DONE:
	{
		struct ipc_msg_set_dcvs_mode *set_dcvs_pkt =
			(struct ipc_msg_set_dcvs_mode *)msg;
		struct ipc_msg_prop_pkt *prop_rsp_pkt =
			(struct ipc_msg_prop_pkt *)msg;
		uint32_t prop_size = 0;
		uint32_t *prop_data = (uint32_t *)((uint8_t *)prop_rsp_pkt +
			sizeof(struct ipc_msg_header_pkt));

		pr_debug("NPU_IPC_MSG_DCVS_NOTIFY %d\n",
			set_dcvs_pkt->activity);
		pr_debug("NPU_IPC_MSG_GET_PROPERTY_DONE %d:0x%x:%d:%d\n",
			prop_rsp_pkt->network_hdl,
			prop_rsp_pkt->prop_id,
			prop_rsp_pkt->num_params,
			prop_rsp_pkt->prop_param[0]);

		update_dcvs_activity(npu_dev, set_dcvs_pkt->activity);
		host_ctx->cmd_ret_status = prop_rsp_pkt->header.status;

		if (prop_rsp_pkt->num_params > 0) {
			/* Copy prop data to kernel buffer */
			prop_size = prop_rsp_pkt->header.size -
				sizeof(struct ipc_msg_header_pkt);
			memcpy(host_ctx->prop_buf, prop_data, prop_size);
		}

		complete_all(&host_ctx->property_done);
		break;
	}
	case NPU_IPC_MSG_GENERAL_NOTIFY:
	{
		struct ipc_msg_general_notify_pkt *notify_msg_pkt =
			(struct ipc_msg_general_notify_pkt *)msg;

		pr_debug("NPU_IPC_MSG_GENERAL_NOTIFY %d:0x%x:%d\n",
			notify_msg_pkt->network_hdl,
			notify_msg_pkt->notify_id,
			notify_msg_pkt->notify_param[0]);

		switch (notify_msg_pkt->notify_id) {
		case NPU_NOTIFY_DCVS_MODE:
			pr_debug("NPU_IPC_MSG_GENERAL_NOTIFY DCVS_MODE %d\n",
				notify_msg_pkt->notify_param[0]);
			update_dcvs_activity(npu_dev,
				notify_msg_pkt->notify_param[0]);
			break;
		default:
			pr_err("Nothing to do\n");
			break;
		}
		break;
	}
	default:
@@ -1096,6 +1141,7 @@ static int npu_send_misc_cmd(struct npu_device *npu_dev, uint32_t q_idx,
	} else {
		pr_debug("Send cmd %d\n",
			((struct ipc_cmd_header_pkt *)cmd_ptr)->cmd_type);
		host_ctx->cmd_ret_status = 0;
		ret = npu_host_ipc_send_cmd(npu_dev, q_idx, cmd_ptr);
	}
	mutex_unlock(&host_ctx->lock);
@@ -1177,6 +1223,13 @@ static int set_perf_mode(struct npu_device *npu_dev)

	networks_perf_mode = find_networks_perf_mode(host_ctx);

	if (npu_dev->pwrctrl.perf_mode_override)
		networks_perf_mode = npu_dev->pwrctrl.perf_mode_override;

	if (npu_dev->pwrctrl.cur_dcvs_activity != NPU_DCVS_ACTIVITY_MAX_PERF)
		networks_perf_mode = min_t(uint32_t, networks_perf_mode,
			npu_dev->pwrctrl.cur_dcvs_activity);

	ret = npu_set_uc_power_level(npu_dev, networks_perf_mode);
	if (ret)
		pr_err("network load failed due to power level set\n");
@@ -1186,35 +1239,10 @@ static int set_perf_mode(struct npu_device *npu_dev)

static int update_dcvs_activity(struct npu_device *npu_dev, uint32_t activity)
{
	int ret = 0;

	npu_dev->pwrctrl.cur_dcvs_activity = activity;
	pr_debug("update dcvs activity to %d\n", activity);

	if (activity > 0) {
		pr_debug("Set clocks back to default setting - exit dcvs mode\n");
		ret = set_perf_mode(npu_dev);
	} else {
		pr_debug("Set clocks to low - enter dcvs mode\n");
		ret = npu_set_uc_power_level(npu_dev, 1);
	}

	return ret;
}

static enum npu_fw_property_id npu_host_to_fw_prop_id(uint32_t prop)
{
	uint32_t fw_prop_id = NPU_FW_PROP_ID_INVALID;

	switch (prop) {
	case MSM_NPU_PROP_ID_DCVS_MODE:
		fw_prop_id = NPU_FW_PROP_ID_DCVS_MODE;
		break;
	default:
		pr_err("Invalid host property id %x\n", prop);
		break;
	}

	return fw_prop_id;
	return set_perf_mode(npu_dev);
}

int32_t npu_host_set_fw_property(struct npu_device *npu_dev,
@@ -1222,14 +1250,11 @@ int32_t npu_host_set_fw_property(struct npu_device *npu_dev,
{
	int ret = 0, i;
	uint32_t prop_param, prop_id;
	struct ipc_cmd_set_prop_pkt *prop_packet = NULL;
	struct ipc_cmd_prop_pkt *prop_packet = NULL;
	struct npu_host_ctx *host_ctx = &npu_dev->host_ctx;
	uint32_t num_of_params, pkt_size;

	prop_id = npu_host_to_fw_prop_id(property->prop_id);
	if (prop_id == NPU_FW_PROP_ID_INVALID)
		return -EINVAL;

	prop_id = property->prop_id;
	num_of_params = min_t(uint32_t, property->num_of_params,
		(uint32_t)PROP_PARAM_MAX_SIZE);
	pkt_size = sizeof(*prop_packet) + num_of_params * sizeof(uint32_t);
@@ -1239,9 +1264,9 @@ int32_t npu_host_set_fw_property(struct npu_device *npu_dev,
		return -ENOMEM;

	switch (prop_id) {
	case NPU_FW_PROP_ID_DCVS_MODE:
	case MSM_NPU_PROP_ID_DCVS_MODE:
		prop_param = min_t(uint32_t, property->prop_param[0],
			(uint32_t)DCVS_MODE_MAX);
			(uint32_t)(npu_dev->pwrctrl.num_pwrlevels - 1));
		property->prop_param[0] = prop_param;
		pr_debug("setting dcvs_mode to %d\n", prop_param);

@@ -1267,7 +1292,7 @@ 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_set_done);
	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);
@@ -1278,7 +1303,7 @@ int32_t npu_host_set_fw_property(struct npu_device *npu_dev,
	}

	ret = wait_for_completion_interruptible_timeout(
		&host_ctx->property_set_done,
		&host_ctx->property_done,
		(host_ctx->fw_dbg_mode & FW_DBG_MODE_INC_TIMEOUT) ?
		NW_DEBUG_TIMEOUT : NW_CMD_TIMEOUT);

@@ -1296,7 +1321,77 @@ int32_t npu_host_set_fw_property(struct npu_device *npu_dev,
set_prop_exit:
	kfree(prop_packet);
	return ret;
}

int32_t npu_host_get_fw_property(struct npu_device *npu_dev,
	struct msm_npu_property *property)
{
	int ret = 0, i;
	struct ipc_cmd_prop_pkt *prop_packet = NULL;
	struct npu_host_ctx *host_ctx = &npu_dev->host_ctx;
	struct msm_npu_property *prop_from_fw;
	uint32_t num_of_params, pkt_size;

	num_of_params = min_t(uint32_t, property->num_of_params,
		(uint32_t)PROP_PARAM_MAX_SIZE);
	pkt_size = sizeof(*prop_packet);
	prop_packet = kzalloc(pkt_size, GFP_KERNEL);

	if (!prop_packet)
		return -ENOMEM;

	prop_packet->header.cmd_type = NPU_IPC_CMD_GET_PROPERTY;
	prop_packet->header.size = pkt_size;
	prop_packet->header.trans_id =
		atomic_add_return(1, &host_ctx->ipc_trans_id);
	prop_packet->header.flags = 0;

	prop_packet->prop_id = property->prop_id;
	prop_packet->num_params = num_of_params;
	prop_packet->network_hdl = property->network_hdl;

	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;
	}

	ret = wait_for_completion_interruptible_timeout(
		&host_ctx->property_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;
	} else if (ret < 0) {
		pr_err("Wait for get_property done interrupted by signal\n");
		goto get_prop_exit;
	}

	ret = host_ctx->cmd_ret_status;
	if (!ret) {
		/* Return prop data retrieved from fw to user */
		prop_from_fw = (struct msm_npu_property *)(host_ctx->prop_buf);
		if (property->prop_id == prop_from_fw->prop_id &&
			property->network_hdl == prop_from_fw->network_hdl) {
			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 {
		pr_err("get fw property failed %d\n", ret);
	}

get_prop_exit:
	kfree(prop_packet);
	return ret;
}

int32_t npu_host_load_network(struct npu_client *client,
@@ -1304,6 +1399,7 @@ int32_t npu_host_load_network(struct npu_client *client,
{
	int ret = 0;
	struct npu_device *npu_dev = client->npu_dev;
	struct npu_pwrctrl *pwr = &npu_dev->pwrctrl;
	struct npu_network *network;
	struct ipc_cmd_load_pkt load_packet;
	struct npu_host_ctx *host_ctx = &npu_dev->host_ctx;
@@ -1326,6 +1422,8 @@ int32_t npu_host_load_network(struct npu_client *client,
	network->first_block_size = load_ioctl->first_block_size;
	network->priority = load_ioctl->priority;
	network->cur_perf_mode = network->init_perf_mode =
		(load_ioctl->perf_mode == PERF_MODE_DEFAULT) ?
			pwr->num_pwrlevels - 1 :
			load_ioctl->perf_mode;

	/* verify mapped physical address */
@@ -1403,6 +1501,7 @@ int32_t npu_host_load_network_v2(struct npu_client *client,
{
	int ret = 0, i;
	struct npu_device *npu_dev = client->npu_dev;
	struct npu_pwrctrl *pwr = &npu_dev->pwrctrl;
	struct npu_network *network;
	struct ipc_cmd_load_pkt_v2 *load_packet = NULL;
	struct npu_host_ctx *host_ctx = &npu_dev->host_ctx;
@@ -1440,6 +1539,8 @@ int32_t npu_host_load_network_v2(struct npu_client *client,
	network->first_block_size = load_ioctl->first_block_size;
	network->priority = load_ioctl->priority;
	network->cur_perf_mode = network->init_perf_mode =
		(load_ioctl->perf_mode == PERF_MODE_DEFAULT) ?
		pwr->num_pwrlevels - 1 :
		load_ioctl->perf_mode;
	network->num_layers = load_ioctl->num_layers;

@@ -2007,7 +2108,6 @@ int32_t npu_host_set_perf_mode(struct npu_client *client, uint32_t network_hdl,
	struct npu_device *npu_dev = client->npu_dev;
	struct npu_host_ctx *host_ctx = &npu_dev->host_ctx;
	struct npu_network *network = NULL;
	uint32_t networks_perf_mode;

	mutex_lock(&host_ctx->lock);

@@ -2033,10 +2133,9 @@ int32_t npu_host_set_perf_mode(struct npu_client *client, uint32_t network_hdl,
		}
	}

	networks_perf_mode = find_networks_perf_mode(host_ctx);
	ret = npu_set_uc_power_level(npu_dev, networks_perf_mode);
	ret = set_perf_mode(npu_dev);
	if (ret)
		pr_err("failed to set power level %d\n", networks_perf_mode);
		pr_err("set_perf_mode failed");

	if (network)
		network_put(network);
@@ -2044,3 +2143,35 @@ int32_t npu_host_set_perf_mode(struct npu_client *client, uint32_t network_hdl,

	return ret;
}

/*
 * get the currently set network or global perf_mode
 * if network_hdl is 0, get global perf_mode_override
 * otherwise get network perf_mode
 */
int32_t npu_host_get_perf_mode(struct npu_client *client, uint32_t network_hdl)
{
	int param_val = 0;
	struct npu_device *npu_dev = client->npu_dev;
	struct npu_host_ctx *host_ctx = &npu_dev->host_ctx;
	struct npu_network *network = NULL;

	mutex_lock(&host_ctx->lock);

	if (network_hdl == 0) {
		param_val = npu_dev->pwrctrl.perf_mode_override;
	} else {
		network = get_network_by_hdl(host_ctx, client, network_hdl);
		if (!network) {
			pr_err("invalid network handle %x\n", network_hdl);
			mutex_unlock(&host_ctx->lock);
			return -EINVAL;
		}
		param_val = network->cur_perf_mode;
		network_put(network);
	}

	mutex_unlock(&host_ctx->lock);

	return param_val;
}
+6 −1
Original line number Diff line number Diff line
@@ -85,7 +85,8 @@ struct npu_host_ctx {
	struct workqueue_struct *wq;
	struct completion loopback_done;
	struct completion fw_deinit_done;
	struct completion property_set_done;
	struct completion property_done;
	void *prop_buf;
	int32_t network_num;
	struct npu_network networks[MAX_LOADED_NETWORK];
	bool sys_cache_disable;
@@ -94,6 +95,7 @@ struct npu_host_ctx {
	uint32_t fw_unload_delay_ms;
	atomic_t ipc_trans_id;
	atomic_t network_execute_cnt;
	int cmd_ret_status;

	uint32_t err_irq_sts;
	uint32_t wdg_irq_sts;
@@ -139,9 +141,12 @@ int32_t npu_host_exec_network_v2(struct npu_client *client,
int32_t npu_host_loopback_test(struct npu_device *npu_dev);
int32_t npu_host_set_fw_property(struct npu_device *npu_dev,
			struct msm_npu_property *property);
int32_t npu_host_get_fw_property(struct npu_device *npu_dev,
			struct msm_npu_property *property);
void npu_host_cleanup_networks(struct npu_client *client);
int32_t npu_host_set_perf_mode(struct npu_client *client, uint32_t network_hdl,
	uint32_t perf_mode);
int32_t npu_host_get_perf_mode(struct npu_client *client, uint32_t network_hdl);
void npu_dump_debug_timeout_stats(struct npu_device *npu_dev);

#endif /* _NPU_MGR_H */
Loading