[PATCH] NAND and mtdconcat

Christian Gan cgan at iders.ca
Thu Mar 6 18:10:31 EST 2003


This is a multi-part message in MIME format.

------=_NextPart_000_015B_01C2E403.4B14E2D0
Content-Type: text/plain;
	charset="iso-8859-1"
Content-Transfer-Encoding: 8bit

Hey all,

Updated patch included with Robert's suggestions.  I agree that either style
is a non-factor in performance, so I might as well use the original style
because it's cleaner.

Thanks!

Christian

> -----Original Message-----
> From: linux-mtd-admin at lists.infradead.org
> [mailto:linux-mtd-admin at lists.infradead.org]On Behalf Of Robert Kaiser
> Sent: Thursday, March 06, 2003 6:10 AM
> To: Christian Gan; rkaiser at sysgo.de; linux-mtd at lists.infradead.org;
> yaffs list
> Subject: Re: [PATCH] NAND and mtdconcat
>
>
> Christian,
>
>
> Am Mittwoch, 5. März 2003 20:21 schrieb Christian Gan:
> > 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?
>
> Looks OK to me. I can't test it right now as I don't have any suitable HW
> available, but I'll take your word that it works ;-)
>
> One question though, you made changes like this:
>
>
> @@ -410,11 +641,12 @@
>  static int concat_suspend(struct mtd_info *mtd)
>  {
>  	struct mtd_concat *concat = CONCAT(mtd);
> +	struct mtd_info *subdev = NULL;
>  	int i, rc = 0;
>
>  	for(i = 0; i < concat->num_subdev; i++)
>  	{
> -		struct mtd_info *subdev = concat->subdev[i];
> +        subdev = concat->subdev[i];
>  		if((rc = subdev->suspend(subdev)) < 0)
>  			return rc;
>  	}
> @@ -424,11 +656,12 @@
>
> all over the place. Why? This might generate slightly more code
> and be slower
> (not that it would be noticeable though).
>
> Other than that, I have no objections.
>
> Rob
>
>
> ----------------------------------------------------------------
> Robert Kaiser                         email: rkaiser at sysgo.de
> SYSGO AG
> Am Pfaffenstein 14                    phone: (49) 6136 9948-762
> D-55270 Klein-Winternheim / Germany   fax:   (49) 6136 9948-10
>
> ______________________________________________________
> Linux MTD discussion mailing list
> http://lists.infradead.org/mailman/listinfo/linux-mtd/
>

------=_NextPart_000_015B_01C2E403.4B14E2D0
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	6 Mar 2003 19:50:31 -0000=0A=
@@ -63,16 +63,16 @@=0A=
 		size_t size, retsize;=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=
@@ -142,6 +142,214 @@=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=
+	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=
+		struct mtd_info *subdev =3D concat->subdev[i];=0A=
+		size_t size, retsize;=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=
+	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=
+		struct mtd_info *subdev =3D concat->subdev[i];=0A=
+		size_t size, retsize;=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=
+	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=
+		struct mtd_info *subdev =3D concat->subdev[i];=0A=
+		size_t size, retsize;=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=
+	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=
+		struct mtd_info *subdev =3D concat->subdev[i];=0A=
+		size_t size, retsize;=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=
@@ -526,9 +734,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_015B_01C2E403.4B14E2D0--





More information about the linux-mtd mailing list