summaryrefslogtreecommitdiffstats
path: root/drivers/mtd/mtdraw.c
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2016-02-08 14:15:52 +0100
committerSascha Hauer <s.hauer@pengutronix.de>2016-02-09 09:26:51 +0100
commitd5128bfaf458081d2d4a0cf736d3cc21967e4f2a (patch)
tree14c6a58abdf003470fa91664dbd3eec128b9b5d1 /drivers/mtd/mtdraw.c
parent4822c7f476f05e6325b1d3a599698fefbfbb8330 (diff)
downloadbarebox-d5128bfaf458081d2d4a0cf736d3cc21967e4f2a.tar.gz
barebox-d5128bfaf458081d2d4a0cf736d3cc21967e4f2a.tar.xz
mtd: Fix mtdraw for Nand > 4GiB
The mtdraw code has some casts to avoid 64bit divisions. For Chips >4GiB using 64bit types become necessary, so use them and to the necessary 64bit math. Signed-off-by: Sascha Hauer <s.hauer@pengutronix.de>
Diffstat (limited to 'drivers/mtd/mtdraw.c')
-rw-r--r--drivers/mtd/mtdraw.c53
1 files changed, 33 insertions, 20 deletions
diff --git a/drivers/mtd/mtdraw.c b/drivers/mtd/mtdraw.c
index ae4bec2a4c..837dcd1e4b 100644
--- a/drivers/mtd/mtdraw.c
+++ b/drivers/mtd/mtdraw.c
@@ -83,6 +83,20 @@ static struct mtd_info *to_mtd(struct cdev *cdev)
return mtdraw->mtd;
}
+static unsigned int mtdraw_offset_to_block(struct mtd_info *mtd, loff_t offset)
+{
+ u64 ofs64 = offset;
+
+ do_div(ofs64, mtd->writesize + mtd->oobsize);
+
+ return ofs64;
+}
+
+static loff_t mtdraw_raw_to_mtd_offset(struct mtd_info *mtd, loff_t offset)
+{
+ return (loff_t)mtdraw_offset_to_block(mtd, offset) * mtd->writesize;
+}
+
static ssize_t mtdraw_read_unaligned(struct mtd_info *mtd, void *dst,
size_t count, int skip, ulong offset)
{
@@ -117,22 +131,21 @@ err:
}
static ssize_t mtdraw_read(struct cdev *cdev, void *buf, size_t count,
- loff_t _offset, ulong flags)
+ loff_t offset, ulong flags)
{
struct mtd_info *mtd = to_mtd(cdev);
ssize_t retlen = 0, ret = 1, toread;
- ulong numpage;
+ ulong numblock;
int skip;
- unsigned long offset = _offset;
- numpage = offset / (mtd->writesize + mtd->oobsize);
- skip = offset % (mtd->writesize + mtd->oobsize);
+ numblock = mtdraw_offset_to_block(mtd, offset);
+ skip = offset - numblock * (mtd->writesize + mtd->oobsize);
while (ret > 0 && count > 0) {
toread = min_t(int, count,
mtd->writesize + mtd->oobsize - skip);
ret = mtdraw_read_unaligned(mtd, buf, toread,
- skip, numpage++ * mtd->writesize);
+ skip, numblock++ * mtd->writesize);
buf += ret;
skip = 0;
count -= ret;
@@ -171,20 +184,21 @@ static void mtdraw_fillbuf(struct mtdraw *mtdraw, const void *src, int nbbytes)
}
static ssize_t mtdraw_write(struct cdev *cdev, const void *buf, size_t count,
- loff_t _offset, ulong flags)
+ loff_t offset, ulong flags)
{
struct mtdraw *mtdraw = to_mtdraw(cdev);
struct mtd_info *mtd = to_mtd(cdev);
int bsz = mtd->writesize + mtd->oobsize;
- ulong numpage;
+ ulong numblock;
size_t retlen = 0, tofill;
- unsigned long offset = _offset;
int ret = 0;
+ numblock = mtdraw_offset_to_block(mtd, offset);
+
if (mtdraw->write_fill &&
mtdraw->write_ofs + mtdraw->write_fill != offset)
return -EINVAL;
- if (mtdraw->write_fill == 0 && offset % bsz)
+ if (mtdraw->write_fill == 0 && offset - numblock * mtd->writesize != 0)
return -EINVAL;
if (mtdraw->write_fill) {
@@ -196,16 +210,16 @@ static ssize_t mtdraw_write(struct cdev *cdev, const void *buf, size_t count,
}
if (mtdraw->write_fill == bsz) {
- numpage = mtdraw->write_ofs / (mtd->writesize + mtd->oobsize);
+ numblock = mtdraw_offset_to_block(mtd, mtdraw->write_ofs);
ret = mtdraw_blkwrite(mtd, mtdraw->writebuf,
- mtd->writesize * numpage);
+ mtd->writesize * numblock);
mtdraw->write_fill = 0;
}
- numpage = offset / (mtd->writesize + mtd->oobsize);
+ numblock = mtdraw_offset_to_block(mtd, offset);
while (ret >= 0 && count >= bsz) {
ret = mtdraw_blkwrite(mtd, buf + retlen,
- mtd->writesize * numpage++);
+ mtd->writesize * numblock++);
count -= ret;
retlen += ret;
offset += ret;
@@ -225,15 +239,14 @@ static ssize_t mtdraw_write(struct cdev *cdev, const void *buf, size_t count,
}
}
-static int mtdraw_erase(struct cdev *cdev, size_t count, loff_t _offset)
+static int mtdraw_erase(struct cdev *cdev, size_t count, loff_t offset)
{
struct mtd_info *mtd = to_mtd(cdev);
struct erase_info erase;
- unsigned long offset = _offset;
int ret;
- offset = offset / (mtd->writesize + mtd->oobsize) * mtd->writesize;
- count = count / (mtd->writesize + mtd->oobsize) * mtd->writesize;
+ offset = mtdraw_raw_to_mtd_offset(mtd, offset);
+ count = mtdraw_raw_to_mtd_offset(mtd, count);
memset(&erase, 0, sizeof(erase));
erase.mtd = mtd;
@@ -241,7 +254,7 @@ static int mtdraw_erase(struct cdev *cdev, size_t count, loff_t _offset)
erase.len = mtd->erasesize;
while (count > 0) {
- debug("erase %d %d\n", erase.addr, erase.len);
+ debug("erase 0x%08llx len: 0x%08llx\n", erase.addr, erase.len);
if (!mtd->allow_erasebad)
ret = mtd_block_isbad(mtd, erase.addr);
@@ -249,7 +262,7 @@ static int mtdraw_erase(struct cdev *cdev, size_t count, loff_t _offset)
ret = 0;
if (ret > 0) {
- printf("Skipping bad block at 0x%08x\n", erase.addr);
+ printf("Skipping bad block at 0x%08llx\n", erase.addr);
} else {
ret = mtd_erase(mtd, &erase);
if (ret)