diff --git a/drivers/soc/qcom/cdsprm.c b/drivers/soc/qcom/cdsprm.c index 33c769a92bbd..8b2961188d6d 100644 --- a/drivers/soc/qcom/cdsprm.c +++ b/drivers/soc/qcom/cdsprm.c @@ -1,6 +1,6 @@ // 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 #include +#include #include #include #include @@ -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,15 +599,92 @@ 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) { - if (!gcdsprm.qos_request) { - pm_qos_add_request(&gcdsprm.pm_qos_req, - PM_QOS_CPU_DMA_LATENCY, latency); - gcdsprm.qos_request = true; + 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 { - pm_qos_update_request(&gcdsprm.pm_qos_req, - latency); + if (!gcdsprm.qos_request) { + pm_qos_add_request(&gcdsprm.pm_qos_req, + PM_QOS_CPU_DMA_LATENCY, latency); + gcdsprm.qos_request = true; + } else { + pm_qos_update_request(&gcdsprm.pm_qos_req, + latency); + } } } @@ -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)