mmc: core: abort rescan if suspend is triggered
There could be a race between suspend and mmc_rescan as follows: At resume: -> mmc_pm_notify -> mmc_rescan is scheduled Suspend is triggered: -> mmc_pm_notify -> wait for mmc_rescan/cancel it -> rescan acquires wakelock if card is detected so as to give user-space a chance to respond -> PM framework cancels suspend since wakelock is active Hence, release the wake-lock if its active in suspend prepare and check for rescan_disable before acquiring wake-lock. This prefers suspend over notifying the user-space of the status of the card, which is fine since with suspend user-space is frozen too. CRs-fixed: 655281 Change-Id: I83783589f9b541d3af73931e9a7b0b144a25538e Signed-off-by: Asutosh Das <asutoshd@codeaurora.org>
This commit is contained in:
parent
354e25a674
commit
c865639f10
|
@ -3411,7 +3411,8 @@ void mmc_rescan(struct work_struct *work)
|
|||
mmc_release_host(host);
|
||||
mmc_rpm_release(host, &host->class_dev);
|
||||
out:
|
||||
if (extend_wakelock)
|
||||
/* only extend the wakelock, if suspend has not started yet */
|
||||
if (extend_wakelock && !host->rescan_disable)
|
||||
wake_lock_timeout(&host->detect_wake_lock, HZ / 2);
|
||||
|
||||
if (host->caps & MMC_CAP_NEEDS_POLL)
|
||||
|
@ -3812,16 +3813,15 @@ int mmc_pm_notify(struct notifier_block *notify_block,
|
|||
spin_unlock_irqrestore(&host->lock, flags);
|
||||
break;
|
||||
}
|
||||
|
||||
/* since its suspending anyway, disable rescan */
|
||||
host->rescan_disable = 1;
|
||||
spin_unlock_irqrestore(&host->lock, flags);
|
||||
|
||||
/* Wait for pending detect work to be completed */
|
||||
if (!(host->caps & MMC_CAP_NEEDS_POLL))
|
||||
flush_work(&host->detect.work);
|
||||
|
||||
spin_lock_irqsave(&host->lock, flags);
|
||||
host->rescan_disable = 1;
|
||||
spin_unlock_irqrestore(&host->lock, flags);
|
||||
|
||||
/*
|
||||
* In some cases, the detect work might be scheduled
|
||||
* just before rescan_disable is set to true.
|
||||
|
@ -3829,6 +3829,13 @@ int mmc_pm_notify(struct notifier_block *notify_block,
|
|||
*/
|
||||
cancel_delayed_work_sync(&host->detect);
|
||||
|
||||
/*
|
||||
* It is possible that the wake-lock has been acquired, since
|
||||
* its being suspended, release the wakelock
|
||||
*/
|
||||
if (wake_lock_active(&host->detect_wake_lock))
|
||||
wake_unlock(&host->detect_wake_lock);
|
||||
|
||||
if (!host->bus_ops || host->bus_ops->suspend)
|
||||
break;
|
||||
|
||||
|
|
|
@ -1380,7 +1380,11 @@ int mmc_attach_sd(struct mmc_host *host)
|
|||
*/
|
||||
#ifdef CONFIG_MMC_PARANOID_SD_INIT
|
||||
retries = 5;
|
||||
while (retries) {
|
||||
/*
|
||||
* Some bad cards may take a long time to init, give preference to
|
||||
* suspend in those cases.
|
||||
*/
|
||||
while (retries && !host->rescan_disable) {
|
||||
err = mmc_sd_init_card(host, host->ocr, NULL);
|
||||
if (err) {
|
||||
retries--;
|
||||
|
@ -1398,6 +1402,9 @@ int mmc_attach_sd(struct mmc_host *host)
|
|||
mmc_hostname(host), err);
|
||||
goto err;
|
||||
}
|
||||
|
||||
if (host->rescan_disable)
|
||||
goto err;
|
||||
#else
|
||||
err = mmc_sd_init_card(host, host->ocr, NULL);
|
||||
if (err)
|
||||
|
@ -1421,9 +1428,9 @@ remove_card:
|
|||
mmc_claim_host(host);
|
||||
err:
|
||||
mmc_detach_bus(host);
|
||||
|
||||
pr_err("%s: error %d whilst initialising SD card\n",
|
||||
mmc_hostname(host), err);
|
||||
if (err)
|
||||
pr_err("%s: error %d whilst initialising SD card: rescan: %d\n",
|
||||
mmc_hostname(host), err, host->rescan_disable);
|
||||
|
||||
return err;
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue