Beispiel #1
0
/**
 *	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);
}
Beispiel #2
0
/**
 *	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;
}
Beispiel #3
0
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);
}
Beispiel #4
0
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);
}
Beispiel #5
0
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;
}