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

Commit d754300a authored by Jilai Wang's avatar Jilai Wang
Browse files

msm: npu: Add NPU DCVS mode support



This change is to allow user to set/get npu DCVS setting via
get/set_property apis.

Change-Id: I606d7bbd4809c70e892e0d3bdbf8fe48b9073ba3
Signed-off-by: default avatarJilai Wang <jilaiw@codeaurora.org>
parent 007833ae
Loading
Loading
Loading
Loading
+6 −0
Original line number Diff line number Diff line
@@ -48,6 +48,8 @@
#define NPU_MAX_PATCH_NUM		160
#define NPU_MAX_BW_DEVS			4

#define PERF_MODE_DEFAULT 0

enum npu_power_level {
	NPU_PWRLEVEL_MINSVS = 0,
	NPU_PWRLEVEL_LOWSVS,
@@ -164,6 +166,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 {
@@ -183,6 +187,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;
};

/**
+124 −25
Original line number Diff line number Diff line
@@ -30,7 +30,6 @@
#define DDR_MAPPED_START_ADDR   0x80000000
#define DDR_MAPPED_SIZE         0x60000000

#define PERF_MODE_DEFAULT 0
#define MBOX_OP_TIMEOUTMS 1000

/* -------------------------------------------------------------------------
@@ -58,6 +57,12 @@ static ssize_t perf_mode_override_show(struct device *dev,
static ssize_t perf_mode_override_store(struct device *dev,
					  struct device_attribute *attr,
					  const char *buf, size_t count);
static ssize_t dcvs_mode_show(struct device *dev,
					 struct device_attribute *attr,
					 char *buf);
static ssize_t dcvs_mode_store(struct device *dev,
					  struct device_attribute *attr,
					  const char *buf, size_t count);
static ssize_t boot_store(struct device *dev,
					  struct device_attribute *attr,
					  const char *buf, size_t count);
@@ -85,6 +90,11 @@ 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 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);
@@ -155,11 +165,13 @@ static DEVICE_ATTR_RO(caps);
static DEVICE_ATTR_RW(pwr);
static DEVICE_ATTR_RW(perf_mode_override);
static DEVICE_ATTR_WO(boot);
static DEVICE_ATTR_RW(dcvs_mode);

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_boot.attr,
	NULL
};
@@ -278,8 +290,8 @@ static ssize_t perf_mode_override_store(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);
	struct npu_host_ctx *host_ctx = &npu_dev->host_ctx;
	uint32_t val;
	int rc;

@@ -290,15 +302,56 @@ static ssize_t perf_mode_override_store(struct device *dev,
	}

	val = min(val, npu_dev->pwrctrl.num_pwrlevels);
	mutex_lock(&host_ctx->lock);
	npu_dev->pwrctrl.perf_mode_override = val;
	NPU_INFO("setting uc_pwrlevel_override to %d\n", val);
	npu_set_power_level(npu_dev, true);
	mutex_unlock(&host_ctx->lock);
	NPU_INFO("setting perf mode to %d\n", val);
	client.npu_dev = npu_dev;
	npu_host_set_perf_mode(&client, 0, val);

	return count;
}

static ssize_t dcvs_mode_show(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 dcvs_mode_store(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) {
		NPU_ERR("Invalid input for dcvs mode setting\n");
		return -EINVAL;
	}

	val = min(val, (uint32_t)(npu_dev->pwrctrl.num_pwrlevels - 1));
	NPU_DBG("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) {
		NPU_ERR("npu_host_set_fw_property failed %d\n", ret);
		return ret;
	}

	npu_dev->pwrctrl.dcvs_mode = val;

	return count;
}
/* -------------------------------------------------------------------------
 * SysFS - npu_boot
 * -------------------------------------------------------------------------
@@ -386,6 +439,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 = pwr->num_pwrlevels;
		NPU_DBG("setting back to power level=%d\n",
			pwr->active_pwrlevel);
	}
@@ -445,14 +499,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
@@ -559,9 +605,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);

@@ -1327,6 +1370,43 @@ 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;
	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);
		if (rc) {
			NPU_ERR("enable fw failed\n");
		} else {
			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");
		disable_fw(npu_dev);
		host_ctx->npu_init_cnt--;
		NPU_DBG("npu_init_cnt %d\n", host_ctx->npu_init_cnt);
	} else {
		NPU_ERR("can't disable fw %d\n", host_ctx->npu_init_cnt);
	}

	return rc;
}

static int npu_set_property(struct npu_client *client,
	unsigned long arg)
{
@@ -1341,9 +1421,19 @@ static int npu_set_property(struct npu_client *client,
	}

	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:
		NPU_ERR("Not supported property %d\n", prop.prop_id);
		ret = -EINVAL;
		ret = npu_host_set_fw_property(client->npu_dev, &prop);
		if (ret)
			NPU_ERR("npu_host_set_fw_property failed\n");
		break;
	}

@@ -1369,6 +1459,10 @@ static int npu_get_property(struct npu_client *client,
	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;
@@ -1379,13 +1473,17 @@ static int npu_get_property(struct npu_client *client,
		prop.prop_param[0] = npu_dev->hw_version;
		break;
	default:
		NPU_ERR("Not supported property %d\n", prop.prop_id);
		return -EINVAL;
		ret = npu_host_get_fw_property(client->npu_dev, &prop);
		if (ret) {
			NPU_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");
		NPU_ERR("fail to copy to user\n");
		return -EFAULT;
	}

@@ -1745,6 +1843,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;
}
+50 −0
Original line number Diff line number Diff line
@@ -33,6 +33,10 @@
#define NPU_IPC_CMD_EXECUTE_V2          0x0000000A
/* npu_ipc_cmd_notify_pwr_packet_t */
#define NPU_IPC_CMD_NOTIFY_PWR          0x0000000B
/* ipc_cmd_set_property_packet */
#define NPU_IPC_CMD_SET_PROPERTY        0x0000000C
/* ipc_cmd_get_property_packet */
#define NPU_IPC_CMD_GET_PROPERTY        0x0000000D

/* Messages sent **from** NPU */
/* IPC Message Response -- uint32_t */
@@ -52,6 +56,15 @@
#define NPU_IPC_MSG_EXECUTE_V2_DONE     0x00010006
/* struct ipc_msg_notify_pwr_pkt */
#define NPU_IPC_MSG_NOTIFY_PWR_DONE     0x00010007
/* ipc_msg_set_property_packet */
#define NPU_IPC_MSG_SET_PROPERTY_DONE   0x00010008
/* ipc_msg_get_property_packet */
#define NPU_IPC_MSG_GET_PROPERTY_DONE   0x00010009
/* 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 */
@@ -100,6 +113,9 @@
/* Debug stats */
#define NUM_LAYER_STATS_PER_EXE_MSG_MAX 110

/* DCVS */
#define NPU_DCVS_ACTIVITY_MAX_PERF 0x100

/* -------------------------------------------------------------------------
 * Data Structures
 * -------------------------------------------------------------------------
@@ -268,6 +284,40 @@ struct ipc_cmd_loopback_pkt {
	uint32_t loopbackParams;
};

/*
 * Generic property definition
 */
struct ipc_cmd_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];
};

/*
 * Generic property response packet definition
 */
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_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
 */
+392 −29

File changed.

Preview size limit exceeded, changes collapsed.

+12 −2
Original line number Diff line number Diff line
@@ -44,7 +44,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;
@@ -73,6 +74,7 @@ struct npu_host_ctx {
	void *subsystem_handle;
	enum fw_state fw_state;
	int32_t fw_ref_cnt;
	int32_t npu_init_cnt;
	int32_t power_vote_num;
	struct work_struct ipc_irq_work;
	struct work_struct wdg_err_irq_work;
@@ -81,11 +83,13 @@ struct npu_host_ctx {
	struct work_struct update_pwr_work;
	struct delayed_work disable_fw_work;
	struct workqueue_struct *wq;
	struct workqueue_struct *wq_pri;
	struct completion misc_cmd_done;
	struct completion fw_deinit_done;
	struct completion fw_bringup_done;
	struct completion fw_shutdown_done;
	struct completion npu_power_up_done;
	void *prop_buf;
	int32_t network_num;
	struct npu_network networks[MAX_LOADED_NETWORK];
	bool sys_cache_disable;
@@ -141,11 +145,17 @@ 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);
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);
int npu_host_notify_fw_pwr_state(struct npu_device *npu_dev,
	uint32_t pwr_level, bool post);
int npu_host_update_power(struct npu_device *npu_dev);

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_info(struct npu_device *npu_dev);
void npu_dump_ipc_packet(struct npu_device *npu_dev, void *cmd_ptr);