aboutsummaryrefslogtreecommitdiff
path: root/drivers/mtd/mtdchar.c
diff options
context:
space:
mode:
authorBrian Norris <computersforpeace@gmail.com>2011-08-30 18:45:37 -0700
committerArtem Bityutskiy <artem.bityutskiy@intel.com>2011-09-11 15:02:18 +0300
commit9ce244b3fb416ce6600e05612ac46b9692dcc638 (patch)
tree34b9b77f38ce65f8efe9f9f40e71efd22bc43507 /drivers/mtd/mtdchar.c
parent10a2bcae99267b28e058b089fda30de7397b69f5 (diff)
mtd: support writing OOB without ECC
This fixes issues with `nandwrite -n -o' and the MEMWRITEOOB[64] ioctls on hardware that writes ECC when writing OOB. The problem arises as follows: `nandwrite -n' can write page data to flash without applying ECC, but when used with the `-o' option, ECC is applied (incorrectly), contrary to the `--noecc' option. I found that this is the case because my hardware computes and writes ECC data to flash upon either OOB write or page write. Thus, to support a proper "no ECC" write, my driver must know when we're performing a raw OOB write vs. a normal ECC OOB write. However, MTD does not pass any raw mode information to the write_oob functions. This patch addresses the problems by: 1) Passing MTD_OOB_RAW down to lower layers, instead of just defaulting to MTD_OOB_PLACE 2) Handling MTD_OOB_RAW within the NAND layer's `nand_do_write_oob' 3) Adding a new (replaceable) function pointer in struct ecc_ctrl; this function should support writing OOB without ECC data. Current hardware often can use the same OOB write function when writing either with or without ECC This was tested with nandsim as well as on actual SLC NAND. Signed-off-by: Brian Norris <computersforpeace@gmail.com> Cc: Jim Quinlan <jim2101024@gmail.com> Signed-off-by: Artem Bityutskiy <artem.bityutskiy@intel.com>
Diffstat (limited to 'drivers/mtd/mtdchar.c')
-rw-r--r--drivers/mtd/mtdchar.c3
1 files changed, 2 insertions, 1 deletions
diff --git a/drivers/mtd/mtdchar.c b/drivers/mtd/mtdchar.c
index b2062547513..bcb7f05fd27 100644
--- a/drivers/mtd/mtdchar.c
+++ b/drivers/mtd/mtdchar.c
@@ -391,6 +391,7 @@ static int mtd_do_writeoob(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;
uint32_t retlen;
int ret = 0;
@@ -412,7 +413,7 @@ static int mtd_do_writeoob(struct file *file, struct mtd_info *mtd,
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;