]> rtime.felk.cvut.cz Git - sojka/nv-tegra/linux-3.10.git/commitdiff
drivers: misc: Put CPU1 online before LP0
authorSai Gurrappadi <sgurrappadi@nvidia.com>
Thu, 1 May 2014 03:06:28 +0000 (20:06 -0700)
committerDiwakar Tundlam <dtundlam@nvidia.com>
Fri, 2 May 2014 18:56:45 +0000 (11:56 -0700)
If CPU1 is offline before suspend, bring it back online so that it can
enter a low enough C-state (C7) for system suspend. Otherwise, CPU1
could potentially be stuck in a lower C-state causing the device to hang
on a LP0 request from CPU0.

Bug 1427140

Change-Id: Ib254b653f63cad401d7b24fa2c4a83801c9e7377
Signed-off-by: Sai Gurrappadi <sgurrappadi@nvidia.com>
Reviewed-on: http://git-master/r/403959
Reviewed-by: Automatic_Commit_Validation_User
Reviewed-by: Peng Du <pdu@nvidia.com>
Reviewed-by: Krishna Sitaraman <ksitaraman@nvidia.com>
Reviewed-by: Diwakar Tundlam <dtundlam@nvidia.com>
drivers/misc/Makefile
drivers/misc/suspend_handler_min_cpus_t132.c [new file with mode: 0644]

index e1674625706375f25d6b3b3c72d24b4639daed5c..9d8111a61bd90aa4a31064c547a14f7de67d9737 100644 (file)
@@ -86,3 +86,4 @@ obj-$(CONFIG_DENVER_CPU)      += force_idle_t132.o
 obj-$(CONFIG_ARCH_TEGRA)        +=tegra_timerinfo.o
 obj-$(CONFIG_MODS)             += mods/
 obj-$(CONFIG_DENVER_CPU)       += idle_test_t132.o
+obj-$(CONFIG_DENVER_CPU)       += suspend_handler_min_cpus_t132.o
diff --git a/drivers/misc/suspend_handler_min_cpus_t132.c b/drivers/misc/suspend_handler_min_cpus_t132.c
new file mode 100644 (file)
index 0000000..4dd84dc
--- /dev/null
@@ -0,0 +1,79 @@
+/*
+ * drivers/misc/suspend_handler_min_cpus_t132.c
+ *
+ * Copyright (c) 2014 NVIDIA CORPORATION.  All rights reserved.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 51 Franklin Street, Fifth Floor, Boston, MA  02110-1301, USA.
+ */
+
+#include <linux/types.h>
+#include <linux/module.h>
+#include <linux/err.h>
+#include <linux/pm_qos.h>
+#include <linux/suspend.h>
+
+static struct pm_qos_request suspend_min_cpus_req;
+
+/*
+ * XXX: LP0 WAR: If CPU1 is offline on LP0, the device will fail to go into LP0
+ * because the CPU gets put into C6 during normal hotplug. This causes LP0 (C7)
+ * to fail thereby hanging the system. Work around this by bringing back CPU1
+ * online and putting it in C7 before requesting LP0 from CPU0
+ */
+static int suspend_pm_notify(struct notifier_block *nb,
+                                       unsigned long event, void *data)
+{
+       if (event == PM_SUSPEND_PREPARE) {
+               pm_qos_update_request(&suspend_min_cpus_req,
+                                       num_possible_cpus());
+               if (num_online_cpus() != num_possible_cpus()) {
+                       pr_err("%s: min online cpu request failed\n",
+                                       __func__);
+                       return NOTIFY_BAD;
+               }
+       } else if (event == PM_POST_SUSPEND)
+               pm_qos_update_request(&suspend_min_cpus_req,
+                               PM_QOS_MIN_ONLINE_CPUS_DEFAULT_VALUE);
+
+       return NOTIFY_OK;
+}
+
+/*
+ * The priority of this suspend notifier should always be higher than
+ * cpu_hotplug's pm_notifier. Otherwise cpu_hotplug will disable hotplug
+ * operations on suspend causing the following cpu_up call in
+ * suspend_pm_notify to fail
+ */
+static struct notifier_block suspend_pm_notifier = {
+       .notifier_call = suspend_pm_notify,
+       .priority = 1,
+};
+
+static int __init suspend_handler_min_cpus_init(void)
+{
+       int err = register_pm_notifier(&suspend_pm_notifier);
+
+       if (err)
+               pr_err("%s: Failed to register pm notifier\n",
+                       __func__);
+
+       pm_qos_add_request(&suspend_min_cpus_req, PM_QOS_MIN_ONLINE_CPUS,
+                       PM_QOS_MIN_ONLINE_CPUS_DEFAULT_VALUE);
+
+       return err;
+}
+module_init(suspend_handler_min_cpus_init);
+
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("T132 Suspend handler for min online cpus constraint");