diff options
author | Sascha Hauer <s.hauer@pengutronix.de> | 2018-10-09 12:00:43 +0200 |
---|---|---|
committer | Sascha Hauer <s.hauer@pengutronix.de> | 2018-10-09 12:00:43 +0200 |
commit | 77dfef32e262cc1092267519e84ee90a8405c51d (patch) | |
tree | 1a2ccd260c55c1a32527e550cad3b221866f086b | |
parent | 51b6c199f3d26a027249724c11b4c15e848c3adb (diff) | |
parent | 8e322f9d7c99232531a7069783875355ef386e40 (diff) | |
download | barebox-77dfef32e262cc1092267519e84ee90a8405c51d.tar.gz barebox-77dfef32e262cc1092267519e84ee90a8405c51d.tar.xz |
Merge branch 'for-next/mtd'
-rw-r--r-- | drivers/mtd/core.c | 5 | ||||
-rw-r--r-- | drivers/mtd/mtdraw.c | 124 |
2 files changed, 63 insertions, 66 deletions
diff --git a/drivers/mtd/core.c b/drivers/mtd/core.c index ae7818a189..15fe9ce798 100644 --- a/drivers/mtd/core.c +++ b/drivers/mtd/core.c @@ -589,11 +589,8 @@ static int mtd_detect(struct device_d *dev) continue; filetype = file_detect_type(buf, bufsize); - if (filetype == filetype_ubi) { + if (filetype == filetype_ubi && ubi_num_get_by_mtd(mtd) < 0) ret = ubi_attach_mtd_dev(mtd, UBI_DEV_NUM_AUTO, 0, 20); - if (ret == -EEXIST) - ret = 0; - } break; } diff --git a/drivers/mtd/mtdraw.c b/drivers/mtd/mtdraw.c index 4f7c3b836c..6e36dc5337 100644 --- a/drivers/mtd/mtdraw.c +++ b/drivers/mtd/mtdraw.c @@ -48,6 +48,7 @@ * @write_fill: number of bytes in writebuf * @write_ofs: offset in character device (mtdraw) where last write(s) stored * bytes because of unaligned writes (ie. remain of writesize+oobsize write) + * @rps: raw page size (writesize+oobsize) * * The mtdraw device must allow unaligned writes. This is enabled by a write buffer which gathers data to issue mtd->write_oob() with full page+oob data. * Suppose writesize=512, oobsize=16. @@ -70,6 +71,7 @@ struct mtdraw { void *writebuf; int write_fill; int write_ofs; + unsigned int rps; }; static struct mtdraw *to_mtdraw(struct cdev *cdev) @@ -77,33 +79,28 @@ static struct mtdraw *to_mtdraw(struct cdev *cdev) return cdev->priv; } -static struct mtd_info *to_mtd(struct cdev *cdev) -{ - struct mtdraw *mtdraw = to_mtdraw(cdev); - return mtdraw->mtd; -} - -static unsigned int mtdraw_offset_to_block(struct mtd_info *mtd, loff_t offset) +static unsigned int mtdraw_offset_to_page(struct mtdraw *mtdraw, loff_t offset) { u64 ofs64 = offset; - do_div(ofs64, mtd->writesize + mtd->oobsize); + do_div(ofs64, mtdraw->rps); return ofs64; } -static ssize_t mtdraw_read_unaligned(struct mtd_info *mtd, void *dst, +static ssize_t mtdraw_read_unaligned(struct mtdraw *mtdraw, void *dst, size_t count, int skip, ulong offset) { + struct mtd_info *mtd = mtdraw->mtd; struct mtd_oob_ops ops; ssize_t ret; int partial = 0; void *tmp = dst; - if (skip || count < mtd->writesize + mtd->oobsize) + if (skip || count < mtdraw->rps) partial = 1; if (partial) - tmp = malloc(mtd->writesize + mtd->oobsize); + tmp = malloc(mtdraw->rps); if (!tmp) return -ENOMEM; ops.mode = MTD_OPS_RAW; @@ -128,42 +125,47 @@ err: static ssize_t mtdraw_read(struct cdev *cdev, void *buf, size_t count, loff_t offset, ulong flags) { - struct mtd_info *mtd = to_mtd(cdev); + struct mtdraw *mtdraw = to_mtdraw(cdev); + struct mtd_info *mtd = mtdraw->mtd; ssize_t retlen = 0, ret = 1, toread; - ulong numblock; + ulong numpage; int skip; - numblock = mtdraw_offset_to_block(mtd, offset); - skip = offset - numblock * (mtd->writesize + mtd->oobsize); + numpage = mtdraw_offset_to_page(mtdraw, offset); + skip = offset - numpage * mtdraw->rps; while (ret > 0 && count > 0) { - toread = min_t(int, count, - mtd->writesize + mtd->oobsize - skip); - ret = mtdraw_read_unaligned(mtd, buf, toread, - skip, numblock++ * mtd->writesize); + toread = min_t(int, count, mtdraw->rps - skip); + ret = mtdraw_read_unaligned(mtdraw, buf, toread, + skip, numpage++ * mtd->writesize); buf += ret; skip = 0; count -= ret; retlen += ret; } + if (ret < 0) - printf("err %zd\n", ret); - else - ret = retlen; - return ret; + return ret; + + return retlen; } #ifdef CONFIG_MTD_WRITE -static loff_t mtdraw_raw_to_mtd_offset(struct mtd_info *mtd, loff_t offset) +static loff_t mtdraw_raw_to_mtd_offset(struct mtdraw *mtdraw, loff_t offset) { - return (loff_t)mtdraw_offset_to_block(mtd, offset) * mtd->writesize; + struct mtd_info *mtd = mtdraw->mtd; + + return (loff_t)mtdraw_offset_to_page(mtdraw, offset) * mtd->writesize; } -static ssize_t mtdraw_blkwrite(struct mtd_info *mtd, const void *buf, +static int mtdraw_pagewrite(struct mtdraw *mtdraw, const void *buf, ulong offset) { + struct mtd_info *mtd = mtdraw->mtd; struct mtd_oob_ops ops; - int ret; + + if (mtd_buf_all_ff(buf, mtdraw->rps)) + return 0; ops.mode = MTD_OPS_RAW; ops.ooboffs = 0; @@ -171,10 +173,7 @@ static ssize_t mtdraw_blkwrite(struct mtd_info *mtd, const void *buf, ops.len = mtd->writesize; ops.oobbuf = (void *)buf + mtd->writesize; ops.ooblen = mtd->oobsize; - ret = mtd_write_oob(mtd, offset, &ops); - if (!ret) - ret = ops.retlen + ops.oobretlen; - return ret; + return mtd_write_oob(mtd, offset, &ops); } static void mtdraw_fillbuf(struct mtdraw *mtdraw, const void *src, int nbbytes) @@ -187,66 +186,65 @@ static ssize_t mtdraw_write(struct cdev *cdev, const void *buf, size_t count, 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 numblock; + struct mtd_info *mtd = mtdraw->mtd; + ulong numpage; size_t retlen = 0, tofill; int ret = 0; - numblock = mtdraw_offset_to_block(mtd, offset); + numpage = mtdraw_offset_to_page(mtdraw, offset); if (mtdraw->write_fill && mtdraw->write_ofs + mtdraw->write_fill != offset) return -EINVAL; - if (mtdraw->write_fill == 0 && offset - numblock * mtd->writesize != 0) + if (mtdraw->write_fill == 0 && offset - numpage * mtdraw->rps != 0) return -EINVAL; if (mtdraw->write_fill) { - tofill = min_t(size_t, count, bsz - mtdraw->write_fill); + tofill = min_t(size_t, count, mtdraw->rps - mtdraw->write_fill); mtdraw_fillbuf(mtdraw, buf, tofill); offset += tofill; count -= tofill; retlen += tofill; } - if (mtdraw->write_fill == bsz) { - numblock = mtdraw_offset_to_block(mtd, mtdraw->write_ofs); - ret = mtdraw_blkwrite(mtd, mtdraw->writebuf, - mtd->writesize * numblock); + if (mtdraw->write_fill == mtdraw->rps) { + numpage = mtdraw_offset_to_page(mtdraw, mtdraw->write_ofs); + ret = mtdraw_pagewrite(mtdraw, mtdraw->writebuf, + mtd->writesize * numpage); + if (ret) + return ret; mtdraw->write_fill = 0; } - numblock = mtdraw_offset_to_block(mtd, offset); - while (ret >= 0 && count >= bsz) { - ret = mtdraw_blkwrite(mtd, buf + retlen, - mtd->writesize * numblock++); - count -= ret; - retlen += ret; - offset += ret; + numpage = mtdraw_offset_to_page(mtdraw, offset); + while (ret >= 0 && count >= mtdraw->rps) { + ret = mtdraw_pagewrite(mtdraw, buf + retlen, + mtd->writesize * numpage++); + if (ret) + return ret; + count -= mtdraw->rps; + retlen += mtdraw->rps; + offset += mtdraw->rps; } - if (ret >= 0 && count) { + if (count) { mtdraw->write_ofs = offset - mtdraw->write_fill; mtdraw_fillbuf(mtdraw, buf + retlen, count); retlen += count; } - if (ret < 0) { - printf("err %d\n", ret); - return ret; - } else { - return retlen; - } + return retlen; } static int mtdraw_erase(struct cdev *cdev, loff_t count, loff_t offset) { - struct mtd_info *mtd = to_mtd(cdev); + struct mtdraw *mtdraw = to_mtdraw(cdev); + struct mtd_info *mtd = mtdraw->mtd; struct erase_info erase; int ret; - offset = mtdraw_raw_to_mtd_offset(mtd, offset); - count = mtdraw_raw_to_mtd_offset(mtd, count); + offset = mtdraw_raw_to_mtd_offset(mtdraw, offset); + count = mtdraw_raw_to_mtd_offset(mtdraw, count); memset(&erase, 0, sizeof(erase)); erase.mtd = mtd; @@ -254,7 +252,8 @@ static int mtdraw_erase(struct cdev *cdev, loff_t count, loff_t offset) erase.len = mtd->erasesize; while (count > 0) { - debug("erase 0x%08llx len: 0x%08llx\n", erase.addr, erase.len); + dev_dbg(&mtd->class_dev, "erase 0x%08llx len: 0x%08llx\n", + erase.addr, erase.len); if (!mtd->allow_erasebad) ret = mtd_block_isbad(mtd, erase.addr); @@ -262,7 +261,8 @@ static int mtdraw_erase(struct cdev *cdev, loff_t count, loff_t offset) ret = 0; if (ret > 0) { - printf("Skipping bad block at 0x%08llx\n", erase.addr); + dev_info(&mtd->class_dev, "Skipping bad block at 0x%08llx\n", + erase.addr); } else { ret = mtd_erase(mtd, &erase); if (ret) @@ -302,12 +302,12 @@ static int add_mtdraw_device(struct mtd_info *mtd, const char *devname, void **p return 0; mtdraw = xzalloc(sizeof(*mtdraw)); + mtdraw->rps = mtd->writesize + mtd->oobsize; mtdraw->writebuf = xmalloc(RAW_WRITEBUF_SIZE); mtdraw->mtd = mtd; mtdraw->cdev.ops = (struct cdev_operations *)&mtd_raw_fops; - mtdraw->cdev.size = mtd_div_by_wb(mtd->size, mtd) * - (mtd->writesize + mtd->oobsize); + mtdraw->cdev.size = mtd_div_by_wb(mtd->size, mtd) * mtdraw->rps; mtdraw->cdev.name = basprintf("%s.raw", mtd->cdev.name); mtdraw->cdev.priv = mtdraw; mtdraw->cdev.dev = &mtd->class_dev; |