[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>
This commit is contained in:
parent
e644f7d628
commit
097f2576eb
|
@ -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 map_info *map = mtd->priv;
|
||||||
struct cfi_private *cfi = map->fldrv_priv;
|
struct cfi_private *cfi = map->fldrv_priv;
|
||||||
unsigned long ofs;
|
unsigned long ofs, last_end = 0;
|
||||||
int chipnum;
|
int chipnum;
|
||||||
int ret = 0;
|
int ret = 0;
|
||||||
|
|
||||||
if (!map->virt || (from + len > mtd->size))
|
if (!map->virt || (from + len > mtd->size))
|
||||||
return -EINVAL;
|
return -EINVAL;
|
||||||
|
|
||||||
*mtdbuf = (void *)map->virt + from;
|
|
||||||
*retlen = 0;
|
|
||||||
|
|
||||||
/* Now lock the chip(s) to POINT state */
|
/* Now lock the chip(s) to POINT state */
|
||||||
|
|
||||||
/* ofs: offset within the first chip that the first read should start */
|
/* ofs: offset within the first chip that the first read should start */
|
||||||
chipnum = (from >> cfi->chipshift);
|
chipnum = (from >> cfi->chipshift);
|
||||||
ofs = from - (chipnum << cfi->chipshift);
|
ofs = from - (chipnum << cfi->chipshift);
|
||||||
|
|
||||||
|
*mtdbuf = (void *)map->virt + cfi->chips[chipnum].start + ofs;
|
||||||
|
*retlen = 0;
|
||||||
|
|
||||||
while (len) {
|
while (len) {
|
||||||
unsigned long thislen;
|
unsigned long thislen;
|
||||||
|
|
||||||
if (chipnum >= cfi->numchips)
|
if (chipnum >= cfi->numchips)
|
||||||
break;
|
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)
|
if ((len + ofs -1) >> cfi->chipshift)
|
||||||
thislen = (1<<cfi->chipshift) - ofs;
|
thislen = (1<<cfi->chipshift) - ofs;
|
||||||
else
|
else
|
||||||
|
@ -1201,6 +1207,7 @@ static int cfi_intelext_point (struct mtd_info *mtd, loff_t from, size_t len, si
|
||||||
len -= thislen;
|
len -= thislen;
|
||||||
|
|
||||||
ofs = 0;
|
ofs = 0;
|
||||||
|
last_end += 1 << cfi->chipshift;
|
||||||
chipnum++;
|
chipnum++;
|
||||||
}
|
}
|
||||||
return 0;
|
return 0;
|
||||||
|
|
Loading…
Reference in New Issue