Fedora kernel-2.6.17-1.2142_FC4 patched with stable patch-2.6.17.4-vs2.0.2-rc26.diff
[linux-2.6.git] / drivers / mtd / ftl.c
index 18cc884..8a878b3 100644 (file)
@@ -1,5 +1,5 @@
 /* This version ported to the Linux-MTD system by dwmw2@infradead.org
- * $Id: ftl.c,v 1.54 2004/11/16 18:33:15 dwmw2 Exp $
+ * $Id: ftl.c,v 1.59 2005/11/29 14:48:31 gleixner Exp $
  *
  * Fixes: Arnaldo Carvalho de Melo <acme@conectiva.com.br>
  * - fixes some leaks on failure in build_maps and ftl_notify_add, cleanups
@@ -53,7 +53,7 @@
     Use of the FTL format for non-PCMCIA applications may be an
     infringement of these patents.  For additional information,
     contact M-Systems (http://www.m-sys.com) directly.
-      
+
 ======================================================================*/
 #include <linux/mtd/blktrans.h>
 #include <linux/module.h>
@@ -160,7 +160,7 @@ static void ftl_erase_callback(struct erase_info *done);
     Scan_header() checks to see if a memory region contains an FTL
     partition.  build_maps() reads all the erase unit headers, builds
     the erase unit map, and then builds the virtual page map.
-    
+
 ======================================================================*/
 
 static int scan_header(partition_t *part)
@@ -176,10 +176,10 @@ static int scan_header(partition_t *part)
         (offset + sizeof(header)) < max_offset;
         offset += part->mbd.mtd->erasesize ? : 0x2000) {
 
-       err = part->mbd.mtd->read(part->mbd.mtd, offset, sizeof(header), &ret, 
+       err = part->mbd.mtd->read(part->mbd.mtd, offset, sizeof(header), &ret,
                              (unsigned char *)&header);
-       
-       if (err) 
+
+       if (err)
            return err;
 
        if (strcmp(header.DataOrgTuple+3, "FTL100") == 0) break;
@@ -232,10 +232,10 @@ static int build_maps(partition_t *part)
     for (i = 0; i < le16_to_cpu(part->header.NumEraseUnits); i++) {
        offset = ((i + le16_to_cpu(part->header.FirstPhysicalEUN))
                      << part->header.EraseUnitSize);
-       ret = part->mbd.mtd->read(part->mbd.mtd, offset, sizeof(header), &retval, 
+       ret = part->mbd.mtd->read(part->mbd.mtd, offset, sizeof(header), &retval,
                              (unsigned char *)&header);
-       
-       if (ret) 
+
+       if (ret)
            goto out_XferInfo;
 
        ret = -1;
@@ -274,7 +274,7 @@ static int build_maps(partition_t *part)
               "don't add up!\n");
        goto out_XferInfo;
     }
-    
+
     /* Set up virtual page map */
     blocks = le32_to_cpu(header.FormattedSize) >> header.BlockSize;
     part->VirtualBlockMap = vmalloc(blocks * sizeof(u_int32_t));
@@ -296,12 +296,12 @@ static int build_maps(partition_t *part)
        part->EUNInfo[i].Free = 0;
        part->EUNInfo[i].Deleted = 0;
        offset = part->EUNInfo[i].Offset + le32_to_cpu(header.BAMOffset);
-       
-       ret = part->mbd.mtd->read(part->mbd.mtd, offset,  
-                             part->BlocksPerUnit * sizeof(u_int32_t), &retval, 
+
+       ret = part->mbd.mtd->read(part->mbd.mtd, offset,
+                             part->BlocksPerUnit * sizeof(u_int32_t), &retval,
                              (unsigned char *)part->bam_cache);
-       
-       if (ret) 
+
+       if (ret)
                goto out_bam_cache;
 
        for (j = 0; j < part->BlocksPerUnit; j++) {
@@ -316,7 +316,7 @@ static int build_maps(partition_t *part)
                part->EUNInfo[i].Deleted++;
        }
     }
-    
+
     ret = 0;
     goto out;
 
@@ -336,7 +336,7 @@ out:
 
     Erase_xfer() schedules an asynchronous erase operation for a
     transfer unit.
-    
+
 ======================================================================*/
 
 static int erase_xfer(partition_t *part,
@@ -351,17 +351,18 @@ static int erase_xfer(partition_t *part,
     xfer->state = XFER_ERASING;
 
     /* Is there a free erase slot? Always in MTD. */
-    
-    
+
+
     erase=kmalloc(sizeof(struct erase_info), GFP_KERNEL);
-    if (!erase) 
+    if (!erase)
             return -ENOMEM;
 
+    erase->mtd = part->mbd.mtd;
     erase->callback = ftl_erase_callback;
     erase->addr = xfer->Offset;
     erase->len = 1 << part->header.EraseUnitSize;
     erase->priv = (u_long)part;
-    
+
     ret = part->mbd.mtd->erase(part->mbd.mtd, erase);
 
     if (!ret)
@@ -376,7 +377,7 @@ static int erase_xfer(partition_t *part,
 
     Prepare_xfer() takes a freshly erased transfer unit and gives
     it an appropriate header.
-    
+
 ======================================================================*/
 
 static void ftl_erase_callback(struct erase_info *erase)
@@ -384,7 +385,7 @@ static void ftl_erase_callback(struct erase_info *erase)
     partition_t *part;
     struct xfer_info_t *xfer;
     int i;
-    
+
     /* Look up the transfer unit */
     part = (partition_t *)(erase->priv);
 
@@ -421,7 +422,7 @@ static int prepare_xfer(partition_t *part, int i)
 
     xfer = &part->XferInfo[i];
     xfer->state = XFER_FAILED;
-    
+
     DEBUG(1, "ftl_cs: preparing xfer unit at 0x%x\n", xfer->Offset);
 
     /* Write the transfer unit header */
@@ -445,7 +446,7 @@ static int prepare_xfer(partition_t *part, int i)
 
     for (i = 0; i < nbam; i++, offset += sizeof(u_int32_t)) {
 
-       ret = part->mbd.mtd->write(part->mbd.mtd, offset, sizeof(u_int32_t), 
+       ret = part->mbd.mtd->write(part->mbd.mtd, offset, sizeof(u_int32_t),
                               &retlen, (u_char *)&ctl);
 
        if (ret)
@@ -453,7 +454,7 @@ static int prepare_xfer(partition_t *part, int i)
     }
     xfer->state = XFER_PREPARED;
     return 0;
-    
+
 } /* prepare_xfer */
 
 /*======================================================================
@@ -465,7 +466,7 @@ static int prepare_xfer(partition_t *part, int i)
     All data blocks are copied to the corresponding blocks in the
     target unit, so the virtual block map does not need to be
     updated.
-    
+
 ======================================================================*/
 
 static int copy_erase_unit(partition_t *part, u_int16_t srcunit,
@@ -485,14 +486,14 @@ static int copy_erase_unit(partition_t *part, u_int16_t srcunit,
     xfer = &part->XferInfo[xferunit];
     DEBUG(2, "ftl_cs: copying block 0x%x to 0x%x\n",
          eun->Offset, xfer->Offset);
-       
-    
+
+
     /* Read current BAM */
     if (part->bam_index != srcunit) {
 
        offset = eun->Offset + le32_to_cpu(part->header.BAMOffset);
 
-       ret = part->mbd.mtd->read(part->mbd.mtd, offset, 
+       ret = part->mbd.mtd->read(part->mbd.mtd, offset,
                              part->BlocksPerUnit * sizeof(u_int32_t),
                              &retlen, (u_char *) (part->bam_cache));
 
@@ -500,11 +501,11 @@ static int copy_erase_unit(partition_t *part, u_int16_t srcunit,
        part->bam_index = 0xffff;
 
        if (ret) {
-           printk( KERN_WARNING "ftl: Failed to read BAM cache in copy_erase_unit()!\n");                
+           printk( KERN_WARNING "ftl: Failed to read BAM cache in copy_erase_unit()!\n");
            return ret;
        }
     }
-    
+
     /* Write the LogicalEUN for the transfer unit */
     xfer->state = XFER_UNKNOWN;
     offset = xfer->Offset + 20; /* Bad! */
@@ -512,12 +513,12 @@ static int copy_erase_unit(partition_t *part, u_int16_t srcunit,
 
     ret = part->mbd.mtd->write(part->mbd.mtd, offset, sizeof(u_int16_t),
                           &retlen, (u_char *) &unit);
-    
+
     if (ret) {
        printk( KERN_WARNING "ftl: Failed to write back to BAM cache in copy_erase_unit()!\n");
        return ret;
     }
-    
+
     /* Copy all data blocks from source unit to transfer unit */
     src = eun->Offset; dest = xfer->Offset;
 
@@ -557,15 +558,15 @@ static int copy_erase_unit(partition_t *part, u_int16_t srcunit,
     }
 
     /* Write the BAM to the transfer unit */
-    ret = part->mbd.mtd->write(part->mbd.mtd, xfer->Offset + le32_to_cpu(part->header.BAMOffset), 
-                    part->BlocksPerUnit * sizeof(int32_t), &retlen, 
+    ret = part->mbd.mtd->write(part->mbd.mtd, xfer->Offset + le32_to_cpu(part->header.BAMOffset),
+                    part->BlocksPerUnit * sizeof(int32_t), &retlen,
                    (u_char *)part->bam_cache);
     if (ret) {
        printk( KERN_WARNING "ftl: Error writing BAM in copy_erase_unit\n");
        return ret;
     }
 
-    
+
     /* All clear? Then update the LogicalEUN again */
     ret = part->mbd.mtd->write(part->mbd.mtd, xfer->Offset + 20, sizeof(u_int16_t),
                           &retlen, (u_char *)&srcunitswap);
@@ -573,9 +574,9 @@ static int copy_erase_unit(partition_t *part, u_int16_t srcunit,
     if (ret) {
        printk(KERN_WARNING "ftl: Error writing new LogicalEUN in copy_erase_unit\n");
        return ret;
-    }    
-    
-    
+    }
+
+
     /* Update the maps and usage stats*/
     i = xfer->EraseCount;
     xfer->EraseCount = eun->EraseCount;
@@ -587,10 +588,10 @@ static int copy_erase_unit(partition_t *part, u_int16_t srcunit,
     part->FreeTotal += free;
     eun->Free = free;
     eun->Deleted = 0;
-    
+
     /* Now, the cache should be valid for the new block */
     part->bam_index = srcunit;
-    
+
     return 0;
 } /* copy_erase_unit */
 
@@ -607,7 +608,7 @@ static int copy_erase_unit(partition_t *part, u_int16_t srcunit,
     oldest data unit instead.  This means that we generally postpone
     the next reclaimation as long as possible, but shuffle static
     stuff around a bit for wear leveling.
-    
+
 ======================================================================*/
 
 static int reclaim_block(partition_t *part)
@@ -665,7 +666,7 @@ static int reclaim_block(partition_t *part)
                else
                    DEBUG(1, "ftl_cs: reclaim failed: no "
                          "suitable transfer units!\n");
-                       
+
                return -EIO;
            }
        }
@@ -714,7 +715,7 @@ static int reclaim_block(partition_t *part)
     returns the block index -- the erase unit is just the currently
     cached unit.  If there are no free blocks, it returns 0 -- this
     is never a valid data block because it contains the header.
-    
+
 ======================================================================*/
 
 #ifdef PSYCHO_DEBUG
@@ -736,7 +737,7 @@ static u_int32_t find_free(partition_t *part)
     u_int32_t blk;
     size_t retlen;
     int ret;
-    
+
     /* Find an erase unit with some free space */
     stop = (part->bam_index == 0xffff) ? 0 : part->bam_index;
     eun = stop;
@@ -748,17 +749,17 @@ static u_int32_t find_free(partition_t *part)
 
     if (part->EUNInfo[eun].Free == 0)
        return 0;
-    
+
     /* Is this unit's BAM cached? */
     if (eun != part->bam_index) {
        /* Invalidate cache */
        part->bam_index = 0xffff;
 
-       ret = part->mbd.mtd->read(part->mbd.mtd, 
+       ret = part->mbd.mtd->read(part->mbd.mtd,
                       part->EUNInfo[eun].Offset + le32_to_cpu(part->header.BAMOffset),
                       part->BlocksPerUnit * sizeof(u_int32_t),
                       &retlen, (u_char *) (part->bam_cache));
-       
+
        if (ret) {
            printk(KERN_WARNING"ftl: Error reading BAM in find_free\n");
            return 0;
@@ -780,14 +781,14 @@ static u_int32_t find_free(partition_t *part)
     }
     DEBUG(2, "ftl_cs: found free block at %d in %d\n", blk, eun);
     return blk;
-    
+
 } /* find_free */
 
 
 /*======================================================================
 
     Read a series of sectors from an FTL partition.
-    
+
 ======================================================================*/
 
 static int ftl_read(partition_t *part, caddr_t buffer,
@@ -797,7 +798,7 @@ static int ftl_read(partition_t *part, caddr_t buffer,
     u_long i;
     int ret;
     size_t offset, retlen;
-    
+
     DEBUG(2, "ftl_cs: ftl_read(0x%p, 0x%lx, %ld)\n",
          part, sector, nblocks);
     if (!(part->state & FTL_FORMATTED)) {
@@ -833,7 +834,7 @@ static int ftl_read(partition_t *part, caddr_t buffer,
 /*======================================================================
 
     Write a series of sectors to an FTL partition
-    
+
 ======================================================================*/
 
 static int set_bam_entry(partition_t *part, u_int32_t log_addr,
@@ -854,7 +855,7 @@ static int set_bam_entry(partition_t *part, u_int32_t log_addr,
     blk = (log_addr % bsize) / SECTOR_SIZE;
     offset = (part->EUNInfo[eun].Offset + blk * sizeof(u_int32_t) +
                  le32_to_cpu(part->header.BAMOffset));
-    
+
 #ifdef PSYCHO_DEBUG
     ret = part->mbd.mtd->read(part->mbd.mtd, offset, sizeof(u_int32_t),
                         &retlen, (u_char *)&old_addr);
@@ -924,7 +925,7 @@ static int ftl_write(partition_t *part, caddr_t buffer,
        if (ret)
            return ret;
     }
-    
+
     bsize = 1 << part->header.EraseUnitSize;
 
     virt_addr = sector * SECTOR_SIZE | BLOCK_DATA;
@@ -948,12 +949,12 @@ static int ftl_write(partition_t *part, caddr_t buffer,
        log_addr = part->bam_index * bsize + blk * SECTOR_SIZE;
        part->EUNInfo[part->bam_index].Free--;
        part->FreeTotal--;
-       if (set_bam_entry(part, log_addr, 0xfffffffe)) 
+       if (set_bam_entry(part, log_addr, 0xfffffffe))
            return -EIO;
        part->EUNInfo[part->bam_index].Deleted++;
        offset = (part->EUNInfo[part->bam_index].Offset +
                      blk * SECTOR_SIZE);
-       ret = part->mbd.mtd->write(part->mbd.mtd, offset, SECTOR_SIZE, &retlen, 
+       ret = part->mbd.mtd->write(part->mbd.mtd, offset, SECTOR_SIZE, &retlen,
                                      buffer);
 
        if (ret) {
@@ -963,7 +964,7 @@ static int ftl_write(partition_t *part, caddr_t buffer,
                   offset);
            return -EIO;
        }
-       
+
        /* Only delete the old entry when the new entry is ready */
        old_addr = part->VirtualBlockMap[sector+i];
        if (old_addr != 0xffffffff) {
@@ -978,7 +979,7 @@ static int ftl_write(partition_t *part, caddr_t buffer,
            return -EIO;
        part->VirtualBlockMap[sector+i] = log_addr;
        part->EUNInfo[part->bam_index].Deleted--;
-       
+
        buffer += SECTOR_SIZE;
        virt_addr += SECTOR_SIZE;
     }
@@ -1016,27 +1017,16 @@ static int ftl_writesect(struct mtd_blktrans_dev *dev,
 
 void ftl_freepart(partition_t *part)
 {
-    if (part->VirtualBlockMap) {
        vfree(part->VirtualBlockMap);
        part->VirtualBlockMap = NULL;
-    }
-    if (part->VirtualPageMap) {
        kfree(part->VirtualPageMap);
        part->VirtualPageMap = NULL;
-    }
-    if (part->EUNInfo) {
        kfree(part->EUNInfo);
        part->EUNInfo = NULL;
-    }
-    if (part->XferInfo) {
        kfree(part->XferInfo);
        part->XferInfo = NULL;
-    }
-    if (part->bam_cache) {
        kfree(part->bam_cache);
        part->bam_cache = NULL;
-    }
-    
 } /* ftl_freepart */
 
 static void ftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
@@ -1044,20 +1034,20 @@ static void ftl_add_mtd(struct mtd_blktrans_ops *tr, struct mtd_info *mtd)
        partition_t *partition;
 
        partition = kmalloc(sizeof(partition_t), GFP_KERNEL);
-               
+
        if (!partition) {
                printk(KERN_WARNING "No memory to scan for FTL on %s\n",
                       mtd->name);
                return;
-       }    
+       }
 
        memset(partition, 0, sizeof(partition_t));
 
        partition->mbd.mtd = mtd;
 
-       if ((scan_header(partition) == 0) && 
+       if ((scan_header(partition) == 0) &&
            (build_maps(partition) == 0)) {
-               
+
                partition->state = FTL_FORMATTED;
 #ifdef PCMCIA_DEBUG
                printk(KERN_INFO "ftl_cs: opening %d KiB FTL partition\n",
@@ -1094,9 +1084,9 @@ struct mtd_blktrans_ops ftl_tr = {
        .owner          = THIS_MODULE,
 };
 
-int init_ftl(void)
+static int init_ftl(void)
 {
-       DEBUG(0, "$Id: ftl.c,v 1.54 2004/11/16 18:33:15 dwmw2 Exp $\n");
+       DEBUG(0, "$Id: ftl.c,v 1.59 2005/11/29 14:48:31 gleixner Exp $\n");
 
        return register_mtd_blktrans(&ftl_tr);
 }