diff --git a/drivers/mmc/mmc.c b/drivers/mmc/mmc.c index 0a117c61cd18..ceae379a4d4c 100644 --- a/drivers/mmc/mmc.c +++ b/drivers/mmc/mmc.c @@ -1079,13 +1079,17 @@ static void mmc_setup(struct mmc_host *host) /** * mmc_detect_change - process change of state on a MMC socket * @host: host which changed state. + * @delay: optional delay to wait before detection (jiffies) * * All we know is that card(s) have been inserted or removed * from the socket(s). We don't know which socket or cards. */ -void mmc_detect_change(struct mmc_host *host) +void mmc_detect_change(struct mmc_host *host, unsigned long delay) { - schedule_work(&host->detect); + if (delay) + schedule_delayed_work(&host->detect, delay); + else + schedule_work(&host->detect); } EXPORT_SYMBOL(mmc_detect_change); @@ -1189,7 +1193,7 @@ int mmc_add_host(struct mmc_host *host) ret = mmc_add_host_sysfs(host); if (ret == 0) { mmc_power_off(host); - mmc_detect_change(host); + mmc_detect_change(host, 0); } return ret; @@ -1259,7 +1263,7 @@ EXPORT_SYMBOL(mmc_suspend_host); */ int mmc_resume_host(struct mmc_host *host) { - mmc_detect_change(host); + mmc_detect_change(host, 0); return 0; } diff --git a/drivers/mmc/mmci.c b/drivers/mmc/mmci.c index 716c4ef4faf6..91c74843dc0d 100644 --- a/drivers/mmc/mmci.c +++ b/drivers/mmc/mmci.c @@ -442,7 +442,7 @@ static void mmci_check_status(unsigned long data) status = host->plat->status(mmc_dev(host->mmc)); if (status ^ host->oldstat) - mmc_detect_change(host->mmc); + mmc_detect_change(host->mmc, 0); host->oldstat = status; mod_timer(&host->timer, jiffies + HZ); diff --git a/drivers/mmc/pxamci.c b/drivers/mmc/pxamci.c index e99a53b09e32..b53af57074e3 100644 --- a/drivers/mmc/pxamci.c +++ b/drivers/mmc/pxamci.c @@ -423,7 +423,9 @@ static void pxamci_dma_irq(int dma, void *devid, struct pt_regs *regs) static irqreturn_t pxamci_detect_irq(int irq, void *devid, struct pt_regs *regs) { - mmc_detect_change(devid); + struct pxamci_host *host = mmc_priv(devid); + + mmc_detect_change(devid, host->pdata->detect_delay); return IRQ_HANDLED; } diff --git a/drivers/mmc/wbsd.c b/drivers/mmc/wbsd.c index dec01d38c782..a62c86fef5cc 100644 --- a/drivers/mmc/wbsd.c +++ b/drivers/mmc/wbsd.c @@ -1122,7 +1122,7 @@ static void wbsd_detect_card(unsigned long data) DBG("Executing card detection\n"); - mmc_detect_change(host->mmc); + mmc_detect_change(host->mmc, 0); } /* @@ -1198,7 +1198,7 @@ static void wbsd_tasklet_card(unsigned long param) */ spin_unlock(&host->lock); - mmc_detect_change(host->mmc); + mmc_detect_change(host->mmc, 0); } else spin_unlock(&host->lock); diff --git a/include/asm-arm/arch-pxa/mmc.h b/include/asm-arm/arch-pxa/mmc.h index 9718063a2119..88c17dd02ed2 100644 --- a/include/asm-arm/arch-pxa/mmc.h +++ b/include/asm-arm/arch-pxa/mmc.h @@ -9,6 +9,7 @@ struct mmc_host; struct pxamci_platform_data { unsigned int ocr_mask; /* available voltages */ + unsigned long detect_delay; /* delay in jiffies before detecting cards after interrupt */ int (*init)(struct device *, irqreturn_t (*)(int, void *, struct pt_regs *), void *); int (*get_ro)(struct device *); void (*setpower)(struct device *, unsigned int); diff --git a/include/linux/mmc/host.h b/include/linux/mmc/host.h index 6014160d9c06..c1f021eddffa 100644 --- a/include/linux/mmc/host.h +++ b/include/linux/mmc/host.h @@ -109,6 +109,8 @@ struct mmc_host { struct mmc_card *card_selected; /* the selected MMC card */ struct work_struct detect; + + unsigned long private[0] ____cacheline_aligned; }; extern struct mmc_host *mmc_alloc_host(int extra, struct device *); @@ -116,14 +118,18 @@ extern int mmc_add_host(struct mmc_host *); extern void mmc_remove_host(struct mmc_host *); extern void mmc_free_host(struct mmc_host *); -#define mmc_priv(x) ((void *)((x) + 1)) +static inline void *mmc_priv(struct mmc_host *host) +{ + return (void *)host->private; +} + #define mmc_dev(x) ((x)->dev) #define mmc_hostname(x) ((x)->class_dev.class_id) extern int mmc_suspend_host(struct mmc_host *, pm_message_t); extern int mmc_resume_host(struct mmc_host *); -extern void mmc_detect_change(struct mmc_host *); +extern void mmc_detect_change(struct mmc_host *, unsigned long delay); extern void mmc_request_done(struct mmc_host *, struct mmc_request *); #endif