aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd
diff options
context:
space:
mode:
authorAndy Lowe <alowe@mvista.com>2007-01-12 18:05:10 -0500
committerDavid Woodhouse <dwmw2@infradead.org>2007-09-23 13:40:49 -0400
commit097f2576eb7dbc8cd5f610847f229f4fea305b80 (patch)
tree809809fbaa7b99d1942ef7583920f17e4f1f1e9d /drivers/mtd
parente644f7d6289456657996df4192de76c5d0a9f9c7 (diff)
[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@mvista.com> Signed-off-by: Nicolas Pitre <nico@cam.org> Signed-off-by: David Woodhouse <dwmw2@infradead.org>
Diffstat (limited to 'drivers/mtd')
-rw-r--r--drivers/mtd/chips/cfi_cmdset_0001.c15
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 39eff9ff575c..c655e971c158 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
1166{ 1166{
1167 struct map_info *map = mtd->priv; 1167 struct map_info *map = mtd->priv;
1168 struct cfi_private *cfi = map->fldrv_priv; 1168 struct cfi_private *cfi = map->fldrv_priv;
1169 unsigned long ofs; 1169 unsigned long ofs, last_end = 0;
1170 int chipnum; 1170 int chipnum;
1171 int ret = 0; 1171 int ret = 0;
1172 1172
1173 if (!map->virt || (from + len > mtd->size)) 1173 if (!map->virt || (from + len > mtd->size))
1174 return -EINVAL; 1174 return -EINVAL;
1175 1175
1176 *mtdbuf = (void *)map->virt + from;
1177 *retlen = 0;
1178
1179 /* Now lock the chip(s) to POINT state */ 1176 /* Now lock the chip(s) to POINT state */
1180 1177
1181 /* ofs: offset within the first chip that the first read should start */ 1178 /* ofs: offset within the first chip that the first read should start */
1182 chipnum = (from >> cfi->chipshift); 1179 chipnum = (from >> cfi->chipshift);
1183 ofs = from - (chipnum << cfi->chipshift); 1180 ofs = from - (chipnum << cfi->chipshift);
1184 1181
1182 *mtdbuf = (void *)map->virt + cfi->chips[chipnum].start + ofs;
1183 *retlen = 0;
1184
1185 while (len) { 1185 while (len) {
1186 unsigned long thislen; 1186 unsigned long thislen;
1187 1187
1188 if (chipnum >= cfi->numchips) 1188 if (chipnum >= cfi->numchips)
1189 break; 1189 break;
1190 1190
1191 /* We cannot point across chips that are virtually disjoint */
1192 if (!last_end)
1193 last_end = cfi->chips[chipnum].start;
1194 else if (cfi->chips[chipnum].start != last_end)
1195 break;
1196
1191 if ((len + ofs -1) >> cfi->chipshift) 1197 if ((len + ofs -1) >> cfi->chipshift)
1192 thislen = (1<<cfi->chipshift) - ofs; 1198 thislen = (1<<cfi->chipshift) - ofs;
1193 else 1199 else
@@ -1201,6 +1207,7 @@ static int cfi_intelext_point (struct mtd_info *mtd, loff_t from, size_t len, si
1201 len -= thislen; 1207 len -= thislen;
1202 1208
1203 ofs = 0; 1209 ofs = 0;
1210 last_end += 1 << cfi->chipshift;
1204 chipnum++; 1211 chipnum++;
1205 } 1212 }
1206 return 0; 1213 return 0;