pxa3xx_nand: remove hardcode irq number
[safe/jmp/linux-2.6] / drivers / mtd / rfd_ftl.c
index a3e00a4..d2aa9c4 100644 (file)
@@ -3,8 +3,6 @@
  *
  * Copyright (C) 2005  Sean Young <sean@mess.org>
  *
- * $Id: rfd_ftl.c,v 1.5 2005/11/07 11:14:21 gleixner Exp $
- *
  * This type of flash translation layer (FTL) is used by the Embedded BIOS
  * by General Software. It is known as the Resident Flash Disk (RFD), see:
  *
@@ -23,8 +21,6 @@
 
 #include <asm/types.h>
 
-#define const_cpu_to_le16      __constant_cpu_to_le16
-
 static int block_size = 0;
 module_param(block_size, int, 0);
 MODULE_PARM_DESC(block_size, "Block size to use by RFD, defaults to erase unit size");
@@ -61,6 +57,7 @@ struct block {
                BLOCK_OK,
                BLOCK_ERASING,
                BLOCK_ERASED,
+               BLOCK_UNUSED,
                BLOCK_FAILED
        } state;
        int free_sectors;
@@ -99,10 +96,8 @@ static int build_block_map(struct partition *part, int block_no)
        block->offset = part->block_size * block_no;
 
        if (le16_to_cpu(part->header_cache[0]) != RFD_MAGIC) {
-               block->state = BLOCK_ERASED; /* assumption */
-               block->free_sectors = part->data_sectors_per_block;
-               part->reserved_block = block_no;
-               return 1;
+               block->state = BLOCK_UNUSED;
+               return -ENOENT;
        }
 
        block->state = BLOCK_OK;
@@ -124,7 +119,7 @@ static int build_block_map(struct partition *part, int block_no)
                        entry = 0;
 
                if (entry >= part->sector_count) {
-                       printk(KERN_NOTICE PREFIX
+                       printk(KERN_WARNING PREFIX
                                "'%s': unit #%d: entry %d corrupt, "
                                "sector %d out of range\n",
                                part->mbd.mtd->name, block_no, i, entry);
@@ -132,7 +127,7 @@ static int build_block_map(struct partition *part, int block_no)
                }
 
                if (part->sector_map[entry] != -1) {
-                       printk(KERN_NOTICE PREFIX
+                       printk(KERN_WARNING PREFIX
                                "'%s': more than one entry for sector %d\n",
                                part->mbd.mtd->name, entry);
                        part->errors = 1;
@@ -159,7 +154,7 @@ static int scan_header(struct partition *part)
        size_t retlen;
 
        sectors_per_block = part->block_size / SECTOR_SIZE;
-       part->total_blocks = part->mbd.mtd->size / part->block_size;
+       part->total_blocks = (u32)part->mbd.mtd->size / part->block_size;
 
        if (part->total_blocks < 2)
                return -ENOENT;
@@ -167,7 +162,7 @@ static int scan_header(struct partition *part)
        /* each erase block has three bytes header, followed by the map */
        part->header_sectors_per_block =
                        ((HEADER_MAP_OFFSET + sectors_per_block) *
-                       sizeof(u16) + SECTOR_SIZE - 1) / SECTOR_SIZE;
+                       sizeof(u16) + SECTOR_SIZE - 1) / SECTOR_SIZE;
 
        part->data_sectors_per_block = sectors_per_block -
                        part->header_sectors_per_block;
@@ -226,7 +221,7 @@ static int scan_header(struct partition *part)
        }
 
        if (part->reserved_block == -1) {
-               printk(KERN_NOTICE PREFIX "'%s': no empty erase unit found\n",
+               printk(KERN_WARNING PREFIX "'%s': no empty erase unit found\n",
                                part->mbd.mtd->name);
 
                part->errors = 1;
@@ -279,16 +274,17 @@ static void erase_callback(struct erase_info *erase)
 
        part = (struct partition*)erase->priv;
 
-       i = erase->addr / part->block_size;
-       if (i >= part->total_blocks || part->blocks[i].offset != erase->addr) {
-               printk(KERN_ERR PREFIX "erase callback for unknown offset %x "
-                               "on '%s'\n", erase->addr, part->mbd.mtd->name);
+       i = (u32)erase->addr / part->block_size;
+       if (i >= part->total_blocks || part->blocks[i].offset != erase->addr ||
+           erase->addr > UINT_MAX) {
+               printk(KERN_ERR PREFIX "erase callback for unknown offset %llx "
+                               "on '%s'\n", (unsigned long long)erase->addr, part->mbd.mtd->name);
                return;
        }
 
        if (erase->state != MTD_ERASE_DONE) {
-               printk(KERN_WARNING PREFIX "erase failed at 0x%x on '%s', "
-                               "state %d\n", erase->addr,
+               printk(KERN_WARNING PREFIX "erase failed at 0x%llx on '%s', "
+                               "state %d\n", (unsigned long long)erase->addr,
                                part->mbd.mtd->name, erase->state);
 
                part->blocks[i].state = BLOCK_FAILED;
@@ -300,7 +296,7 @@ static void erase_callback(struct erase_info *erase)
                return;
        }
 
-       magic = const_cpu_to_le16(RFD_MAGIC);
+       magic = cpu_to_le16(RFD_MAGIC);
 
        part->blocks[i].state = BLOCK_ERASED;
        part->blocks[i].free_sectors = part->data_sectors_per_block;
@@ -315,7 +311,7 @@ static void erase_callback(struct erase_info *erase)
                rc = -EIO;
 
        if (rc) {
-               printk(KERN_NOTICE PREFIX "'%s': unable to write RFD "
+               printk(KERN_ERR PREFIX "'%s': unable to write RFD "
                                "header at 0x%lx\n",
                                part->mbd.mtd->name,
                                part->blocks[i].offset);
@@ -348,9 +344,9 @@ static int erase_block(struct partition *part, int block)
        rc = part->mbd.mtd->erase(part->mbd.mtd, erase);
 
        if (rc) {
-               printk(KERN_WARNING PREFIX "erase of region %x,%x on '%s' "
-                               "failed\n", erase->addr, erase->len,
-                               part->mbd.mtd->name);
+               printk(KERN_ERR PREFIX "erase of region %llx,%llx on '%s' "
+                               "failed\n", (unsigned long long)erase->addr,
+                               (unsigned long long)erase->len, part->mbd.mtd->name);
                kfree(erase);
        }
 
@@ -383,7 +379,7 @@ static int move_block_contents(struct partition *part, int block_no, u_long *old
                rc = -EIO;
 
        if (rc) {
-               printk(KERN_NOTICE PREFIX "error reading '%s' at "
+               printk(KERN_ERR PREFIX "error reading '%s' at "
                        "0x%lx\n", part->mbd.mtd->name,
                        part->blocks[block_no].offset);
 
@@ -423,7 +419,7 @@ static int move_block_contents(struct partition *part, int block_no, u_long *old
                        rc = -EIO;
 
                if (rc) {
-                       printk(KERN_NOTICE PREFIX "'%s': Unable to "
+                       printk(KERN_ERR PREFIX "'%s': Unable to "
                                "read sector for relocation\n",
                                part->mbd.mtd->name);
 
@@ -520,7 +516,7 @@ static int reclaim_block(struct partition *part, u_long *old_sector)
  * because if we fill that one up first it'll have the most chance of having
  * the least live sectors at reclaim.
  */
-static int find_free_block(const struct partition *part)
+static int find_free_block(struct partition *part)
 {
        int block, stop;
 
@@ -533,6 +529,9 @@ static int find_free_block(const struct partition *part)
                                block != part->reserved_block)
                        return block;
 
+               if (part->blocks[block].state == BLOCK_UNUSED)
+                       erase_block(part, block);
+
                if (++block >= part->total_blocks)
                        block = 0;
 
@@ -541,7 +540,7 @@ static int find_free_block(const struct partition *part)
        return -1;
 }
 
-static int find_writeable_block(struct partition *part, u_long *old_sector)
+static int find_writable_block(struct partition *part, u_long *old_sector)
 {
        int rc, block;
        size_t retlen;
@@ -570,7 +569,7 @@ static int find_writeable_block(struct partition *part, u_long *old_sector)
                rc = -EIO;
 
        if (rc) {
-               printk(KERN_NOTICE PREFIX "'%s': unable to read header at "
+               printk(KERN_ERR PREFIX "'%s': unable to read header at "
                                "0x%lx\n", part->mbd.mtd->name,
                                part->blocks[block].offset);
                goto err;
@@ -587,7 +586,7 @@ static int mark_sector_deleted(struct partition *part, u_long old_addr)
        int block, offset, rc;
        u_long addr;
        size_t retlen;
-       u16 del = const_cpu_to_le16(SECTOR_DELETED);
+       u16 del = cpu_to_le16(SECTOR_DELETED);
 
        block = old_addr / part->block_size;
        offset = (old_addr % part->block_size) / SECTOR_SIZE -
@@ -602,7 +601,7 @@ static int mark_sector_deleted(struct partition *part, u_long old_addr)
                rc = -EIO;
 
        if (rc) {
-               printk(KERN_WARNING PREFIX "error writing '%s' at "
+               printk(KERN_ERR PREFIX "error writing '%s' at "
                        "0x%lx\n", part->mbd.mtd->name, addr);
                if (rc)
                        goto err;
@@ -652,7 +651,7 @@ static int do_writesect(struct mtd_blktrans_dev *dev, u_long sector, char *buf,
        if (part->current_block == -1 ||
                !part->blocks[part->current_block].free_sectors) {
 
-               rc = find_writeable_block(part, old_addr);
+               rc = find_writable_block(part, old_addr);
                if (rc)
                        goto err;
        }
@@ -675,7 +674,7 @@ static int do_writesect(struct mtd_blktrans_dev *dev, u_long sector, char *buf,
                rc = -EIO;
 
        if (rc) {
-               printk(KERN_WARNING PREFIX "error writing '%s' at 0x%lx\n",
+               printk(KERN_ERR PREFIX "error writing '%s' at 0x%lx\n",
                                part->mbd.mtd->name, addr);
                if (rc)
                        goto err;
@@ -695,7 +694,7 @@ static int do_writesect(struct mtd_blktrans_dev *dev, u_long sector, char *buf,
                rc = -EIO;
 
        if (rc) {
-               printk(KERN_WARNING PREFIX "error writing '%s' at 0x%lx\n",
+               printk(KERN_ERR PREFIX "error writing '%s' at 0x%lx\n",
                                part->mbd.mtd->name, addr);
                if (rc)
                        goto err;
@@ -763,10 +762,10 @@ static void rfd_ftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
 {
        struct partition *part;
 
-       if (mtd->type != MTD_NORFLASH)
+       if (mtd->type != MTD_NORFLASH || mtd->size > UINT_MAX)
                return;
 
-       part = kcalloc(1, sizeof(struct partition), GFP_KERNEL);
+       part = kzalloc(sizeof(struct partition), GFP_KERNEL);
        if (!part)
                return;
 
@@ -776,23 +775,21 @@ static void rfd_ftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
                part->block_size = block_size;
        else {
                if (!mtd->erasesize) {
-                       printk(KERN_NOTICE PREFIX "please provide block_size");
-                       return;
-               }
-               else
+                       printk(KERN_WARNING PREFIX "please provide block_size");
+                       goto out;
+               } else
                        part->block_size = mtd->erasesize;
        }
 
        if (scan_header(part) == 0) {
                part->mbd.size = part->sector_count;
-               part->mbd.blksize = SECTOR_SIZE;
                part->mbd.tr = tr;
                part->mbd.devnum = -1;
                if (!(mtd->flags & MTD_WRITEABLE))
                        part->mbd.readonly = 1;
                else if (part->errors) {
-                       printk(KERN_NOTICE PREFIX "'%s': errors found, "
-                                       "setting read-only", mtd->name);
+                       printk(KERN_WARNING PREFIX "'%s': errors found, "
+                                       "setting read-only\n", mtd->name);
                        part->mbd.readonly = 1;
                }
 
@@ -802,7 +799,7 @@ static void rfd_ftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
                if (!add_mtd_blktrans_dev((void*)part))
                        return;
        }
-
+out:
        kfree(part);
 }
 
@@ -823,10 +820,12 @@ static void rfd_ftl_remove_dev(struct mtd_blktrans_dev *dev)
        kfree(part);
 }
 
-struct mtd_blktrans_ops rfd_ftl_tr = {
+static struct mtd_blktrans_ops rfd_ftl_tr = {
        .name           = "rfd",
        .major          = RFD_FTL_MAJOR,
        .part_bits      = PART_BITS,
+       .blksize        = SECTOR_SIZE,
+
        .readsect       = rfd_ftl_readsect,
        .writesect      = rfd_ftl_writesect,
        .getgeo         = rfd_ftl_getgeo,