64-bit MTD

Jon Masters jonathan at jonmasters.org
Tue Dec 6 12:53:22 EST 2005


Hi folks,
                                                                                
I'm doing some work on making a 64-bit version of MTD for Liberte
Software (http://www.libertesoft.co.uk/). I've attached a patch
against Montavista Linux Pro 3.1 (based on kernel 2.4.20). Please
don't consider this a final release but a work in progress.
                                                                                
This is successfully working in house with a suitably modified version
of YAFFS2. I will endeavour to finish cleaning this up and release a
patch for current 2.6 as soon as possible. We will followup with some
more mails about DMA in MTD and performance improvements for YAFFS2.
                                                                                
Jon.

diff -urN kernel-2.4.20_orig/drivers/mtd/chips/cfi_cmdset_0001.c kernel-2.4.20/drivers/mtd/chips/cfi_cmdset_0001.c
--- kernel-2.4.20_orig/drivers/mtd/chips/cfi_cmdset_0001.c	2005-10-13 16:49:46.000000000 +0100
+++ kernel-2.4.20/drivers/mtd/chips/cfi_cmdset_0001.c	2005-11-30 13:17:28.000000000 +0000
@@ -24,6 +24,7 @@
 #include <linux/init.h>
 #include <asm/io.h>
 #include <asm/byteorder.h>
+#include <asm/div64.h>
 
 #include <linux/errno.h>
 #include <linux/slab.h>
@@ -1195,7 +1196,7 @@
 {
 	struct map_info *map = mtd->priv;
 	struct cfi_private *cfi = map->fldrv_priv;
-	unsigned long adr;
+	u_int64_t adr, mvl_tmp_1, mvl_tmp_2;
 	int chipnum, ret = 0;
 	int i, first;
 	struct mtd_erase_region_info *regions = mtd->eraseregions;
@@ -1263,7 +1264,10 @@
 		adr += regions[i].erasesize;
 		len -= regions[i].erasesize;
 
-		if (adr % (1<< cfi->chipshift) == ((regions[i].offset + (regions[i].erasesize * regions[i].numblocks)) %( 1<< cfi->chipshift)))
+		//if (adr % (1<< cfi->chipshift) == ((regions[i].offset + (regions[i].erasesize * regions[i].numblocks)) %( 1<< cfi->chipshift)))
+		mvl_tmp_1 = adr;
+		mvl_tmp_2 = (regions[i].offset + (regions[i].erasesize * regions[i].numblocks));
+		if (do_div(mvl_tmp_1,(1<< cfi->chipshift)) == do_div(mvl_tmp_2,( 1<< cfi->chipshift)))
 			i++;
 
 		if (adr >> cfi->chipshift) {
diff -urN kernel-2.4.20_orig/drivers/mtd/chips/cfi_cmdset_0002.c kernel-2.4.20/drivers/mtd/chips/cfi_cmdset_0002.c
--- kernel-2.4.20_orig/drivers/mtd/chips/cfi_cmdset_0002.c	2005-10-13 16:49:46.000000000 +0100
+++ kernel-2.4.20/drivers/mtd/chips/cfi_cmdset_0002.c	2005-11-30 13:14:14.000000000 +0000
@@ -25,6 +25,7 @@
 #include <linux/init.h>
 #include <asm/io.h>
 #include <asm/byteorder.h>
+#include <asm/div64.h>
 
 #include <linux/errno.h>
 #include <linux/slab.h>
@@ -1326,7 +1327,7 @@
 {
 	struct map_info *map = mtd->priv;
 	struct cfi_private *cfi = map->fldrv_priv;
-	unsigned long adr;
+	u_int64_t adr, mvl_tmp_1, mvl_tmp_2;
 	int chipnum, ret = 0;
 	int i, first;
 	struct mtd_erase_region_info *regions = mtd->eraseregions;
@@ -1394,7 +1395,10 @@
 		adr += regions[i].erasesize;
 		len -= regions[i].erasesize;
 
-		if (adr % (1<< cfi->chipshift) == ((regions[i].offset + (regions[i].erasesize * regions[i].numblocks)) %( 1<< cfi->chipshift)))
+		//if (adr % (1<< cfi->chipshift) == ((regions[i].offset + (regions[i].erasesize * regions[i].numblocks)) %( 1<< cfi->chipshift)))
+		mvl_tmp_1 = adr;
+		mvl_tmp_2 = (regions[i].offset + (regions[i].erasesize * regions[i].numblocks));
+		if (do_div(mvl_tmp_1,(1<< cfi->chipshift)) == do_div(mvl_tmp_2,( 1<< cfi->chipshift)))
 			i++;
 
 		if (adr >> cfi->chipshift) {
diff -urN kernel-2.4.20_orig/drivers/mtd/chips/cfi_cmdset_0020.c kernel-2.4.20/drivers/mtd/chips/cfi_cmdset_0020.c
--- kernel-2.4.20_orig/drivers/mtd/chips/cfi_cmdset_0020.c	2004-07-07 13:56:41.000000000 +0100
+++ kernel-2.4.20/drivers/mtd/chips/cfi_cmdset_0020.c	2005-11-30 13:14:00.000000000 +0000
@@ -24,6 +24,7 @@
 #include <linux/init.h>
 #include <asm/io.h>
 #include <asm/byteorder.h>
+#include <asm/div64.h>
 
 #include <linux/errno.h>
 #include <linux/init.h>
@@ -887,7 +888,7 @@
 int cfi_staa_erase_varsize(struct mtd_info *mtd, struct erase_info *instr)
 {	struct map_info *map = mtd->priv;
 	struct cfi_private *cfi = map->fldrv_priv;
-	unsigned long adr, len;
+	u_int64_t adr, len, mvl_tmp_1, mvl_tmp_2;
 	int chipnum, ret = 0;
 	int i, first;
 	struct mtd_erase_region_info *regions = mtd->eraseregions;
@@ -955,8 +956,11 @@
 
 		adr += regions[i].erasesize;
 		len -= regions[i].erasesize;
-
-		if (adr % (1<< cfi->chipshift) == ((regions[i].offset + (regions[i].erasesize * regions[i].numblocks)) %( 1<< cfi->chipshift)))
+	
+		//if (adr % (1<< cfi->chipshift) == ((regions[i].offset + (regions[i].erasesize * regions[i].numblocks)) %( 1<< cfi->chipshift)))
+		mvl_tmp_1 = adr;
+		mvl_tmp_2 = (regions[i].offset + (regions[i].erasesize * regions[i].numblocks));
+		if (do_div(mvl_tmp_1,(1<< cfi->chipshift)) == do_div(mvl_tmp_2,( 1<< cfi->chipshift)))
 			i++;
 
 		if (adr >> cfi->chipshift) {
diff -urN kernel-2.4.20_orig/drivers/mtd/mtdchar.c kernel-2.4.20/drivers/mtd/mtdchar.c
--- kernel-2.4.20_orig/drivers/mtd/mtdchar.c	2005-10-13 16:49:46.000000000 +0100
+++ kernel-2.4.20/drivers/mtd/mtdchar.c	2005-11-30 15:03:39.000000000 +0000
@@ -296,8 +296,10 @@
 
 	case MEMGETINFO:
 		if (copy_to_user((struct mtd_info *)arg, mtd,
-				 sizeof(struct mtd_info_user)))
+				 sizeof(struct mtd_info_user))) {
+			printk("MVL_DEBUG: can't copy mtd_info in ioctl.\n");
 			return -EFAULT;
+		}
 		break;
 
 	case MEMERASE:
@@ -317,11 +319,14 @@
 			init_waitqueue_head(&waitq);
 
 			memset (erase,0,sizeof(struct erase_info));
-			if (copy_from_user(&erase->addr, (u_long *)arg,
-					   2 * sizeof(u_long))) {
+			if (copy_from_user(&erase->addr, (u_int64_t *)arg,
+					   2 * sizeof(u_int64_t))) {
 				kfree(erase);
 				return -EFAULT;
 			}
+			//printk("MVL_DEBUG: MEMERASE: erase->addr: 0x%08llx, length: 0x%llx.\n",
+			//erase->addr,erase->len);
+
 			erase->mtd = mtd;
 			erase->callback = mtd_erase_callback;
 			erase->priv = (unsigned long)&waitq;
@@ -367,6 +372,8 @@
 		if (buf.length > 0x4096)
 			return -EINVAL;
 
+		//printk("MVL_DEBUG: MEMWRITEOOB: buf.start = 0x%016llx, buf.length = 0x%16llx.\n",buf.start,buf.length);
+
 		if (!mtd->write_oob)
 			ret = -EOPNOTSUPP;
 		else
diff -urN kernel-2.4.20_orig/drivers/mtd/mtdcore.c kernel-2.4.20/drivers/mtd/mtdcore.c
--- kernel-2.4.20_orig/drivers/mtd/mtdcore.c	2005-10-13 16:49:46.000000000 +0100
+++ kernel-2.4.20/drivers/mtd/mtdcore.c	2005-11-30 12:13:27.000000000 +0000
@@ -345,7 +345,7 @@
 	if (!this)
 		return 0;
 
-	return sprintf(buf, "mtd%d: %8.8x %8.8x \"%s\"\n", i, this->size,
+	return sprintf(buf, "mtd%d: %016.8llx %8.8x \"%s\"\n", i, this->size,
 		       this->erasesize, this->name);
 }
 
@@ -362,7 +362,7 @@
 
 	down(&mtd_table_mutex);
 
-	len = sprintf(page, "dev:    size   erasesize  name\n");
+	len = sprintf(page, "dev:    size           erasesize  name\n");
         for (i=0; i< MAX_MTD_DEVICES; i++) {
 
                 l = mtd_proc_info(page + len, i);
diff -urN kernel-2.4.20_orig/drivers/mtd/nand/nand.c kernel-2.4.20/drivers/mtd/nand/nand.c
--- kernel-2.4.20_orig/drivers/mtd/nand/nand.c	2005-11-29 22:34:51.000000000 +0000
+++ kernel-2.4.20/drivers/mtd/nand/nand.c	2005-11-30 13:59:47.000000000 +0000
@@ -1815,7 +1813,8 @@
  */
 static int nand_erase (struct mtd_info *mtd, struct erase_info *instr)
 {
-	int page, len, status, pages_per_block, ret, chipnr;
+	int page, status, pages_per_block, ret, chipnr;
+	u_int64_t len;
 	struct nand_chip *this = mtd->priv;
 	u_int64_t mvl_tmp = 0;
 
diff -urN kernel-2.4.20_orig/include/linux/mtd/mtd.h kernel-2.4.20/include/linux/mtd/mtd.h
--- kernel-2.4.20_orig/include/linux/mtd/mtd.h	2005-11-29 22:27:55.000000000 +0000
+++ kernel-2.4.20/include/linux/mtd/mtd.h	2005-11-30 13:45:41.000000000 +0000
@@ -20,13 +20,13 @@
 #endif /* __KERNEL__ */
 
 struct erase_info_user {
-	u_int32_t start;
-	u_int32_t length;
+	u_int64_t start;
+	u_int64_t length;
 };
 
 struct mtd_oob_buf {
-	u_int32_t start;
-	u_int32_t length;
+	u_int64_t start;
+	u_int64_t length;
 	unsigned char *ptr;
 };
 
@@ -77,7 +77,7 @@
 struct mtd_info_user {
 	u_char type;
 	u_int32_t flags;
-	u_int32_t size;	 // Total size of the MTD
+	u_int64_t size;	 // Total size of the MTD
 	u_int32_t erasesize;
 	u_int32_t oobblock;  // Size of OOB blocks (e.g. 512)
 	u_int32_t oobsize;   // Amount of OOB data per block (e.g. 16)
@@ -86,10 +86,10 @@
 };
 
 struct region_info_user {
-	u_int32_t offset;		/* At which this region starts, 
+	u_int64_t offset;		/* At which this region starts, 
 					 * from the beginning of the MTD */
 	u_int32_t erasesize;		/* For this region */
-	u_int32_t numblocks;		/* Number of blocks in this region */
+	u_int64_t numblocks;		/* Number of blocks in this region */
 	u_int32_t regionindex;
 };
 
@@ -144,9 +144,9 @@
 };
 
 struct mtd_erase_region_info {
-	u_int32_t offset;			/* At which this region starts, from the beginning of the MTD */
+	u_int64_t offset;			/* At which this region starts, from the beginning of the MTD */
 	u_int32_t erasesize;		/* For this region */
-	u_int32_t numblocks;		/* Number of blocks of erasesize in this region */
+	u_int64_t numblocks;		/* Number of blocks of erasesize in this region */
 };
 
 struct mtd_info {




More information about the linux-mtd mailing list