diff options
author | Brian Norris <computersforpeace@gmail.com> | 2012-05-02 10:14:55 -0700 |
---|---|---|
committer | David Woodhouse <David.Woodhouse@intel.com> | 2012-05-13 23:20:00 -0500 |
commit | 1fbb938dff5b6bb4514a4e7600276b03c7f08e25 (patch) | |
tree | 49ab8089580041bcbd767ff7a57aa7188ee6b6c0 /drivers/mtd/nand/nand_base.c | |
parent | b4f7aa84d6ff44327ab91a2973ebf0c2a7797d24 (diff) | |
download | op-kernel-dev-1fbb938dff5b6bb4514a4e7600276b03c7f08e25.zip op-kernel-dev-1fbb938dff5b6bb4514a4e7600276b03c7f08e25.tar.gz |
mtd: nand: add 'oob_required' argument to NAND {read,write}_page interfaces
New NAND controllers can perform read/write via HW engines which don't expose
OOB data in their DMA mode. To reflect this, we should rework the nand_chip /
nand_ecc_ctrl interfaces that assume that drivers will always read/write OOB
data in the nand_chip.oob_poi buffer. A better interface includes a boolean
argument that explicitly tells the callee when OOB data is requested by the
calling layer (for reading/writing to/from nand_chip.oob_poi).
This patch adds the 'oob_required' parameter to each relevant {read,write}_page
interface; all 'oob_required' parameters are left unused for now. The next
patch will set the parameter properly in the nand_base.c callers, and follow-up
patches will make use of 'oob_required' in some of the callee functions.
Note that currently, there is no harm in ignoring the 'oob_required' parameter
and *always* utilizing nand_chip.oob_poi, but there can be
performance/complexity/design benefits from avoiding filling oob_poi in the
common case. I will try to implement this for some drivers which can be ported
easily.
Note: I couldn't compile-test all of these easily, as some had ARCH
dependencies.
[dwmw2: Merge later 1/0 vs. true/false cleanup]
Signed-off-by: Brian Norris <computersforpeace@gmail.com>
Reviewed-by: Shmulik Ladkani <shmulik.ladkani@gmail.com>
Acked-by: Jiandong Zheng <jdzheng@broadcom.com>
Acked-by: Mike Dunn <mikedunn@newsguy.com>
Signed-off-by: Artem Bityutskiy <artem.bityutskiy@linux.intel.com>
Signed-off-by: David Woodhouse <David.Woodhouse@intel.com>
Diffstat (limited to 'drivers/mtd/nand/nand_base.c')
-rw-r--r-- | drivers/mtd/nand/nand_base.c | 56 |
1 files changed, 35 insertions, 21 deletions
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 5ec4d2c..6d4894a 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -1066,12 +1066,13 @@ EXPORT_SYMBOL(nand_lock); * @mtd: mtd info structure * @chip: nand chip info structure * @buf: buffer to store read data + * @oob_required: caller requires OOB data read to chip->oob_poi * @page: page number to read * * Not for syndrome calculating ECC controllers, which use a special oob layout. */ static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int page) + uint8_t *buf, int oob_required, int page) { chip->read_buf(mtd, buf, mtd->writesize); chip->read_buf(mtd, chip->oob_poi, mtd->oobsize); @@ -1083,13 +1084,14 @@ static int nand_read_page_raw(struct mtd_info *mtd, struct nand_chip *chip, * @mtd: mtd info structure * @chip: nand chip info structure * @buf: buffer to store read data + * @oob_required: caller requires OOB data read to chip->oob_poi * @page: page number to read * * We need a special oob layout and handling even when OOB isn't used. */ static int nand_read_page_raw_syndrome(struct mtd_info *mtd, - struct nand_chip *chip, - uint8_t *buf, int page) + struct nand_chip *chip, uint8_t *buf, + int oob_required, int page) { int eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; @@ -1126,10 +1128,11 @@ static int nand_read_page_raw_syndrome(struct mtd_info *mtd, * @mtd: mtd info structure * @chip: nand chip info structure * @buf: buffer to store read data + * @oob_required: caller requires OOB data read to chip->oob_poi * @page: page number to read */ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int page) + uint8_t *buf, int oob_required, int page) { int i, eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; @@ -1140,7 +1143,7 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, uint32_t *eccpos = chip->ecc.layout->eccpos; unsigned int max_bitflips = 0; - chip->ecc.read_page_raw(mtd, chip, buf, page); + chip->ecc.read_page_raw(mtd, chip, buf, 1, page); for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) chip->ecc.calculate(mtd, p, &ecc_calc[i]); @@ -1263,12 +1266,13 @@ static int nand_read_subpage(struct mtd_info *mtd, struct nand_chip *chip, * @mtd: mtd info structure * @chip: nand chip info structure * @buf: buffer to store read data + * @oob_required: caller requires OOB data read to chip->oob_poi * @page: page number to read * * Not for syndrome calculating ECC controllers which need a special oob layout. */ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int page) + uint8_t *buf, int oob_required, int page) { int i, eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; @@ -1311,6 +1315,7 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, * @mtd: mtd info structure * @chip: nand chip info structure * @buf: buffer to store read data + * @oob_required: caller requires OOB data read to chip->oob_poi * @page: page number to read * * Hardware ECC for large page chips, require OOB to be read first. For this @@ -1320,7 +1325,7 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, * the data area, by overwriting the NAND manufacturer bad block markings. */ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd, - struct nand_chip *chip, uint8_t *buf, int page) + struct nand_chip *chip, uint8_t *buf, int oob_required, int page) { int i, eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; @@ -1362,13 +1367,14 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd, * @mtd: mtd info structure * @chip: nand chip info structure * @buf: buffer to store read data + * @oob_required: caller requires OOB data read to chip->oob_poi * @page: page number to read * * The hw generator calculates the error syndrome automatically. Therefore we * need a special oob layout and handling. */ static int nand_read_page_syndrome(struct mtd_info *mtd, struct nand_chip *chip, - uint8_t *buf, int page) + uint8_t *buf, int oob_required, int page) { int i, eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; @@ -1514,14 +1520,14 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t from, * the read methods return max bitflips per ecc step. */ if (unlikely(ops->mode == MTD_OPS_RAW)) - ret = chip->ecc.read_page_raw(mtd, chip, - bufpoi, page); + ret = chip->ecc.read_page_raw(mtd, chip, bufpoi, + 1, page); else if (!aligned && NAND_SUBPAGE_READ(chip) && !oob) ret = chip->ecc.read_subpage(mtd, chip, col, bytes, bufpoi); else ret = chip->ecc.read_page(mtd, chip, bufpoi, - page); + 1, page); if (ret < 0) { if (!aligned) /* Invalidate page cache */ @@ -1913,11 +1919,12 @@ out: * @mtd: mtd info structure * @chip: nand chip info structure * @buf: data buffer + * @oob_required: must write chip->oob_poi to OOB * * Not for syndrome calculating ECC controllers, which use a special oob layout. */ static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf) + const uint8_t *buf, int oob_required) { chip->write_buf(mtd, buf, mtd->writesize); chip->write_buf(mtd, chip->oob_poi, mtd->oobsize); @@ -1928,12 +1935,13 @@ static void nand_write_page_raw(struct mtd_info *mtd, struct nand_chip *chip, * @mtd: mtd info structure * @chip: nand chip info structure * @buf: data buffer + * @oob_required: must write chip->oob_poi to OOB * * We need a special oob layout and handling even when ECC isn't checked. */ static void nand_write_page_raw_syndrome(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf) + const uint8_t *buf, int oob_required) { int eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; @@ -1967,9 +1975,10 @@ static void nand_write_page_raw_syndrome(struct mtd_info *mtd, * @mtd: mtd info structure * @chip: nand chip info structure * @buf: data buffer + * @oob_required: must write chip->oob_poi to OOB */ static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf) + const uint8_t *buf, int oob_required) { int i, eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; @@ -1985,7 +1994,7 @@ static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, for (i = 0; i < chip->ecc.total; i++) chip->oob_poi[eccpos[i]] = ecc_calc[i]; - chip->ecc.write_page_raw(mtd, chip, buf); + chip->ecc.write_page_raw(mtd, chip, buf, 1); } /** @@ -1993,9 +2002,10 @@ static void nand_write_page_swecc(struct mtd_info *mtd, struct nand_chip *chip, * @mtd: mtd info structure * @chip: nand chip info structure * @buf: data buffer + * @oob_required: must write chip->oob_poi to OOB */ static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf) + const uint8_t *buf, int oob_required) { int i, eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; @@ -2021,12 +2031,14 @@ static void nand_write_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip, * @mtd: mtd info structure * @chip: nand chip info structure * @buf: data buffer + * @oob_required: must write chip->oob_poi to OOB * * The hw generator calculates the error syndrome automatically. Therefore we * need a special oob layout and handling. */ static void nand_write_page_syndrome(struct mtd_info *mtd, - struct nand_chip *chip, const uint8_t *buf) + struct nand_chip *chip, + const uint8_t *buf, int oob_required) { int i, eccsize = chip->ecc.size; int eccbytes = chip->ecc.bytes; @@ -2065,21 +2077,23 @@ static void nand_write_page_syndrome(struct mtd_info *mtd, * @mtd: MTD device structure * @chip: NAND chip descriptor * @buf: the data to write + * @oob_required: must write chip->oob_poi to OOB * @page: page number to write * @cached: cached programming * @raw: use _raw version of write_page */ static int nand_write_page(struct mtd_info *mtd, struct nand_chip *chip, - const uint8_t *buf, int page, int cached, int raw) + const uint8_t *buf, int oob_required, int page, + int cached, int raw) { int status; chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page); if (unlikely(raw)) - chip->ecc.write_page_raw(mtd, chip, buf); + chip->ecc.write_page_raw(mtd, chip, buf, oob_required); else - chip->ecc.write_page(mtd, chip, buf); + chip->ecc.write_page(mtd, chip, buf, oob_required); /* * Cached progamming disabled for now. Not sure if it's worth the @@ -2261,7 +2275,7 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t to, memset(chip->oob_poi, 0xff, mtd->oobsize); } - ret = chip->write_page(mtd, chip, wbuf, page, cached, + ret = chip->write_page(mtd, chip, wbuf, 1, page, cached, (ops->mode == MTD_OPS_RAW)); if (ret) break; |