From 38a8e511af315f074873c871027b7795ccae970f Mon Sep 17 00:00:00 2001 From: Lina Iyer Date: Sun, 26 Apr 2020 11:28:22 -0600 Subject: [PATCH] drivers: lpm-levels: use correct CPUHP notifications for QoS Adding and removing dev PM QoS notifications uses mutex lock and therefore cannot be called from CPU starting notifications. Update QoS notifier in a stage when interrupts are allowed. Change-Id: I21ce6a23d51e97d9f05e96a1772c028c4760ec7d Signed-off-by: Lina Iyer --- drivers/cpuidle/lpm-levels.c | 30 ++++++++++++++++++++++++------ include/linux/cpuhotplug.h | 3 +++ 2 files changed, 27 insertions(+), 6 deletions(-) diff --git a/drivers/cpuidle/lpm-levels.c b/drivers/cpuidle/lpm-levels.c index 1cfd746be4ff..3d26a5860c16 100644 --- a/drivers/cpuidle/lpm-levels.c +++ b/drivers/cpuidle/lpm-levels.c @@ -144,6 +144,24 @@ static int lpm_cpu_qos_notify(struct notifier_block *nb, return NOTIFY_OK; } +static int lpm_offline_cpu(unsigned int cpu) +{ + struct device *dev = get_cpu_device(cpu); + + dev_pm_qos_remove_notifier(dev, &dev_pm_qos_nb[cpu], + DEV_PM_QOS_RESUME_LATENCY); + return 0; +} + +static int lpm_online_cpu(unsigned int cpu) +{ + struct device *dev = get_cpu_device(cpu); + + dev_pm_qos_add_notifier(dev, &dev_pm_qos_nb[cpu], + DEV_PM_QOS_RESUME_LATENCY); + return 0; +} + /** * msm_cpuidle_get_deep_idle_latency - Get deep idle latency value * @@ -194,10 +212,7 @@ static void update_debug_pc_event(enum debug_event event, uint32_t arg1, static int lpm_dying_cpu(unsigned int cpu) { struct lpm_cluster *cluster = per_cpu(cpu_lpm, cpu)->parent; - struct device *dev = get_cpu_device(cpu); - dev_pm_qos_remove_notifier(dev, &dev_pm_qos_nb[cpu], - DEV_PM_QOS_RESUME_LATENCY); update_debug_pc_event(CPU_HP_DYING, cpu, cluster->num_children_in_sync.bits[0], cluster->child_cpus.bits[0], false); @@ -208,10 +223,7 @@ static int lpm_dying_cpu(unsigned int cpu) static int lpm_starting_cpu(unsigned int cpu) { struct lpm_cluster *cluster = per_cpu(cpu_lpm, cpu)->parent; - struct device *dev = get_cpu_device(cpu); - dev_pm_qos_add_notifier(dev, &dev_pm_qos_nb[cpu], - DEV_PM_QOS_RESUME_LATENCY); update_debug_pc_event(CPU_HP_STARTING, cpu, cluster->num_children_in_sync.bits[0], cluster->child_cpus.bits[0], false); @@ -1588,6 +1600,12 @@ static int lpm_probe(struct platform_device *pdev) if (ret) goto failed; + ret = cpuhp_setup_state(CPUHP_AP_QCOM_CPU_QOS_ONLINE, + "AP_QCOM_CPU_QOS_ONLINE", + lpm_online_cpu, lpm_offline_cpu); + if (ret) + goto failed; + module_kobj = kset_find_obj(module_kset, KBUILD_MODNAME); if (!module_kobj) { pr_err("Cannot find kobject for module %s\n", KBUILD_MODNAME); diff --git a/include/linux/cpuhotplug.h b/include/linux/cpuhotplug.h index 06026d950de8..a26f0ea9d9fc 100644 --- a/include/linux/cpuhotplug.h +++ b/include/linux/cpuhotplug.h @@ -184,6 +184,9 @@ enum cpuhp_state { CPUHP_AP_PERF_ARM_L2X0_ONLINE, CPUHP_AP_PERF_ARM_QCOM_L2_ONLINE, CPUHP_AP_PERF_ARM_QCOM_L3_ONLINE, +#ifdef CONFIG_ARM_QCOM_LPM_CPUIDLE + CPUHP_AP_QCOM_CPU_QOS_ONLINE, +#endif CPUHP_AP_PERF_ARM_APM_XGENE_ONLINE, CPUHP_AP_PERF_ARM_CAVIUM_TX2_UNCORE_ONLINE, CPUHP_AP_PERF_POWERPC_NEST_IMC_ONLINE,