Index: linux-wbsd/drivers/mmc/wbsd.c =================================================================== --- linux-wbsd/drivers/mmc/wbsd.c (revision 147) +++ linux-wbsd/drivers/mmc/wbsd.c (working copy) @@ -1099,6 +1099,20 @@ \*****************************************************************************/ /* + * Helper function for card detection + */ +static void wbsd_detect_card(unsigned long data) +{ + struct wbsd_host *host = (struct wbsd_host*)data; + + BUG_ON(host == NULL); + + DBG("Executing card detection\n"); + + mmc_detect_change(host->mmc); +} + +/* * Tasklets */ @@ -1123,7 +1137,6 @@ { struct wbsd_host* host = (struct wbsd_host*)param; u8 csr; - int change = 0; spin_lock(&host->lock); @@ -1142,14 +1155,20 @@ { DBG("Card inserted\n"); host->flags |= WBSD_FCARD_PRESENT; - change = 1; + + /* + * Delay card detection to allow electrical connections + * to stabilise. + */ + mod_timer(&host->timer, jiffies + HZ/2); } + + spin_unlock(&host->lock); } else if (host->flags & WBSD_FCARD_PRESENT) { DBG("Card removed\n"); host->flags &= ~WBSD_FCARD_PRESENT; - change = 1; if (host->mrq) { @@ -1160,15 +1179,14 @@ host->mrq->cmd->error = MMC_ERR_FAILED; tasklet_schedule(&host->finish_tasklet); } - } - - /* - * Unlock first since we might get a call back. - */ - spin_unlock(&host->lock); + + /* + * Unlock first since we might get a call back. + */ + spin_unlock(&host->lock); - if (change) mmc_detect_change(host->mmc); + } } static void wbsd_tasklet_fifo(unsigned long param) @@ -1374,6 +1392,13 @@ spin_lock_init(&host->lock); /* + * Set up detection timer + */ + init_timer(&host->timer); + host->timer.data = (unsigned long)host; + host->timer.function = wbsd_detect_card; + + /* * Maximum number of segments. Worst case is one sector per segment * so this will be 64kB/512. */ @@ -1400,11 +1425,17 @@ static void __devexit wbsd_free_mmc(struct device* dev) { struct mmc_host* mmc; + struct wbsd_host* host; mmc = dev_get_drvdata(dev); if (!mmc) return; + host = mmc_priv(mmc); + BUG_ON(host == NULL); + + del_timer_sync(&host->timer); + mmc_free_host(mmc); dev_set_drvdata(dev, NULL); Index: linux-wbsd/drivers/mmc/wbsd.h =================================================================== --- linux-wbsd/drivers/mmc/wbsd.h (revision 147) +++ linux-wbsd/drivers/mmc/wbsd.h (working copy) @@ -190,4 +190,6 @@ struct tasklet_struct timeout_tasklet; struct tasklet_struct finish_tasklet; struct tasklet_struct block_tasklet; + + struct timer_list timer; /* Card detection timer */ };