summaryrefslogtreecommitdiff
path: root/drivers/misc
diff options
context:
space:
mode:
authorSai Gurrappadi <sgurrappadi@nvidia.com>2014-04-30 20:06:28 -0700
committerRiham Haidar <rhaidar@nvidia.com>2014-05-02 16:40:06 -0700
commit7e2ffe6c059b6fbae01480605e5aef8093e5fb4c (patch)
tree98e73116895708c017d926ac7d29f8146b62a47b /drivers/misc
parent1c4f6e7394b65bfbb6a68e151373981f6f60c96a (diff)
drivers: misc: Put CPU1 online before LP0
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/404108 Reviewed-by: Automatic_Commit_Validation_User GVS: Gerrit_Virtual_Submit Reviewed-by: Peng Du <pdu@nvidia.com> Reviewed-by: Krishna Sitaraman <ksitaraman@nvidia.com> Reviewed-by: Diwakar Tundlam <dtundlam@nvidia.com>
Diffstat (limited to 'drivers/misc')
-rw-r--r--drivers/misc/Makefile1
-rw-r--r--drivers/misc/suspend_handler_min_cpus_t132.c79
2 files changed, 80 insertions, 0 deletions
diff --git a/drivers/misc/Makefile b/drivers/misc/Makefile
index e16746257063..9d8111a61bd9 100644
--- a/drivers/misc/Makefile
+++ b/drivers/misc/Makefile
@@ -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
index 000000000000..4dd84dc30875
--- /dev/null
+++ b/drivers/misc/suspend_handler_min_cpus_t132.c
@@ -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");