mtd/drivers/mtd rfd_ftl.c,1.3,1.4

sean at infradead.org sean at infradead.org
Sun Jul 31 18:49:17 EDT 2005


Update of /home/cvs/mtd/drivers/mtd
In directory phoenix.infradead.org:/tmp/cvs-serv28980

Modified Files:
	rfd_ftl.c 
Log Message:
Minor optimisation and cleanup


Index: rfd_ftl.c
===================================================================
RCS file: /home/cvs/mtd/drivers/mtd/rfd_ftl.c,v
retrieving revision 1.3
retrieving revision 1.4
diff -u -r1.3 -r1.4
--- rfd_ftl.c	26 Jun 2005 22:46:12 -0000	1.3
+++ rfd_ftl.c	31 Jul 2005 22:49:14 -0000	1.4
@@ -21,6 +21,8 @@
 
 #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");
@@ -52,6 +54,8 @@
 
 #define SECTOR_SIZE		512
 
+#define SECTORS_PER_TRACK	63
+
 struct block {
 	enum {
 		BLOCK_OK,
@@ -79,6 +83,8 @@
 	u16 *header_cache;		/* cached header */
 
 	int is_reclaiming;
+	int cylinders;
+	int errors;
 	u_long *sector_map;
 	struct block *blocks;
 };
@@ -129,6 +135,7 @@
 			printk(KERN_NOTICE PREFIX 
 				"'%s': more than one entry for sector %d\n",
 				part->mbd.mtd->name, entry);
+			part->errors = 1;
 			continue;
 		}
 
@@ -159,15 +166,20 @@
 
 	/* 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;
+			((HEADER_MAP_OFFSET + sectors_per_block) * 
+		 	sizeof(u16) + SECTOR_SIZE - 1) / SECTOR_SIZE;
+
 	part->data_sectors_per_block = sectors_per_block - 
-				part->header_sectors_per_block;
+			part->header_sectors_per_block;
 
 	part->header_size = (HEADER_MAP_OFFSET + 
-				part->data_sectors_per_block) * sizeof(u16);
-	part->sector_count = part->data_sectors_per_block * 
-				(part->total_blocks - 1);
+			part->data_sectors_per_block) * sizeof(u16);
+
+	part->cylinders = (part->data_sectors_per_block *
+			(part->total_blocks - 1) - 1) / SECTORS_PER_TRACK;
+
+	part->sector_count = part->cylinders * SECTORS_PER_TRACK;
+
 	part->current_block = -1;
 	part->reserved_block = -1;
 	part->is_reclaiming = 0;
@@ -191,7 +203,7 @@
 	for (i=0; i<part->sector_count; i++) 
 		part->sector_map[i] = -1;
 
-	for (i=0, blocks_found= 0; i<part->total_blocks; i++) {
+	for (i=0, blocks_found=0; i<part->total_blocks; i++) {
 		rc = part->mbd.mtd->read(part->mbd.mtd, 
 				i * part->block_size, part->header_size,
 				&retlen, (u_char*)part->header_cache);
@@ -207,12 +219,19 @@
 	}
 
 	if (blocks_found == 0) {
-		printk(KERN_NOTICE PREFIX "no RFD magic found in '%s'.\n",
+		printk(KERN_NOTICE PREFIX "no RFD magic found in '%s'\n",
 				part->mbd.mtd->name);
 		rc = -ENOENT;
 		goto err;
 	}
-	
+
+	if (part->reserved_block == -1) {
+		printk(KERN_NOTICE PREFIX "'%s': no empty erase unit found\n", 
+				part->mbd.mtd->name);
+
+		part->errors = 1;
+	}
+
 	return 0;
 
 err:
@@ -225,7 +244,7 @@
 
 static int rfd_ftl_readsect(struct mtd_blktrans_dev *dev, u_long sector, char *buf)
 {
-	struct partition *part= (struct partition*)dev;
+	struct partition *part = (struct partition*)dev;
 	u_long addr;
 	size_t retlen;
 	int rc;
@@ -254,24 +273,20 @@
 static void erase_callback(struct erase_info *erase)
 {
 	struct partition *part;
-	int i;
+	u16 magic;
+	int i, rc;
+	size_t retlen;
 
 	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 "internal error: erase callback "
-				"for unknown offset %x on '%s'\n", 
-				erase->addr, part->mbd.mtd->name);
+		printk(KERN_ERR PREFIX "erase callback for unknown offset %x "
+				"on '%s'\n", erase->addr, part->mbd.mtd->name);
 		return;
 	}
 
-	if (erase->state == MTD_ERASE_DONE) {
-		part->blocks[i].state = BLOCK_ERASED;
-		part->blocks[i].free_sectors = part->data_sectors_per_block;
-		part->blocks[i].used_sectors = 0;
-		part->blocks[i].erases++;
-	} else {
+	if (erase->state != MTD_ERASE_DONE) {
 		printk(KERN_WARNING PREFIX "erase failed at 0x%x on '%s', "
 				"state %d\n", erase->addr, 
 				part->mbd.mtd->name, erase->state);
@@ -279,8 +294,36 @@
 		part->blocks[i].state = BLOCK_FAILED;
 		part->blocks[i].free_sectors = 0;
 		part->blocks[i].used_sectors = 0;
+
+		kfree(erase);
+
+		return;
 	}
 
+	magic = const_cpu_to_le16(RFD_MAGIC);
+
+	part->blocks[i].state = BLOCK_ERASED;
+	part->blocks[i].free_sectors = part->data_sectors_per_block;
+	part->blocks[i].used_sectors = 0;
+	part->blocks[i].erases++;
+
+	rc = part->mbd.mtd->write(part->mbd.mtd, 
+		part->blocks[i].offset, sizeof(magic), &retlen, 
+		(u_char*)&magic);
+	
+	if (!rc && retlen != sizeof(magic))
+		rc = -EIO;
+
+	if (rc) {
+		printk(KERN_NOTICE PREFIX "'%s': unable to write RFD "
+				"header at 0x%lx\n",
+				part->mbd.mtd->name, 
+				part->blocks[i].offset);
+		part->blocks[i].state = BLOCK_FAILED;
+	}
+	else
+		part->blocks[i].state = BLOCK_OK;
+
 	kfree(erase);
 }
 
@@ -404,7 +447,7 @@
 	return rc;
 }
 
-static int reclaim_block (struct partition *part, u_long *old_sector) 
+static int reclaim_block(struct partition *part, u_long *old_sector) 
 {
 	int block, best_block, score, old_sector_block;
 	int rc;
@@ -472,7 +515,12 @@
 	return rc;
 }
 
-static int find_free_block (struct partition *part)
+/*
+ * IMPROVE: It would be best to choose the block with the most deleted sectors,
+ * 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)
 {
 	int block, stop;
 
@@ -493,7 +541,7 @@
 	return -1;
 }
 
-static int find_writeable_block (struct partition *part, u_long *old_sector)
+static int find_writeable_block(struct partition *part, u_long *old_sector)
 {
 	int rc, block;
 	size_t retlen;
@@ -515,29 +563,8 @@
 		}
 	}
 
-	if (part->blocks[block].state == BLOCK_ERASED) {
-		u16 magic = cpu_to_le16(RFD_MAGIC);
-
-		rc = part->mbd.mtd->write(part->mbd.mtd, 
-			part->blocks[block].offset, sizeof(magic), &retlen, 
-			(u_char*)&magic);
-		
-		if (!rc && retlen != sizeof(magic))
-			rc = -EIO;
-
-		if (rc) {
-			printk(KERN_NOTICE PREFIX "'%s': unable to write RFD "
-					"header at 0x%lx\n",
-					part->mbd.mtd->name, 
-					part->blocks[block].offset);
-			goto err;
-		}
-		part->blocks[block].state = BLOCK_OK;
-	}
-
-	rc = part->mbd.mtd->read(part->mbd.mtd, 
-		part->blocks[block].offset, part->header_size,
-				&retlen, (u_char*)part->header_cache);
+	rc = part->mbd.mtd->read(part->mbd.mtd, part->blocks[block].offset, 
+		part->header_size, &retlen, (u_char*)part->header_cache);
 
 	if (!rc && retlen != part->header_size)
 		rc = -EIO;
@@ -555,12 +582,12 @@
 	return rc;
 }	
 
-static int mark_sector_removed(struct partition *part, u_long old_addr)
+static int mark_sector_deleted(struct partition *part, u_long old_addr)
 {
 	int block, offset, rc;
 	u_long addr;
 	size_t retlen;
-	u16 del = cpu_to_le16(SECTOR_DELETED);
+	u16 del = const_cpu_to_le16(SECTOR_DELETED);
 
 	block = old_addr / part->block_size;
 	offset = (old_addr % part->block_size) / SECTOR_SIZE - 
@@ -593,9 +620,29 @@
 	return rc;
 }
 
+static int find_free_sector(const struct partition *part, const struct block *block)
+{
+	int i, stop;
+
+	i = stop = part->data_sectors_per_block - block->free_sectors;
+
+	do {
+		if (le16_to_cpu(part->header_cache[HEADER_MAP_OFFSET + i]) 
+				== SECTOR_FREE)
+			return i;
+
+		if (++i == part->data_sectors_per_block)
+			i = 0;
+	}
+	while(i != stop);
+
+	return -1;
+}
+
 static int do_writesect(struct mtd_blktrans_dev *dev, u_long sector, char *buf, ulong *old_addr)
 {
-	struct partition *part= (struct partition*)dev;
+	struct partition *part = (struct partition*)dev;
+	struct block *block;
 	u_long addr;
 	int i;
 	int rc;
@@ -610,15 +657,17 @@
 			goto err;
 	}
 
-	for (i=0; i<part->data_sectors_per_block; i++) {
-		if (le16_to_cpu(part->header_cache[HEADER_MAP_OFFSET + i]) 
-				== SECTOR_FREE)
-			break;
-	}
-	BUG_ON(part->data_sectors_per_block == i);
+	block = &part->blocks[part->current_block];
+
+	i = find_free_sector(part, block);
 
+	if (i < 0) {
+		rc = -ENOSPC;
+		goto err;
+	}
+		
 	addr = (i + part->header_sectors_per_block) * SECTOR_SIZE + 
-		part->blocks[part->current_block].offset;
+		block->offset;
 	rc = part->mbd.mtd->write(part->mbd.mtd, 
 		addr, SECTOR_SIZE, &retlen, (u_char*)buf);
 
@@ -638,8 +687,7 @@
 
 	part->header_cache[i + HEADER_MAP_OFFSET] = entry;
 
-	addr = part->blocks[part->current_block].offset +
-			(HEADER_MAP_OFFSET + i) * sizeof(u16);
+	addr = block->offset + (HEADER_MAP_OFFSET + i) * sizeof(u16);
 	rc = part->mbd.mtd->write(part->mbd.mtd, addr,
 			sizeof(entry), &retlen, (u_char*)&entry);
 
@@ -652,8 +700,8 @@
 		if (rc) 
 			goto err;
 	}
-	part->blocks[part->current_block].used_sectors++;
-	part->blocks[part->current_block].free_sectors--;
+	block->used_sectors++;
+	block->free_sectors--;
 
 err:
 	return rc;
@@ -661,7 +709,7 @@
 
 static int rfd_ftl_writesect(struct mtd_blktrans_dev *dev, u_long sector, char *buf)
 {
-	struct partition *part= (struct partition*)dev;
+	struct partition *part = (struct partition*)dev;
 	u_long old_addr;
 	int i;
 	int rc = 0;
@@ -694,7 +742,7 @@
 		part->sector_map[sector] = -1;
 
 	if (old_addr != -1)
-		rc = mark_sector_removed(part, old_addr);
+		rc = mark_sector_deleted(part, old_addr);
 
 err:
 	return rc;
@@ -705,8 +753,8 @@
 	struct partition *part = (struct partition*)dev;
 
 	geo->heads = 1;
-	geo->sectors = part->data_sectors_per_block;
-	geo->cylinders = part->total_blocks - 1;
+	geo->sectors = SECTORS_PER_TRACK;
+	geo->cylinders = part->cylinders;
 
 	return 0;
 }
@@ -715,7 +763,7 @@
 {
 	struct partition *part;
 
-	if(mtd->type != MTD_NORFLASH)
+	if (mtd->type != MTD_NORFLASH)
 		return;
 
 	part = kcalloc(1, sizeof(struct partition), GFP_KERNEL);
@@ -742,11 +790,9 @@
 		part->mbd.devnum = -1;
 		if (!(mtd->flags & MTD_WRITEABLE))
 			part->mbd.readonly = 1;
-		else if (part->reserved_block == -1) {
-			printk(KERN_NOTICE PREFIX "'%s': no empty erase unit "
-				"found, setting read-only\n",
-				part->mbd.mtd->name);
-	
+		else if (part->errors) {
+			printk(KERN_NOTICE PREFIX "'%s': errors found, "
+					"setting read-only", mtd->name);
 			part->mbd.readonly = 1;
 		}
 





More information about the linux-mtd-cvs mailing list