mirror of
https://github.com/followmsi/android_kernel_google_msm.git
synced 2024-11-06 23:17:41 +00:00
7e87a4dc87
The wakeup_reason driver works by having a callback log_wakeup_reason(), be called by the resume path once for each wakeup interrupt, with the irq number as argument. It then saves this interrupt in an array, and reports it when requested (via /sys/kernel/wakeup_reasons/last_resume_reason) and also prints the information out in kmsg. This approach works, but it has the deficiency that often the reported wakeup interrupt, while correct, is not the interrupt truly responsible for the wakeup. The reason for this is due to chained interrupt controllers (whether in hardware or simulated in software). It could be, for example, that the power button is wired to a GPIO handled by a single interrupt for all GPIOs, which interrupt then determines the GPIO and maps this to a software interrupt. Whether this is done in software, or by chaining interrupt controllers, the end result is that the wakeup reason will show not the interrupt associated with the power button, but the base-GPIO interrupt instead. This patch reworks the wakeup_sources driver such that it reports those final interrupts we are interested in, and not the intermediate (and not the base) ones. It does so as follows: -- The assumption is that generic_handle_irq() is called to dispatch all interrupts; due to this, chained interrupts result in recursive calls of generic_handle_irq(). -- We reconstruct the chains of interrupts that originate with the base wakeup interrupt and terminate with the interrupt we are interested in by tracing the calls to generic_handle_irq() -- The tracing works by maitaining a per-cpu counter that is incremented with each call to generic_handle_irq(); that counter is reported to the wakeup_sources driver by a pair of functions, called log_possible_wakeup_reason_start() and log_possible_wakeup_reason_complete(). The former is called before generic_handle_irq() handles the interrupt (thereby potentially calling itself recusively) and the latter afterward. -- The two functions mentioned above are complemented by log_base_wake_reason() (renamed from log_wakeup_reason()), which is used to report the base wakeup interrupts to the wakeup_reason driver. -- The three functions work together to build a set of trees, one per base wakeup reason, the leaves of which correspond to the interrupts we are interesed in; these trees can be arbitratily complex, though in reality they most often are a single node, or a chain of two nodes. The complexity supports arbitrarily involved interrupt dispatch. -- On resume, we build the tree; once the tree is completed, we walk it recursively, and print out to kmesg the (more useful) list of wakeup sources; simiarly, we walk the tree and print the leaves when /sys/kernel/wakeup_reasons/last_resume_reason is read. Signed-off-by: Iliyan Malchev <malchev@google.com> Change-Id: If8acb2951b61d2c6bcf4d011fe04d7f91057d139 |
||
---|---|---|
.. | ||
autosleep.c | ||
block_io.c | ||
console.c | ||
consoleearlysuspend.c | ||
earlysuspend.c | ||
fbearlysuspend.c | ||
hibernate.c | ||
Kconfig | ||
main.c | ||
Makefile | ||
power.h | ||
poweroff.c | ||
process.c | ||
qos.c | ||
snapshot.c | ||
suspend.c | ||
suspend_test.c | ||
suspend_time.c | ||
swap.c | ||
user.c | ||
userwakelock.c | ||
wakelock.c | ||
wakeup_reason.c |