• Ulf Hansson's avatar
    mmc: core: Fix hanging on I/O during system suspend for removable cards · 17a17bf5
    Ulf Hansson authored
    The mmc core uses a PM notifier to temporarily during system suspend, turn
    off the card detection mechanism for removal/insertion of (e)MMC/SD/SDIO
    cards. Additionally, the notifier may be used to remove an SDIO card
    entirely, if a corresponding SDIO functional driver don't have the system
    suspend/resume callbacks assigned. This behaviour has been around for a
    very long time.
    
    However, a recent bug report tells us there are problems with this
    approach. More precisely, when receiving the PM_SUSPEND_PREPARE
    notification, we may end up hanging on I/O to be completed, thus also
    preventing the system from getting suspended.
    
    In the end what happens, is that the cancel_delayed_work_sync() in
    mmc_pm_notify() ends up waiting for mmc_rescan() to complete - and since
    mmc_rescan() wants to claim the host, it needs to wait for the I/O to be
    completed first.
    
    Typically, this problem is triggered in Android, if there is ongoing I/O
    while the user decides to suspend, resume and then suspend the system
    again. This due to that after the resume, an mmc_rescan() work gets punted
    to the workqueue, which job is to verify that the card remains inserted
    after the system has resumed.
    
    To fix this problem, userspace needs to become frozen to suspend the I/O,
    prior to turning off the card detection mechanism. Therefore, let's drop
    the PM notifiers for mmc subsystem altogether and rely on the card
    detection to be turned off/on as a part of the system_freezable_wq, that we
    are already using.
    
    Moreover, to allow and SDIO card to be removed during system suspend, let's
    manage this from a ->prepare() callback, assigned at the mmc_host_class
    level. In this way, we can use the parent device (the mmc_host_class
    device), to remove the card device that is the child, in the
    device_prepare() phase.
    Reported-by: default avatarKiwoong Kim <kwmad.kim@samsung.com>
    Cc: stable@vger.kernel.org # v4.5+
    Signed-off-by: default avatarUlf Hansson <ulf.hansson@linaro.org>
    Reviewed-by: default avatarLinus Walleij <linus.walleij@linaro.org>
    Link: https://lore.kernel.org/r/20210310152900.149380-1-ulf.hansson@linaro.orgReviewed-by: default avatarKiwoong Kim <kwmad.kim@samsung.com>
    17a17bf5
core.h 5.43 KB