summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSascha Hauer <s.hauer@pengutronix.de>2018-10-09 12:00:43 +0200
committerSascha Hauer <s.hauer@pengutronix.de>2018-10-09 12:00:43 +0200
commit77dfef32e262cc1092267519e84ee90a8405c51d (patch)
tree1a2ccd260c55c1a32527e550cad3b221866f086b
parent51b6c199f3d26a027249724c11b4c15e848c3adb (diff)
parent8e322f9d7c99232531a7069783875355ef386e40 (diff)
downloadbarebox-77dfef32e262cc1092267519e84ee90a8405c51d.tar.gz
barebox-77dfef32e262cc1092267519e84ee90a8405c51d.tar.xz
Merge branch 'for-next/mtd'
-rw-r--r--drivers/mtd/core.c5
-rw-r--r--drivers/mtd/mtdraw.c124
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;