auto suspend aborts with SD card remove call from pm notifier
From: srinath mannam <hidden>
Date: 2015-08-12 10:25:44
Hi
We have seen an issue in autosleep suspend sequence. While validating
the autosleep in the android setup using POWER input event.
Android version: KitKat
Linux kernel Version: 3.10
Issue description:
1. Android attempts autosleep with POWER input event.
2. In autosleep sequence at the time of suspend, suspend_prepare
will call pm notifier function “mmc_pm_notify” in PM_SUSPEND_PREPARE
mode.
3. With mmc pm notifier call mmc card is removed. Connected SD
card is removal disk.In the removable sd card scenario pm notifier
function will call the card remove. card remove function send events to
user space, then user space will acquire the wakeup sources.
4. Android user space demon has received the card removed events
and acquires the NETLINK wakeup source for cleanup.
5. In the same suspend_prepare sequence “try_to_freeze_tasks”
function is called from freeze_processes function.
6. try_to_freeze_tasks function has aborted because of pending
wakeup source NETLINK and returns error to suspend_prepare call.
7. With above error suspend_prepare calls mmc pm notifier function
in PM_POST_SUSPEND mode.
8. With mmc pm notifier call mmc card is detected back.
9. Android user space demon has received the card detected events
and releases the NETLINK wakeup source.
10. Android re-attempts the autosleep and repeats same sequence of 2
to 9. This goes infinite.
try_to_freeze_tasks:
In this function all the tasks are going to freeze in while loop before
end_time and also checks the pm_wakeup_pending condition.
The highlighted part in the below code is checks for the pending wakeup
sources. In my issue NETLINK is the pending wakeup source.
If I move the highlighted code block to outside of the loop then I did
not seen any pending wakeup sources, because NETLINK wakeup source is
released by the time all the tasks are freeze.
At the time of second iteration of the loop the NETLINK wakeup source
has released, If I did not break the loop with pm_wakeup_pending
condition check in the first iteration. This is verified in my issue
scenario.
But moving the pm_wakeup_pending condition check outside of the loop may
not the right solution;
Because there may be scenarios like wakeup sources are based on devices
which need pm notifier call with PM_POST_SUSPEND.
Could you please suggest me the right solution?
while (true) {
todo = 0;
read_lock(&tasklist_lock);
do_each_thread(g, p) {
if (p == current || !freeze_task(p))
continue;
if (!freezer_should_skip(p))
todo++;
} while_each_thread(g, p);
read_unlock(&tasklist_lock);
if (!user_only) {
wq_busy = freeze_workqueues_busy();
todo += wq_busy;
}
if (!todo || time_after(jiffies, end_time))
break;
/----------------------------------------------------------------------
-----------/
if (pm_wakeup_pending()) { “This check is true in my
case because of NETLINK wakeup source is active”
#ifdef CONFIG_PM_SLEEP
pm_get_active_wakeup_sources(suspend_abort,
MAX_SUSPEND_ABORT_LEN);
log_suspend_abort_reason(suspend_abort);
#endif
wakeup = true;
break;
}
/-----------------------------------------------------------------------
----------/
/*
* We need to retry, but first give the freezing tasks
some
* time to enter the refrigerator. Start with an
initial
* 1 ms sleep followed by exponential backoff until 8
ms.
*/
usleep_range(sleep_usecs / 2, sleep_usecs);
if (sleep_usecs < 8 * USEC_PER_MSEC)
sleep_usecs *= 2;
}
Thanks & Regards,
Srinath Babu Mannam