]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
mtd: nand: add 'oob_required' argument to NAND {read,write}_page interfaces
authorHuang Shijie <b32955@freescale.com>
Wed, 5 Sep 2012 08:30:53 +0000 (16:30 +0800)
committerOliver Wendt <ow@karo-electronics.de>
Mon, 30 Sep 2013 12:12:56 +0000 (14:12 +0200)
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.

[Huang Shijie: I remove the unused code for the other drivers.]

[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>
Signed-off-by: Huang Shijie <b32955@freescale.com>
drivers/mtd/nand/gpmi-nand/gpmi-nand.c
drivers/mtd/nand/nand_base.c
include/linux/mtd/nand.h

index f25b7c27b101952440e0e05416919d0fef5f224a..b9d16c9bdf7481c09eb4bbcbae66be78cb37a154 100644 (file)
@@ -873,7 +873,7 @@ static void block_mark_swapping(struct gpmi_nand_data *this,
 }
 
 static int gpmi_ecc_read_page(struct mtd_info *mtd, struct nand_chip *chip,
-                               uint8_t *buf, int page)
+                               uint8_t *buf, int oob_required, int page)
 {
        struct gpmi_nand_data *this = chip->priv;
        struct bch_geometry *nfc_geo = &this->bch_geometry;
@@ -959,8 +959,8 @@ exit_nfc:
        return ret;
 }
 
-static void gpmi_ecc_write_page(struct mtd_info *mtd,
-                               struct nand_chip *chip, const uint8_t *buf)
+static void gpmi_ecc_write_page(struct mtd_info *mtd, struct nand_chip *chip,
+                               const uint8_t *buf, int oob_required)
 {
        struct gpmi_nand_data *this = chip->priv;
        struct bch_geometry *nfc_geo = &this->bch_geometry;
@@ -1040,7 +1040,7 @@ static int gpmi_verify_buf(struct mtd_info *mtd, const uint8_t * buf, int len)
 {
        struct nand_chip *nand = mtd->priv;
 
-       gpmi_ecc_read_page(mtd, nand, verify_buf, len);
+       gpmi_ecc_read_page(mtd, nand, verify_buf, 0, len);
        if (memcmp(buf, verify_buf, len))
                return -EFAULT;
        return 0;
@@ -1353,7 +1353,7 @@ static int __devinit mx23_write_transcription_stamp(struct gpmi_nand_data *this)
                /* Write the first page of the current stride. */
                dev_dbg(dev, "Writing an NCB fingerprint in page 0x%x\n", page);
                chip->cmdfunc(mtd, NAND_CMD_SEQIN, 0x00, page);
-               chip->ecc.write_page_raw(mtd, chip, buffer);
+               chip->ecc.write_page_raw(mtd, chip, buffer, 0);
                chip->cmdfunc(mtd, NAND_CMD_PAGEPROG, -1, -1);
 
                /* Wait for the write to finish. */
index e799e94da3ab529093a998366a58f5a6c265950f..003ce95488a4f9435220b1e21c079a90eac675a3 100644 (file)
@@ -1051,12 +1051,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);
@@ -1068,13 +1069,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;
@@ -1111,10 +1113,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;
@@ -1124,7 +1127,7 @@ static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
        uint8_t *ecc_code = chip->buffers->ecccode;
        uint32_t *eccpos = chip->ecc.layout->eccpos;
 
-       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]);
@@ -1239,12 +1242,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;
@@ -1284,6 +1288,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.
@@ -1294,7 +1299,7 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
  * 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;
@@ -1333,13 +1338,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. Therefor
  * 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;
@@ -1485,13 +1491,13 @@ int nand_do_read_ops(struct mtd_info *mtd, loff_t from,
                        /* Now read the page into the buffer */
                        if (unlikely(ops->mode == MTD_OOB_RAW))
                                ret = chip->ecc.read_page_raw(mtd, chip,
-                                                             bufpoi, page);
+                                                             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)
                                break;
 
@@ -1893,11 +1899,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);
@@ -1908,12 +1915,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;
@@ -1947,9 +1955,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;
@@ -1965,7 +1974,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);
 }
 
 /**
@@ -1973,9 +1982,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;
@@ -2001,12 +2011,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. Therefor
  * 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;
@@ -2045,21 +2057,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 its worth the
@@ -2238,7 +2252,7 @@ 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_OOB_RAW));
                if (ret)
                        break;
index 1cd6d901dcd4d5ef56010954d02832a7570af138..57aac193a9430452130646034767af7c9f798d8a 100644 (file)
@@ -373,15 +373,15 @@ struct nand_ecc_ctrl {
        int (*correct)(struct mtd_info *mtd, uint8_t *dat, uint8_t *read_ecc,
                        uint8_t *calc_ecc);
        int (*read_page_raw)(struct mtd_info *mtd, struct nand_chip *chip,
-                       uint8_t *buf, int page);
+                       uint8_t *buf, int oob_required, int page);
        void (*write_page_raw)(struct mtd_info *mtd, struct nand_chip *chip,
-                       const uint8_t *buf);
+                       const uint8_t *buf, int oob_required);
        int (*read_page)(struct mtd_info *mtd, struct nand_chip *chip,
-                       uint8_t *buf, int page);
+                       uint8_t *buf, int oob_required, int page);
        int (*read_subpage)(struct mtd_info *mtd, struct nand_chip *chip,
                        uint32_t offs, uint32_t len, uint8_t *buf);
        void (*write_page)(struct mtd_info *mtd, struct nand_chip *chip,
-                       const uint8_t *buf);
+                       const uint8_t *buf, int oob_required);
        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,
@@ -507,7 +507,8 @@ struct nand_chip {
        int (*errstat)(struct mtd_info *mtd, struct nand_chip *this, int state,
                        int status, int page);
        int (*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 chip_delay;
        unsigned int options;