/** * mmc_release_host - release a host * @host: mmc host to release * * Release a MMC host, allowing others to claim the host * for their operations. */ void mmc_release_host(struct mmc_host *host) { WARN_ON(!host->claimed); mmc_host_lazy_disable(host); mmc_do_release_host(host); }
/** * mmc_suspend_host - suspend a host * @host: mmc host */ int mmc_suspend_host(struct mmc_host *host) { int err = 0; if (mmc_bus_needs_resume(host)) return 0; if (host->caps & MMC_CAP_DISABLE) cancel_delayed_work(&host->disable); mmc_bus_get(host); if (host->bus_ops && !host->bus_dead) { /* * A long response time is not acceptable for device drivers * when doing suspend. Prevent mmc_claim_host in the suspend * sequence, to potentially wait "forever" by trying to * pre-claim the host. * * Skip try claim host for SDIO cards, doing so fixes deadlock * conditions. The function driver suspend may again call into * SDIO driver within a different context for enabling power * save mode in the card and hence wait in mmc_claim_host * causing deadlock. */ if (!(host->card && mmc_card_sdio(host->card))) if (!mmc_try_claim_host(host)) err = -EBUSY; if (!err) { if (host->bus_ops->suspend) err = host->bus_ops->suspend(host); if (!(host->card && mmc_card_sdio(host->card))) mmc_do_release_host(host); if (err == -ENOSYS || !host->bus_ops->resume) { /* * We simply "remove" the card in this case. * It will be redetected on resume. */ if (host->bus_ops->remove) host->bus_ops->remove(host); mmc_claim_host(host); mmc_detach_bus(host); mmc_power_off(host); mmc_release_host(host); host->pm_flags = 0; err = 0; } } } mmc_bus_put(host); if (!err && !(host->pm_flags & MMC_PM_KEEP_POWER)) mmc_power_off(host); return err; }
void mmc_host_deeper_disable(struct work_struct *work) { struct mmc_host *host = container_of(work, struct mmc_host, disable.work); /* If the host is claimed then we do not want to disable it anymore */ if (!mmc_try_claim_host(host)) return; mmc_host_do_disable(host, 1); mmc_do_release_host(host); }
void mmc_host_deeper_disable(struct work_struct *work) { struct mmc_host *host = container_of(work, struct mmc_host, disable.work); /* If the host is claimed then we do not want to disable it anymore */ if (!mmc_try_claim_host(host)) goto out; mmc_host_do_disable(host, 1); mmc_do_release_host(host); out: wake_unlock(&mmc_delayed_work_wake_lock); }
void mmc_host_deeper_disable(struct work_struct *work) { struct mmc_host *host = container_of(work, struct mmc_host, disable.work); /* If the host is claimed then we do not want to disable it anymore */ if (!mmc_try_claim_host(host)) goto out; mmc_host_do_disable(host, 1); mmc_do_release_host(host); out: #if 0 //Robert, 20101006, KB62_CR766 : Fix unexpectedly remove SD card issue wake_unlock(&mmc_delayed_work_wake_lock); #endif printk(KERN_ERR "mmc_try_claim_host(host) = 0\n"); }
static int sprd_mmc_host_runtime_suspend(struct device *dev) { int rc = -EBUSY; unsigned long flags; struct platform_device *pdev = container_of(dev, struct platform_device, dev); struct sdhci_host *host = platform_get_drvdata(pdev); struct mmc_host *mmc = host->mmc; if(dev->driver != NULL) { if(mmc_try_claim_host(mmc)) { sdhci_runtime_suspend_host(host); spin_lock_irqsave(&host->lock, flags); if(host->ops->set_clock) host->ops->set_clock(host, 0); spin_unlock_irqrestore(&host->lock, flags); mmc_do_release_host(mmc); rc = 0; } } return rc; }