From patchwork Mon Dec 2 05:52:32 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viresh Kumar X-Patchwork-Id: 21913 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-yh0-f72.google.com (mail-yh0-f72.google.com [209.85.213.72]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id 1E35420DB9 for ; Mon, 2 Dec 2013 05:52:50 +0000 (UTC) Received: by mail-yh0-f72.google.com with SMTP id z6sf29051581yhz.3 for ; Sun, 01 Dec 2013 21:52:49 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:mime-version:delivered-to:from:to:cc:subject :date:message-id:in-reply-to:references:in-reply-to:references :x-original-sender:x-original-authentication-results:precedence :mailing-list:list-id:list-post:list-help:list-archive :list-unsubscribe; bh=EYCCr3yAoFa+Ze0Sj3zBG/B6eOq6byDSjmiGsustz/g=; b=KbW0sUJZxe7YZ8pUq1hA1kxd7zB1E0Td8fq7Io+KuT0/QoPb7oFyoxEKwZM0iZEooM ksAhaMunJL5FU0uTuhS/BrdUBuZB7WjlBsudtCeRsIhxnU6gFk9YhjkmHH/G3OW5uvT2 7zgzV4krgF0Lf/lXjhxh9HCizuSLzxfxqOomTYYPKuV6Nfq34COUQzALSb1uYK6mr5Pc grX4wOS0hSogmgEgvuXcEv0QIjbR+zd8TvVocI4t7lSa35fk5BM8PwABID6Fi1BTWfij VjirfoQY6RE3TUPwCnF72yhiBT0uvsDiq6ii6wTYlyl6QA2mRIPIwHU0rVIeVkizL3dz p4tQ== X-Gm-Message-State: ALoCoQmTuAuvO1BVNYpLNTgPRCE10epVrYlXYWmFuUkmy9iUc3gwAJ6cgCQW1aaQxQWDluNIYIWy X-Received: by 10.236.51.9 with SMTP id a9mr28955920yhc.41.1385963569810; Sun, 01 Dec 2013 21:52:49 -0800 (PST) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.49.94.81 with SMTP id da17ls2533506qeb.22.gmail; Sun, 01 Dec 2013 21:52:49 -0800 (PST) X-Received: by 10.220.123.6 with SMTP id n6mr190381vcr.28.1385963569708; Sun, 01 Dec 2013 21:52:49 -0800 (PST) Received: from mail-vc0-f173.google.com (mail-vc0-f173.google.com [209.85.220.173]) by mx.google.com with ESMTPS id de6si29039093vcb.34.2013.12.01.21.52.49 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Sun, 01 Dec 2013 21:52:49 -0800 (PST) Received-SPF: neutral (google.com: 209.85.220.173 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) client-ip=209.85.220.173; Received: by mail-vc0-f173.google.com with SMTP id ia6so8253203vcb.32 for ; Sun, 01 Dec 2013 21:52:49 -0800 (PST) X-Received: by 10.53.9.201 with SMTP id du9mr157845vdd.36.1385963569596; Sun, 01 Dec 2013 21:52:49 -0800 (PST) X-Forwarded-To: patchwork-forward@linaro.org X-Forwarded-For: patch@linaro.org patchwork-forward@linaro.org Delivered-To: patches@linaro.org Received: by 10.220.174.196 with SMTP id u4csp92652vcz; Sun, 1 Dec 2013 21:52:49 -0800 (PST) X-Received: by 10.49.120.8 with SMTP id ky8mr44563502qeb.29.1385963569094; Sun, 01 Dec 2013 21:52:49 -0800 (PST) Received: from mail-qe0-f48.google.com (mail-qe0-f48.google.com [209.85.128.48]) by mx.google.com with ESMTPS id j9si4782236qec.107.2013.12.01.21.52.49 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Sun, 01 Dec 2013 21:52:49 -0800 (PST) Received-SPF: neutral (google.com: 209.85.128.48 is neither permitted nor denied by best guess record for domain of viresh.kumar@linaro.org) client-ip=209.85.128.48; Received: by mail-qe0-f48.google.com with SMTP id gc15so12768057qeb.35 for ; Sun, 01 Dec 2013 21:52:49 -0800 (PST) X-Received: by 10.49.98.35 with SMTP id ef3mr52850392qeb.30.1385963568945; Sun, 01 Dec 2013 21:52:48 -0800 (PST) Received: from localhost (git.linaro.org. [54.235.93.228]) by mx.google.com with ESMTPSA id ki4sm90479225qeb.0.2013.12.01.21.52.47 for (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Sun, 01 Dec 2013 21:52:48 -0800 (PST) From: Viresh Kumar To: rjw@rjwysocki.net Cc: linaro-kernel@lists.linaro.org, patches@linaro.org, cpufreq@vger.kernel.org, linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org, nm@ti.com, swarren@wwwdotorg.org, kgene.kim@samsung.com, linux-samsung-soc@vger.kernel.org, linux-tegra@vger.kernel.org, tianyu.lan@intel.com, jhbird.choi@samsung.com, Viresh Kumar Subject: [PATCH V4 2/6] cpufreq: call driver's suspend/resume for each policy Date: Mon, 2 Dec 2013 11:22:32 +0530 Message-Id: <7e336f59970b44b7c999671ed8df5bdf7af73761.1385962528.git.viresh.kumar@linaro.org> X-Mailer: git-send-email 1.7.12.rc2.18.g61b472e In-Reply-To: References: In-Reply-To: References: X-Removed-Original-Auth: Dkim didn't pass. X-Original-Sender: viresh.kumar@linaro.org X-Original-Authentication-Results: mx.google.com; spf=neutral (google.com: 209.85.220.173 is neither permitted nor denied by best guess record for domain of patch+caf_=patchwork-forward=linaro.org@linaro.org) smtp.mail=patch+caf_=patchwork-forward=linaro.org@linaro.org Precedence: list Mailing-list: list patchwork-forward@linaro.org; contact patchwork-forward+owners@linaro.org List-ID: X-Google-Group-Id: 836684582541 List-Post: , List-Help: , List-Archive: List-Unsubscribe: , Earlier cpufreq suspend/resume callbacks into drivers were getting called only for the boot CPU, as by the time callbacks were called non-boot CPUs were already removed. Because we might still need driver specific actions on suspend/resume, its better to use earlier infrastructure from the early suspend/late resume calls. In effect, we call suspend/resume for each policy. The resume part also takes care of synchronising frequency for boot CPU, which might turn out be different than what cpufreq core believes. Hence, the earlier syscore infrastructure is getting removed now. Tested-by: Lan Tianyu Tested-by: Nishanth Menon Tested-by: Stephen Warren Signed-off-by: Viresh Kumar --- drivers/cpufreq/cpufreq.c | 112 +++++++++++++--------------------------------- 1 file changed, 32 insertions(+), 80 deletions(-) diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index a7fcb84..443c053 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -27,7 +27,6 @@ #include #include #include -#include #include #include @@ -1531,6 +1530,14 @@ static struct subsys_interface cpufreq_interface = { .remove_dev = cpufreq_remove_dev, }; +/** + * cpufreq_suspend() - Suspend CPUFreq governors + * + * Called during system wide Suspend/Hibernate cycles for suspending governors + * as some platforms can't change frequency after this point in suspend cycle. + * Because some of the devices (like: i2c, regulators, etc) they use for + * changing frequency are suspended quickly after this point. + */ void cpufreq_suspend(void) { struct cpufreq_policy *policy; @@ -1540,14 +1547,25 @@ void cpufreq_suspend(void) pr_debug("%s: Suspending Governors\n", __func__); - list_for_each_entry(policy, &cpufreq_policy_list, policy_list) + list_for_each_entry(policy, &cpufreq_policy_list, policy_list) { if (__cpufreq_governor(policy, CPUFREQ_GOV_STOP)) pr_err("%s: Failed to stop governor for policy: %p\n", __func__, policy); + else if (cpufreq_driver->suspend + && cpufreq_driver->suspend(policy)) + pr_err("%s: Failed to suspend driver: %p\n", __func__, + policy); + } cpufreq_suspended = true; } +/** + * cpufreq_resume() - Resume CPUFreq governors + * + * Called during system wide Suspend/Hibernate cycle for resuming governors that + * are suspended with cpufreq_suspend(). + */ void cpufreq_resume(void) { struct cpufreq_policy *policy; @@ -1559,91 +1577,26 @@ void cpufreq_resume(void) cpufreq_suspended = false; - list_for_each_entry(policy, &cpufreq_policy_list, policy_list) + list_for_each_entry(policy, &cpufreq_policy_list, policy_list) { if (__cpufreq_governor(policy, CPUFREQ_GOV_START) || __cpufreq_governor(policy, CPUFREQ_GOV_LIMITS)) pr_err("%s: Failed to start governor for policy: %p\n", __func__, policy); -} - -/** - * cpufreq_bp_suspend - Prepare the boot CPU for system suspend. - * - * This function is only executed for the boot processor. The other CPUs - * have been put offline by means of CPU hotplug. - */ -static int cpufreq_bp_suspend(void) -{ - int ret = 0; - - int cpu = smp_processor_id(); - struct cpufreq_policy *policy; - - pr_debug("suspending cpu %u\n", cpu); - - /* If there's no policy for the boot CPU, we have nothing to do. */ - policy = cpufreq_cpu_get(cpu); - if (!policy) - return 0; - - if (cpufreq_driver->suspend) { - ret = cpufreq_driver->suspend(policy); - if (ret) - printk(KERN_ERR "cpufreq: suspend failed in ->suspend " - "step on CPU %u\n", policy->cpu); - } - - cpufreq_cpu_put(policy); - return ret; -} - -/** - * cpufreq_bp_resume - Restore proper frequency handling of the boot CPU. - * - * 1.) resume CPUfreq hardware support (cpufreq_driver->resume()) - * 2.) schedule call cpufreq_update_policy() ASAP as interrupts are - * restored. It will verify that the current freq is in sync with - * what we believe it to be. This is a bit later than when it - * should be, but nonethteless it's better than calling - * cpufreq_driver->get() here which might re-enable interrupts... - * - * This function is only executed for the boot CPU. The other CPUs have not - * been turned on yet. - */ -static void cpufreq_bp_resume(void) -{ - int ret = 0; - - int cpu = smp_processor_id(); - struct cpufreq_policy *policy; - - pr_debug("resuming cpu %u\n", cpu); - - /* If there's no policy for the boot CPU, we have nothing to do. */ - policy = cpufreq_cpu_get(cpu); - if (!policy) - return; + else if (cpufreq_driver->resume + && cpufreq_driver->resume(policy)) + pr_err("%s: Failed to resume driver: %p\n", __func__, + policy); - if (cpufreq_driver->resume) { - ret = cpufreq_driver->resume(policy); - if (ret) { - printk(KERN_ERR "cpufreq: resume failed in ->resume " - "step on CPU %u\n", policy->cpu); - goto fail; - } + /* + * schedule call cpufreq_update_policy() for boot CPU, i.e. last + * policy in list. It will verify that the current freq is in + * sync with what we believe it to be. + */ + if (list_is_last(&policy->policy_list, &cpufreq_policy_list)) + schedule_work(&policy->update); } - - schedule_work(&policy->update); - -fail: - cpufreq_cpu_put(policy); } -static struct syscore_ops cpufreq_syscore_ops = { - .suspend = cpufreq_bp_suspend, - .resume = cpufreq_bp_resume, -}; - /** * cpufreq_get_current_driver - return current driver's name * @@ -2320,7 +2273,6 @@ static int __init cpufreq_core_init(void) cpufreq_global_kobject = kobject_create(); BUG_ON(!cpufreq_global_kobject); - register_syscore_ops(&cpufreq_syscore_ops); return 0; }