/** * mmc_suspend_host - suspend a host * @host: mmc host * @state: suspend mode (PM_SUSPEND_xxx) */ int mmc_suspend_host(struct mmc_host *host, pm_message_t state) { 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) { if (host->bus_ops->suspend) err = host->bus_ops->suspend(host); } mmc_bus_put(host); if (!err && !(host->pm_flags & MMC_PM_KEEP_POWER)) mmc_power_off(host); return err; }
/** * 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); if (unlikely(cancel_delayed_work(&host->detect))) { atomic_dec(&wakelock_refs); } mmc_flush_scheduled_work(); mmc_bus_get(host); if (host->bus_ops && !host->bus_dead) { if (host->bus_ops->suspend) err = host->bus_ops->suspend(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_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; }
int mmc_resume_bus(struct mmc_host *host) { unsigned long flags; int err = 0; if (!mmc_bus_needs_resume(host)) return -EINVAL; printk("%s: Starting deferred resume\n", mmc_hostname(host)); spin_lock_irqsave(&host->lock, flags); host->bus_resume_flags &= ~MMC_BUSRESUME_NEEDS_RESUME; host->rescan_disable = 0; spin_unlock_irqrestore(&host->lock, flags); mmc_bus_get(host); if (host->bus_ops && !host->bus_dead) { mmc_power_up(host); BUG_ON(!host->bus_ops->resume); err = host->bus_ops->resume(host); } #ifdef CONFIG_MACH_P1 if (!err) { #endif /* CONFIG_MACH_P1 */ if (host->bus_ops->detect && !host->bus_dead) host->bus_ops->detect(host); #ifdef CONFIG_MACH_P1 } else { printk(KERN_WARNING "%s: error %d during resume " "(card was removed?)\n", mmc_hostname(host), err); } #endif /* CONFIG_MACH_P1 */ mmc_bus_put(host); printk("%s: Deferred resume completed\n", mmc_hostname(host)); return err; }
int mmc_resume_bus(struct mmc_host *host) { if (!mmc_bus_needs_resume(host)) return -EINVAL; printk("%s: Starting deferred resume\n", mmc_hostname(host)); host->bus_resume_flags &= ~MMC_BUSRESUME_NEEDS_RESUME; mmc_bus_get(host); if (host->bus_ops) { if (!host->bus_dead) { mmc_power_up(host); BUG_ON(!host->bus_ops->resume); host->bus_ops->resume(host); } if (host->bus_ops->detect && !host->bus_dead) host->bus_ops->detect(host); } mmc_bus_put(host); printk("%s: Deferred resume completed\n", mmc_hostname(host)); return 0; }
/** * mmc_suspend_host - suspend a host * @host: mmc host * @state: suspend mode (PM_SUSPEND_xxx) */ int mmc_suspend_host(struct mmc_host *host, pm_message_t state) { int err = 0; if (mmc_bus_needs_resume(host)) return 0; if (host->caps & MMC_CAP_DISABLE) cancel_delayed_work(&host->disable); cancel_delayed_work(&host->detect); mmc_flush_scheduled_work(); mmc_bus_get(host); if (host->bus_ops && !host->bus_dead) { if (host->bus_ops->suspend) err = host->bus_ops->suspend(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_release_host(host); err = 0; } } mmc_bus_put(host); mmc_flush_scheduled_work(); if (!err) mmc_power_off(host); return err; }
/** * 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); cancel_delayed_work(&host->detect); mmc_flush_scheduled_work(); mmc_bus_get(host); if (host->bus_ops && !host->bus_dead) { if (host->bus_ops->suspend) err = host->bus_ops->suspend(host); } mmc_bus_put(host); #ifndef CONFIG_WILINK_NLCP if (!err && !(host->pm_flags & MMC_PM_KEEP_POWER)) #else if (!err && !mmc_card_keep_power(host)) #endif { if(suspend_debug) printk("P off mmc \n"); mmc_power_off(host); } if(host->nesting_cnt < 0) // Mahesh non line fetch patch host->nesting_cnt = 0; return err; }
/** * mmc_suspend_host - suspend a host * @host: mmc host * @state: suspend mode (PM_SUSPEND_xxx) */ int mmc_suspend_host(struct mmc_host *host, pm_message_t state) { int err = 0; if (mmc_bus_needs_resume(host)) return 0; //B: Robert, 20101006, KB62_CR766 : Fix unexpectedly remove SD card issue cancel_delayed_work(&host->detect); mmc_flush_scheduled_work(); //E: Robert, 20101006, KB62_CR766 if (host->caps & MMC_CAP_DISABLE) cancel_delayed_work(&host->disable); mmc_bus_get(host); if (host->bus_ops && !host->bus_dead) { if (host->bus_ops->suspend) err = host->bus_ops->suspend(host); //B: Robert, 20101006, KB62_CR766 : Fix unexpectedly remove SD card issue if (!host->bus_ops->resume) { if (host->bus_ops->remove) host->bus_ops->remove(host); mmc_claim_host(host); mmc_detach_bus(host); mmc_release_host(host); } //E: Robert, 20101006, KB62_CR766 } mmc_bus_put(host); if (!err) mmc_power_off(host); return err; }
/** * 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); cancel_delayed_work(&host->detect); mmc_flush_scheduled_work(); 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; } } } #ifdef CONFIG_PM_RUNTIME if (mmc_bus_manual_resume(host)) host->bus_resume_flags |= MMC_BUSRESUME_NEEDS_RESUME; #endif mmc_bus_put(host); if (!err && !(host->pm_flags & MMC_PM_KEEP_POWER)) mmc_power_off(host); return err; }
/* Do the card removal on suspend if card is assumed removeable * Do that in pm notifier while userspace isn't yet frozen, so we will be able * to sync the card. */ int mmc_pm_notify(struct notifier_block *notify_block, unsigned long mode, void *unused) { struct mmc_host *host = container_of( notify_block, struct mmc_host, pm_notify); unsigned long flags; switch (mode) { case PM_HIBERNATION_PREPARE: case PM_SUSPEND_PREPARE: spin_lock_irqsave(&host->lock, flags); if (mmc_bus_needs_resume(host)) { spin_unlock_irqrestore(&host->lock, flags); break; } host->rescan_disable = 1; spin_unlock_irqrestore(&host->lock, flags); cancel_delayed_work_sync(&host->detect); if (!host->bus_ops || host->bus_ops->suspend) break; if (host->bus_ops->remove) host->bus_ops->remove(host); mmc_claim_host(host); mmc_detach_bus(host); mmc_release_host(host); break; case PM_POST_SUSPEND: case PM_POST_HIBERNATION: spin_lock_irqsave(&host->lock, flags); if (mmc_bus_manual_resume(host)) { spin_unlock_irqrestore(&host->lock, flags); break; } host->rescan_disable = 0; spin_unlock_irqrestore(&host->lock, flags); #if defined(CONFIG_MACH_ACER_A4) || defined(CONFIG_MACH_ACER_A5) printk("*** %s: trigger polling\n", __func__); if (host && host->card && host->card->cis.vendor == ATHR_MANUF_CODE) { printk("*** %s: WIFI slot. Skip detect.\n", __func__); return 0; } #endif #if defined(CONFIG_MACH_ACER_A4) if (host && !strcmp(mmc_hostname(host), "mmc1")) { pr_info("*** %s: mmc1. Skip detect.\n", __func__); return 0; } #endif #if defined(CONFIG_MACH_ACER_A5) if (host && !strcmp(mmc_hostname(host), "mmc0")) { pr_info("*** %s: mmc0 slot. Skip detect.\n", __func__); return 0; } if (host && !strcmp(mmc_hostname(host), "mmc2")) { pr_info("*** %s: mmc2 slot. Skip detect.\n", __func__); return 0; } #endif mmc_detect_change(host, 0); } return 0; }