[PATCH] MMC: wbsd delayed insertion
authorPierre Ossman <drzeus@drzeus.cx>
Fri, 1 Jul 2005 11:13:55 +0000 (12:13 +0100)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Fri, 1 Jul 2005 11:13:55 +0000 (12:13 +0100)
Wait 0.5 seconds before scanning for cards after an insertion interrupt.
The electrical connection needs this time to stabilise for some cards.

Signed-off-by: Pierre Ossman <drzeus@drzeus.cx>
Signed-off-by: Russell King <rmk+kernel@arm.linux.org.uk>
drivers/mmc/wbsd.c
drivers/mmc/wbsd.h

index b7fbd30b49a0de18d1b05cf30bcfe62c0f64efac..0bd9b53fa8989e0c61e73df755b31c54e6b460e0 100644 (file)
@@ -1050,6 +1050,20 @@ static struct mmc_host_ops wbsd_ops = {
  *                                                                           *
 \*****************************************************************************/
 
+/*
+ * 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
  */
@@ -1075,7 +1089,6 @@ static void wbsd_tasklet_card(unsigned long param)
 {
        struct wbsd_host* host = (struct wbsd_host*)param;
        u8 csr;
-       int change = 0;
        
        spin_lock(&host->lock);
        
@@ -1094,14 +1107,20 @@ static void wbsd_tasklet_card(unsigned long param)
                {
                        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)
                {
@@ -1112,15 +1131,14 @@ static void wbsd_tasklet_card(unsigned long param)
                        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)
@@ -1324,6 +1342,13 @@ static int __devinit wbsd_alloc_mmc(struct device* dev)
        
        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.
@@ -1351,11 +1376,17 @@ static int __devinit wbsd_alloc_mmc(struct device* dev)
 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 864f30828d01fe4f52da21502c91f3cec18e6ed4..9f5383e6e5936de52f1ee13f33f51a562eb5c1a7 100644 (file)
@@ -187,4 +187,6 @@ struct wbsd_host
        struct tasklet_struct   timeout_tasklet;
        struct tasklet_struct   finish_tasklet;
        struct tasklet_struct   block_tasklet;
+       
+       struct timer_list       timer;          /* Card detection timer */
 };