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

Commit 16a2c185 authored by Bavyasritha Alahari's avatar Bavyasritha Alahari
Browse files

soc: qcom: Set QOS only to silver cluster



CDSPRM module implements a RPMSG interface to communicate with CDSP
while providing a way for CDSP to vote for CPU QoS to benefit CDSP
applications performance.Glink IRQ mostly is taken by the silver cluster.
CDSPRM driver vote for sliver cluster prevents collapsing gold cluster
This saves significant power.

Change-Id: I6cac71e7ab85d823dfc44b19dd85a0dde62455db
Acked-by: default avatarSreekanth Gande <sgande@qti.qualcomm.com>
Signed-off-by: default avatarBavyasritha Alahari <alahari@codeaurora.org>
parent 9c25b460
Loading
Loading
Loading
Loading
+103 −14
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0-only
/*
 * Copyright (c) 2018-2020, The Linux Foundation. All rights reserved.
 * Copyright (c) 2018-2021, The Linux Foundation. All rights reserved.
 */

/*
@@ -13,6 +13,7 @@

#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/slab.h>
#include <linux/completion.h>
#include <linux/string.h>
#include <linux/err.h>
@@ -231,6 +232,7 @@ struct cdsprm {
	bool				b_rpmsg_register;
	bool				b_qosinitdone;
	bool				b_applyingNpuLimit;
	bool				b_silver_en;
	int					latency_request;
	int					b_cdsprm_devinit;
	int					b_hvxrm_devinit;
@@ -245,6 +247,9 @@ struct cdsprm {
	int (*set_l3_freq_cached)(unsigned int freq_khz);
	int (*set_corner_limit)(enum cdsprm_npu_corner);
	int (*set_corner_limit_cached)(enum cdsprm_npu_corner);
	u32 *coreno;
	u32 corecount;
	struct dev_pm_qos_request *dev_pm_qos_req;
};

static struct cdsprm gcdsprm;
@@ -594,8 +599,84 @@ void cdsprm_unregister_cdspl3gov(void)
}
EXPORT_SYMBOL(cdsprm_unregister_cdspl3gov);

static void qos_cores_init(struct device *dev)
{
	int i, err = 0;
	u32 *cpucores = NULL;

	of_find_property(dev->of_node,
					"qcom,qos-cores", &gcdsprm.corecount);

	if (gcdsprm.corecount) {
		gcdsprm.corecount /= sizeof(u32);

		cpucores = kcalloc(gcdsprm.corecount,
					sizeof(u32), GFP_KERNEL);

		if (cpucores == NULL) {
			dev_err(dev,
					"kcalloc failed for cpucores\n");
			gcdsprm.b_silver_en = false;
		}

		for (i = 0; i < gcdsprm.corecount; i++) {
			err = of_property_read_u32_index(dev->of_node,
						 "qcom,qos-cores", i, &cpucores[i]);
			if (err) {
				dev_err(dev,
					"%s: failed to read QOS coree for core:%d\n",
						__func__, i);
				gcdsprm.b_silver_en = false;
			}
		}

		gcdsprm.coreno = cpucores;

		gcdsprm.dev_pm_qos_req = kcalloc(gcdsprm.corecount,
				sizeof(struct dev_pm_qos_request), GFP_KERNEL);

		if (gcdsprm.dev_pm_qos_req == NULL) {
			dev_err(dev,
					"kcalloc failed for dev_pm_qos_req\n");
			gcdsprm.b_silver_en = false;
		}
	}
}

static void set_qos_latency(int latency)
{
	int err = 0;
	u32 ii = 0;
	int cpu;

	if (gcdsprm.b_silver_en) {

		for (ii = 0; ii < gcdsprm.corecount; ii++) {
			cpu = gcdsprm.coreno[ii];

			if (!gcdsprm.qos_request) {
				err = dev_pm_qos_add_request(
						get_cpu_device(cpu),
						&gcdsprm.dev_pm_qos_req[ii],
						DEV_PM_QOS_RESUME_LATENCY,
						latency);
			} else {
				err = dev_pm_qos_update_request(
						&gcdsprm.dev_pm_qos_req[ii],
						latency);
			}

			if (err < 0) {
				pr_err("%s: %s: PM voting cpu:%d fail,err %d,QoS update %d\n",
					current->comm, __func__, cpu,
					err, gcdsprm.qos_request);
				break;
			}
		}

		if (err >= 0)
			gcdsprm.qos_request = true;
	} else {
		if (!gcdsprm.qos_request) {
			pm_qos_add_request(&gcdsprm.pm_qos_req,
				PM_QOS_CPU_DMA_LATENCY, latency);
@@ -605,6 +686,7 @@ static void set_qos_latency(int latency)
				latency);
		}
	}
}

static void process_rm_request(struct sysmon_msg *msg)
{
@@ -646,9 +728,9 @@ static void process_rm_request(struct sysmon_msg *msg)
		} else if ((rm_msg->b_qos_flag ==
					SYSMON_CDSP_QOS_FLAG_DISABLE) &&
				(gcdsprm.latency_request !=
					QOS_LATENCY_DISABLE_VALUE)) {
			set_qos_latency(QOS_LATENCY_DISABLE_VALUE);
			gcdsprm.latency_request = QOS_LATENCY_DISABLE_VALUE;
					PM_QOS_RESUME_LATENCY_DEFAULT_VALUE)) {
			set_qos_latency(PM_QOS_RESUME_LATENCY_DEFAULT_VALUE);
			gcdsprm.latency_request = PM_QOS_RESUME_LATENCY_DEFAULT_VALUE;
			pr_debug("Set qos latency to %d\n",
					gcdsprm.latency_request);
		}
@@ -689,8 +771,8 @@ static void process_delayed_rm_request(struct work_struct *work)
		curr_timestamp = __arch_counter_get_cntvct();
	}

	set_qos_latency(QOS_LATENCY_DISABLE_VALUE);
	gcdsprm.latency_request = QOS_LATENCY_DISABLE_VALUE;
	set_qos_latency(PM_QOS_RESUME_LATENCY_DEFAULT_VALUE);
	gcdsprm.latency_request = PM_QOS_RESUME_LATENCY_DEFAULT_VALUE;
	pr_debug("Set qos latency to %d\n", gcdsprm.latency_request);
	gcdsprm.dt_state = CDSP_DELAY_THREAD_EXITING;

@@ -1142,10 +1224,17 @@ static int cdsp_rm_driver_probe(struct platform_device *pdev)
{
	int n, m, i, ret;
	u32 p;

	struct device *dev = &pdev->dev;
	struct thermal_cooling_device *tcdev = 0;
	unsigned int cooling_cells = 0;

	gcdsprm.b_silver_en = of_property_read_bool(dev->of_node,
					"qcom,qos-cores");

	if (gcdsprm.b_silver_en)
		qos_cores_init(dev);

	if (of_property_read_u32(dev->of_node,
			"qcom,qos-latency-us", &gcdsprm.qos_latency_us)) {
		return -EINVAL;
@@ -1505,8 +1594,8 @@ static void __exit cdsprm_exit(void)

	pr_info("Exit module called\n");
	if (gcdsprm.qos_request) {
		set_qos_latency(QOS_LATENCY_DISABLE_VALUE);
		gcdsprm.latency_request = QOS_LATENCY_DISABLE_VALUE;
		set_qos_latency(PM_QOS_RESUME_LATENCY_DEFAULT_VALUE);
		gcdsprm.latency_request = PM_QOS_RESUME_LATENCY_DEFAULT_VALUE;
	}

	if (gcdsprm.hvx_tcdev)