[MTD] fix CFI point method for discontiguous maps

Linux-MTD Mailing List linux-mtd at lists.infradead.org
Sun Sep 23 13:59:01 EDT 2007


Gitweb:     http://git.infradead.org/?p=mtd-2.6.git;a=commit;h=097f2576eb7dbc8cd5f610847f229f4fea305b80
Commit:     097f2576eb7dbc8cd5f610847f229f4fea305b80
Parent:     e644f7d6289456657996df4192de76c5d0a9f9c7
Author:     Andy Lowe <alowe at mvista.com>
AuthorDate: Fri Jan 12 18:05:10 2007 -0500
Committer:  David Woodhouse <dwmw2 at infradead.org>
CommitDate: Sun Sep 23 18:40:49 2007 +0100

    [MTD] fix CFI point method for discontiguous maps
    
    The CFI probe routine is capable of detecting flash banks consisting of
    identical chips mapped to physically discontiguous addresses.  (One
    common way this can occur is if a flash bank is populated with chips of
    less capacity than the hardware was designed to support.)  The CFI
    point() routine currently ignores any such gaps.  This patch fixes
    the CFI point() routine so that it truncates any request that would
    span a gap.
    
    Signed-off-by: Andy Lowe <alowe at mvista.com>
    Signed-off-by: Nicolas Pitre <nico at cam.org>
    Signed-off-by: David Woodhouse <dwmw2 at infradead.org>
---
 drivers/mtd/chips/cfi_cmdset_0001.c |   15 +++++++++++----
 1 files changed, 11 insertions(+), 4 deletions(-)

diff --git a/drivers/mtd/chips/cfi_cmdset_0001.c b/drivers/mtd/chips/cfi_cmdset_0001.c
index 39eff9f..c655e97 100644
--- a/drivers/mtd/chips/cfi_cmdset_0001.c
+++ b/drivers/mtd/chips/cfi_cmdset_0001.c
@@ -1166,28 +1166,34 @@ static int cfi_intelext_point (struct mtd_info *mtd, loff_t from, size_t len, si
 {
 	struct map_info *map = mtd->priv;
 	struct cfi_private *cfi = map->fldrv_priv;
-	unsigned long ofs;
+	unsigned long ofs, last_end = 0;
 	int chipnum;
 	int ret = 0;
 
 	if (!map->virt || (from + len > mtd->size))
 		return -EINVAL;
 
-	*mtdbuf = (void *)map->virt + from;
-	*retlen = 0;
-
 	/* Now lock the chip(s) to POINT state */
 
 	/* ofs: offset within the first chip that the first read should start */
 	chipnum = (from >> cfi->chipshift);
 	ofs = from - (chipnum << cfi->chipshift);
 
+	*mtdbuf = (void *)map->virt + cfi->chips[chipnum].start + ofs;
+	*retlen = 0;
+
 	while (len) {
 		unsigned long thislen;
 
 		if (chipnum >= cfi->numchips)
 			break;
 
+		/* We cannot point across chips that are virtually disjoint */
+		if (!last_end)
+			last_end = cfi->chips[chipnum].start;
+		else if (cfi->chips[chipnum].start != last_end)
+			break;
+
 		if ((len + ofs -1) >> cfi->chipshift)
 			thislen = (1<<cfi->chipshift) - ofs;
 		else
@@ -1201,6 +1207,7 @@ static int cfi_intelext_point (struct mtd_info *mtd, loff_t from, size_t len, si
 		len -= thislen;
 
 		ofs = 0;
+		last_end += 1 << cfi->chipshift;
 		chipnum++;
 	}
 	return 0;



More information about the linux-mtd-cvs mailing list