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

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

Merge "msm: npu: Use mutex to protect power level change"

parents 854a936b e7443aaa
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;
}
}