Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/drzeus/mmc
authorLinus Torvalds <torvalds@woody.linux-foundation.org>
Fri, 24 Aug 2007 04:36:13 +0000 (21:36 -0700)
committerLinus Torvalds <torvalds@woody.linux-foundation.org>
Fri, 24 Aug 2007 04:36:13 +0000 (21:36 -0700)
* 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/drzeus/mmc:
  sdhci: tell which spurious interrupt we got
  sdhci: handle data interrupts during command
  mmc: ignore bad max block size in sdhci
  sdhci: be more cautious about block count register
  drivers/mmc/core/host.c: kmalloc + memset conversion to kzalloc
  drivers/mmc/core/bus.c: kmalloc + memset conversion to kzalloc

drivers/mmc/core/bus.c
drivers/mmc/core/host.c
drivers/mmc/host/sdhci.c
drivers/mmc/host/sdhci.h

index fe0e785ed7d2f57634fac42f5d6613417646affa..817a79462b3d5747e75057ac7f6819d925ae4d4e 100644 (file)
@@ -186,12 +186,10 @@ struct mmc_card *mmc_alloc_card(struct mmc_host *host)
 {
        struct mmc_card *card;
 
-       card = kmalloc(sizeof(struct mmc_card), GFP_KERNEL);
+       card = kzalloc(sizeof(struct mmc_card), GFP_KERNEL);
        if (!card)
                return ERR_PTR(-ENOMEM);
 
-       memset(card, 0, sizeof(struct mmc_card));
-
        card->host = host;
 
        device_initialize(&card->dev);
index 6a7e29849603dd86e29242c81e6184b1bd6d7033..2c7ce8f43a9a60367a6f75397a7da831c3afe8d3 100644 (file)
@@ -58,12 +58,10 @@ struct mmc_host *mmc_alloc_host(int extra, struct device *dev)
 {
        struct mmc_host *host;
 
-       host = kmalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL);
+       host = kzalloc(sizeof(struct mmc_host) + extra, GFP_KERNEL);
        if (!host)
                return NULL;
 
-       memset(host, 0, sizeof(struct mmc_host) + extra);
-
        host->parent = dev;
        host->class_dev.parent = dev;
        host->class_dev.class = &mmc_host_class;
index f2bc87ac24f7fe9151dcc948ffedb921d798116c..20a7d89e01bac08032fa874ecc081fc7a44a322d 100644 (file)
@@ -385,6 +385,9 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data)
        BUG_ON(data->blksz > host->mmc->max_blk_size);
        BUG_ON(data->blocks > 65535);
 
+       host->data = data;
+       host->data_early = 0;
+
        /* timeout in us */
        target_timeout = data->timeout_ns / 1000 +
                data->timeout_clks / host->clock;
@@ -443,11 +446,11 @@ static void sdhci_set_transfer_mode(struct sdhci_host *host,
 {
        u16 mode;
 
-       WARN_ON(host->data);
-
        if (data == NULL)
                return;
 
+       WARN_ON(!host->data);
+
        mode = SDHCI_TRNS_BLK_CNT_EN;
        if (data->blocks > 1)
                mode |= SDHCI_TRNS_MULTI;
@@ -477,8 +480,8 @@ static void sdhci_finish_data(struct sdhci_host *host)
        /*
         * Controller doesn't count down when in single block mode.
         */
-       if ((data->blocks == 1) && (data->error == MMC_ERR_NONE))
-               blocks = 0;
+       if (data->blocks == 1)
+               blocks = (data->error == MMC_ERR_NONE) ? 0 : 1;
        else
                blocks = readw(host->ioaddr + SDHCI_BLOCK_COUNT);
        data->bytes_xfered = data->blksz * (data->blocks - blocks);
@@ -600,9 +603,10 @@ static void sdhci_finish_command(struct sdhci_host *host)
 
        host->cmd->error = MMC_ERR_NONE;
 
-       if (host->cmd->data)
-               host->data = host->cmd->data;
-       else
+       if (host->data && host->data_early)
+               sdhci_finish_data(host);
+
+       if (!host->cmd->data)
                tasklet_schedule(&host->finish_tasklet);
 
        host->cmd = NULL;
@@ -929,9 +933,9 @@ static void sdhci_cmd_irq(struct sdhci_host *host, u32 intmask)
        BUG_ON(intmask == 0);
 
        if (!host->cmd) {
-               printk(KERN_ERR "%s: Got command interrupt even though no "
-                       "command operation was in progress.\n",
-                       mmc_hostname(host->mmc));
+               printk(KERN_ERR "%s: Got command interrupt 0x%08x even "
+                       "though no command operation was in progress.\n",
+                       mmc_hostname(host->mmc), (unsigned)intmask);
                sdhci_dumpregs(host);
                return;
        }
@@ -961,9 +965,9 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
                if (intmask & SDHCI_INT_DATA_END)
                        return;
 
-               printk(KERN_ERR "%s: Got data interrupt even though no "
-                       "data operation was in progress.\n",
-                       mmc_hostname(host->mmc));
+               printk(KERN_ERR "%s: Got data interrupt 0x%08x even "
+                       "though no data operation was in progress.\n",
+                       mmc_hostname(host->mmc), (unsigned)intmask);
                sdhci_dumpregs(host);
 
                return;
@@ -991,8 +995,18 @@ static void sdhci_data_irq(struct sdhci_host *host, u32 intmask)
                        writel(readl(host->ioaddr + SDHCI_DMA_ADDRESS),
                                host->ioaddr + SDHCI_DMA_ADDRESS);
 
-               if (intmask & SDHCI_INT_DATA_END)
-                       sdhci_finish_data(host);
+               if (intmask & SDHCI_INT_DATA_END) {
+                       if (host->cmd) {
+                               /*
+                                * Data managed to finish before the
+                                * command completed. Make sure we do
+                                * things in the proper order.
+                                */
+                               host->data_early = 1;
+                       } else {
+                               sdhci_finish_data(host);
+                       }
+               }
        }
 }
 
@@ -1347,12 +1361,11 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
         */
        mmc->max_blk_size = (caps & SDHCI_MAX_BLOCK_MASK) >> SDHCI_MAX_BLOCK_SHIFT;
        if (mmc->max_blk_size >= 3) {
-               printk(KERN_ERR "%s: Invalid maximum block size.\n",
+               printk(KERN_WARNING "%s: Invalid maximum block size, assuming 512\n",
                        host->slot_descr);
-               ret = -ENODEV;
-               goto unmap;
-       }
-       mmc->max_blk_size = 512 << mmc->max_blk_size;
+               mmc->max_blk_size = 512;
+       } else
+               mmc->max_blk_size = 512 << mmc->max_blk_size;
 
        /*
         * Maximum block count.
index d157776c11491d1f58d7c255acf8dd03d448a1f7..e28987d6d2ebf4f12d9ea180916d811571fc63e2 100644 (file)
@@ -182,6 +182,7 @@ struct sdhci_host {
        struct mmc_request      *mrq;           /* Current request */
        struct mmc_command      *cmd;           /* Current command */
        struct mmc_data         *data;          /* Current data request */
+       int                     data_early:1;   /* Data finished before cmd */
 
        struct scatterlist      *cur_sg;        /* We're working on this */
        int                     num_sg;         /* Entries left */