Skip to content
Snippets Groups Projects
Commit c30b6332 authored by Wei Wang's avatar Wei Wang Committed by Charles Li
Browse files

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
parent 90f3c69f
No related branches found
No related tags found
No related merge requests found
...@@ -436,12 +436,13 @@ bool log_possible_wakeup_reason(int irq, ...@@ -436,12 +436,13 @@ bool log_possible_wakeup_reason(int irq,
void log_suspend_abort_reason(const char *fmt, ...) void log_suspend_abort_reason(const char *fmt, ...)
{ {
va_list args; 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. //Suspend abort reason has already been logged.
if (suspend_abort) { if (suspend_abort) {
spin_unlock(&resume_reason_lock); spin_unlock_irqrestore(&resume_reason_lock, flags);
return; return;
} }
...@@ -450,7 +451,7 @@ void log_suspend_abort_reason(const char *fmt, ...) ...@@ -450,7 +451,7 @@ void log_suspend_abort_reason(const char *fmt, ...)
vsnprintf(abort_reason, MAX_SUSPEND_ABORT_LEN, fmt, args); vsnprintf(abort_reason, MAX_SUSPEND_ABORT_LEN, fmt, args);
va_end(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) 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) ...@@ -462,9 +463,10 @@ static bool match_node(struct wakeup_irq_node *n, void *_p)
int check_wakeup_reason(int irq) int check_wakeup_reason(int irq)
{ {
bool found; 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); 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; return found;
} }
...@@ -544,11 +546,12 @@ void clear_wakeup_reasons(void) ...@@ -544,11 +546,12 @@ void clear_wakeup_reasons(void)
static int wakeup_reason_pm_event(struct notifier_block *notifier, static int wakeup_reason_pm_event(struct notifier_block *notifier,
unsigned long pm_event, void *unused) unsigned long pm_event, void *unused)
{ {
unsigned long flags;
switch (pm_event) { switch (pm_event) {
case PM_SUSPEND_PREPARE: case PM_SUSPEND_PREPARE:
spin_lock(&resume_reason_lock); spin_lock_irqsave(&resume_reason_lock, flags);
suspend_abort = false; suspend_abort = false;
spin_unlock(&resume_reason_lock); spin_unlock_irqrestore(&resume_reason_lock, flags);
/* monotonic time since boot */ /* monotonic time since boot */
last_monotime = ktime_get(); last_monotime = ktime_get();
/* monotonic time since boot including the time spent in suspend */ /* monotonic time since boot including the time spent in suspend */
......
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Please register or to comment