mtd: m25p80: fix null pointer dereference bug
[safe/jmp/linux-2.6] / drivers / mtd / devices / m25p80.c
index 9be0229..10ed195 100644 (file)
@@ -54,7 +54,7 @@
 #define        SR_SRWD                 0x80    /* SR write protect */
 
 /* Define max times to check status register before we give up. */
-#define        MAX_READY_WAIT_COUNT    100000
+#define        MAX_READY_WAIT_JIFFIES  (40 * HZ)       /* M25P16 specs 40s max chip erase */
 #define        CMD_SIZE                4
 
 #ifdef CONFIG_M25PXX_USE_FAST_READ
 #define FAST_READ_DUMMY_BYTE 0
 #endif
 
-#ifdef CONFIG_MTD_PARTITIONS
-#define        mtd_has_partitions()    (1)
-#else
-#define        mtd_has_partitions()    (0)
-#endif
-
 /****************************************************************************/
 
 struct m25p {
@@ -145,20 +139,20 @@ static inline int write_enable(struct m25p *flash)
  */
 static int wait_till_ready(struct m25p *flash)
 {
-       int count;
+       unsigned long deadline;
        int sr;
 
-       /* one chip guarantees max 5 msec wait here after page writes,
-        * but potentially three seconds (!) after page erase.
-        */
-       for (count = 0; count < MAX_READY_WAIT_COUNT; count++) {
+       deadline = jiffies + MAX_READY_WAIT_JIFFIES;
+
+       do {
                if ((sr = read_sr(flash)) < 0)
                        break;
                else if (!(sr & SR_WIP))
                        return 0;
 
-               /* REVISIT sometimes sleeping would be best */
-       }
+               cond_resched();
+
+       } while (!time_after_eq(jiffies, deadline));
 
        return 1;
 }
@@ -171,8 +165,8 @@ static int wait_till_ready(struct m25p *flash)
 static int erase_chip(struct m25p *flash)
 {
        DEBUG(MTD_DEBUG_LEVEL3, "%s: %s %lldKiB\n",
-                       flash->spi->dev.bus_id, __func__,
-                       (long long)(flash->mtd.size >> 10));
+             dev_name(&flash->spi->dev), __func__,
+             (long long)(flash->mtd.size >> 10));
 
        /* Wait until finished previous write command. */
        if (wait_till_ready(flash))
@@ -198,7 +192,7 @@ static int erase_chip(struct m25p *flash)
 static int erase_sector(struct m25p *flash, u32 offset)
 {
        DEBUG(MTD_DEBUG_LEVEL3, "%s: %s %dKiB at 0x%08x\n",
-                       flash->spi->dev.bus_id, __func__,
+                       dev_name(&flash->spi->dev), __func__,
                        flash->mtd.erasesize / 1024, offset);
 
        /* Wait until finished previous write command. */
@@ -236,8 +230,8 @@ static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr)
        uint32_t rem;
 
        DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%llx, len %lld\n",
-                       flash->spi->dev.bus_id, __func__, "at",
-                       (long long)instr->addr, (long long)instr->len);
+             dev_name(&flash->spi->dev), __func__, "at",
+             (long long)instr->addr, (long long)instr->len);
 
        /* sanity checks */
        if (instr->addr + instr->len > flash->mtd.size)
@@ -252,10 +246,12 @@ static int m25p80_erase(struct mtd_info *mtd, struct erase_info *instr)
        mutex_lock(&flash->lock);
 
        /* whole-chip erase? */
-       if (len == flash->mtd.size && erase_chip(flash)) {
-               instr->state = MTD_ERASE_FAILED;
-               mutex_unlock(&flash->lock);
-               return -EIO;
+       if (len == flash->mtd.size) {
+               if (erase_chip(flash)) {
+                       instr->state = MTD_ERASE_FAILED;
+                       mutex_unlock(&flash->lock);
+                       return -EIO;
+               }
 
        /* REVISIT in some cases we could speed up erasing large regions
         * by using OPCODE_SE instead of OPCODE_BE_4K.  We may have set up
@@ -296,7 +292,7 @@ static int m25p80_read(struct mtd_info *mtd, loff_t from, size_t len,
        struct spi_message m;
 
        DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n",
-                       flash->spi->dev.bus_id, __func__, "from",
+                       dev_name(&flash->spi->dev), __func__, "from",
                        (u32)from, len);
 
        /* sanity checks */
@@ -368,7 +364,7 @@ static int m25p80_write(struct mtd_info *mtd, loff_t to, size_t len,
        struct spi_message m;
 
        DEBUG(MTD_DEBUG_LEVEL2, "%s: %s %s 0x%08x, len %zd\n",
-                       flash->spi->dev.bus_id, __func__, "to",
+                       dev_name(&flash->spi->dev), __func__, "to",
                        (u32)to, len);
 
        if (retlen)
@@ -504,6 +500,9 @@ static struct flash_info __devinitdata m25p_data [] = {
        { "at26df161a", 0x1f4601, 0, 64 * 1024, 32, SECT_4K, },
        { "at26df321",  0x1f4701, 0, 64 * 1024, 64, SECT_4K, },
 
+       /* Macronix */
+       { "mx25l12805d", 0xc22018, 0, 64 * 1024, 256, },
+
        /* Spansion -- single (large) sector size only, at least
         * for the chips listed here (without boot sectors).
         */
@@ -532,6 +531,7 @@ static struct flash_info __devinitdata m25p_data [] = {
        { "m25p64",  0x202017,  0, 64 * 1024, 128, },
        { "m25p128", 0x202018, 0, 256 * 1024, 64, },
 
+       { "m45pe10", 0x204011,  0, 64 * 1024, 2, },
        { "m45pe80", 0x204014,  0, 64 * 1024, 16, },
        { "m45pe16", 0x204015,  0, 64 * 1024, 32, },
 
@@ -564,7 +564,7 @@ static struct flash_info *__devinit jedec_probe(struct spi_device *spi)
        tmp = spi_write_then_read(spi, &code, 1, id, 5);
        if (tmp < 0) {
                DEBUG(MTD_DEBUG_LEVEL0, "%s: error %d reading JEDEC ID\n",
-                       spi->dev.bus_id, tmp);
+                       dev_name(&spi->dev), tmp);
                return NULL;
        }
        jedec = id[0];
@@ -618,7 +618,7 @@ static int __devinit m25p_probe(struct spi_device *spi)
                /* unrecognized chip? */
                if (i == ARRAY_SIZE(m25p_data)) {
                        DEBUG(MTD_DEBUG_LEVEL0, "%s: unrecognized id %s\n",
-                                       spi->dev.bus_id, data->type);
+                                       dev_name(&spi->dev), data->type);
                        info = NULL;
 
                /* recognized; is that chip really what's there? */
@@ -659,7 +659,7 @@ static int __devinit m25p_probe(struct spi_device *spi)
        if (data && data->name)
                flash->mtd.name = data->name;
        else
-               flash->mtd.name = spi->dev.bus_id;
+               flash->mtd.name = dev_name(&spi->dev);
 
        flash->mtd.type = MTD_NORFLASH;
        flash->mtd.writesize = 1;
@@ -678,6 +678,8 @@ static int __devinit m25p_probe(struct spi_device *spi)
                flash->mtd.erasesize = info->sector_size;
        }
 
+       flash->mtd.dev.parent = &spi->dev;
+
        dev_info(&spi->dev, "%s (%lld Kbytes)\n", info->name,
                        (long long)flash->mtd.size >> 10);
 
@@ -708,12 +710,13 @@ static int __devinit m25p_probe(struct spi_device *spi)
                struct mtd_partition    *parts = NULL;
                int                     nr_parts = 0;
 
-#ifdef CONFIG_MTD_CMDLINE_PARTS
-               static const char *part_probes[] = { "cmdlinepart", NULL, };
+               if (mtd_has_cmdlinepart()) {
+                       static const char *part_probes[]
+                                       = { "cmdlinepart", NULL, };
 
-               nr_parts = parse_mtd_partitions(&flash->mtd,
-                               part_probes, &parts, 0);
-#endif
+                       nr_parts = parse_mtd_partitions(&flash->mtd,
+                                       part_probes, &parts, 0);
+               }
 
                if (nr_parts <= 0 && data && data->parts) {
                        parts = data->parts;
@@ -733,7 +736,7 @@ static int __devinit m25p_probe(struct spi_device *spi)
                        flash->partitioned = 1;
                        return add_mtd_partitions(&flash->mtd, parts, nr_parts);
                }
-       } else if (data->nr_parts)
+       } else if (data && data->nr_parts)
                dev_warn(&spi->dev, "ignoring %d default partitions on %s\n",
                                data->nr_parts, data->name);