summaryrefslogtreecommitdiff
path: root/kernel
diff options
context:
space:
mode:
authorWei Wang <wvw@google.com>2016-10-27 11:03:12 -0700
committerMichael Bestas <mkbestas@lineageos.org>2019-12-23 23:43:35 +0200
commitc84c6fa6b63762567d6f29e4591d9d3597328636 (patch)
tree4d11bbdb6c17559c436d15a2af7edbb9eb04cda9 /kernel
parent8b858a0720d0044744268cfdcec17cd6aa9dddeb (diff)
power: wakeup_reason: make log function work in interrupt context
If log_suspend_abort_reason called in interrupt context, the spinlock may deadlock. With https://lkml.org/lkml/2014/9/1/404, wakeup mechanism changed, so log_suspend_abort_reason can be placed in interrupt context to retrieve the abort reasons. Bug: 32371978 Change-Id: I6902770e54b663d21b47289daec19401fc0dbed4 Signed-off-by: Wei Wang <wvw@google.com>
Diffstat (limited to 'kernel')
-rw-r--r--kernel/power/wakeup_reason.c17
1 files changed, 10 insertions, 7 deletions
diff --git a/kernel/power/wakeup_reason.c b/kernel/power/wakeup_reason.c
index 538eb7aa8112..20d218a73cae 100644
--- a/kernel/power/wakeup_reason.c
+++ b/kernel/power/wakeup_reason.c
@@ -436,12 +436,13 @@ bool log_possible_wakeup_reason(int irq,
void log_suspend_abort_reason(const char *fmt, ...)
{
va_list args;
+ unsigned long flags;
- spin_lock(&resume_reason_lock);
+ spin_lock_irqsave(&resume_reason_lock, flags);
//Suspend abort reason has already been logged.
if (suspend_abort) {
- spin_unlock(&resume_reason_lock);
+ spin_unlock_irqrestore(&resume_reason_lock, flags);
return;
}
@@ -450,7 +451,7 @@ void log_suspend_abort_reason(const char *fmt, ...)
vsnprintf(abort_reason, MAX_SUSPEND_ABORT_LEN, fmt, args);
va_end(args);
- spin_unlock(&resume_reason_lock);
+ spin_unlock_irqrestore(&resume_reason_lock, flags);
}
static bool match_node(struct wakeup_irq_node *n, void *_p)
@@ -462,9 +463,10 @@ static bool match_node(struct wakeup_irq_node *n, void *_p)
int check_wakeup_reason(int irq)
{
bool found;
- spin_lock(&resume_reason_lock);
+ unsigned long flags;
+ spin_lock_irqsave(&resume_reason_lock, flags);
found = !walk_irq_node_tree(base_irq_nodes, match_node, &irq);
- spin_unlock(&resume_reason_lock);
+ spin_unlock_irqrestore(&resume_reason_lock, flags);
return found;
}
@@ -544,11 +546,12 @@ void clear_wakeup_reasons(void)
static int wakeup_reason_pm_event(struct notifier_block *notifier,
unsigned long pm_event, void *unused)
{
+ unsigned long flags;
switch (pm_event) {
case PM_SUSPEND_PREPARE:
- spin_lock(&resume_reason_lock);
+ spin_lock_irqsave(&resume_reason_lock, flags);
suspend_abort = false;
- spin_unlock(&resume_reason_lock);
+ spin_unlock_irqrestore(&resume_reason_lock, flags);
/* monotonic time since boot */
last_monotime = ktime_get();
/* monotonic time since boot including the time spent in suspend */