Hi Andy,

Andy Green <andy.gr...@linaro.org> writes:

> Hi -
>
> Yesterday I studied suspend status on 3.0 kernel for Panda, for mem
> suspend it's working pretty well in Ubuntu case, desktop is coming
> back up woken by USB keyboard action, WLAN is workable after
> reassociation.
>
> However in Android case, the same tree merged with common-android-3.0
> to get Androidization is blowing chunks in suspend / resume, entering
> a loop where it aborts suspend and then tries to suspend again all the
> time.

I've been hit by the same problem when I was trying to implement
hibernation on Panda.

> Increasing the debug level in wakelock code shows at least two guys
> that can make trouble, locks "mmc_delayed_work" and "alarm_rtc".
>
> "mmc_delayed_work" casues wakelock stuff to return -EAGAIN, and
> "alarm_rtc" seems to timeout as a wakelock, but leave the alarm device
> in a state where it will abort suspend on -EBUSY.
>
> I took a look in drivers/mmc/core/core.c to see what the wakelock
> support patches had done there and was a bit surprised.
>
> They have a single wakelock to cover delayed work in there, however
> there are multiple delayed works possible to be queued, eg delayed
> disable and delayed detect actions, and although they wrap scheduling
> the delayed work to also lock the wakelock, they don't wrap cancelling
> it, eg -->

Yes, they unlock the wakelock when the delayed work is done, in the
handler.

> So here when preparing for suspend we can cancel the delayed work we
> presumably arranged wakelock coverage for, without unlocking the
> wakelock.

When the delayed work was canceled and handled immediately the wakelock
should have been unlocked.

The problem is here:

int mmc_pm_notify(struct notifier_block *notify_block,
                                        unsigned long mode, void *unused)
{
...
        switch (mode) {
        case PM_HIBERNATION_PREPARE:
        case PM_SUSPEND_PREPARE:
...
                mmc_release_host(host);

Which calls

void mmc_release_host(struct mmc_host *host)
{
...
      mmc_host_lazy_disable(host);
...
}

Since omap_hsmmc has non-zero host->disable_delay by default, this will
schedule a new delayed_work thus acquire new wakelock.

I tried to fix this by ignore the host->disable_delay if
host->rescan_disable is non-zero, which means we are in suspend phase,
and it worked.

-- 
Kanru

_______________________________________________
linaro-dev mailing list
linaro-dev@lists.linaro.org
http://lists.linaro.org/mailman/listinfo/linaro-dev

Reply via email to