drivers/mtd/rfd_ftl.c: implement discard
Subsystems (2)
PATCH 1/1 drivers/mtd/rfd_ftl.c: implement discard
Now that discard is supported implement it in RFD FTL. Also stop writing to flash once an error has been detected and various other cleanups.
Signed-off-by Sean Young <[email protected]>
--
drivers/mtd/rfd_ftl.c +46 -16
@@ -1,7 +1,7 @@/* * rfd_ftl.c -- resident flash disk (flash translation layer) * -* Copyright (C) 2005 Sean Young <[email protected]> +* Copyright (C) 2005, 2008 Sean Young <[email protected]> * * 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:
@@ -241,7 +241,7 @@ err:static int rfd_ftl_readsect (struct mtd_blktrans_dev *dev,u_long sector,char *buf) { -struct partition *part = (struct partition *)dev; + struct partition *part = container_of(dev, struct partition, mbd);u_long addr;size_t retlen;int rc;
@@ -293,6 +293,7 @@ static void erase_callback(struct erase_info *erase) part->blocks[i].used_sectors =0 ;kfree (erase); + part->errors++;return ; }
@@ -317,6 +318,7 @@ static void erase_callback(struct erase_info *erase) part->mbd.mtd->name, part->blocks[i].offset); part->blocks[i].state =BLOCK_FAILED ; + part->errors++; }else part->blocks[i].state =BLOCK_OK ;
@@ -349,6 +351,7 @@ static int erase_block(struct partition *part, int block)"failed\n" , erase->addr, erase->len, part->mbd.mtd->name);kfree (erase); + part->errors++; } err:
@@ -383,7 +386,7 @@ static int move_block_contents(struct partition *part, int block_no, u_long *old printk(KERN_ERR PREFIX "error reading '%s' at ""0x%lx\n" , part->mbd.mtd->name, part->blocks[block_no].offset); - + part->errors++; goto err; }
@@ -423,7 +426,7 @@ static int move_block_contents(struct partition *part, int block_no, u_long *old printk(KERN_ERR PREFIX "'%s': Unable to ""read sector for relocation\n" , part->mbd.mtd->name); - + part->errors++; goto err; }
@@ -604,9 +607,10 @@ static int mark_sector_deleted(struct partition *part, u_long old_addr)if (rc) { printk(KERN_ERR PREFIX "error writing '%s' at " "0x%lx\n", part->mbd.mtd->name, addr); -if (rc) - goto err; + part->errors++; + goto err; } +if (block = part->current_block) part->header_cache[offset +HEADER_MAP_OFFSET ] = del;
@@ -639,9 +643,10 @@ static int find_free_sector(const struct partition *part, const struct block *blreturn -1 ; } -static int do_writesect (struct mtd_blktrans_dev *dev,u_long sector,char *buf,ulong *old_addr) +static int do_writesect (struct mtd_blktrans_dev *dev,u_long sector,char *buf, +u_long *old_addr) { -struct partition *part = (struct partition *)dev; + struct partition *part = container_of(dev, struct partition, mbd);struct block *block;u_long addr;int i;
@@ -677,8 +682,8 @@ static int do_writesect(struct mtd_blktrans_dev *dev, u_long sector, char *buf,if (rc) { printk(KERN_ERR PREFIX "error writing '%s' at 0x%lx\n", part->mbd.mtd->name, addr); -if (rc) - goto err; + part->errors++; + goto err; } part->sector_map[sector] = addr;
@@ -697,8 +702,8 @@ static int do_writesect(struct mtd_blktrans_dev *dev, u_long sector, char *buf,if (rc) { printk(KERN_ERR PREFIX "error writing '%s' at 0x%lx\n", part->mbd.mtd->name, addr); -if (rc) - goto err; + part->errors++; + goto err; } block->used_sectors++; block->free_sectors--;
@@ -709,14 +714,14 @@ err:static int rfd_ftl_writesect (struct mtd_blktrans_dev *dev,u_long sector,char *buf) { -struct partition *part = (struct partition *)dev; + struct partition *part = container_of(dev, struct partition, mbd);u_long old_addr;int i;int rc =0 ;pr_debug ("rfd_ftl_writesect(sector=0x%lx)\n" , sector); -if (part->reserved_block =-1 ) { +if (part->reserved_block =-1 || part->errors) { rc = -EACCES ; goto err; }
@@ -750,7 +755,7 @@ err:static int rfd_ftl_getgeo (struct mtd_blktrans_dev *dev,struct hd_geometry *geo) { -struct partition *part = (struct partition *)dev; + struct partition *part = container_of(dev, struct partition, mbd); geo->heads =1 ; geo->sectors =SECTORS_PER_TRACK ;
@@ -759,6 +764,30 @@ static int rfd_ftl_getgeo(struct mtd_blktrans_dev *dev, struct hd_geometry *geo)return 0 ; } +static int rfd_ftl_discardsect (struct mtd_blktrans_dev *dev,u_long sector, +uint nr_sects) +{ + struct partition *part = container_of(dev, struct partition, mbd); +u_long addr; +int rc; + +if (part->errors) +return -EACCES ; + +for (rc =0 ; nr_sects && rc =0 ; sector++, nr_sects--) { +if (sector >= part->sector_count) +return -EIO ; + + addr = part->sector_map[sector]; + part->sector_map[sector] =-1 ; + +if (addr !=-1 ) + rc =mark_sector_deleted (part, addr); + } + +return rc; +} +static void rfd_ftl_add_mtd (struct mtd_blktrans_ops *tr,struct mtd_info *mtd) {struct partition *part;
@@ -806,7 +835,7 @@ out:static void rfd_ftl_remove_dev (struct mtd_blktrans_dev *dev) { -struct partition *part = (struct partition *)dev; + struct partition *part = container_of(dev, struct partition, mbd);int i;for (i=0 ; i<part->total_blocks; i++) {
@@ -829,6 +858,7 @@ static struct mtd_blktrans_ops rfd_ftl_tr = { .readsect = rfd_ftl_readsect, .writesect = rfd_ftl_writesect, + .discard = rfd_ftl_discardsect, .getgeo = rfd_ftl_getgeo, .add_mtd = rfd_ftl_add_mtd, .remove_dev = rfd_ftl_remove_dev,