public inbox for linux-mtd@lists.infradead.org
 help / color / mirror / Atom feed
* [patch] Allow any filesystem on MTD Nand when Read Only
@ 2004-05-05 12:33 Pantelis Antoniou
  2004-05-05 12:57 ` David Woodhouse
  2004-05-05 15:26 ` David Daney
  0 siblings, 2 replies; 12+ messages in thread
From: Pantelis Antoniou @ 2004-05-05 12:33 UTC (permalink / raw)
  To: linux-mtd, Thomas Gleixner, David Woodhouse, David Daney

[-- Attachment #1: Type: text/plain, Size: 789 bytes --]

Hello there.

The following patch allows you to have any filesystem over NAND when mounted
read only.

The main drive for this was that I wanted to use CRAMFS over NAND flash 
since
it has a much higher compression ratio than JFFS2.

How it works is pretty simple.

It's pretty reasonable assumption that bad blocks are created only when
writting to NAND. So in the read-only case it is possible to skip over 
the bad
blocks and offer a bad-block free block device to the upper layers.
This allows us to utilize any filesystem when  read-only.

In order to speed the mount operation the bad block detection is 
performed lazilly.

Using the patch I was able to mount as read-only CRAMFS/JFFS2 partitions
which contained simulated bad-blocks.

Awaiting your comments...

Regards

Pantelis


[-- Attachment #2: ro-mtdblock.diff --]
[-- Type: text/x-patch, Size: 18936 bytes --]

diff -ruN mtd-original/drivers/mtd/chips/amd_flash.c mtd-work/drivers/mtd/chips/amd_flash.c
--- mtd-original/drivers/mtd/chips/amd_flash.c	2003-06-13 01:00:05.000000000 +0300
+++ mtd-work/drivers/mtd/chips/amd_flash.c	2004-05-05 15:07:29.784400712 +0300
@@ -760,6 +760,9 @@
 	mtd->lock = amd_flash_lock;
 	mtd->unlock = amd_flash_unlock;
 
+	mtd->block_read = mtd->read;
+	mtd->block_write = mtd->write;
+
 	private = kmalloc(sizeof(*private) + (sizeof(struct flchip) *
 					      temp.numchips), GFP_KERNEL);
 	if (!private) {
diff -ruN mtd-original/drivers/mtd/chips/cfi_cmdset_0001.c mtd-work/drivers/mtd/chips/cfi_cmdset_0001.c
--- mtd-original/drivers/mtd/chips/cfi_cmdset_0001.c	2004-03-26 01:00:04.000000000 +0200
+++ mtd-work/drivers/mtd/chips/cfi_cmdset_0001.c	2004-05-05 15:07:29.786400408 +0300
@@ -307,6 +307,10 @@
 	mtd->unlock = cfi_intelext_unlock;
 	mtd->suspend = cfi_intelext_suspend;
 	mtd->resume = cfi_intelext_resume;
+
+	mtd->block_read = mtd->read;
+	mtd->block_write = mtd->write;
+
 	mtd->flags = MTD_CAP_NORFLASH;
 	map->fldrv = &cfi_intelext_chipdrv;
 	mtd->name = map->name;
diff -ruN mtd-original/drivers/mtd/chips/cfi_cmdset_0002.c mtd-work/drivers/mtd/chips/cfi_cmdset_0002.c
--- mtd-original/drivers/mtd/chips/cfi_cmdset_0002.c	2004-04-15 01:00:09.000000000 +0300
+++ mtd-work/drivers/mtd/chips/cfi_cmdset_0002.c	2004-05-05 15:07:29.788400104 +0300
@@ -367,6 +367,10 @@
 	mtd->sync = cfi_amdstd_sync;
 	mtd->suspend = cfi_amdstd_suspend;
 	mtd->resume = cfi_amdstd_resume;
+
+	mtd->block_read = mtd->read;
+	mtd->block_write = mtd->write;
+
 	mtd->flags = MTD_CAP_NORFLASH;
 	map->fldrv = &cfi_amdstd_chipdrv;
 	mtd->name = map->name;
diff -ruN mtd-original/drivers/mtd/chips/cfi_cmdset_0020.c mtd-work/drivers/mtd/chips/cfi_cmdset_0020.c
--- mtd-original/drivers/mtd/chips/cfi_cmdset_0020.c	2003-10-17 01:00:07.000000000 +0300
+++ mtd-work/drivers/mtd/chips/cfi_cmdset_0020.c	2004-05-05 15:07:29.789399952 +0300
@@ -226,6 +226,10 @@
 	mtd->unlock = cfi_staa_unlock;
 	mtd->suspend = cfi_staa_suspend;
 	mtd->resume = cfi_staa_resume;
+
+	mtd->block_read = mtd->read;
+	mtd->block_write = mtd->write;
+
 	mtd->flags = MTD_CAP_NORFLASH;
 	mtd->flags |= MTD_ECC; /* FIXME: Not all STMicro flashes have this */
 	mtd->eccsize = 8; /* FIXME: Should be 0 for STMicro flashes w/out ECC */
diff -ruN mtd-original/drivers/mtd/chips/map_ram.c mtd-work/drivers/mtd/chips/map_ram.c
--- mtd-original/drivers/mtd/chips/map_ram.c	2003-05-29 01:00:10.000000000 +0300
+++ mtd-work/drivers/mtd/chips/map_ram.c	2004-05-05 15:07:29.790399800 +0300
@@ -76,6 +76,9 @@
  	while(mtd->size & (mtd->erasesize - 1))
 		mtd->erasesize >>= 1;
 
+	mtd->block_read = mtd->read;
+	mtd->block_write = mtd->write;
+
 	__module_get(THIS_MODULE);
 	return mtd;
 }
diff -ruN mtd-original/drivers/mtd/chips/map_rom.c mtd-work/drivers/mtd/chips/map_rom.c
--- mtd-original/drivers/mtd/chips/map_rom.c	2003-05-29 01:00:10.000000000 +0300
+++ mtd-work/drivers/mtd/chips/map_rom.c	2004-05-05 15:07:29.790399800 +0300
@@ -46,6 +46,10 @@
 	mtd->read = maprom_read;
 	mtd->write = maprom_write;
 	mtd->sync = maprom_nop;
+
+	mtd->block_read = mtd->read;
+	mtd->block_write = mtd->write;
+
 	mtd->flags = MTD_CAP_ROM;
 	mtd->erasesize = 131072;
  	while(mtd->size & (mtd->erasesize - 1))
diff -ruN mtd-original/drivers/mtd/chips/sharp.c mtd-work/drivers/mtd/chips/sharp.c
--- mtd-original/drivers/mtd/chips/sharp.c	2003-05-29 01:00:10.000000000 +0300
+++ mtd-work/drivers/mtd/chips/sharp.c	2004-05-05 15:07:29.791399648 +0300
@@ -139,6 +139,10 @@
 	mtd->sync = sharp_sync;
 	mtd->suspend = sharp_suspend;
 	mtd->resume = sharp_resume;
+
+	mtd->block_read = mtd->read;
+	mtd->block_write = mtd->write;
+
 	mtd->flags = MTD_CAP_NORFLASH;
 	mtd->name = map->name;
 
diff -ruN mtd-original/drivers/mtd/devices/doc2000.c mtd-work/drivers/mtd/devices/doc2000.c
--- mtd-original/drivers/mtd/devices/doc2000.c	2004-04-08 01:00:04.000000000 +0300
+++ mtd-work/drivers/mtd/devices/doc2000.c	2004-05-05 15:07:29.792399496 +0300
@@ -605,6 +605,9 @@
 	mtd->write_oob = doc_write_oob;
 	mtd->sync = NULL;
 
+	mtd->block_read = mtd->read;
+	mtd->block_write = mtd->write;
+
 	this->totlen = 0;
 	this->numchips = 0;
 
diff -ruN mtd-original/drivers/mtd/devices/doc2001.c mtd-work/drivers/mtd/devices/doc2001.c
--- mtd-original/drivers/mtd/devices/doc2001.c	2004-04-05 01:00:05.000000000 +0300
+++ mtd-work/drivers/mtd/devices/doc2001.c	2004-05-05 15:07:29.793399344 +0300
@@ -380,6 +380,9 @@
 	mtd->write_oob = doc_write_oob;
 	mtd->sync = NULL;
 
+	mtd->block_read = mtd->read;
+	mtd->block_write = mtd->write;
+
 	this->totlen = 0;
 	this->numchips = 0;
 	this->curfloor = -1;
diff -ruN mtd-original/drivers/mtd/devices/doc2001plus.c mtd-work/drivers/mtd/devices/doc2001plus.c
--- mtd-original/drivers/mtd/devices/doc2001plus.c	2004-04-05 01:00:05.000000000 +0300
+++ mtd-work/drivers/mtd/devices/doc2001plus.c	2004-05-05 15:07:29.795399040 +0300
@@ -504,6 +504,9 @@
 	mtd->write_oob = doc_write_oob;
 	mtd->sync = NULL;
 
+	mtd->block_read = mtd->read;
+	mtd->block_write = mtd->write;
+
 	this->totlen = 0;
 	this->numchips = 0;
 	this->curfloor = -1;
diff -ruN mtd-original/drivers/mtd/devices/ms02-nv.c mtd-work/drivers/mtd/devices/ms02-nv.c
--- mtd-original/drivers/mtd/devices/ms02-nv.c	2003-08-20 01:00:35.000000000 +0300
+++ mtd-work/drivers/mtd/devices/ms02-nv.c	2004-05-05 15:07:29.795399040 +0300
@@ -226,6 +226,9 @@
 	mtd->read = ms02nv_read;
 	mtd->write = ms02nv_write;
 
+	mtd->block_read = mtd->read;
+	mtd->block_write = mtd->write;
+
 	ret = -EIO;
 	if (add_mtd_device(mtd)) {
 		printk(KERN_ERR
diff -ruN mtd-original/drivers/mtd/devices/mtdram.c mtd-work/drivers/mtd/devices/mtdram.c
--- mtd-original/drivers/mtd/devices/mtdram.c	2003-05-24 01:00:19.000000000 +0300
+++ mtd-work/drivers/mtd/devices/mtdram.c	2004-05-05 15:07:29.796398888 +0300
@@ -145,6 +145,9 @@
    mtd->read = ram_read;
    mtd->write = ram_write;
 
+   mtd->block_read = mtd->read;
+   mtd->block_write = mtd->write;
+
    if (add_mtd_device(mtd)) {
      return -EIO;
    }
diff -ruN mtd-original/drivers/mtd/mtdblock.c mtd-work/drivers/mtd/mtdblock.c
--- mtd-original/drivers/mtd/mtdblock.c	2003-10-05 01:00:04.000000000 +0300
+++ mtd-work/drivers/mtd/mtdblock.c	2004-05-05 15:07:29.796398888 +0300
@@ -84,7 +84,7 @@
 	 * Next, writhe data to flash.
 	 */
 
-	ret = MTD_WRITE (mtd, pos, len, &retlen, buf);
+	ret = MTD_BLOCK_WRITE (mtd, pos, len, &retlen, buf);
 	if (ret)
 		return ret;
 	if (retlen != len)
@@ -134,7 +134,7 @@
 		mtd->name, pos, len);
 	
 	if (!sect_size)
-		return MTD_WRITE (mtd, pos, len, &retlen, buf);
+		return MTD_BLOCK_WRITE (mtd, pos, len, &retlen, buf);
 
 	while (len > 0) {
 		unsigned long sect_start = (pos/sect_size)*sect_size;
@@ -166,7 +166,7 @@
 			    mtdblk->cache_offset != sect_start) {
 				/* fill the cache with the current sector */
 				mtdblk->cache_state = STATE_EMPTY;
-				ret = MTD_READ(mtd, sect_start, sect_size, &retlen, mtdblk->cache_data);
+				ret = MTD_BLOCK_READ(mtd, sect_start, sect_size, &retlen, mtdblk->cache_data);
 				if (ret)
 					return ret;
 				if (retlen != sect_size)
@@ -203,7 +203,7 @@
 			mtd->name, pos, len);
 	
 	if (!sect_size)
-		return MTD_READ (mtd, pos, len, &retlen, buf);
+		return MTD_BLOCK_READ (mtd, pos, len, &retlen, buf);
 
 	while (len > 0) {
 		unsigned long sect_start = (pos/sect_size)*sect_size;
@@ -222,7 +222,7 @@
 		    mtdblk->cache_offset == sect_start) {
 			memcpy (buf, mtdblk->cache_data + offset, size);
 		} else {
-			ret = MTD_READ (mtd, pos, size, &retlen, buf);
+			ret = MTD_BLOCK_READ (mtd, pos, size, &retlen, buf);
 			if (ret)
 				return ret;
 			if (retlen != size)
diff -ruN mtd-original/drivers/mtd/mtdcore.c mtd-work/drivers/mtd/mtdcore.c
--- mtd-original/drivers/mtd/mtdcore.c	2003-05-24 01:00:14.000000000 +0300
+++ mtd-work/drivers/mtd/mtdcore.c	2004-05-05 15:07:29.797398736 +0300
@@ -286,6 +286,64 @@
 	return ret;
 }
 
+loff_t map_over_bad_blocks(struct mtd_info *mtd, loff_t from)
+{
+	int i, block;
+
+	/* if no bad block checking is possible bail out */
+	if (mtd->block_isbad == NULL)
+		return from;
+
+	/* first time in */
+	if (mtd->block_map == NULL) {
+		mtd->block_top = mtd->size / mtd->erasesize;
+		mtd->block_map = kmalloc(sizeof(*mtd->block_map) * mtd->block_top, GFP_KERNEL);
+		if (mtd->block_map == NULL) {
+			printk (KERN_WARNING "nand_scan(): unable to allocate block map\n");
+			return -ENOMEM;
+		}
+		for (i = 0; i < mtd->block_top; i++)
+			mtd->block_map[i] = -1;
+
+		for (i = 0; i < mtd->block_top; i++)
+			if ((*mtd->block_isbad)(mtd, i * mtd->erasesize) == 0)
+				break;
+
+		if (i >= mtd->block_top) {
+			printk (KERN_WARNING "nand_scan(): all blocks bad!\n");
+			return -EIO;
+		}
+		mtd->block_scantop = 0;
+		mtd->block_map[0] = i;
+
+		DEBUG(0, "mtd: map %d -> %d\n", mtd->block_scantop, mtd->block_map[mtd->block_scantop]);
+	}
+
+	block = ((int)from / mtd->erasesize);
+	if (block >= mtd->block_top)
+		return (loff_t)-1;
+
+	/* scan for bad block up to where we want */
+	while (block >= mtd->block_scantop) {
+		/* find a non bad block */
+		for (i = mtd->block_map[mtd->block_scantop] + 1; i < mtd->block_top; i++)
+			if ((*mtd->block_isbad)(mtd, i * mtd->erasesize) == 0)
+				break;
+
+		/* exchausted ? */
+		if (i >= mtd->block_top) {
+			printk (KERN_WARNING "nand_scan(): no more good blocks!\n");
+			return (loff_t)-1;
+		}
+
+		mtd->block_map[++mtd->block_scantop] = i;
+		DEBUG(0, "mtd: map %d -> %d\n", mtd->block_scantop, mtd->block_map[mtd->block_scantop]);
+	}
+
+	block = mtd->block_map[(int)from / mtd->erasesize];
+	from = (block * mtd->erasesize) | ((int)from & (mtd->erasesize - 1));
+	return from;
+}
 
 EXPORT_SYMBOL(add_mtd_device);
 EXPORT_SYMBOL(del_mtd_device);
@@ -296,6 +354,8 @@
 EXPORT_SYMBOL(default_mtd_writev);
 EXPORT_SYMBOL(default_mtd_readv);
 
+EXPORT_SYMBOL(map_over_bad_blocks);
+
 /*====================================================================*/
 /* Power management code */
 
diff -ruN mtd-original/drivers/mtd/mtdpart.c mtd-work/drivers/mtd/mtdpart.c
--- mtd-original/drivers/mtd/mtdpart.c	2004-03-30 01:00:17.000000000 +0300
+++ mtd-work/drivers/mtd/mtdpart.c	2004-05-05 15:07:29.798398584 +0300
@@ -301,6 +301,56 @@
 	return part->master->block_markbad(part->master, ofs);
 }
 
+/* note that the partition block reads do not call the master block_read function because 
+   they do their own bad block management */
+static int part_block_read (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf)
+{
+	struct mtd_part *part = PART(mtd);
+	struct mtd_info *master = part->master;
+
+	if (from >= mtd->size)
+		len = 0;
+	else if (from + len > mtd->size)
+		len = mtd->size - from;
+
+	if (master->block_read == NULL)	
+		return master->read (master, from + part->offset, len, retlen, buf);
+
+	/* for writeable partitions just read */
+	if ((mtd->flags & MTD_WRITEABLE) == MTD_WRITEABLE)
+		return master->read (master, from + part->offset, len, retlen, buf);
+
+	from = map_over_bad_blocks(mtd, from);
+
+	/* exchausted memory; simulated read of 0xff */
+	if (from == (loff_t)-1) {
+		memset(buf, 0xff, len);
+		*retlen = len;
+		return 0;
+	}
+
+	/* the length must always be less than the erase size */
+	BUG_ON(len > mtd->erasesize);
+
+	return master->read (master, from + part->offset, len, retlen, buf);
+}
+
+static int part_block_write (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char * buf)
+{
+	struct mtd_part *part = PART(mtd);
+	struct mtd_info *master = part->master;
+
+	if (to >= mtd->size)
+		len = 0;
+	else if (to + len > mtd->size)
+		len = mtd->size - to;
+
+	if (master->block_write == NULL)
+		return master->write (master, to + part->offset, len, retlen, buf);
+	else
+		return master->block_write (master, to + part->offset, len, retlen, buf);
+}
+
 /* 
  * This function unregisters and destroy all slave MTD objects which are 
  * attached to the given master MTD object.
@@ -415,6 +465,12 @@
 			slave->mtd.block_isbad = part_block_isbad;
 		if (master->block_markbad)
 			slave->mtd.block_markbad = part_block_markbad;
+
+		if (master->block_read)
+			slave->mtd.block_read = part_block_read;
+		if (master->block_write)
+			slave->mtd.block_write = part_block_write;
+
 		slave->mtd.erase = part_erase;
 		slave->master = master;
 		slave->offset = parts[i].offset;
diff -ruN mtd-original/drivers/mtd/nand/nand.c mtd-work/drivers/mtd/nand/nand.c
--- mtd-original/drivers/mtd/nand/nand.c	2004-05-05 01:00:35.000000000 +0300
+++ mtd-work/drivers/mtd/nand/nand.c	2004-05-05 15:11:21.522171216 +0300
@@ -50,6 +50,8 @@
 #include <linux/mtd/compatmac.h>
 #include <linux/interrupt.h>
 #include <linux/bitops.h>
+#include <linux/slab.h>
+#include <linux/mtd/mtd.h>
 #include <asm/io.h>
 
 /* Define default oob placement schemes for large and small page devices */
@@ -111,6 +113,9 @@
 static int nand_erase (struct mtd_info *mtd, struct erase_info *instr);
 static void nand_sync (struct mtd_info *mtd);
 
+static int nand_block_read (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf);
+static int nand_block_write (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char * buf);
+
 /* Some internal functions */
 static int nand_write_page (struct mtd_info *mtd, struct nand_chip *this, int page, u_char *oob_buf,
 		struct nand_oobinfo *oobsel, int mode);
@@ -1163,7 +1168,7 @@
 	/* Check, if the buffer must be filled with ff again */
 	if (this->oobdirty) {	
 		memset (this->oob_buf, 0xff, 
-			mtd->oobsize * (mtd->erasesize / mtd->oobblock));
+			mtd->oobsize << (this->erase_shift - this->page_shift));
 		this->oobdirty = 0;
 	}	
 	
@@ -1671,7 +1676,7 @@
 	chipnr = (int)((unsigned long)instr->addr / this->chipsize);
 
 	/* Calculate pages in each block */
-	pages_per_block = mtd->erasesize / mtd->oobblock;
+	pages_per_block = 1 << (this->erase_shift - this->page_shift);
 
 	/* Select the NAND device */
 	this->select_chip(mtd, chipnr);
@@ -1941,6 +1946,7 @@
 		
 		/* Calculate the address shift from the page size */	
 		this->page_shift = ffs(mtd->oobblock) - 1;
+		this->erase_shift = ffs(mtd->erasesize) - 1;
 
 		/* Set the bad block position */
 		this->badblockpos = mtd->oobblock > 512 ? 
@@ -1994,7 +2000,7 @@
 	/* Convert chipsize to number of pages per chip -1. */
 	this->pagemask = (this->chipsize >> this->page_shift) - 1;
 	/* Preset the internal oob buffer */
-	memset(this->oob_buf, 0xff, mtd->oobsize * (mtd->erasesize / mtd->oobblock));	
+	memset(this->oob_buf, 0xff, mtd->oobsize << (this->erase_shift - this->page_shift));
 
 	/* If no default placement scheme is given, select an
 	 * appropriate one */
@@ -2068,8 +2074,6 @@
 		BUG();	
 	}	
 	
-	mtd->eccsize = this->eccsize;
-	
 	/* Set the number of read / write steps for one page to ensure ECC generation */
 	switch (this->eccmode) {
 	case NAND_ECC_HW3_512:
@@ -2120,12 +2124,65 @@
 	mtd->resume = NULL;
 	mtd->block_isbad = nand_block_isbad;
 	mtd->block_markbad = nand_block_markbad;
+
+	mtd->block_read = nand_block_read;
+	mtd->block_write = nand_block_write;
+
 	mtd->owner = THIS_MODULE;
 
 	/* Return happy */
 	return 0;
 }
 
+/*************************************************************************************************/
+
+/*
+ * This function simply calls nand_read_ecc with oob buffer and oobsel = NULL
+ * after mapping over any bad blocks when read only.
+ *
+ * @mtd:	MTD device structure
+ * @from:	offset to read from
+ * @len:	number of bytes to read
+ * @retlen:	pointer to variable to store the number of read bytes
+ * @buf:	the databuffer to put data
+*/
+static int nand_block_read (struct mtd_info *mtd, loff_t from, size_t len, size_t * retlen, u_char * buf)
+{
+	/* if partition writable just read with ECC */
+	if ((mtd->flags & MTD_WRITEABLE) == MTD_WRITEABLE)
+		return nand_read_ecc (mtd, from, len, retlen, buf, NULL, NULL);
+
+	from = map_over_bad_blocks(mtd, from);
+
+	/* exchausted memory; simulated read of 0xff */
+	if (from == (loff_t)-1) {
+		memset(buf, 0xff, len);
+		*retlen = len;
+		return 0;
+	}
+
+	/* the length must always be less than the erase size */
+	BUG_ON(len > mtd->erasesize);
+
+	/* do the read by just skipping over any bad blocks as they weren't there */
+	return nand_read_ecc (mtd, from, len, retlen, buf, NULL, NULL);
+}			   
+
+/*
+ * This function simply calls nand_write_ecc with oob buffer and oobsel = NULL
+ *
+ * @mtd:	MTD device structure
+ * @to:		offset to write to
+ * @len:	number of bytes to write
+ * @retlen:	pointer to variable to store the number of written bytes
+ * @buf:	the data to write
+*/
+static int nand_block_write (struct mtd_info *mtd, loff_t to, size_t len, size_t * retlen, const u_char * buf)
+{
+	BUG_ON((mtd->flags & MTD_WRITEABLE) == MTD_WRITEABLE);	/* must be writable to work */
+	return (nand_write_ecc (mtd, to, len, retlen, buf, NULL, NULL));
+}			   
+
 EXPORT_SYMBOL (nand_scan);
 
 MODULE_LICENSE ("GPL");
diff -ruN mtd-original/include/linux/mtd/mtd.h mtd-work/include/linux/mtd/mtd.h
--- mtd-original/include/linux/mtd/mtd.h	2004-04-15 01:00:10.000000000 +0300
+++ mtd-work/include/linux/mtd/mtd.h	2004-05-05 15:06:37.650326296 +0300
@@ -166,6 +166,10 @@
 	u_int32_t ecctype;
 	u_int32_t eccsize;
 	
+	/* block map for RO */
+	int		*block_map;
+	int		 block_top;
+	int		 block_scantop;
 
 	// Kernel-only stuff starts here.
 	char *name;
@@ -240,6 +244,10 @@
 	int (*block_isbad) (struct mtd_info *mtd, loff_t ofs);
 	int (*block_markbad) (struct mtd_info *mtd, loff_t ofs);
 
+	/* block read */
+	int (*block_read) (struct mtd_info *mtd, loff_t from, size_t len, size_t *retlen, u_char *buf);
+	int (*block_write) (struct mtd_info *mtd, loff_t to, size_t len, size_t *retlen, const u_char *buf);
+
 	void *priv;
 
 	struct module *owner;
@@ -273,6 +281,8 @@
 int default_mtd_readv(struct mtd_info *mtd, struct iovec *vecs,
 		      unsigned long count, loff_t from, size_t *retlen);
 
+loff_t map_over_bad_blocks(struct mtd_info *mtd, loff_t from);
+
 #define MTD_ERASE(mtd, args...) (*(mtd->erase))(mtd, args)
 #define MTD_POINT(mtd, a,b,c,d) (*(mtd->point))(mtd, a,b,c, (u_char **)(d))
 #define MTD_UNPOINT(mtd, arg) (*(mtd->unpoint))(mtd, (u_char *)arg)
@@ -286,6 +296,9 @@
 #define MTD_WRITEOOB(mtd, args...) (*(mtd->write_oob))(mtd, args)
 #define MTD_SYNC(mtd) do { if (mtd->sync) (*(mtd->sync))(mtd);  } while (0) 
 
+#define MTD_BLOCK_READ(mtd, args...) (*(mtd->block_read))(mtd, args)
+#define MTD_BLOCK_WRITE(mtd, args...) (*(mtd->block_write))(mtd, args)
+
 /*
  * Debugging macro and defines
  */
diff -ruN mtd-original/include/linux/mtd/nand.h mtd-work/include/linux/mtd/nand.h
--- mtd-original/include/linux/mtd/nand.h	2004-04-17 01:00:05.000000000 +0300
+++ mtd-work/include/linux/mtd/nand.h	2004-05-05 15:06:37.664324168 +0300
@@ -235,6 +235,7 @@
 	wait_queue_head_t wq;
 	nand_state_t 	state;
 	int 		page_shift;
+	int		erase_shift;
 	u_char 		*data_buf;
 	u_char		*oob_buf;
 	int		oobdirty;

[-- Attachment #3: ro-mtdblock.diffstat --]
[-- Type: text/plain, Size: 990 bytes --]

 drivers/mtd/chips/amd_flash.c       |    3 +
 drivers/mtd/chips/cfi_cmdset_0001.c |    4 ++
 drivers/mtd/chips/cfi_cmdset_0002.c |    4 ++
 drivers/mtd/chips/cfi_cmdset_0020.c |    4 ++
 drivers/mtd/chips/map_ram.c         |    3 +
 drivers/mtd/chips/map_rom.c         |    4 ++
 drivers/mtd/chips/sharp.c           |    4 ++
 drivers/mtd/devices/doc2000.c       |    3 +
 drivers/mtd/devices/doc2001.c       |    3 +
 drivers/mtd/devices/doc2001plus.c   |    3 +
 drivers/mtd/devices/ms02-nv.c       |    3 +
 drivers/mtd/devices/mtdram.c        |    3 +
 drivers/mtd/mtdblock.c              |   10 ++---
 drivers/mtd/mtdcore.c               |   60 ++++++++++++++++++++++++++++++++
 drivers/mtd/mtdpart.c               |   56 ++++++++++++++++++++++++++++++
 drivers/mtd/nand/nand.c             |   67 +++++++++++++++++++++++++++++++++---
 include/linux/mtd/mtd.h             |   13 ++++++
 include/linux/mtd/nand.h            |    1 
 18 files changed, 238 insertions(+), 10 deletions(-)

^ permalink raw reply	[flat|nested] 12+ messages in thread
[parent not found: <AEB09EDA2548094C81ED6AA93269F63D01D09322@siebe001.apac.nokia.com>]
[parent not found: <AEB09EDA2548094C81ED6AA93269F63D01D09323@siebe001.apac.nokia.com>]

end of thread, other threads:[~2004-05-06  9:58 UTC | newest]

Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-05-05 12:33 [patch] Allow any filesystem on MTD Nand when Read Only Pantelis Antoniou
2004-05-05 12:57 ` David Woodhouse
2004-05-05 13:03   ` Pantelis Antoniou
2004-05-05 15:26 ` David Daney
2004-05-05 17:44   ` Phillip Lougher
2004-05-05 19:07     ` David Daney
2004-05-06  7:12     ` Pantelis Antoniou
     [not found] <AEB09EDA2548094C81ED6AA93269F63D01D09322@siebe001.apac.nokia.com>
2004-05-06  7:20 ` Pantelis Antoniou
2004-05-06  8:02   ` Thomas Gleixner
     [not found] <AEB09EDA2548094C81ED6AA93269F63D01D09323@siebe001.apac.nokia.com>
2004-05-06  9:39 ` Pantelis Antoniou
2004-05-06  9:48 ` Thomas Gleixner
2004-05-06  9:45   ` Pantelis Antoniou

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox