[MMC] sdhci: Test for invalid block size
authorPierre Ossman <drzeus@drzeus.cx>
Sun, 2 Jul 2006 15:52:10 +0000 (16:52 +0100)
committerRussell King <rmk+kernel@arm.linux.org.uk>
Sun, 2 Jul 2006 15:52:10 +0000 (16:52 +0100)
The controller has an upper limit on the block size. Make sure we do not
cross it.

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

index 95fe0fdac4849a43f3f6d5345e92a7f61731fae8..302dd5bde751cb84ac73113d64cb9b23a75b7566 100644 (file)
@@ -328,6 +328,8 @@ static void sdhci_prepare_data(struct sdhci_host *host, struct mmc_data *data)
 
        /* Sanity checks */
        BUG_ON(data->blksz * data->blocks > 524288);
+       BUG_ON(data->blksz > host->max_block);
+       BUG_ON(data->blocks > 65535);
 
        /* timeout in us */
        target_timeout = data->timeout_ns / 1000 +
@@ -1158,6 +1160,15 @@ static int __devinit sdhci_probe_slot(struct pci_dev *pdev, int slot)
        if (caps & SDHCI_TIMEOUT_CLK_UNIT)
                host->timeout_clk *= 1000;
 
+       host->max_block = (caps & SDHCI_MAX_BLOCK_MASK) >> SDHCI_MAX_BLOCK_SHIFT;
+       if (host->max_block >= 3) {
+               printk(KERN_ERR "%s: Invalid maximum block size.\n",
+                       host->slot_descr);
+               ret = -ENODEV;
+               goto unmap;
+       }
+       host->max_block = 512 << host->max_block;
+
        /*
         * Set host parameters.
         */
index 8ed2a8973db6ff6fb4cb4f90f2508fce06e02448..b1aa3acf0906875f330b883658afb233bf793457 100644 (file)
 #define  SDHCI_TIMEOUT_CLK_UNIT        0x00000080
 #define  SDHCI_CLOCK_BASE_MASK 0x00003F00
 #define  SDHCI_CLOCK_BASE_SHIFT        8
+#define  SDHCI_MAX_BLOCK_MASK  0x00030000
+#define  SDHCI_MAX_BLOCK_SHIFT  16
 #define  SDHCI_CAN_DO_DMA      0x00400000
 #define  SDHCI_CAN_VDD_330     0x01000000
 #define  SDHCI_CAN_VDD_300     0x02000000
@@ -161,6 +163,7 @@ struct sdhci_host {
 
        unsigned int            max_clk;        /* Max possible freq (MHz) */
        unsigned int            timeout_clk;    /* Timeout freq (KHz) */
+       unsigned int            max_block;      /* Max block size (bytes) */
 
        unsigned int            clock;          /* Current clock (MHz) */
        unsigned short          power;          /* Current voltage */