[PATCH] NAND and mtdconcat

Christian Gan cgan at iders.ca
Wed Mar 5 14:21:02 EST 2003


This is a multi-part message in MIME format.

------=_NextPart_000_0132_01C2E31A.116CC0F0
Content-Type: text/plain;
	charset="iso-8859-1"
Content-Transfer-Encoding: 7bit

Hello all,

Attached is a patch for mtdconcat.c that supports NAND functions for the
oob.  I've tested it on my own bench and it seems to work great on two 64MB
NANDs concatenated into one MTD.

Robert, since you were the original author of this file, can you verify it
for me?

Thanks!

------=_NextPart_000_0132_01C2E31A.116CC0F0
Content-Type: application/octet-stream;
	name="mtdconcat.diff"
Content-Transfer-Encoding: quoted-printable
Content-Disposition: attachment;
	filename="mtdconcat.diff"

Index: mtdconcat.c=0A=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=0A=
RCS file: /home/cvs/mtd/drivers/mtd/mtdconcat.c,v=0A=
retrieving revision 1.3=0A=
diff -u -r1.3 mtdconcat.c=0A=
--- mtdconcat.c	21 May 2002 21:04:25 -0000	1.3=0A=
+++ mtdconcat.c	5 Mar 2003 19:13:45 -0000=0A=
@@ -52,6 +52,8 @@=0A=
 			size_t *retlen, u_char *buf)=0A=
 {=0A=
 	struct mtd_concat *concat =3D CONCAT(mtd);=0A=
+    struct mtd_info *subdev =3D NULL;=0A=
+	size_t size, retsize;=0A=
 	int err =3D -EINVAL;=0A=
 	int i;=0A=
 =0A=
@@ -59,20 +61,21 @@=0A=
 =0A=
 	for(i =3D 0; i < concat->num_subdev; i++)=0A=
 	{=0A=
-		struct mtd_info *subdev =3D concat->subdev[i];=0A=
-		size_t size, retsize;=0A=
+		subdev =3D concat->subdev[i];=0A=
+		size =3D 0;=0A=
+        retsize =3D 0;=0A=
 =0A=
 		if (from >=3D subdev->size)=0A=
-		{=0A=
+		{   /* Not destined for this subdev */=0A=
 			size  =3D 0;=0A=
 			from -=3D subdev->size;=0A=
 		}=0A=
 		else=0A=
 		{=0A=
 			if (from + len > subdev->size)=0A=
-				size =3D subdev->size - from;=0A=
+				size =3D subdev->size - from; /* First part goes into this subdev */=0A=
 			else=0A=
-				size =3D len;=0A=
+				size =3D len; /* Entire transaction goes into this subdev */=0A=
 =0A=
 			err =3D subdev->read(subdev, from, size, &retsize, buf);=0A=
 =0A=
@@ -96,6 +99,8 @@=0A=
 			size_t *retlen, const u_char *buf)=0A=
 {=0A=
 	struct mtd_concat *concat =3D CONCAT(mtd);=0A=
+	struct mtd_info *subdev =3D NULL;=0A=
+	size_t size, retsize;=0A=
 	int err =3D -EINVAL;=0A=
 	int i;=0A=
 =0A=
@@ -106,8 +111,9 @@=0A=
 =0A=
 	for(i =3D 0; i < concat->num_subdev; i++)=0A=
 	{=0A=
-		struct mtd_info *subdev =3D concat->subdev[i];=0A=
-		size_t size, retsize;=0A=
+		subdev =3D concat->subdev[i];=0A=
+		size =3D 0;=0A=
+        retsize =3D 0;=0A=
 =0A=
 		if (to >=3D subdev->size)=0A=
 		{=0A=
@@ -142,6 +148,226 @@=0A=
 	return err;=0A=
 }=0A=
 =0A=
+static int concat_read_ecc (struct mtd_info *mtd, loff_t from, size_t =
len,=0A=
+            size_t *retlen, u_char *buf, u_char *eccbuf, int oobsel)=0A=
+{=0A=
+	struct mtd_concat *concat =3D CONCAT(mtd);=0A=
+	struct mtd_info *subdev =3D NULL;=0A=
+	size_t size, retsize;=0A=
+	int err =3D -EINVAL;=0A=
+	int i;=0A=
+=0A=
+	*retlen =3D 0;=0A=
+=0A=
+	for(i =3D 0; i < concat->num_subdev; i++)=0A=
+	{=0A=
+		subdev =3D concat->subdev[i];=0A=
+		size =3D 0;=0A=
+        retsize =3D 0;=0A=
+=0A=
+		if (from >=3D subdev->size)=0A=
+		{   /* Not destined for this subdev */=0A=
+			size  =3D 0;=0A=
+			from -=3D subdev->size;=0A=
+		}=0A=
+		else=0A=
+		{=0A=
+			if (from + len > subdev->size)=0A=
+				size =3D subdev->size - from; /* First part goes into this subdev */=0A=
+			else=0A=
+				size =3D len; /* Entire transaction goes into this subdev */=0A=
+            =0A=
+            if (subdev->read_ecc)=0A=
+    			err =3D subdev->read_ecc(subdev, from, size, &retsize, buf, =
eccbuf, oobsel);=0A=
+            else=0A=
+                err =3D -EINVAL;=0A=
+=0A=
+			if(err)=0A=
+				break;=0A=
+=0A=
+			*retlen +=3D retsize;=0A=
+			len -=3D size;=0A=
+			if(len =3D=3D 0)=0A=
+				break;=0A=
+=0A=
+			err =3D -EINVAL;=0A=
+			buf +=3D size;=0A=
+            if (eccbuf)=0A=
+            {=0A=
+                eccbuf +=3D subdev->oobsize;=0A=
+                /* in nand.c at least, eccbufs are tagged with 2 =
(int)eccstatus',=0A=
+                   we must account for these */=0A=
+                eccbuf +=3D 2 * (sizeof(int)); =0A=
+            }=0A=
+			from =3D 0;=0A=
+		}=0A=
+	}=0A=
+	return err;=0A=
+}=0A=
+=0A=
+static int concat_write_ecc (struct mtd_info *mtd, loff_t to, size_t =
len,=0A=
+            size_t *retlen, const u_char *buf, u_char *eccbuf, int =
oobsel)=0A=
+{=0A=
+	struct mtd_concat *concat =3D CONCAT(mtd);=0A=
+	struct mtd_info *subdev =3D NULL;=0A=
+	size_t size, retsize;=0A=
+	int err =3D -EINVAL;=0A=
+	int i;=0A=
+=0A=
+	if (!(mtd->flags & MTD_WRITEABLE))=0A=
+		return -EROFS;=0A=
+=0A=
+	*retlen =3D 0;=0A=
+=0A=
+	for(i =3D 0; i < concat->num_subdev; i++)=0A=
+	{=0A=
+		subdev =3D concat->subdev[i];=0A=
+		size =3D 0;=0A=
+        retsize =3D 0;=0A=
+=0A=
+		if (to >=3D subdev->size)=0A=
+		{=0A=
+			size  =3D 0;=0A=
+			to -=3D subdev->size;=0A=
+		}=0A=
+		else=0A=
+		{=0A=
+			if (to + len > subdev->size)=0A=
+				size =3D subdev->size - to;=0A=
+			else=0A=
+				size =3D len;=0A=
+=0A=
+			if (!(subdev->flags & MTD_WRITEABLE))=0A=
+				err =3D -EROFS;=0A=
+			else if (subdev->write_ecc)=0A=
+				err =3D subdev->write_ecc(subdev, to, size, &retsize, buf, eccbuf, =
oobsel);=0A=
+            else=0A=
+                err =3D -EINVAL;=0A=
+=0A=
+			if(err)=0A=
+				break;=0A=
+=0A=
+			*retlen +=3D retsize;=0A=
+			len -=3D size;=0A=
+			if(len =3D=3D 0)=0A=
+				break;=0A=
+=0A=
+			err =3D -EINVAL;=0A=
+			buf +=3D size;=0A=
+            if (eccbuf)=0A=
+                eccbuf +=3D subdev->oobsize;=0A=
+			to =3D 0;=0A=
+		}=0A=
+	}=0A=
+	return err;=0A=
+}=0A=
+=0A=
+static int concat_read_oob (struct mtd_info *mtd, loff_t from, size_t =
len,=0A=
+            size_t *retlen, u_char *buf)=0A=
+{=0A=
+	struct mtd_concat *concat =3D CONCAT(mtd);=0A=
+	struct mtd_info *subdev =3D NULL;=0A=
+	size_t size, retsize;=0A=
+	int err =3D -EINVAL;=0A=
+	int i;=0A=
+=0A=
+	*retlen =3D 0;=0A=
+=0A=
+	for(i =3D 0; i < concat->num_subdev; i++)=0A=
+	{=0A=
+		subdev =3D concat->subdev[i];=0A=
+		size =3D 0;=0A=
+        retsize =3D 0;=0A=
+=0A=
+		if (from >=3D subdev->size)=0A=
+		{   /* Not destined for this subdev */=0A=
+			size  =3D 0;=0A=
+			from -=3D subdev->size;=0A=
+		}=0A=
+		else=0A=
+		{=0A=
+			if (from + len > subdev->size)=0A=
+				size =3D subdev->size - from; /* First part goes into this subdev */=0A=
+			else=0A=
+				size =3D len; /* Entire transaction goes into this subdev */=0A=
+            =0A=
+            if (subdev->read_oob)=0A=
+    			err =3D subdev->read_oob(subdev, from, size, &retsize, buf);=0A=
+            else=0A=
+                err =3D -EINVAL;=0A=
+=0A=
+			if(err)=0A=
+				break;=0A=
+=0A=
+			*retlen +=3D retsize;=0A=
+			len -=3D size;=0A=
+			if(len =3D=3D 0)=0A=
+				break;=0A=
+=0A=
+			err =3D -EINVAL;=0A=
+			buf +=3D size;=0A=
+			from =3D 0;=0A=
+		}=0A=
+	}=0A=
+	return err;=0A=
+}=0A=
+=0A=
+static int concat_write_oob (struct mtd_info *mtd, loff_t to, size_t =
len, =0A=
+            size_t *retlen, const u_char *buf)=0A=
+{=0A=
+	struct mtd_concat *concat =3D CONCAT(mtd);=0A=
+	struct mtd_info *subdev =3D NULL;=0A=
+	size_t size, retsize;=0A=
+	int err =3D -EINVAL;=0A=
+	int i;=0A=
+=0A=
+	if (!(mtd->flags & MTD_WRITEABLE))=0A=
+		return -EROFS;=0A=
+=0A=
+	*retlen =3D 0;=0A=
+=0A=
+	for(i =3D 0; i < concat->num_subdev; i++)=0A=
+	{=0A=
+		subdev =3D concat->subdev[i];=0A=
+		size =3D 0;=0A=
+        retsize =3D 0;=0A=
+=0A=
+		if (to >=3D subdev->size)=0A=
+		{=0A=
+			size  =3D 0;=0A=
+			to -=3D subdev->size;=0A=
+		}=0A=
+		else=0A=
+		{=0A=
+			if (to + len > subdev->size)=0A=
+				size =3D subdev->size - to;=0A=
+			else=0A=
+				size =3D len;=0A=
+=0A=
+			if (!(subdev->flags & MTD_WRITEABLE))=0A=
+				err =3D -EROFS;=0A=
+			else if (subdev->write_oob)=0A=
+				err =3D subdev->write_oob(subdev, to, size, &retsize, buf);=0A=
+            else=0A=
+                err =3D -EINVAL;=0A=
+=0A=
+			if(err)=0A=
+				break;=0A=
+=0A=
+			*retlen +=3D retsize;=0A=
+			len -=3D size;=0A=
+			if(len =3D=3D 0)=0A=
+				break;=0A=
+=0A=
+			err =3D -EINVAL;=0A=
+			buf +=3D size;=0A=
+			to =3D 0;=0A=
+		}=0A=
+	}=0A=
+	return err;=0A=
+}=0A=
+=0A=
+=0A=
 static void concat_erase_callback (struct erase_info *instr)=0A=
 {=0A=
 	wake_up((wait_queue_head_t *)instr->priv);=0A=
@@ -316,6 +542,8 @@=0A=
 static int concat_lock (struct mtd_info *mtd, loff_t ofs, size_t len)=0A=
 {=0A=
 	struct mtd_concat *concat =3D CONCAT(mtd);=0A=
+	struct mtd_info *subdev =3D NULL;=0A=
+	size_t size;=0A=
 	int i, err =3D -EINVAL;=0A=
 =0A=
 	if ((len + ofs) > mtd->size) =0A=
@@ -323,8 +551,8 @@=0A=
 =0A=
 	for(i =3D 0; i < concat->num_subdev; i++)=0A=
 	{=0A=
-		struct mtd_info *subdev =3D concat->subdev[i];=0A=
-		size_t size;=0A=
+		subdev =3D concat->subdev[i];=0A=
+		size =3D 0;=0A=
 =0A=
 		if (ofs >=3D subdev->size)=0A=
 		{=0A=
@@ -357,6 +585,8 @@=0A=
 static int concat_unlock (struct mtd_info *mtd, loff_t ofs, size_t len)=0A=
 {=0A=
 	struct mtd_concat *concat =3D CONCAT(mtd);=0A=
+	struct mtd_info *subdev =3D NULL;=0A=
+	size_t size;=0A=
 	int i, err =3D 0;=0A=
 =0A=
 	if ((len + ofs) > mtd->size) =0A=
@@ -364,8 +594,8 @@=0A=
 =0A=
 	for(i =3D 0; i < concat->num_subdev; i++)=0A=
 	{=0A=
-		struct mtd_info *subdev =3D concat->subdev[i];=0A=
-		size_t size;=0A=
+		subdev =3D concat->subdev[i];=0A=
+		size =3D 0;=0A=
 =0A=
 		if (ofs >=3D subdev->size)=0A=
 		{=0A=
@@ -398,11 +628,12 @@=0A=
 static void concat_sync(struct mtd_info *mtd)=0A=
 {=0A=
 	struct mtd_concat *concat =3D CONCAT(mtd);=0A=
+	struct mtd_info *subdev =3D NULL;    =0A=
 	int i;=0A=
 =0A=
 	for(i =3D 0; i < concat->num_subdev; i++)=0A=
 	{=0A=
-		struct mtd_info *subdev =3D concat->subdev[i];=0A=
+		subdev =3D concat->subdev[i];=0A=
 		subdev->sync(subdev);=0A=
 	}=0A=
 }=0A=
@@ -410,11 +641,12 @@=0A=
 static int concat_suspend(struct mtd_info *mtd)=0A=
 {=0A=
 	struct mtd_concat *concat =3D CONCAT(mtd);=0A=
+	struct mtd_info *subdev =3D NULL;    =0A=
 	int i, rc =3D 0;=0A=
 =0A=
 	for(i =3D 0; i < concat->num_subdev; i++)=0A=
 	{=0A=
-		struct mtd_info *subdev =3D concat->subdev[i];=0A=
+        subdev =3D concat->subdev[i];=0A=
 		if((rc =3D subdev->suspend(subdev)) < 0)=0A=
 			return rc;=0A=
 	}=0A=
@@ -424,11 +656,12 @@=0A=
 static void concat_resume(struct mtd_info *mtd)=0A=
 {=0A=
 	struct mtd_concat *concat =3D CONCAT(mtd);=0A=
+    struct mtd_info *subdev =3D NULL;    =0A=
 	int i;=0A=
 =0A=
 	for(i =3D 0; i < concat->num_subdev; i++)=0A=
 	{=0A=
-		struct mtd_info *subdev =3D concat->subdev[i];=0A=
+        subdev =3D concat->subdev[i];		=0A=
 		subdev->resume(subdev);=0A=
 	}=0A=
 }=0A=
@@ -526,9 +759,13 @@=0A=
 	 *       because they are messy to implement and they are not=0A=
 	 *       used to a great extent anyway.=0A=
 	 */=0A=
-	concat->mtd.erase   =3D concat_erase;=0A=
-	concat->mtd.read    =3D concat_read;=0A=
-	concat->mtd.write   =3D concat_write;=0A=
+	concat->mtd.erase     =3D concat_erase;=0A=
+	concat->mtd.read      =3D concat_read;    =0A=
+	concat->mtd.write     =3D concat_write;=0A=
+	concat->mtd.read_ecc  =3D concat_read_ecc;    =0A=
+	concat->mtd.write_ecc =3D concat_write_ecc;=0A=
+	concat->mtd.read_oob  =3D concat_read_oob;    =0A=
+	concat->mtd.write_oob =3D concat_write_oob;=0A=
 	concat->mtd.sync    =3D concat_sync;=0A=
 	concat->mtd.lock    =3D concat_lock;=0A=
 	concat->mtd.unlock  =3D concat_unlock;=0A=

------=_NextPart_000_0132_01C2E31A.116CC0F0--





More information about the linux-mtd mailing list