diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c index bcb7f05fd27b6c61387a190e5caf0459e856a5d3..d0eaef67b9bb2a87fd89950e4c5a6013fce5a5a7 100644 --- a/drivers/mtd/mtdchar.c +++ b/drivers/mtd/mtdchar.c @@ -435,9 +435,11 @@ static int mtd_do_writeoob(struct file *file, struct mtd_info *mtd, return ret; } -static int mtd_do_readoob(struct mtd_info *mtd, uint64_t start, - uint32_t length, void __user *ptr, uint32_t __user *retp) +static int mtd_do_readoob(struct file *file, struct mtd_info *mtd, + uint64_t start, uint32_t length, void __user *ptr, + uint32_t __user *retp) { + struct mtd_file_info *mfi = file->private_data; struct mtd_oob_ops ops; int ret = 0; @@ -455,7 +457,7 @@ static int mtd_do_readoob(struct mtd_info *mtd, uint64_t start, ops.ooblen = length; ops.ooboffs = start & (mtd->writesize - 1); ops.datbuf = NULL; - ops.mode = MTD_OOB_PLACE; + ops.mode = (mfi->mode == MTD_MODE_RAW) ? MTD_OOB_RAW : MTD_OOB_PLACE; if (ops.ooboffs && ops.ooblen > (mtd->oobsize - ops.ooboffs)) return -EINVAL; @@ -716,7 +718,7 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg) if (copy_from_user(&buf, argp, sizeof(buf))) ret = -EFAULT; else - ret = mtd_do_readoob(mtd, buf.start, buf.length, + ret = mtd_do_readoob(file, mtd, buf.start, buf.length, buf.ptr, &buf_user->start); break; } @@ -743,7 +745,7 @@ static int mtd_ioctl(struct file *file, u_int cmd, u_long arg) if (copy_from_user(&buf, argp, sizeof(buf))) ret = -EFAULT; else - ret = mtd_do_readoob(mtd, buf.start, buf.length, + ret = mtd_do_readoob(file, mtd, buf.start, buf.length, (void __user *)(uintptr_t)buf.usr_ptr, &buf_user->length); break; @@ -1029,7 +1031,7 @@ static long mtd_compat_ioctl(struct file *file, unsigned int cmd, if (copy_from_user(&buf, argp, sizeof(buf))) ret = -EFAULT; else - ret = mtd_do_readoob(mtd, buf.start, + ret = mtd_do_readoob(file, mtd, buf.start, buf.length, compat_ptr(buf.ptr), &buf_user->start); break; diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index b61a7c7bd097bb8e903dc391e1fc6393b6f08dde..ad40607f5f249d1df98570b8ee99dbcc016c244b 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -1787,7 +1787,10 @@ static int nand_do_read_oob(struct mtd_info *mtd, loff_t from, page = realpage & chip->pagemask; while (1) { - sndcmd = chip->ecc.read_oob(mtd, chip, page, sndcmd); + if (ops->mode == MTD_OOB_RAW) + sndcmd = chip->ecc.read_oob_raw(mtd, chip, page, sndcmd); + else + sndcmd = chip->ecc.read_oob(mtd, chip, page, sndcmd); len = min(len, readlen); buf = nand_transfer_oob(chip, buf, ops, len); @@ -3385,6 +3388,8 @@ int nand_scan_tail(struct mtd_info *mtd) } /* For many systems, the standard OOB write also works for raw */ + if (!chip->ecc.read_oob_raw) + chip->ecc.read_oob_raw = chip->ecc.read_oob; if (!chip->ecc.write_oob_raw) chip->ecc.write_oob_raw = chip->ecc.write_oob; diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index c7113a9cd66dc94b0cf38c57ea12ebcd55247e68..0b3d464cba131ca9ce00adfbfce8730bf329c859 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -341,6 +341,7 @@ struct nand_hw_control { * @write_page: function to write a page according to the ECC generator * requirements. * @write_oob_raw: function to write chip OOB data without ECC + * @read_oob_raw: function to read chip OOB data without ECC * @read_oob: function to read chip OOB data * @write_oob: function to write chip OOB data */ @@ -371,6 +372,8 @@ struct nand_ecc_ctrl { const uint8_t *buf); int (*write_oob_raw)(struct mtd_info *mtd, struct nand_chip *chip, int page); + int (*read_oob_raw)(struct mtd_info *mtd, struct nand_chip *chip, + int page, int sndcmd); int (*read_oob)(struct mtd_info *mtd, struct nand_chip *chip, int page, int sndcmd); int (*write_oob)(struct mtd_info *mtd, struct nand_chip *chip,