From patchwork Fri Nov 22 11:29:48 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Viresh Kumar X-Patchwork-Id: 21678 Return-Path: X-Original-To: linaro@patches.linaro.org Delivered-To: linaro@patches.linaro.org Received: from mail-pb0-f70.google.com (mail-pb0-f70.google.com [209.85.160.70]) by ip-10-151-82-157.ec2.internal (Postfix) with ESMTPS id D83F32096D for ; Fri, 22 Nov 2013 11:30:02 +0000 (UTC) Received: by mail-pb0-f70.google.com with SMTP id rq2sf2012933pbb.9 for ; Fri, 22 Nov 2013 03:30:02 -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=KdOIqit+V0MQxbdu2j6ww/kf6thyHtvFzXYm81iD++E=; b=WSJBdm4YA7T/P/0K1ai1R1fM0LlMC/x3m4as2kFKg3oZBi1zRhs4wgD3ZCbPBODDDA a63BDH1C/JvwnNJ6X8+hs1POR1vdXmpXTNAPzmKeV399YH/SbUWFxKt/A2HoNMKI8yPv /iWP5e5RZF5ERFwKAcVR7d3U9VOOSqB0k3eACMGuyTbzluQ9qpUm3fsimi9ZtbmX5AWa lYv1ay/TS3OpTnGKRZsmeRUypfu7hXF8pM4D9+UoO+NX+81L1P1BoDxSy+IDfsOxDrYH Fjc4HZ357QNEML3VpA4cjRfql8igMOgpnS/McO/wCtNZ5Q1oEy+vYP2nsMa0+qpGZ21b JtEQ== X-Gm-Message-State: ALoCoQmboEdBY5bzpxWBbnY7zHUfXAFp7M17sG1zp9bmgCBIy7olVJZrLMHe3gOCr2BFDqrVBO75 X-Received: by 10.66.102.36 with SMTP id fl4mr3822034pab.20.1385119801772; Fri, 22 Nov 2013 03:30:01 -0800 (PST) MIME-Version: 1.0 X-BeenThere: patchwork-forward@linaro.org Received: by 10.49.82.226 with SMTP id l2ls969381qey.33.gmail; Fri, 22 Nov 2013 03:30:01 -0800 (PST) X-Received: by 10.220.244.132 with SMTP id lq4mr547551vcb.31.1385119801615; Fri, 22 Nov 2013 03:30:01 -0800 (PST) Received: from mail-vc0-f180.google.com (mail-vc0-f180.google.com [209.85.220.180]) by mx.google.com with ESMTPS id sv4si3223154vdc.120.2013.11.22.03.30.01 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 22 Nov 2013 03:30:01 -0800 (PST) Received-SPF: neutral (google.com: 209.85.220.180 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.180; Received: by mail-vc0-f180.google.com with SMTP id if17so756889vcb.11 for ; Fri, 22 Nov 2013 03:30:01 -0800 (PST) X-Received: by 10.52.65.228 with SMTP id a4mr5440432vdt.16.1385119801499; Fri, 22 Nov 2013 03:30:01 -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 u4csp32841vcz; Fri, 22 Nov 2013 03:30:01 -0800 (PST) X-Received: by 10.224.165.12 with SMTP id g12mr19354243qay.89.1385119800972; Fri, 22 Nov 2013 03:30:00 -0800 (PST) Received: from mail-qa0-f46.google.com (mail-qa0-f46.google.com [209.85.216.46]) by mx.google.com with ESMTPS id j1si21623839qaf.22.2013.11.22.03.30.00 for (version=TLSv1 cipher=ECDHE-RSA-RC4-SHA bits=128/128); Fri, 22 Nov 2013 03:30:00 -0800 (PST) Received-SPF: neutral (google.com: 209.85.216.46 is neither permitted nor denied by best guess record for domain of viresh.kumar@linaro.org) client-ip=209.85.216.46; Received: by mail-qa0-f46.google.com with SMTP id f11so361731qae.19 for ; Fri, 22 Nov 2013 03:30:00 -0800 (PST) X-Received: by 10.229.58.4 with SMTP id e4mr20472493qch.22.1385119800309; Fri, 22 Nov 2013 03:30:00 -0800 (PST) Received: from localhost (git.linaro.org. [54.235.93.228]) by mx.google.com with ESMTPSA id r5sm88244823qaj.13.2013.11.22.03.29.58 for (version=TLSv1.2 cipher=RC4-SHA bits=128/128); Fri, 22 Nov 2013 03:29:59 -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, tianyu.lan@intel.com, nm@ti.com, jinchoi@broadcom.com, sebastian.capella@linaro.org, Viresh Kumar Subject: [PATCH V2 1/2] cpufreq: suspend governors on system suspend/hibernate Date: Fri, 22 Nov 2013 16:59:48 +0530 Message-Id: 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.180 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: , This patch adds cpufreq callbacks to dpm_{suspend|resume}_noirq() for handling suspend/resume of cpufreq governors. This is required for early suspend and late resume of governors. There are multiple problems that are fixed by this patch: - Nishanth Menon (TI) found an interesting problem on his platform, OMAP. His board wasn't working well with suspend/resume as calls for removing non-boot CPUs was turning out into a call to drivers ->target() which then tries to play with regulators. But regulators and their I2C bus were already suspended and this resulted in a failure. This is why we need a PM notifier here. - Lan Tianyu (Intel) & Jinhyuk Choi (Broadcom) found another issue where tunables configuration for clusters/sockets with non-boot CPUs was getting lost after suspend/resume, as we were notifying governors with CPUFREQ_GOV_POLICY_EXIT on removal of the last cpu for that policy and so deallocating memory for tunables. Reported-by: Lan Tianyu Reported-by: Nishanth Menon Reported-by: Jinhyuk Choi Signed-off-by: Viresh Kumar --- drivers/base/power/main.c | 3 +++ drivers/cpufreq/cpufreq.c | 62 +++++++++++++++++++++++++++++++++++++++++++++++ include/linux/cpufreq.h | 3 +++ 3 files changed, 68 insertions(+) diff --git a/drivers/base/power/main.c b/drivers/base/power/main.c index c12e9b9..0fbe792 100644 --- a/drivers/base/power/main.c +++ b/drivers/base/power/main.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include @@ -540,6 +541,7 @@ static void dpm_resume_noirq(pm_message_t state) dpm_show_time(starttime, state, "noirq"); resume_device_irqs(); cpuidle_resume(); + cpufreq_resume(); } /** @@ -955,6 +957,7 @@ static int dpm_suspend_noirq(pm_message_t state) ktime_t starttime = ktime_get(); int error = 0; + cpufreq_suspend(); cpuidle_pause(); suspend_device_irqs(); mutex_lock(&dpm_list_mtx); diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c index 02d534d..540bd87 100644 --- a/drivers/cpufreq/cpufreq.c +++ b/drivers/cpufreq/cpufreq.c @@ -26,6 +26,7 @@ #include #include #include +#include #include #include #include @@ -47,6 +48,9 @@ static LIST_HEAD(cpufreq_policy_list); static DEFINE_PER_CPU(char[CPUFREQ_NAME_LEN], cpufreq_cpu_governor); #endif +/* Flag to suspend/resume CPUFreq governors */ +static bool cpufreq_suspended; + static inline bool has_target(void) { return cpufreq_driver->target_index || cpufreq_driver->target; @@ -1462,6 +1466,54 @@ static struct subsys_interface cpufreq_interface = { .remove_dev = cpufreq_remove_dev, }; +/* + * Callbacks for suspending/resuming 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; + unsigned long flags; + + if (!has_target()) + return; + + pr_debug("%s: Suspending Governors\n", __func__); + + 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); + + write_lock_irqsave(&cpufreq_driver_lock, flags); + cpufreq_suspended = true; + write_unlock_irqrestore(&cpufreq_driver_lock, flags); +} + +void cpufreq_resume(void) +{ + struct cpufreq_policy *policy; + unsigned long flags; + + if (!has_target()) + return; + + pr_debug("%s: Resuming Governors\n", __func__); + + write_lock_irqsave(&cpufreq_driver_lock, flags); + cpufreq_suspended = false; + write_unlock_irqrestore(&cpufreq_driver_lock, flags); + + 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. * @@ -1752,6 +1804,8 @@ EXPORT_SYMBOL_GPL(cpufreq_driver_target); static int __cpufreq_governor(struct cpufreq_policy *policy, unsigned int event) { + unsigned long flags; + bool is_suspended; int ret; /* Only must be defined when default governor is known to have latency @@ -1764,6 +1818,14 @@ static int __cpufreq_governor(struct cpufreq_policy *policy, struct cpufreq_governor *gov = NULL; #endif + /* Don't start any governor operations if we are entering suspend */ + read_lock_irqsave(&cpufreq_driver_lock, flags); + is_suspended = cpufreq_suspended; + read_unlock_irqrestore(&cpufreq_driver_lock, flags); + + if (is_suspended) + return 0; + if (policy->governor->max_transition_latency && policy->cpuinfo.transition_latency > policy->governor->max_transition_latency) { diff --git a/include/linux/cpufreq.h b/include/linux/cpufreq.h index dc196bb..6d93f91 100644 --- a/include/linux/cpufreq.h +++ b/include/linux/cpufreq.h @@ -255,6 +255,9 @@ struct cpufreq_driver { int cpufreq_register_driver(struct cpufreq_driver *driver_data); int cpufreq_unregister_driver(struct cpufreq_driver *driver_data); +void cpufreq_suspend(void); +void cpufreq_resume(void); + const char *cpufreq_get_current_driver(void); static inline void cpufreq_verify_within_limits(struct cpufreq_policy *policy,