Skip to content

Commit

Permalink
---
Browse files Browse the repository at this point in the history
yaml
---
r: 208425
b: refs/heads/master
c: 4c2ef25
h: refs/heads/master
i:
  208423: b98ba71
v: v3
  • Loading branch information
Maxim Levitsky authored and Linus Torvalds committed Aug 11, 2010
1 parent 1cdebdc commit 0be8916
Show file tree
Hide file tree
Showing 4 changed files with 65 additions and 27 deletions.
2 changes: 1 addition & 1 deletion [refs]
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
---
refs/heads/master: 7310ece86ad7da027f85a37a0638164118a5d12f
refs/heads/master: 4c2ef25fe0b847d2ae818f74758ddb0be1c27d8e
83 changes: 57 additions & 26 deletions trunk/drivers/mmc/core/core.c
Original file line number Diff line number Diff line change
Expand Up @@ -1057,6 +1057,17 @@ void mmc_rescan(struct work_struct *work)
container_of(work, struct mmc_host, detect.work);
u32 ocr;
int err;
unsigned long flags;

spin_lock_irqsave(&host->lock, flags);

if (host->rescan_disable) {
spin_unlock_irqrestore(&host->lock, flags);
return;
}

spin_unlock_irqrestore(&host->lock, flags);


mmc_bus_get(host);

Expand Down Expand Up @@ -1274,19 +1285,6 @@ int mmc_suspend_host(struct mmc_host *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);

Expand Down Expand Up @@ -1318,28 +1316,61 @@ int mmc_resume_host(struct mmc_host *host)
printk(KERN_WARNING "%s: error %d during resume "
"(card was removed?)\n",
mmc_hostname(host), err);
if (host->bus_ops->remove)
host->bus_ops->remove(host);
mmc_claim_host(host);
mmc_detach_bus(host);
mmc_release_host(host);
/* no need to bother upper layers */
err = 0;
}
}
mmc_bus_put(host);

/*
* We add a slight delay here so that resume can progress
* in parallel.
*/
mmc_detect_change(host, 1);

return err;
}

EXPORT_SYMBOL(mmc_resume_host);

/* 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);
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;

mmc_claim_host(host);

if (host->bus_ops->remove)
host->bus_ops->remove(host);

mmc_detach_bus(host);
mmc_release_host(host);
host->pm_flags = 0;
break;

case PM_POST_SUSPEND:
case PM_POST_HIBERNATION:

spin_lock_irqsave(&host->lock, flags);
host->rescan_disable = 0;
spin_unlock_irqrestore(&host->lock, flags);
mmc_detect_change(host, 0);

}

return 0;
}
#endif

static int __init mmc_init(void)
Expand Down
4 changes: 4 additions & 0 deletions trunk/drivers/mmc/core/host.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include <linux/pagemap.h>
#include <linux/leds.h>
#include <linux/slab.h>
#include <linux/suspend.h>

#include <linux/mmc/host.h>

Expand Down Expand Up @@ -85,6 +86,7 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
init_waitqueue_head(&host->wq);
INIT_DELAYED_WORK(&host->detect, mmc_rescan);
INIT_DELAYED_WORK_DEFERRABLE(&host->disable, mmc_host_deeper_disable);
host->pm_notify.notifier_call = mmc_pm_notify;

/*
* By default, hosts do not support SGIO or large requests.
Expand Down Expand Up @@ -133,6 +135,7 @@ int mmc_add_host(struct mmc_host *host)
#endif

mmc_start_host(host);
register_pm_notifier(&host->pm_notify);

return 0;
}
Expand All @@ -149,6 +152,7 @@ EXPORT_SYMBOL(mmc_add_host);
*/
void mmc_remove_host(struct mmc_host *host)
{
unregister_pm_notifier(&host->pm_notify);
mmc_stop_host(host);

#ifdef CONFIG_DEBUG_FS
Expand Down
3 changes: 3 additions & 0 deletions trunk/include/linux/mmc/host.h
Original file line number Diff line number Diff line change
Expand Up @@ -124,6 +124,7 @@ struct mmc_host {
unsigned int f_min;
unsigned int f_max;
u32 ocr_avail;
struct notifier_block pm_notify;

#define MMC_VDD_165_195 0x00000080 /* VDD voltage 1.65 - 1.95 */
#define MMC_VDD_20_21 0x00000100 /* VDD voltage 2.0 ~ 2.1 */
Expand Down Expand Up @@ -183,6 +184,7 @@ struct mmc_host {

/* Only used with MMC_CAP_DISABLE */
int enabled; /* host is enabled */
int rescan_disable; /* disable card detection */
int nesting_cnt; /* "enable" nesting count */
int en_dis_recurs; /* detect recursion */
unsigned int disable_delay; /* disable delay in msecs */
Expand Down Expand Up @@ -257,6 +259,7 @@ int mmc_card_can_sleep(struct mmc_host *host);
int mmc_host_enable(struct mmc_host *host);
int mmc_host_disable(struct mmc_host *host);
int mmc_host_lazy_disable(struct mmc_host *host);
int mmc_pm_notify(struct notifier_block *notify_block, unsigned long, void *);

static inline void mmc_set_disable_delay(struct mmc_host *host,
unsigned int disable_delay)
Expand Down

0 comments on commit 0be8916

Please sign in to comment.