From b67959cb83dd96df13c16234390b4199a0cfbe46 Mon Sep 17 00:00:00 2001 From: Vivek Aknurwar Date: Thu, 3 Mar 2022 11:08:37 -0800 Subject: [PATCH 1/4] cpufreq: qcom-hw: Add trace for irq and throttle freq polling Add trace events in irq handler and throttle frequency polling to capture DCVSH updates to sched and or when lmh irq is high. Change-Id: I96c1af1abeb24971b8d060457feee1dbadcdb028 Signed-off-by: Vivek Aknurwar Signed-off-by: Mike Tipton --- drivers/cpufreq/qcom-cpufreq-hw.c | 14 ++++++- include/trace/events/dcvsh.h | 63 +++++++++++++++++++++++++++++++ 2 files changed, 75 insertions(+), 2 deletions(-) create mode 100644 include/trace/events/dcvsh.h diff --git a/drivers/cpufreq/qcom-cpufreq-hw.c b/drivers/cpufreq/qcom-cpufreq-hw.c index 3d077c644624..a63c58cf8408 100644 --- a/drivers/cpufreq/qcom-cpufreq-hw.c +++ b/drivers/cpufreq/qcom-cpufreq-hw.c @@ -17,6 +17,9 @@ #include #include +#define CREATE_TRACE_POINTS +#include + #define LUT_MAX_ENTRIES 40U #define LUT_SRC GENMASK(31, 30) #define LUT_L_VAL GENMASK(7, 0) @@ -379,6 +382,8 @@ static void qcom_lmh_dcvs_notify(struct qcom_cpufreq_data *data) } else { throttled_freq = freq_hz / HZ_PER_KHZ; + trace_dcvsh_freq(cpu, qcom_cpufreq_hw_get(cpu), throttled_freq); + /* Update thermal pressure (the boost frequencies are accepted) */ arch_update_thermal_pressure(policy->related_cpus, throttled_freq); @@ -397,11 +402,13 @@ static void qcom_lmh_dcvs_notify(struct qcom_cpufreq_data *data) * If h/w throttled frequency is higher than what cpufreq has requested * for, then stop polling and switch back to interrupt mechanism. */ - if (throttled_freq >= qcom_cpufreq_hw_get(cpu)) + if (throttled_freq >= qcom_cpufreq_hw_get(cpu)) { enable_irq(data->throttle_irq); - else + trace_dcvsh_throttle(cpu, 0); + } else { mod_delayed_work(system_highpri_wq, &data->throttle_work, msecs_to_jiffies(10)); + } out: mutex_unlock(&data->throttle_lock); @@ -418,9 +425,11 @@ static void qcom_lmh_dcvs_poll(struct work_struct *work) static irqreturn_t qcom_lmh_dcvs_handle_irq(int irq, void *data) { struct qcom_cpufreq_data *c_data = data; + struct cpufreq_policy *policy = c_data->policy; /* Disable interrupt and enable polling */ disable_irq_nosync(c_data->throttle_irq); + trace_dcvsh_throttle(cpumask_first(policy->cpus), 1); schedule_delayed_work(&c_data->throttle_work, 0); if (c_data->soc_data->reg_intr_clr) @@ -532,6 +541,7 @@ static int qcom_cpufreq_hw_cpu_offline(struct cpufreq_policy *policy) irq_set_affinity_hint(data->throttle_irq, NULL); arch_update_thermal_pressure(policy->related_cpus, U32_MAX); + trace_dcvsh_throttle(cpumask_first(policy->related_cpus), 0); return 0; } diff --git a/include/trace/events/dcvsh.h b/include/trace/events/dcvsh.h new file mode 100644 index 000000000000..54c72bbc7aca --- /dev/null +++ b/include/trace/events/dcvsh.h @@ -0,0 +1,63 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* + * Copyright (c) 2022, Qualcomm Innovation Center, Inc. All rights reserved. + */ + +#undef TRACE_SYSTEM +#define TRACE_SYSTEM dcvsh + +#if !defined(_TRACE_DCVSH_H) || defined(TRACE_HEADER_MULTI_READ) +#define _TRACE_DCVSH_H + +#include + +TRACE_EVENT(dcvsh_freq, + + TP_PROTO(unsigned long cpu, unsigned long req_freq, + unsigned long throttled_freq), + + TP_ARGS(cpu, req_freq, throttled_freq), + + TP_STRUCT__entry( + __field(unsigned long, cpu) + __field(unsigned long, req_freq) + __field(unsigned long, throttled_freq) + ), + + TP_fast_assign( + __entry->cpu = cpu; + __entry->req_freq = req_freq; + __entry->throttled_freq = throttled_freq; + ), + + TP_printk("cpu:%lu requested_freq:%lu throttled_freq:%lu", + __entry->cpu, + __entry->req_freq, + __entry->throttled_freq) +); + +TRACE_EVENT(dcvsh_throttle, + + TP_PROTO(unsigned long cpu, bool state), + + TP_ARGS(cpu, state), + + TP_STRUCT__entry( + __field(unsigned long, cpu) + __field(bool, state) + ), + + TP_fast_assign( + __entry->cpu = cpu; + __entry->state = state; + ), + + TP_printk("cpu:%lu throttle_%s", + __entry->cpu, + __entry->state ? "begin" : "end") +); + +#endif /* _TRACE_DCVSH_H */ + +/* This part must be outside protection */ +#include From 48acc4c51909b0f22676eb409a90b0383809afae Mon Sep 17 00:00:00 2001 From: Abhijeet Dharmapurikar Date: Wed, 3 Nov 2021 22:05:10 -0700 Subject: [PATCH 2/4] cpufreq: qcom-hw: switch to non deferrable work Currently, when lmh interrupt fires we notify the scheduler about thermal pressure. The scheduler reduces the capacity of the cpu(s) for which the interrupt fired, while we requeue our deferrable work. This leads to an interesting deadlock, since the cpu is running with reduced capacity, the scheduler does not put any task on it, extending the idle time and causing it to remain at reduced capacity - leading to severe underutilization of the cpu(s). Switch to using delayed work instead of deferrable work. This will cause us to exit idle until the thermal condition is recovered. Change-Id: I4c27c9a952ed556336297eb25e815c848b8266eb Signed-off-by: Abhijeet Dharmapurikar Signed-off-by: Vivek Aknurwar --- drivers/cpufreq/qcom-cpufreq-hw.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cpufreq/qcom-cpufreq-hw.c b/drivers/cpufreq/qcom-cpufreq-hw.c index a63c58cf8408..cb172d17437f 100644 --- a/drivers/cpufreq/qcom-cpufreq-hw.c +++ b/drivers/cpufreq/qcom-cpufreq-hw.c @@ -491,7 +491,7 @@ static int qcom_cpufreq_hw_lmh_init(struct cpufreq_policy *policy, int index) data->policy = policy; mutex_init(&data->throttle_lock); - INIT_DEFERRABLE_WORK(&data->throttle_work, qcom_lmh_dcvs_poll); + INIT_DELAYED_WORK(&data->throttle_work, qcom_lmh_dcvs_poll); snprintf(data->irq_name, sizeof(data->irq_name), "dcvsh-irq-%u", policy->cpu); ret = request_threaded_irq(data->throttle_irq, NULL, qcom_lmh_dcvs_handle_irq, From 263dd3f6cec065844576e7a6e76abf5cbbfdd324 Mon Sep 17 00:00:00 2001 From: Imran Shaik Date: Thu, 21 Apr 2022 11:05:38 +0530 Subject: [PATCH 3/4] cpufreq: qcom-hw: Remove kfree() and unmap_base/release_region labels Remove unmap_base/release_region labels to avoid kernel crash when there is no cpufreq hardware data available and explicit kfree() and iounmap() not required since they are dev managed. Trying to vfree() nonexistent vm area ((____ptrval____)) WARNING: CPU: 3 PID: 90 at mm/vmalloc.c:2608 __vunmap+0x9c/0x2a8 Modules linked in: CPU:3 PID:90 Comm:kworker/u8:1 Tainted: G W 5.15.20-ge6916696ed47-dirty #1 Hardware name: Qualcomm Technologies, Inc. Cinder RU RUMI (DT) Workqueue: events_unbound deferred_probe_work_func pstate: 60400005 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) pc : __vunmap+0x9c/0x2a8 lr : __vunmap+0x9c/0x2a8 Call trace: __vunmap+0x9c/0x2a8 vunmap+0x64/0x7c iounmap+0x2c/0x40 devm_ioremap_release+0x18/0x28 devres_release_all+0xd0/0x19c really_probe+0xfc/0x354 __driver_probe_device+0x11c/0x184 driver_probe_device+0x4c/0x18c kernel crash at mm/slub.c:363! Modules linked in: CPU:0 PID:7 Comm:kworker/u8:0 Tainted: G W 5.15.20-ge6916696ed47-dirty #1 Hardware name: Qualcomm Technologies, Inc. Cinder RU RUMI (DT) Workqueue: events_unbound deferred_probe_work_func pstate: 60400005 (nZCv daif +PAN -UAO -TCO -DIT -SSBS BTYPE=--) pc : kfree+0x31c/0x38c lr : kfree+0x108/0x38c Call trace: kfree+0x31c/0x38c qcom_cpufreq_hw_cpu_init+0x340/0x408 cpufreq_online+0x300/0x80c cpufreq_add_dev+0x48/0xb8 subsys_interface_register+0xe4/0x140 cpufreq_register_driver+0x174/0x2c8 qcom_cpufreq_hw_driver_probe+0x144/0x1b4 platform_probe+0xb0/0xd8 Change-Id: I75e0d40d6aa68f541cc87393e9bbef2628c1cf96 Signed-off-by: Imran Shaik --- drivers/cpufreq/qcom-cpufreq-hw.c | 11 ++--------- 1 file changed, 2 insertions(+), 9 deletions(-) diff --git a/drivers/cpufreq/qcom-cpufreq-hw.c b/drivers/cpufreq/qcom-cpufreq-hw.c index cb172d17437f..39e36c9e4966 100644 --- a/drivers/cpufreq/qcom-cpufreq-hw.c +++ b/drivers/cpufreq/qcom-cpufreq-hw.c @@ -602,14 +602,12 @@ static int qcom_cpufreq_hw_cpu_init(struct cpufreq_policy *policy) base = devm_ioremap(dev, res->start, resource_size(res)); if (!base) { dev_err(dev, "failed to map resource %pR\n", res); - ret = -ENOMEM; - goto release_region; + return -ENOMEM; } data = devm_kzalloc(dev, sizeof(*data), GFP_KERNEL); if (!data) { - ret = -ENOMEM; - goto unmap_base; + return -ENOMEM; } data->soc_data = of_device_get_match_data(&pdev->dev); @@ -664,12 +662,7 @@ static int qcom_cpufreq_hw_cpu_init(struct cpufreq_policy *policy) return 0; error: - kfree(data); policy->driver_data = NULL; -unmap_base: - iounmap(base); -release_region: - release_mem_region(res->start, resource_size(res)); return ret; } From be83eb2675e366152445c625191e339f5887b476 Mon Sep 17 00:00:00 2001 From: Vivek Aknurwar Date: Mon, 6 Jun 2022 22:43:06 -0700 Subject: [PATCH 4/4] cpufreq: qcom-hw: Enable boost support Enable platform specific boost support to be able to set boost frequencies if available. Change-Id: I392ef4cb0dc0b5d6fa9b4b898fe85248f9cf994d Signed-off-by: Vivek Aknurwar --- drivers/cpufreq/qcom-cpufreq-hw.c | 1 + 1 file changed, 1 insertion(+) diff --git a/drivers/cpufreq/qcom-cpufreq-hw.c b/drivers/cpufreq/qcom-cpufreq-hw.c index 39e36c9e4966..91636fd5f4d4 100644 --- a/drivers/cpufreq/qcom-cpufreq-hw.c +++ b/drivers/cpufreq/qcom-cpufreq-hw.c @@ -708,6 +708,7 @@ static struct cpufreq_driver cpufreq_qcom_hw_driver = { .name = "qcom-cpufreq-hw", .attr = qcom_cpufreq_hw_attr, .ready = qcom_cpufreq_ready, + .boost_enabled = true, }; static int qcom_cpufreq_hw_driver_probe(struct platform_device *pdev)