From: "Srivatsa S. Bhat" <srivatsa.bhat@linux.vnet.ibm.com>
To: rjw@sisk.pl, viresh.kumar@linaro.org, toralf.foerster@gmx.de,
robert.jarzmik@intel.com, durgadoss.r@intel.com,
tianyu.lan@intel.com, lantianyu1986@gmail.com,
dirk.brandewie@gmail.com
Cc: stern@rowland.harvard.edu,
"Srivatsa S. Bhat" <srivatsa.bhat@linux.vnet.ibm.com>,
linux-pm@vger.kernel.org, linux-kernel@vger.kernel.org
Subject: [PATCH 7/8] cpufreq: Preserve policy structure across suspend/resume
Date: Fri, 12 Jul 2013 03:47:08 +0530 [thread overview]
Message-ID: <20130711221704.547.64296.stgit@srivatsabhat.in.ibm.com> (raw)
In-Reply-To: <20130711221419.547.69781.stgit@srivatsabhat.in.ibm.com>
To perform light-weight cpu-init and teardown in the cpufreq subsystem
during suspend/resume, we need to separate out the 2 main functionalities
of the cpufreq CPU hotplug callbacks, as outlined below:
1. Init/tear-down of core cpufreq and CPU-specific components, which are
critical to the correct functioning of the cpufreq subsystem.
2. Init/tear-down of cpufreq sysfs files during suspend/resume.
The first part requires accurate updates to the policy structure such as
its ->cpus and ->related_cpus masks, whereas the second part requires that
the policy->kobj structure is not released or re-initialized during
suspend/resume.
To handle both these requirements, we need to allow updates to the policy
structure throughout suspend/resume, but prevent the structure from getting
freed up. Also, we must have a mechanism by which the cpu-up callbacks can
restore the policy structure, without allocating things afresh. (That also
helps avoid memory leaks).
To achieve this, we use 2 schemes:
a. Use a fallback per-cpu storage area for preserving the policy structures
during suspend, so that they can be restored during resume appropriately.
b. Use the 'frozen' flag to determine when to free or allocate the policy
structure vs when to restore the policy from the saved fallback storage.
Thus we can successfully preserve the structure across suspend/resume.
Effectively, this helps us complete the separation of the 'light-weight'
and the 'full' init/tear-down sequences in the cpufreq subsystem, so that
this can be made use of in the suspend/resume scenario.
Signed-off-by: Srivatsa S. Bhat <srivatsa.bhat@linux.vnet.ibm.com>
---
drivers/cpufreq/cpufreq.c | 69 ++++++++++++++++++++++++++++++++++-----------
1 file changed, 52 insertions(+), 17 deletions(-)
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 1128753..15ced5f 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -44,6 +44,7 @@
*/
static struct cpufreq_driver *cpufreq_driver;
static DEFINE_PER_CPU(struct cpufreq_policy *, cpufreq_cpu_data);
+static DEFINE_PER_CPU(struct cpufreq_policy *, cpufreq_cpu_data_fallback);
static DEFINE_RWLOCK(cpufreq_driver_lock);
static DEFINE_MUTEX(cpufreq_governor_lock);
@@ -942,6 +943,20 @@ static int cpufreq_add_policy_cpu(unsigned int cpu, unsigned int sibling,
}
#endif
+static struct cpufreq_policy *cpufreq_policy_restore(unsigned int cpu)
+{
+ struct cpufreq_policy *policy;
+ unsigned long flags;
+
+ write_lock_irqsave(&cpufreq_driver_lock, flags);
+
+ policy = per_cpu(cpufreq_cpu_data_fallback, cpu);
+
+ write_unlock_irqrestore(&cpufreq_driver_lock, flags);
+
+ return policy;
+}
+
static struct cpufreq_policy *cpufreq_policy_alloc(void)
{
struct cpufreq_policy *policy;
@@ -1019,7 +1034,12 @@ static int __cpufreq_add_dev(struct device *dev, struct subsys_interface *sif,
goto module_out;
}
- policy = cpufreq_policy_alloc();
+ if (frozen)
+ /* Restore the saved policy when doing light-weight init */
+ policy = cpufreq_policy_restore(cpu);
+ else
+ policy = cpufreq_policy_alloc();
+
if (!policy)
goto nomem_out;
@@ -1199,6 +1219,10 @@ static int __cpufreq_remove_dev(struct device *dev,
data = per_cpu(cpufreq_cpu_data, cpu);
per_cpu(cpufreq_cpu_data, cpu) = NULL;
+ /* Save the policy somewhere when doing a light-weight tear-down */
+ if (frozen)
+ per_cpu(cpufreq_cpu_data_fallback, cpu) = data;
+
write_unlock_irqrestore(&cpufreq_driver_lock, flags);
if (!data) {
@@ -1239,29 +1263,40 @@ static int __cpufreq_remove_dev(struct device *dev,
if ((cpus == 1) && (cpufreq_driver->target))
__cpufreq_governor(data, CPUFREQ_GOV_POLICY_EXIT);
- pr_debug("%s: removing link, cpu: %d\n", __func__, cpu);
- cpufreq_cpu_put(data);
+ if (!frozen) {
+ pr_debug("%s: removing link, cpu: %d\n", __func__, cpu);
+ cpufreq_cpu_put(data);
+ }
/* If cpu is last user of policy, free policy */
if (cpus == 1) {
- lock_policy_rwsem_read(cpu);
- kobj = &data->kobj;
- cmp = &data->kobj_unregister;
- unlock_policy_rwsem_read(cpu);
- kobject_put(kobj);
-
- /* we need to make sure that the underlying kobj is actually
- * not referenced anymore by anybody before we proceed with
- * unloading.
- */
- pr_debug("waiting for dropping of refcount\n");
- wait_for_completion(cmp);
- pr_debug("wait complete\n");
+ if (!frozen) {
+ lock_policy_rwsem_read(cpu);
+ kobj = &data->kobj;
+ cmp = &data->kobj_unregister;
+ unlock_policy_rwsem_read(cpu);
+ kobject_put(kobj);
+
+ /*
+ * We need to make sure that the underlying kobj is
+ * actually not referenced anymore by anybody before we
+ * proceed with unloading.
+ */
+ pr_debug("waiting for dropping of refcount\n");
+ wait_for_completion(cmp);
+ pr_debug("wait complete\n");
+ }
+ /*
+ * Perform the ->exit() even during light-weight tear-down,
+ * since this is a core component, and is essential for the
+ * the subsequent light-weight ->init() to succeed.
+ */
if (cpufreq_driver->exit)
cpufreq_driver->exit(data);
- cpufreq_policy_free(data);
+ if (!frozen)
+ cpufreq_policy_free(data);
} else if (cpufreq_driver->target) {
__cpufreq_governor(data, CPUFREQ_GOV_START);
next prev parent reply other threads:[~2013-07-11 22:20 UTC|newest]
Thread overview: 51+ messages / expand[flat|nested] mbox.gz Atom feed top
2013-07-11 22:15 [PATCH 0/8] Cpufreq, cpu hotplug, suspend/resume related fixes Srivatsa S. Bhat
2013-07-11 22:15 ` [PATCH 1/8] cpufreq: Revert commit a66b2e to fix cpufreq regression during suspend/resume Srivatsa S. Bhat
2013-07-12 7:18 ` Viresh Kumar
2013-07-13 12:46 ` Paul Bolle
2013-07-15 6:18 ` Srivatsa S. Bhat
2013-07-11 22:15 ` [PATCH 2/8] cpufreq: Fix misplaced call to cpufreq_update_policy() Srivatsa S. Bhat
2013-07-12 7:06 ` Viresh Kumar
2013-07-15 6:20 ` Srivatsa S. Bhat
2013-07-15 11:37 ` Rafael J. Wysocki
2013-07-11 22:16 ` [PATCH 3/8] cpufreq: Add helper to perform alloc/free of policy structure Srivatsa S. Bhat
2013-07-12 7:09 ` Viresh Kumar
2013-07-15 6:24 ` Srivatsa S. Bhat
2013-07-11 22:16 ` [PATCH 4/8] cpufreq: Extract non-interface related stuff from cpufreq_add_dev_interface Srivatsa S. Bhat
2013-07-12 7:17 ` Viresh Kumar
2013-07-11 22:16 ` [PATCH 5/8] cpufreq: Extract the handover of policy cpu to a helper function Srivatsa S. Bhat
2013-07-12 7:19 ` Viresh Kumar
2013-07-11 22:16 ` [PATCH 6/8] cpufreq: Introduce a flag ('frozen') to separate full vs temporary init/teardown Srivatsa S. Bhat
2013-07-12 7:31 ` Viresh Kumar
2013-07-11 22:17 ` Srivatsa S. Bhat [this message]
2013-07-15 9:55 ` [PATCH 7/8] cpufreq: Preserve policy structure across suspend/resume Viresh Kumar
2013-07-15 10:05 ` Srivatsa S. Bhat
2013-07-15 10:21 ` Viresh Kumar
2013-07-15 11:52 ` Srivatsa S. Bhat
2013-07-15 11:35 ` Rafael J. Wysocki
2013-07-15 11:53 ` Srivatsa S. Bhat
2013-07-16 6:15 ` Viresh Kumar
2013-07-16 8:56 ` Srivatsa S. Bhat
2013-07-16 9:10 ` Viresh Kumar
2013-07-16 9:29 ` Srivatsa S. Bhat
2013-07-16 9:35 ` Viresh Kumar
2013-07-16 9:54 ` Srivatsa S. Bhat
2013-07-11 22:17 ` [PATCH 8/8] cpufreq: Perform light-weight init/teardown during suspend/resume Srivatsa S. Bhat
2013-07-11 22:25 ` [PATCH 0/8] Cpufreq, cpu hotplug, suspend/resume related fixes Jarzmik, Robert
2013-07-11 22:33 ` Rafael J. Wysocki
2013-07-11 22:23 ` Srivatsa S. Bhat
2013-07-16 15:15 ` Toralf Förster
2013-07-16 21:32 ` Rafael J. Wysocki
2013-07-17 5:03 ` Srivatsa S. Bhat
2013-07-17 15:27 ` Toralf Förster
2013-07-17 15:49 ` Srivatsa S. Bhat
2013-07-21 8:43 ` Srivatsa S. Bhat
2013-07-21 9:40 ` Toralf Förster
2013-07-21 10:38 ` Srivatsa S. Bhat
2013-07-21 12:59 ` Rafael J. Wysocki
2013-07-15 17:38 ` Toralf Förster
2013-07-15 23:25 ` Rafael J. Wysocki
2013-07-13 9:23 ` Toralf Förster
2013-07-13 13:50 ` Toralf Förster
2013-07-15 6:40 ` Srivatsa S. Bhat
2013-07-15 8:27 ` Lan Tianyu
2013-07-15 8:43 ` Srivatsa S. Bhat
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20130711221704.547.64296.stgit@srivatsabhat.in.ibm.com \
--to=srivatsa.bhat@linux.vnet.ibm.com \
--cc=dirk.brandewie@gmail.com \
--cc=durgadoss.r@intel.com \
--cc=lantianyu1986@gmail.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pm@vger.kernel.org \
--cc=rjw@sisk.pl \
--cc=robert.jarzmik@intel.com \
--cc=stern@rowland.harvard.edu \
--cc=tianyu.lan@intel.com \
--cc=toralf.foerster@gmx.de \
--cc=viresh.kumar@linaro.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).