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

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

Merge "msm: npu: Add MSM_NPU_SET_PROP API to set npu driver/fw property"

parents c0d9347a 15061d5e
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -51,6 +51,8 @@
#define NPU_MAX_STATS_BUF_SIZE 16384
#define NPU_MAX_PATCH_NUM		160

#define DCVS_MODE_MAX 100

enum npu_power_level {
	NPU_PWRLEVEL_MINSVS = 0,
	NPU_PWRLEVEL_LOWSVS,
@@ -154,6 +156,8 @@ struct npu_reg {
 * @uc_pwrlevel - power level from user driver setting
 * @perf_mode_override - perf mode from sysfs to override perf mode
 *                       settings from user driver
 * @dcvs_mode - dcvs mode from sysfs to turn on dcvs mode
 *              settings from user driver
 * @devbw - bw device
 */
struct npu_pwrctrl {
@@ -172,6 +176,8 @@ struct npu_pwrctrl {
	uint32_t cdsprm_pwrlevel;
	uint32_t fmax_pwrlevel;
	uint32_t perf_mode_override;
	uint32_t dcvs_mode;
	uint32_t cur_dcvs_activity;
};

/**
+114 −3
Original line number Diff line number Diff line
@@ -68,6 +68,12 @@ static ssize_t npu_show_perf_mode_override(struct device *dev,
static ssize_t npu_store_perf_mode_override(struct device *dev,
					  struct device_attribute *attr,
					  const char *buf, size_t count);
static ssize_t npu_show_dcvs_mode(struct device *dev,
					 struct device_attribute *attr,
					 char *buf);
static ssize_t npu_store_dcvs_mode(struct device *dev,
					  struct device_attribute *attr,
					  const char *buf, size_t count);
static ssize_t npu_show_fw_unload_delay_ms(struct device *dev,
					 struct device_attribute *attr,
					 char *buf);
@@ -108,6 +114,9 @@ static int npu_exec_network_v2(struct npu_client *client,
	unsigned long arg);
static int npu_receive_event(struct npu_client *client,
	unsigned long arg);
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 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);
@@ -178,6 +187,8 @@ static DEVICE_ATTR(caps, 0444, npu_show_capabilities, NULL);
static DEVICE_ATTR(pwr, 0644, npu_show_pwr_state, npu_store_pwr_state);
static DEVICE_ATTR(perf_mode_override, 0644,
	npu_show_perf_mode_override, npu_store_perf_mode_override);
static DEVICE_ATTR(dcvs_mode, 0644,
	npu_show_dcvs_mode, npu_store_dcvs_mode);
static DEVICE_ATTR(fw_unload_delay_ms, 0644,
	npu_show_fw_unload_delay_ms, npu_store_fw_unload_delay_ms);
static DEVICE_ATTR(fw_state, 0644, npu_show_fw_state, npu_store_fw_state);
@@ -186,6 +197,7 @@ static struct attribute *npu_fs_attrs[] = {
	&dev_attr_caps.attr,
	&dev_attr_pwr.attr,
	&dev_attr_perf_mode_override.attr,
	&dev_attr_dcvs_mode.attr,
	&dev_attr_fw_state.attr,
	&dev_attr_fw_unload_delay_ms.attr,
	NULL
@@ -289,7 +301,7 @@ static ssize_t npu_store_pwr_state(struct device *dev,
}

/* -------------------------------------------------------------------------
 * SysFS - Power State
 * SysFS - perf_mode_override
 * -------------------------------------------------------------------------
 */
static ssize_t npu_show_perf_mode_override(struct device *dev,
@@ -324,6 +336,50 @@ static ssize_t npu_store_perf_mode_override(struct device *dev,
	return count;
}

static ssize_t npu_show_dcvs_mode(struct device *dev,
					 struct device_attribute *attr,
					 char *buf)
{
	struct npu_device *npu_dev = dev_get_drvdata(dev);
	struct npu_pwrctrl *pwr = &npu_dev->pwrctrl;

	return scnprintf(buf, PAGE_SIZE, "%d\n", pwr->dcvs_mode);
}

static ssize_t npu_store_dcvs_mode(struct device *dev,
					  struct device_attribute *attr,
					  const char *buf, size_t count)
{
	struct npu_device *npu_dev = dev_get_drvdata(dev);
	struct msm_npu_property prop;
	uint32_t val;
	int ret = 0;

	ret = kstrtou32(buf, 10, &val);
	if (ret) {
		pr_err("Invalid input for dcvs mode setting\n");
		return -EINVAL;
	}

	val = min(val, (uint32_t)DCVS_MODE_MAX);
	pr_debug("sysfs: setting dcvs_mode to %d\n", val);

	prop.prop_id = MSM_NPU_PROP_ID_DCVS_MODE;
	prop.num_of_params = 1;
	prop.network_hdl = 0;
	prop.prop_param[0] = val;

	ret = npu_host_set_fw_property(npu_dev, &prop);
	if (ret) {
		pr_err("npu_host_set_fw_property failed %d\n", ret);
		return ret;
	}

	npu_dev->pwrctrl.dcvs_mode = val;

	return count;
}

/* -------------------------------------------------------------------------
 * SysFS - Delayed FW unload
 * -------------------------------------------------------------------------
@@ -582,6 +638,7 @@ 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++;
@@ -593,7 +650,6 @@ int npu_enable_core_power(struct npu_device *npu_dev)
void npu_disable_core_power(struct npu_device *npu_dev)
{
	struct npu_pwrctrl *pwr = &npu_dev->pwrctrl;
	struct npu_thermalctrl *thermalctrl = &npu_dev->thermalctrl;

	mutex_lock(&npu_dev->dev_lock);
	if (!pwr->pwr_vote_num) {
@@ -606,9 +662,10 @@ void npu_disable_core_power(struct npu_device *npu_dev)
		npu_suspend_devbw(npu_dev);
		npu_disable_core_clocks(npu_dev);
		npu_disable_regulators(npu_dev);
		pwr->active_pwrlevel = thermalctrl->pwr_level;
		pwr->active_pwrlevel = pwr->default_pwrlevel;
		pwr->uc_pwrlevel = pwr->max_pwrlevel;
		pwr->cdsprm_pwrlevel = pwr->max_pwrlevel;
		pwr->cur_dcvs_activity = 0;
		pr_debug("setting back to power level=%d\n",
			pwr->active_pwrlevel);
	}
@@ -1563,6 +1620,57 @@ static int npu_receive_event(struct npu_client *client,
	return ret;
}

static int npu_set_fw_state(struct npu_client *client, uint32_t enable)
{
	struct npu_device *npu_dev = client->npu_dev;
	int rc = 0;

	if (enable) {
		pr_debug("%s: enable fw\n", __func__);
		rc = fw_init(npu_dev);
		if (rc)
			pr_err("enable fw failed\n");
	} else {
		pr_debug("%s: disable fw\n", __func__);
		fw_deinit(npu_dev, false, true);
	}

	return rc;
}

static int npu_set_property(struct npu_client *client,
	unsigned long arg)
{
	struct msm_npu_property prop;
	void __user *argp = (void __user *)arg;
	int ret = -EINVAL;

	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:
		ret = npu_set_fw_state(client,
			(uint32_t)prop.prop_param[0]);
		break;
	case MSM_NPU_PROP_ID_PERF_MODE:
		ret = npu_host_set_perf_mode(client,
			(uint32_t)prop.network_hdl,
			(uint32_t)prop.prop_param[0]);
		break;
	default:
		ret = npu_host_set_fw_property(client->npu_dev, &prop);
		if (ret)
			pr_err("npu_host_set_fw_property failed\n");
		break;
	}

	return ret;
}

static long npu_ioctl(struct file *file, unsigned int cmd,
						 unsigned long arg)
{
@@ -1597,6 +1705,9 @@ static long npu_ioctl(struct file *file, unsigned int cmd,
	case MSM_NPU_RECEIVE_EVENT:
		ret = npu_receive_event(client, arg);
		break;
	case MSM_NPU_SET_PROP:
		ret = npu_set_property(client, arg);
		break;
	default:
		pr_err("unexpected IOCTL %x\n", cmd);
	}
+42 −1
Original line number Diff line number Diff line
/* Copyright (c) 2018, The Linux Foundation. All rights reserved.
/* Copyright (c) 2018-2019, The Linux Foundation. All rights reserved.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 and
@@ -38,6 +38,8 @@
#define NPU_IPC_CMD_LOAD_V2             0x00000009
/* ipc_cmd_execute_packet_v2 */
#define NPU_IPC_CMD_EXECUTE_V2          0x0000000A
/* ipc_cmd_set_property_packet */
#define NPU_IPC_CMD_SET_PROPERTY        0x0000000B

/* Messages sent **from** NPU */
/* IPC Message Response -- uint32_t */
@@ -55,6 +57,10 @@
#define NPU_IPC_MSG_LOOPBACK_DONE       0x00010005
/* ipc_msg_execute_pkt_v2 */
#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

/* Logging message size */
/* Number 32-bit elements for the maximum log message size */
@@ -103,6 +109,11 @@
/* 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,
};

/* -------------------------------------------------------------------------
 * Data Structures
 * -------------------------------------------------------------------------
@@ -271,6 +282,27 @@ struct ipc_cmd_loopback_pkt {
	uint32_t loopbackParams;
};

/*
 * Set property packet definition
 */
struct ipc_cmd_set_prop_pkt {
	struct ipc_cmd_header_pkt header;
	uint32_t prop_id;
	uint32_t num_params;
	uint32_t network_hdl;
	uint32_t prop_param[0];
};

/*
 * Set property response packet definition
 */
struct ipc_msg_set_prop_pkt {
	struct ipc_msg_header_pkt header;
	uint32_t prop_id;
	uint32_t network_hdl;
	uint32_t prop_value;
};

/*
 * LOAD response packet definition
 */
@@ -417,4 +449,13 @@ 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 */
+234 −35
Original line number Diff line number Diff line
@@ -66,6 +66,7 @@ static int npu_send_misc_cmd(struct npu_device *npu_dev, uint32_t q_idx,
static int npu_queue_event(struct npu_client *client, struct npu_kevent *evt);
static int npu_notify_dsp(struct npu_device *npu_dev, bool pwr_up);
static int npu_notify_aop(struct npu_device *npu_dev, bool on);
static int update_dcvs_activity(struct npu_device *npu_dev, uint32_t activity);
static void npu_destroy_wq(struct npu_host_ctx *host_ctx);
static struct workqueue_struct *npu_create_wq(struct npu_host_ctx *host_ctx,
	const char *name);
@@ -299,8 +300,10 @@ int npu_host_init(struct npu_device *npu_dev)
	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);
	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)
@@ -701,6 +704,7 @@ static void app_msg_proc(struct npu_host_ctx *host_ctx, uint32_t *msg)
	uint32_t msg_id;
	struct npu_network *network = NULL;
	struct npu_kevent kevt;
	struct npu_device *npu_dev = host_ctx->npu_dev;

	msg_id = msg[1];
	switch (msg_id) {
@@ -908,6 +912,29 @@ static void app_msg_proc(struct npu_host_ctx *host_ctx, uint32_t *msg)
		complete_all(&host_ctx->loopback_done);
		break;
	}
	case NPU_IPC_MSG_SET_PROPERTY_DONE:
	{
		struct ipc_msg_set_prop_pkt *set_prop_rsp_pkt =
			(struct ipc_msg_set_prop_pkt *)msg;

		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);
		break;
	}
	case NPU_IPC_MSG_DCVS_NOTIFY:
	{
		struct ipc_msg_set_dcvs_mode *set_dcvs_pkt =
			(struct ipc_msg_set_dcvs_mode *)msg;

		pr_debug("NPU_IPC_MSG_DCVS_NOTIFY %d\n",
			set_dcvs_pkt->activity);

		update_dcvs_activity(npu_dev, set_dcvs_pkt->activity);
		break;
	}
	default:
		pr_err("Not supported apps response received %d\n",
			msg_id);
@@ -1125,18 +1152,153 @@ static uint32_t find_networks_perf_mode(struct npu_host_ctx *host_ctx)

	network = host_ctx->networks;

	if (!host_ctx->network_num) {
		/* if no network exists, set to the lowest level */
		max_perf_mode = 1;
	} else {
		/* find the max level among all the networks */
		for (i = 0; i < host_ctx->network_num; i++) {
		if ((network->perf_mode != 0) &&
			(network->perf_mode > max_perf_mode))
			max_perf_mode = network->perf_mode;
			if ((network->cur_perf_mode != 0) &&
				(network->cur_perf_mode > max_perf_mode))
				max_perf_mode = network->cur_perf_mode;
			network++;
		}
	}
	pr_debug("max perf mode for networks: %d\n", max_perf_mode);

	return max_perf_mode;
}

static int set_perf_mode(struct npu_device *npu_dev)
{
	int ret = 0;
	uint32_t networks_perf_mode;
	struct npu_host_ctx *host_ctx = &npu_dev->host_ctx;

	networks_perf_mode = find_networks_perf_mode(host_ctx);

	ret = npu_set_uc_power_level(npu_dev, networks_perf_mode);
	if (ret)
		pr_err("network load failed due to power level set\n");

	return ret;
}

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

	npu_dev->pwrctrl.cur_dcvs_activity = 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;
}

int32_t npu_host_set_fw_property(struct npu_device *npu_dev,
	struct msm_npu_property *property)
{
	int ret = 0, i;
	uint32_t prop_param, prop_id;
	struct ipc_cmd_set_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;

	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);
	prop_packet = kzalloc(pkt_size, GFP_KERNEL);

	if (!prop_packet)
		return -ENOMEM;

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

		if (property->network_hdl == 0) {
			npu_dev->pwrctrl.dcvs_mode = prop_param;
			pr_debug("Set global dcvs mode %d\n", prop_param);
		}
		break;
	default:
		pr_err("unsupported property received %d\n", property->prop_id);
		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 =
		atomic_add_return(1, &host_ctx->ipc_trans_id);
	prop_packet->header.flags = 0;

	prop_packet->prop_id = prop_id;
	prop_packet->num_params = num_of_params;
	prop_packet->network_hdl = property->network_hdl;
	for (i = 0; i < num_of_params; i++)
		prop_packet->prop_param[i] = property->prop_param[i];

	reinit_completion(&host_ctx->property_set_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;
	}

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

set_prop_exit:
	kfree(prop_packet);
	return ret;

}

int32_t npu_host_load_network(struct npu_client *client,
			struct msm_npu_load_network_ioctl *load_ioctl)
{
@@ -1145,7 +1307,6 @@ int32_t npu_host_load_network(struct npu_client *client,
	struct npu_network *network;
	struct ipc_cmd_load_pkt load_packet;
	struct npu_host_ctx *host_ctx = &npu_dev->host_ctx;
	uint32_t networks_perf_mode = 0;

	ret = fw_init(npu_dev);
	if (ret)
@@ -1164,7 +1325,8 @@ int32_t npu_host_load_network(struct npu_client *client,
	network->phy_add = load_ioctl->buf_phys_addr;
	network->first_block_size = load_ioctl->first_block_size;
	network->priority = load_ioctl->priority;
	network->perf_mode = load_ioctl->perf_mode;
	network->cur_perf_mode = network->init_perf_mode =
		load_ioctl->perf_mode;

	/* verify mapped physical address */
	if (!npu_mem_verify_addr(client, network->phy_add)) {
@@ -1172,14 +1334,6 @@ int32_t npu_host_load_network(struct npu_client *client,
		goto error_free_network;
	}

	networks_perf_mode = find_networks_perf_mode(host_ctx);

	ret = npu_set_uc_power_level(npu_dev, networks_perf_mode);
	if (ret) {
		pr_err("network load failed due to power level set\n");
		goto error_free_network;
	}

	load_packet.header.cmd_type = NPU_IPC_CMD_LOAD;
	load_packet.header.size = sizeof(struct ipc_cmd_load_pkt);
	load_packet.header.trans_id =
@@ -1229,6 +1383,7 @@ int32_t npu_host_load_network(struct npu_client *client,
	load_ioctl->network_hdl = network->network_hdl;
	network->is_active = true;
	network_put(network);

	mutex_unlock(&host_ctx->lock);

	return ret;
@@ -1251,7 +1406,6 @@ int32_t npu_host_load_network_v2(struct npu_client *client,
	struct npu_network *network;
	struct ipc_cmd_load_pkt_v2 *load_packet = NULL;
	struct npu_host_ctx *host_ctx = &npu_dev->host_ctx;
	uint32_t networks_perf_mode = 0;
	uint32_t num_patch_params, pkt_size;

	ret = fw_init(npu_dev);
@@ -1285,7 +1439,8 @@ int32_t npu_host_load_network_v2(struct npu_client *client,
	network->phy_add = load_ioctl->buf_phys_addr;
	network->first_block_size = load_ioctl->first_block_size;
	network->priority = load_ioctl->priority;
	network->perf_mode = load_ioctl->perf_mode;
	network->cur_perf_mode = network->init_perf_mode =
		load_ioctl->perf_mode;
	network->num_layers = load_ioctl->num_layers;

	/* verify mapped physical address */
@@ -1295,14 +1450,6 @@ int32_t npu_host_load_network_v2(struct npu_client *client,
		goto error_free_network;
	}

	networks_perf_mode = find_networks_perf_mode(host_ctx);

	ret = npu_set_uc_power_level(npu_dev, networks_perf_mode);
	if (ret) {
		pr_err("network load failed due to power level set\n");
		goto error_free_network;
	}

	load_packet->header.cmd_type = NPU_IPC_CMD_LOAD_V2;
	load_packet->header.size = pkt_size;
	load_packet->header.trans_id =
@@ -1356,6 +1503,7 @@ int32_t npu_host_load_network_v2(struct npu_client *client,
	network->is_active = true;
	kfree(load_packet);
	network_put(network);

	mutex_unlock(&host_ctx->lock);

	return ret;
@@ -1378,7 +1526,6 @@ int32_t npu_host_unload_network(struct npu_client *client,
	struct ipc_cmd_unload_pkt unload_packet;
	struct npu_network *network;
	struct npu_host_ctx *host_ctx = &npu_dev->host_ctx;
	uint32_t networks_perf_mode;

	/* get the corresponding network for ipc trans id purpose */
	mutex_lock(&host_ctx->lock);
@@ -1464,11 +1611,11 @@ int32_t npu_host_unload_network(struct npu_client *client,
	 */
	network_put(network);
	free_network(host_ctx, client, network->id);

	/* recalculate uc_power_level after unload network */
	networks_perf_mode = find_networks_perf_mode(host_ctx);
	ret = npu_set_uc_power_level(npu_dev, networks_perf_mode);
	if (ret)
		pr_err("network unload failed to set power level\n");
	if (npu_dev->pwrctrl.cur_dcvs_activity)
		set_perf_mode(npu_dev);

	mutex_unlock(&host_ctx->lock);
	if (host_ctx->fw_unload_delay_ms) {
		flush_delayed_work(&host_ctx->fw_deinit_work);
@@ -1502,7 +1649,7 @@ int32_t npu_host_exec_network(struct npu_client *client,
		return -EINVAL;
	}

	if (atomic_inc_return(&host_ctx->network_exeute_cnt) == 1)
	if (atomic_inc_return(&host_ctx->network_execute_cnt) == 1)
		npu_notify_cdsprm_cxlimit_activity(npu_dev, true);

	if (!network->is_active) {
@@ -1609,7 +1756,7 @@ int32_t npu_host_exec_network(struct npu_client *client,
		host_error_hdlr(npu_dev, true);
	}

	if (atomic_dec_return(&host_ctx->network_exeute_cnt) == 0)
	if (atomic_dec_return(&host_ctx->network_execute_cnt) == 0)
		npu_notify_cdsprm_cxlimit_activity(npu_dev, false);

	return ret;
@@ -1637,7 +1784,7 @@ int32_t npu_host_exec_network_v2(struct npu_client *client,
		return -EINVAL;
	}

	if (atomic_inc_return(&host_ctx->network_exeute_cnt) == 1)
	if (atomic_inc_return(&host_ctx->network_execute_cnt) == 1)
		npu_notify_cdsprm_cxlimit_activity(npu_dev, true);

	if (!network->is_active) {
@@ -1766,7 +1913,7 @@ int32_t npu_host_exec_network_v2(struct npu_client *client,
		host_error_hdlr(npu_dev, true);
	}

	if (atomic_dec_return(&host_ctx->network_exeute_cnt) == 0)
	if (atomic_dec_return(&host_ctx->network_execute_cnt) == 0)
		npu_notify_cdsprm_cxlimit_activity(npu_dev, false);

	return ret;
@@ -1845,3 +1992,55 @@ void npu_host_cleanup_networks(struct npu_client *client)
		npu_host_unmap_buf(client, &unmap_req);
	}
}

/*
 * set network or global perf_mode
 * if network_hdl is 0, set global perf_mode_override
 * otherwise set network perf_mode: if perf_mode is 0,
 * change network perf_mode to initial perf_mode from
 * load_network
 */
int32_t npu_host_set_perf_mode(struct npu_client *client, uint32_t network_hdl,
	uint32_t perf_mode)
{
	int ret = 0;
	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);

	if (network_hdl == 0) {
		pr_debug("change perf_mode_override to %d\n", perf_mode);
		npu_dev->pwrctrl.perf_mode_override = perf_mode;
	} 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;
		}

		if (perf_mode == 0) {
			network->cur_perf_mode = network->init_perf_mode;
			pr_debug("change network %d perf_mode back to %d\n",
				network_hdl, network->cur_perf_mode);
		} else {
			network->cur_perf_mode = perf_mode;
			pr_debug("change network %d perf_mode to %d\n",
				network_hdl, network->cur_perf_mode);
		}
	}

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

	if (network)
		network_put(network);
	mutex_unlock(&host_ctx->lock);

	return ret;
}
+9 −3
Original line number Diff line number Diff line
@@ -49,7 +49,8 @@ struct npu_network {
	uint32_t first_block_size;
	uint32_t network_hdl;
	uint32_t priority;
	uint32_t perf_mode;
	uint32_t cur_perf_mode;
	uint32_t init_perf_mode;
	uint32_t num_layers;
	void *stats_buf;
	void __user *stats_buf_u;
@@ -74,6 +75,7 @@ enum fw_state {
struct npu_host_ctx {
	struct mutex lock;
	void *subsystem_handle;
	struct npu_device *npu_dev;
	enum fw_state fw_state;
	int32_t fw_ref_cnt;
	int32_t power_vote_num;
@@ -83,6 +85,7 @@ struct npu_host_ctx {
	struct workqueue_struct *wq;
	struct completion loopback_done;
	struct completion fw_deinit_done;
	struct completion property_set_done;
	int32_t network_num;
	struct npu_network networks[MAX_LOADED_NETWORK];
	bool sys_cache_disable;
@@ -90,7 +93,7 @@ struct npu_host_ctx {
	uint32_t exec_flags_override;
	uint32_t fw_unload_delay_ms;
	atomic_t ipc_trans_id;
	atomic_t network_exeute_cnt;
	atomic_t network_execute_cnt;

	uint32_t err_irq_sts;
	uint32_t wdg_irq_sts;
@@ -134,8 +137,11 @@ int32_t npu_host_exec_network_v2(struct npu_client *client,
	struct msm_npu_exec_network_ioctl_v2 *exec_ioctl,
	struct msm_npu_patch_buf_info *patch_buf_info);
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);
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);
void npu_dump_debug_timeout_stats(struct npu_device *npu_dev);

#endif /* _NPU_MGR_H */
Loading