From patchwork Wed Aug 28 08:50:13 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viresh Kumar X-Patchwork-Id: 172351 Delivered-To: patch@linaro.org Received: by 2002:a92:d204:0:0:0:0:0 with SMTP id y4csp445055ily; Wed, 28 Aug 2019 01:50:22 -0700 (PDT) X-Google-Smtp-Source: APXvYqwAOmZUgJHu0lmo7h5sUvfpX/2wxO/wJ05oke8WRB59XXwoX8VxjfbKYEwv0ZxUZ8mcNoG0 X-Received: by 2002:a17:902:e413:: with SMTP id ci19mr3205176plb.256.1566982222628; Wed, 28 Aug 2019 01:50:22 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1566982222; cv=none; d=google.com; s=arc-20160816; b=urddh6e76VA7glr9clx0x1C5exKtsXAs2dP9h5zVW9tXynXnCU+B+d2thdd7BJTef8 DxlhSqgigwU6BEKBeOC2xtAtZybmzFvXAUVXD39NbCCrDBLqoDrdVl5qXOVSkanPHaqs baiX1vdaZjE+GR8NdtzvOV7cUNt1Be953ivBXW/9NSB0+76WLD7XWvvy14ZfNmR55ETm B7y2VBPsSMTDMWLvmiBWhPe6zP3l9XgAIO5v+iZuaJN63DHcC0qqzxOM3ZWw3ibxLrqw jH6ev/OkrbePg7hbhTs+zhHxLyW5mJUVPGEMlMU7nCu07Z3hkj8ofEFX87QZGeNEMmOU OxLw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from :dkim-signature; bh=+Nnv8QQTbl6/pTPsiKbtpWJmv+kviSXUlOqzZyVEImo=; b=jn1WxFSrr2ItJIxE3JxxcMhI6gKluit0ioeofGJcjcNn4ItjiOwCBnLR6NXN3efhBo tp9f2dU2Nsb6MCh1hY33rcaC8S7FC7iL1vDEffUK5PZ0kWBuz4UmCqLzaP2VxuUoXFhQ f15gYUkfEUow854Ay0w0dh8CpVPFo+/RXwEpOpMQxpht7tosoraPZdXets+mMTMBwjX8 3Bg92nxy+cE1pPmK2k6MJ+mAsBL5M7gkTcsXN1MoBRCUwql1Ki+kXP0ObTlo1OaALRdc DY/8mSYkQhv9zjx73vWIr1vbXuWI7QJuiR4VbaF5LOrQwHTJiH5Ku0qrL611OEJXzK1h 7Gvg== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=xhcPOf4J; spf=pass (google.com: best guess record for domain of linux-pm-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-pm-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id w9si1413635plz.346.2019.08.28.01.50.22; Wed, 28 Aug 2019 01:50:22 -0700 (PDT) Received-SPF: pass (google.com: best guess record for domain of linux-pm-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org header.s=google header.b=xhcPOf4J; spf=pass (google.com: best guess record for domain of linux-pm-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-pm-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1726415AbfH1IuV (ORCPT + 11 others); Wed, 28 Aug 2019 04:50:21 -0400 Received: from mail-pl1-f196.google.com ([209.85.214.196]:33058 "EHLO mail-pl1-f196.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726259AbfH1IuV (ORCPT ); Wed, 28 Aug 2019 04:50:21 -0400 Received: by mail-pl1-f196.google.com with SMTP id go14so930079plb.0 for ; Wed, 28 Aug 2019 01:50:21 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references :mime-version:content-transfer-encoding; bh=+Nnv8QQTbl6/pTPsiKbtpWJmv+kviSXUlOqzZyVEImo=; b=xhcPOf4JUVCsmsu4786wPuDswAHx6EjrHiu7JBN928Ur2OmJBgkJmq7Zk5ZiLcNu82 L7s7c/LWhKYbHh3o0WFv4JwcJ9gQx83/CS4O9ejMBxLzSo/aOxGsxZEFPk+Tca27Vjkc WUhdwZO5tb0sWW91JMs2bX8equX1xf+C8ynwV/ZtBpSz1PKxYcMfVu6zqQAK8V9q4JCQ uN8j5Vm/bNQ9dxtYdKRZwwwUUDBFcL6zBpUDAXKzZwtBppYuUd4cgn4h5TuC7CjwDpD2 +t+Q4J6ZIHhZBISMvIEDegKjdDicUoW9mr/ysUxQz3qNqtMA90YqwgbuPiDz6urrdg3G dk6A== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references:mime-version:content-transfer-encoding; bh=+Nnv8QQTbl6/pTPsiKbtpWJmv+kviSXUlOqzZyVEImo=; b=Q80JZMFP4/XfYBUkuyylCuVMLWmd929/CMwnSCw6ZRE6iGR3JO7qA2xccdeY0BLrgd EyswoPy/KGiIoOAlszT9XjQJ6CCBWSpwU7Kw1JmTeGHXaipWt6WZzaFTRX5wokSM4rmO 0WXiByRE9lPlJA8qvXWrEHg0XmVKy65OabJb0Du7AzWowJ/H39TvmBKcyhWDUWrSsBVF DiZ/wD5pBikEHf8xLyzku2cJoSoPFpnlKh3qWpNXdz6z+95locTXdfwSQpoO8Pc44t1r /Z+1TdL/Pm/VHqzbn5x7Rd9W/iBh0GPLB4j7+9QsPfGNqG96aKVz/ZcXUwb2zWu1SfyT 8PBw== X-Gm-Message-State: APjAAAUkOU5LCJROcHy7/FyU6FFtsh4ohjAeh0t1cNKl6Yam1sbnEBo3 +ekmVRKzE5N04D10EcUSnync/Q== X-Received: by 2002:a17:902:2ea2:: with SMTP id r31mr3246852plb.200.1566982220339; Wed, 28 Aug 2019 01:50:20 -0700 (PDT) Received: from localhost ([122.171.230.51]) by smtp.gmail.com with ESMTPSA id s7sm2940771pfb.138.2019.08.28.01.50.18 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 28 Aug 2019 01:50:19 -0700 (PDT) From: Viresh Kumar To: Rafael Wysocki , Len Brown , Zhang Rui , Robert Moore , Erik Schmauss Cc: Viresh Kumar , linux-pm@vger.kernel.org, Vincent Guittot , linux-acpi@vger.kernel.org, linux-kernel@vger.kernel.org, devel@acpica.org Subject: [PATCH V3 05/10] ACPI: cpufreq: Switch to QoS requests instead of cpufreq notifier Date: Wed, 28 Aug 2019 14:20:13 +0530 Message-Id: X-Mailer: git-send-email 2.21.0.rc0.269.g1a574e7a288b In-Reply-To: <86dc4a082ea00c278c0e1d7f3fcbdc4ab9af2eec.1563862014.git.viresh.kumar@linaro.org> References: <86dc4a082ea00c278c0e1d7f3fcbdc4ab9af2eec.1563862014.git.viresh.kumar@linaro.org> MIME-Version: 1.0 Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org The cpufreq core now takes the min/max frequency constraints via QoS requests and the CPUFREQ_ADJUST notifier shall get removed later on. Switch over to using the QoS request for maximum frequency constraint for acpi driver. Signed-off-by: Viresh Kumar --- V3: - Before updating qos request, make sure they are successfully added in the first place using dev_pm_qos_request_active() helper. - reset ignore_ppc from acpi_processor_ignore_ppc_init(). drivers/acpi/processor_driver.c | 39 ++++++++++-- drivers/acpi/processor_perflib.c | 100 ++++++++++++------------------- drivers/acpi/processor_thermal.c | 84 +++++++++++++------------- include/acpi/processor.h | 26 +++++--- 4 files changed, 132 insertions(+), 117 deletions(-) -- 2.21.0.rc0.269.g1a574e7a288b diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c index aea8d674a33d..08da9c29f1e9 100644 --- a/drivers/acpi/processor_driver.c +++ b/drivers/acpi/processor_driver.c @@ -284,6 +284,29 @@ static int acpi_processor_stop(struct device *dev) return 0; } +bool acpi_processor_cpufreq_init; + +static int acpi_processor_notifier(struct notifier_block *nb, + unsigned long event, void *data) +{ + struct cpufreq_policy *policy = data; + int cpu = policy->cpu; + + if (event == CPUFREQ_CREATE_POLICY) { + acpi_thermal_cpufreq_init(cpu); + acpi_processor_ppc_init(cpu); + } else if (event == CPUFREQ_REMOVE_POLICY) { + acpi_processor_ppc_exit(cpu); + acpi_thermal_cpufreq_exit(cpu); + } + + return 0; +} + +static struct notifier_block acpi_processor_notifier_block = { + .notifier_call = acpi_processor_notifier, +}; + /* * We keep the driver loaded even when ACPI is not running. * This is needed for the powernow-k8 driver, that works even without @@ -310,8 +333,12 @@ static int __init acpi_processor_driver_init(void) cpuhp_setup_state_nocalls(CPUHP_ACPI_CPUDRV_DEAD, "acpi/cpu-drv:dead", NULL, acpi_soft_cpu_dead); - acpi_thermal_cpufreq_init(); - acpi_processor_ppc_init(); + if (!cpufreq_register_notifier(&acpi_processor_notifier_block, + CPUFREQ_POLICY_NOTIFIER)) { + acpi_processor_cpufreq_init = true; + acpi_processor_ignore_ppc_init(); + } + acpi_processor_throttling_init(); return 0; err: @@ -324,8 +351,12 @@ static void __exit acpi_processor_driver_exit(void) if (acpi_disabled) return; - acpi_processor_ppc_exit(); - acpi_thermal_cpufreq_exit(); + if (acpi_processor_cpufreq_init) { + cpufreq_unregister_notifier(&acpi_processor_notifier_block, + CPUFREQ_POLICY_NOTIFIER); + acpi_processor_cpufreq_init = false; + } + cpuhp_remove_state_nocalls(hp_online); cpuhp_remove_state_nocalls(CPUHP_ACPI_CPUDRV_DEAD); driver_unregister(&acpi_processor_driver); diff --git a/drivers/acpi/processor_perflib.c b/drivers/acpi/processor_perflib.c index ee87cb6f6e59..2261713d1aec 100644 --- a/drivers/acpi/processor_perflib.c +++ b/drivers/acpi/processor_perflib.c @@ -50,57 +50,13 @@ module_param(ignore_ppc, int, 0644); MODULE_PARM_DESC(ignore_ppc, "If the frequency of your machine gets wrongly" \ "limited by BIOS, this should help"); -#define PPC_REGISTERED 1 -#define PPC_IN_USE 2 - -static int acpi_processor_ppc_status; - -static int acpi_processor_ppc_notifier(struct notifier_block *nb, - unsigned long event, void *data) -{ - struct cpufreq_policy *policy = data; - struct acpi_processor *pr; - unsigned int ppc = 0; - - if (ignore_ppc < 0) - ignore_ppc = 0; - - if (ignore_ppc) - return 0; - - if (event != CPUFREQ_ADJUST) - return 0; - - mutex_lock(&performance_mutex); - - pr = per_cpu(processors, policy->cpu); - if (!pr || !pr->performance) - goto out; - - ppc = (unsigned int)pr->performance_platform_limit; - - if (ppc >= pr->performance->state_count) - goto out; - - cpufreq_verify_within_limits(policy, 0, - pr->performance->states[ppc]. - core_frequency * 1000); - - out: - mutex_unlock(&performance_mutex); - - return 0; -} - -static struct notifier_block acpi_ppc_notifier_block = { - .notifier_call = acpi_processor_ppc_notifier, -}; +static bool acpi_processor_ppc_in_use; static int acpi_processor_get_platform_limit(struct acpi_processor *pr) { acpi_status status = 0; unsigned long long ppc = 0; - + int ret; if (!pr) return -EINVAL; @@ -112,7 +68,7 @@ static int acpi_processor_get_platform_limit(struct acpi_processor *pr) status = acpi_evaluate_integer(pr->handle, "_PPC", NULL, &ppc); if (status != AE_NOT_FOUND) - acpi_processor_ppc_status |= PPC_IN_USE; + acpi_processor_ppc_in_use = true; if (ACPI_FAILURE(status) && status != AE_NOT_FOUND) { ACPI_EXCEPTION((AE_INFO, status, "Evaluating _PPC")); @@ -124,6 +80,17 @@ static int acpi_processor_get_platform_limit(struct acpi_processor *pr) pr->performance_platform_limit = (int)ppc; + if (ppc >= pr->performance->state_count || + unlikely(!dev_pm_qos_request_active(&pr->perflib_req))) + return 0; + + ret = dev_pm_qos_update_request(&pr->perflib_req, + pr->performance->states[ppc].core_frequency * 1000); + if (ret < 0) { + pr_warn("Failed to update perflib freq constraint: CPU%d (%d)\n", + pr->id, ret); + } + return 0; } @@ -184,23 +151,32 @@ int acpi_processor_get_bios_limit(int cpu, unsigned int *limit) } EXPORT_SYMBOL(acpi_processor_get_bios_limit); -void acpi_processor_ppc_init(void) +void acpi_processor_ignore_ppc_init(void) { - if (!cpufreq_register_notifier - (&acpi_ppc_notifier_block, CPUFREQ_POLICY_NOTIFIER)) - acpi_processor_ppc_status |= PPC_REGISTERED; - else - printk(KERN_DEBUG - "Warning: Processor Platform Limit not supported.\n"); + if (ignore_ppc < 0) + ignore_ppc = 0; +} + +void acpi_processor_ppc_init(int cpu) +{ + struct acpi_processor *pr = per_cpu(processors, cpu); + int ret; + + ret = dev_pm_qos_add_request(get_cpu_device(cpu), + &pr->perflib_req, DEV_PM_QOS_MAX_FREQUENCY, + INT_MAX); + if (ret < 0) { + pr_err("Failed to add freq constraint for CPU%d (%d)\n", cpu, + ret); + return; + } } -void acpi_processor_ppc_exit(void) +void acpi_processor_ppc_exit(int cpu) { - if (acpi_processor_ppc_status & PPC_REGISTERED) - cpufreq_unregister_notifier(&acpi_ppc_notifier_block, - CPUFREQ_POLICY_NOTIFIER); + struct acpi_processor *pr = per_cpu(processors, cpu); - acpi_processor_ppc_status &= ~PPC_REGISTERED; + dev_pm_qos_remove_request(&pr->perflib_req); } static int acpi_processor_get_performance_control(struct acpi_processor *pr) @@ -477,7 +453,7 @@ int acpi_processor_notify_smm(struct module *calling_module) static int is_done = 0; int result; - if (!(acpi_processor_ppc_status & PPC_REGISTERED)) + if (!acpi_processor_cpufreq_init) return -EBUSY; if (!try_module_get(calling_module)) @@ -513,7 +489,7 @@ int acpi_processor_notify_smm(struct module *calling_module) * we can allow the cpufreq driver to be rmmod'ed. */ is_done = 1; - if (!(acpi_processor_ppc_status & PPC_IN_USE)) + if (!acpi_processor_ppc_in_use) module_put(calling_module); return 0; @@ -742,7 +718,7 @@ acpi_processor_register_performance(struct acpi_processor_performance { struct acpi_processor *pr; - if (!(acpi_processor_ppc_status & PPC_REGISTERED)) + if (!acpi_processor_cpufreq_init) return -EINVAL; mutex_lock(&performance_mutex); diff --git a/drivers/acpi/processor_thermal.c b/drivers/acpi/processor_thermal.c index 50fb0107375e..ec2638f1df4f 100644 --- a/drivers/acpi/processor_thermal.c +++ b/drivers/acpi/processor_thermal.c @@ -35,7 +35,6 @@ ACPI_MODULE_NAME("processor_thermal"); #define CPUFREQ_THERMAL_MAX_STEP 3 static DEFINE_PER_CPU(unsigned int, cpufreq_thermal_reduction_pctg); -static unsigned int acpi_thermal_cpufreq_is_init = 0; #define reduction_pctg(cpu) \ per_cpu(cpufreq_thermal_reduction_pctg, phys_package_first_cpu(cpu)) @@ -61,35 +60,11 @@ static int phys_package_first_cpu(int cpu) static int cpu_has_cpufreq(unsigned int cpu) { struct cpufreq_policy policy; - if (!acpi_thermal_cpufreq_is_init || cpufreq_get_policy(&policy, cpu)) + if (!acpi_processor_cpufreq_init || cpufreq_get_policy(&policy, cpu)) return 0; return 1; } -static int acpi_thermal_cpufreq_notifier(struct notifier_block *nb, - unsigned long event, void *data) -{ - struct cpufreq_policy *policy = data; - unsigned long max_freq = 0; - - if (event != CPUFREQ_ADJUST) - goto out; - - max_freq = ( - policy->cpuinfo.max_freq * - (100 - reduction_pctg(policy->cpu) * 20) - ) / 100; - - cpufreq_verify_within_limits(policy, 0, max_freq); - - out: - return 0; -} - -static struct notifier_block acpi_thermal_cpufreq_notifier_block = { - .notifier_call = acpi_thermal_cpufreq_notifier, -}; - static int cpufreq_get_max_state(unsigned int cpu) { if (!cpu_has_cpufreq(cpu)) @@ -108,7 +83,10 @@ static int cpufreq_get_cur_state(unsigned int cpu) static int cpufreq_set_cur_state(unsigned int cpu, int state) { - int i; + struct cpufreq_policy *policy; + struct acpi_processor *pr; + unsigned long max_freq; + int i, ret; if (!cpu_has_cpufreq(cpu)) return 0; @@ -121,33 +99,53 @@ static int cpufreq_set_cur_state(unsigned int cpu, int state) * frequency. */ for_each_online_cpu(i) { - if (topology_physical_package_id(i) == + if (topology_physical_package_id(i) != topology_physical_package_id(cpu)) - cpufreq_update_policy(i); + continue; + + pr = per_cpu(processors, i); + + if (unlikely(!dev_pm_qos_request_active(&pr->thermal_req))) + continue; + + policy = cpufreq_cpu_get(i); + if (!policy) + return -EINVAL; + + max_freq = (policy->cpuinfo.max_freq * (100 - reduction_pctg(i) * 20)) / 100; + + cpufreq_cpu_put(policy); + + ret = dev_pm_qos_update_request(&pr->thermal_req, max_freq); + if (ret < 0) { + pr_warn("Failed to update thermal freq constraint: CPU%d (%d)\n", + pr->id, ret); + } } return 0; } -void acpi_thermal_cpufreq_init(void) +void acpi_thermal_cpufreq_init(int cpu) { - int i; - - i = cpufreq_register_notifier(&acpi_thermal_cpufreq_notifier_block, - CPUFREQ_POLICY_NOTIFIER); - if (!i) - acpi_thermal_cpufreq_is_init = 1; + struct acpi_processor *pr = per_cpu(processors, cpu); + int ret; + + ret = dev_pm_qos_add_request(get_cpu_device(cpu), + &pr->thermal_req, DEV_PM_QOS_MAX_FREQUENCY, + INT_MAX); + if (ret < 0) { + pr_err("Failed to add freq constraint for CPU%d (%d)\n", cpu, + ret); + return; + } } -void acpi_thermal_cpufreq_exit(void) +void acpi_thermal_cpufreq_exit(int cpu) { - if (acpi_thermal_cpufreq_is_init) - cpufreq_unregister_notifier - (&acpi_thermal_cpufreq_notifier_block, - CPUFREQ_POLICY_NOTIFIER); + struct acpi_processor *pr = per_cpu(processors, cpu); - acpi_thermal_cpufreq_is_init = 0; + dev_pm_qos_remove_request(&pr->thermal_req); } - #else /* ! CONFIG_CPU_FREQ */ static int cpufreq_get_max_state(unsigned int cpu) { diff --git a/include/acpi/processor.h b/include/acpi/processor.h index 1194a4c78d55..f936033cb9e6 100644 --- a/include/acpi/processor.h +++ b/include/acpi/processor.h @@ -4,6 +4,8 @@ #include #include +#include +#include #include #include @@ -230,6 +232,8 @@ struct acpi_processor { struct acpi_processor_limit limit; struct thermal_cooling_device *cdev; struct device *dev; /* Processor device. */ + struct dev_pm_qos_request perflib_req; + struct dev_pm_qos_request thermal_req; }; struct acpi_processor_errata { @@ -296,16 +300,22 @@ static inline void acpi_processor_ffh_cstate_enter(struct acpi_processor_cx /* in processor_perflib.c */ #ifdef CONFIG_CPU_FREQ -void acpi_processor_ppc_init(void); -void acpi_processor_ppc_exit(void); +extern bool acpi_processor_cpufreq_init; +void acpi_processor_ignore_ppc_init(void); +void acpi_processor_ppc_init(int cpu); +void acpi_processor_ppc_exit(int cpu); void acpi_processor_ppc_has_changed(struct acpi_processor *pr, int event_flag); extern int acpi_processor_get_bios_limit(int cpu, unsigned int *limit); #else -static inline void acpi_processor_ppc_init(void) +static inline void acpi_processor_ignore_ppc_init(void) { return; } -static inline void acpi_processor_ppc_exit(void) +static inline void acpi_processor_ppc_init(int cpu) +{ + return; +} +static inline void acpi_processor_ppc_exit(int cpu) { return; } @@ -421,14 +431,14 @@ static inline int acpi_processor_hotplug(struct acpi_processor *pr) int acpi_processor_get_limit_info(struct acpi_processor *pr); extern const struct thermal_cooling_device_ops processor_cooling_ops; #if defined(CONFIG_ACPI_CPU_FREQ_PSS) & defined(CONFIG_CPU_FREQ) -void acpi_thermal_cpufreq_init(void); -void acpi_thermal_cpufreq_exit(void); +void acpi_thermal_cpufreq_init(int cpu); +void acpi_thermal_cpufreq_exit(int cpu); #else -static inline void acpi_thermal_cpufreq_init(void) +static inline void acpi_thermal_cpufreq_init(int cpu) { return; } -static inline void acpi_thermal_cpufreq_exit(void) +static inline void acpi_thermal_cpufreq_exit(int cpu) { return; }