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

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

msm: npu: Use mutex to protect power level change



NPU power level can be changed by multiple sources, so it's
necessary to use mutex to protect it while it's updated by
one of the sources.

Change-Id: I3e99866f0f279fac16463055867225402c03e369
Signed-off-by: default avatarJilai Wang <jilaiw@codeaurora.org>
parent 54f3590a
Loading
Loading
Loading
Loading
+10 −1
Original line number Original line Diff line number Diff line
@@ -276,6 +276,7 @@ static ssize_t perf_mode_override_store(struct device *dev,
					  const char *buf, size_t count)
					  const char *buf, size_t count)
{
{
	struct npu_device *npu_dev = dev_get_drvdata(dev);
	struct npu_device *npu_dev = dev_get_drvdata(dev);
	struct npu_host_ctx *host_ctx = &npu_dev->host_ctx;
	uint32_t val;
	uint32_t val;
	int rc;
	int rc;


@@ -286,9 +287,11 @@ static ssize_t perf_mode_override_store(struct device *dev,
	}
	}


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


	return count;
	return count;
}
}
@@ -707,17 +710,23 @@ static int
npu_set_cur_state(struct thermal_cooling_device *cdev, unsigned long state)
npu_set_cur_state(struct thermal_cooling_device *cdev, unsigned long state)
{
{
	struct npu_device *npu_dev = cdev->devdata;
	struct npu_device *npu_dev = cdev->devdata;
	struct npu_host_ctx *host_ctx = &npu_dev->host_ctx;
	struct npu_thermalctrl *thermal = &npu_dev->thermalctrl;
	struct npu_thermalctrl *thermal = &npu_dev->thermalctrl;
	int rc = 0;


	NPU_DBG("request state=%lu\n", state);
	NPU_DBG("request state=%lu\n", state);
	if (state > thermal->max_state)
	if (state > thermal->max_state)
		return -EINVAL;
		return -EINVAL;


	mutex_lock(&host_ctx->lock);
	thermal->current_state = state;
	thermal->current_state = state;
	thermal->pwr_level =  npu_power_level_from_index(npu_dev,
	thermal->pwr_level =  npu_power_level_from_index(npu_dev,
		thermal->max_state - state);
		thermal->max_state - state);


	return npu_set_power_level(npu_dev, true);
	rc = npu_set_power_level(npu_dev, true);
	mutex_unlock(&host_ctx->lock);

	return rc;
}
}


/* -------------------------------------------------------------------------
/* -------------------------------------------------------------------------
+38 −32
Original line number Original line Diff line number Diff line
@@ -348,14 +348,7 @@ static int npu_notify_fw_pwr_state(struct npu_device *npu_dev,
int npu_host_notify_fw_pwr_state(struct npu_device *npu_dev,
int npu_host_notify_fw_pwr_state(struct npu_device *npu_dev,
	uint32_t pwr_level, bool post)
	uint32_t pwr_level, bool post)
{
{
	struct npu_host_ctx *host_ctx = &npu_dev->host_ctx;
	return npu_notify_fw_pwr_state(npu_dev, pwr_level, post);
	int ret;

	mutex_lock(&host_ctx->lock);
	ret = npu_notify_fw_pwr_state(npu_dev, pwr_level, post);
	mutex_unlock(&host_ctx->lock);

	return ret;
}
}


static int npu_notifier_cb(struct notifier_block *this, unsigned long code,
static int npu_notifier_cb(struct notifier_block *this, unsigned long code,
@@ -1341,6 +1334,10 @@ static uint32_t find_networks_perf_mode(struct npu_host_ctx *host_ctx)


	network = host_ctx->networks;
	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 */
		/* find the max level among all the networks */
		for (i = 0; i < host_ctx->network_num; i++) {
		for (i = 0; i < host_ctx->network_num; i++) {
			if ((network->perf_mode != 0) &&
			if ((network->perf_mode != 0) &&
@@ -1348,11 +1345,27 @@ static uint32_t find_networks_perf_mode(struct npu_host_ctx *host_ctx)
				max_perf_mode = network->perf_mode;
				max_perf_mode = network->perf_mode;
			network++;
			network++;
		}
		}
	NPU_DBG("max perf mode for networks: %d\n", max_perf_mode);
	}
	pr_debug("max perf mode for networks: %d\n", max_perf_mode);


	return 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)
		NPU_ERR("set uc power level %d failed\n", networks_perf_mode);

	return ret;
}

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


	ret = enable_fw(npu_dev);
	ret = enable_fw(npu_dev);
	if (ret)
	if (ret)
@@ -1388,11 +1400,9 @@ int32_t npu_host_load_network(struct npu_client *client,
		goto error_free_network;
		goto error_free_network;
	}
	}


	networks_perf_mode = find_networks_perf_mode(host_ctx);
	ret = set_perf_mode(npu_dev);

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


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


	ret = enable_fw(npu_dev);
	ret = enable_fw(npu_dev);
@@ -1512,11 +1521,10 @@ int32_t npu_host_load_network_v2(struct npu_client *client,
	}
	}


	NPU_DBG("network address %llx\n", network->phy_add);
	NPU_DBG("network address %llx\n", network->phy_add);
	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) {
	if (ret) {
		NPU_ERR("network load failed due to power level set\n");
		NPU_ERR("set_perf_mode failed\n");
		goto error_free_network;
		goto error_free_network;
	}
	}


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


	/* get the corresponding network for ipc trans id purpose */
	/* get the corresponding network for ipc trans id purpose */
	mutex_lock(&host_ctx->lock);
	mutex_lock(&host_ctx->lock);
@@ -1681,15 +1688,14 @@ int32_t npu_host_unload_network(struct npu_client *client,
	 */
	 */
	network_put(network);
	network_put(network);
	free_network(host_ctx, client, network->id);
	free_network(host_ctx, client, network->id);
	/* recalculate uc_power_level after unload network */
	/* update perf mode */
	networks_perf_mode = find_networks_perf_mode(host_ctx);
	if (set_perf_mode(npu_dev))
	if (networks_perf_mode > 0) {
		NPU_WARN("set_perf_mode failed\n");
		ret = npu_set_uc_power_level(npu_dev, networks_perf_mode);

		if (ret)
			NPU_WARN("restore uc power level failed\n");
	}
	mutex_unlock(&host_ctx->lock);
	mutex_unlock(&host_ctx->lock);

	disable_fw(npu_dev);
	disable_fw(npu_dev);

	return ret;
	return ret;
}
}