msm: subsystem_restart: Prevent suspend from occuring during a restart
If a subsystem encounters a fatal error and communicates
this error to the applications processor just as the
application processor is about to enter a sleep mode
(in a suspend cycle), that subsystem may not be restarted
until the system resumes. To prevent this, take a
wakelock as soon as subsystem restart is requested.
For this to work, every client of subsystem restart
must ensure that they call into subsystem restart
from within the context of the interrupt that indicates
a fatal error in that subsystem.
Change-Id: I2e4ab2bc6ca45d3a7abbc8321de32ccd66ab0996
Signed-off-by: Vikram Mulukutla <markivx@codeaurora.org>
diff --git a/arch/arm/mach-msm/subsystem_restart.c b/arch/arm/mach-msm/subsystem_restart.c
index 04dc392..c3fd8c5 100644
--- a/arch/arm/mach-msm/subsystem_restart.c
+++ b/arch/arm/mach-msm/subsystem_restart.c
@@ -23,6 +23,8 @@
#include <linux/io.h>
#include <linux/kthread.h>
#include <linux/time.h>
+#include <linux/wakelock.h>
+#include <linux/suspend.h>
#include <asm/current.h>
@@ -45,6 +47,8 @@
struct restart_thread_data {
struct subsys_data *subsys;
+ struct wake_lock ssr_wake_lock;
+ char wakelockname[64];
int coupled;
};
@@ -334,10 +338,8 @@
/* Try to acquire shutdown_lock. If this fails, these subsystems are
* already being restarted - return.
*/
- if (!mutex_trylock(shutdown_lock)) {
- kfree(data);
- do_exit(0);
- }
+ if (!mutex_trylock(shutdown_lock))
+ goto out;
pr_debug("[%p]: Attempting to get powerup lock!\n", current);
@@ -430,6 +432,9 @@
pr_debug("[%p]: Released powerup lock!\n", current);
+out:
+ wake_unlock(&r_work->ssr_wake_lock);
+ wake_lock_destroy(&r_work->ssr_wake_lock);
kfree(data);
do_exit(0);
}
@@ -482,6 +487,12 @@
pr_debug("Restarting %s [level=%d]!\n", subsys_name,
restart_level);
+ snprintf(data->wakelockname, sizeof(data->wakelockname),
+ "ssr(%s)", subsys_name);
+ wake_lock_init(&data->ssr_wake_lock, WAKE_LOCK_SUSPEND,
+ data->wakelockname);
+ wake_lock(&data->ssr_wake_lock);
+
/* Let the kthread handle the actual restarting. Using a
* workqueue will not work since all restart requests are
* serialized and it prevents the short circuiting of