diff options
author | Sai Gurrappadi <sgurrappadi@nvidia.com> | 2014-04-30 20:06:28 -0700 |
---|---|---|
committer | Riham Haidar <rhaidar@nvidia.com> | 2014-05-02 16:40:06 -0700 |
commit | 7e2ffe6c059b6fbae01480605e5aef8093e5fb4c (patch) | |
tree | 98e73116895708c017d926ac7d29f8146b62a47b /drivers/misc | |
parent | 1c4f6e7394b65bfbb6a68e151373981f6f60c96a (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/Makefile | 1 | ||||
-rw-r--r-- | drivers/misc/suspend_handler_min_cpus_t132.c | 79 |
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"); |