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: Sreekanth Gande <sgande@qti.qualcomm.com> Signed-off-by: Bavyasritha Alahari <alahari@codeaurora.org>
This commit is contained in:
@@ -1,6 +1,6 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-only
|
||||
/*
|
||||
* Copyright (c) 2018-2019, 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>
|
||||
@@ -179,6 +180,7 @@ struct cdsprm {
|
||||
bool b_rpmsg_register;
|
||||
bool b_qosinitdone;
|
||||
bool b_applyingNpuLimit;
|
||||
bool b_silver_en;
|
||||
int latency_request;
|
||||
struct dentry *debugfs_dir;
|
||||
struct dentry *debugfs_file;
|
||||
@@ -186,6 +188,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;
|
||||
@@ -454,8 +459,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;
|
||||
} else {
|
||||
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);
|
||||
@@ -465,6 +546,7 @@ static void set_qos_latency(int latency)
|
||||
latency);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void process_rm_request(struct sysmon_msg *msg)
|
||||
{
|
||||
@@ -506,9 +588,10 @@ 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);
|
||||
}
|
||||
@@ -549,8 +632,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;
|
||||
|
||||
@@ -640,16 +723,22 @@ static int process_cdsp_request_thread(void *data)
|
||||
result = wait_event_interruptible(cdsprm_wq,
|
||||
(req = get_next_request()));
|
||||
|
||||
if (kthread_should_stop())
|
||||
break;
|
||||
|
||||
if (result)
|
||||
continue;
|
||||
|
||||
if (!req)
|
||||
break;
|
||||
|
||||
msg = &req->msg;
|
||||
|
||||
if ((msg->feature_id == SYSMON_CDSP_FEATURE_RM_RX) &&
|
||||
if (msg && (msg->feature_id == SYSMON_CDSP_FEATURE_RM_RX) &&
|
||||
gcdsprm.b_qosinitdone) {
|
||||
process_rm_request(msg);
|
||||
} else if (msg->feature_id ==
|
||||
SYSMON_CDSP_FEATURE_L3_RX) {
|
||||
} else if (msg && (msg->feature_id ==
|
||||
SYSMON_CDSP_FEATURE_L3_RX)) {
|
||||
l3_clock_khz = msg->fs.l3_struct.l3_clock_khz;
|
||||
|
||||
spin_lock_irqsave(&gcdsprm.l3_lock, flags);
|
||||
@@ -661,8 +750,8 @@ static int process_cdsp_request_thread(void *data)
|
||||
pr_debug("Set L3 clock %d done\n",
|
||||
l3_clock_khz);
|
||||
}
|
||||
} else if (msg->feature_id ==
|
||||
SYSMON_CDSP_FEATURE_NPU_LIMIT_RX) {
|
||||
} else if (msg && (msg->feature_id ==
|
||||
SYSMON_CDSP_FEATURE_NPU_LIMIT_RX)) {
|
||||
mutex_lock(&gcdsprm.npu_activity_lock);
|
||||
|
||||
gcdsprm.set_corner_limit_cached =
|
||||
@@ -706,8 +795,8 @@ static int process_cdsp_request_thread(void *data)
|
||||
pr_err("rpmsg send failed %d\n", result);
|
||||
else
|
||||
pr_debug("NPU limit ack sent\n");
|
||||
} else if (msg->feature_id ==
|
||||
SYSMON_CDSP_FEATURE_VERSION_RX) {
|
||||
} else if (msg && (msg->feature_id ==
|
||||
SYSMON_CDSP_FEATURE_VERSION_RX)) {
|
||||
cdsprm_rpmsg_send_details();
|
||||
pr_debug("Sent preserved data to DSP\n");
|
||||
}
|
||||
@@ -928,6 +1017,12 @@ static int cdsp_rm_driver_probe(struct platform_device *pdev)
|
||||
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;
|
||||
@@ -1101,6 +1196,7 @@ static int __init cdsprm_init(void)
|
||||
goto bail;
|
||||
}
|
||||
|
||||
|
||||
err = platform_driver_register(&hvx_rm);
|
||||
|
||||
if (err) {
|
||||
|
||||
Reference in New Issue
Block a user