From: Cai Zhiyong <caizhiy...@huawei.com>
Date: Fri, 27 Dec 2013 20:23:09 +0800
Subject: [PATCH] mtd: nand: remove NAND_MAX_OOBSIZE and NAND_MAX_PAGESIZE

remove NAND_MAX_OOBSIZE and NAND_MAX_PAGESIZE, dynamic allocate
NAND buffer after detecting NAND writesize and oobsize.

 - save memory. when use MACRO allocate static buffer, use a small
   page size NAND chip, the buffer is still 8k, the memory is wasted.

 - reduce maintenance. NAND chip pagesize and oobsize update frequently,
   allocate buffer according to the detecting size will reduce maintenance.

 - this fix was suggested by Brian Norris [computersforpe...@gmail.com]
                         and Huang Shijie [b32...@freescale.com]

Signed-off-by: Cai Zhiyong <caizhiy...@huawei.com>
---
 drivers/mtd/nand/cafe_nand.c           | 15 +++++++--
 drivers/mtd/nand/denali.c              |  9 -----
 drivers/mtd/nand/denali.h              |  2 +-
 drivers/mtd/nand/fsmc_nand.c           |  4 +--
 drivers/mtd/nand/gpmi-nand/gpmi-nand.c |  4 +--
 drivers/mtd/nand/mxc_nand.c            |  5 ++-
 drivers/mtd/nand/nand_base.c           | 60 ++++++++++++++++++++--------------
 drivers/mtd/nand/nand_bbt.c            |  2 +-
 drivers/mtd/nand/omap2.c               |  6 ++--
 include/linux/mtd/nand.h               | 17 +++-------
 10 files changed, 66 insertions(+), 58 deletions(-)

diff --git a/drivers/mtd/nand/cafe_nand.c b/drivers/mtd/nand/cafe_nand.c
index c34985a..c784621 100644
--- a/drivers/mtd/nand/cafe_nand.c
+++ b/drivers/mtd/nand/cafe_nand.c
@@ -53,6 +53,9 @@
 #define CAFE_GLOBAL_IRQ_MASK   0x300c
 #define CAFE_NAND_RESET                0x3034
 
+#define CAFE_MAX_OOBSIZE       744
+#define CAFE_MAX_PAGESIZE      8192
+
 /* Missing from the datasheet: bit 19 of CTRL1 sets CE0 vs. CE1 */
 #define CTRL1_CHIPSELECT       (1<<19)
 
@@ -657,13 +660,21 @@ static int cafe_nand_probe(struct pci_dev *pdev,
                err = -ENOMEM;
                goto out_free_mtd;
        }
-       cafe->dmabuf = dma_alloc_coherent(&cafe->pdev->dev, 2112 + 
sizeof(struct nand_buffers),
+       cafe->dmabuf = dma_alloc_coherent(&cafe->pdev->dev,
+                                         (2112 + CAFE_MAX_OOBSIZE * 3
+                                          + CAFE_MAX_PAGESIZE),
                                          &cafe->dmaaddr, GFP_KERNEL);
        if (!cafe->dmabuf) {
                err = -ENOMEM;
                goto out_ior;
        }
-       cafe->nand.buffers = (void *)cafe->dmabuf + 2112;
+
+       cafe->nand.buffers.buffer = (void *)cafe->dmabuf + 2112;
+       cafe->nand.buffers.ecccalc = cafe->nand.buffers.buffer;
+       cafe->nand.buffers.ecccode = cafe->nand.buffers.ecccalc
+               + CAFE_MAX_OOBSIZE;
+       cafe->nand.buffers.databuf = cafe->nand.buffers.ecccode
+               + CAFE_MAX_OOBSIZE;
 
        cafe->rs = init_rs_non_canonical(12, &cafe_mul, 0, 1, 8);
        if (!cafe->rs) {
diff --git a/drivers/mtd/nand/denali.c b/drivers/mtd/nand/denali.c
index 3a3a47f..e86c995 100644
--- a/drivers/mtd/nand/denali.c
+++ b/drivers/mtd/nand/denali.c
@@ -1475,15 +1475,6 @@ int denali_init(struct denali_nand_info *denali)
                goto failed_req_irq;
        }
 
-       /* MTD supported page sizes vary by kernel. We validate our
-        * kernel supports the device here.
-        */
-       if (denali->mtd.writesize > NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE) {
-               ret = -ENODEV;
-               pr_err("Spectra: device size not supported by this version of 
MTD.");
-               goto failed_req_irq;
-       }
-
        /* support for multi nand
         * MTD known nothing about multi nand,
         * so we should tell it the real pagesize
diff --git a/drivers/mtd/nand/denali.h b/drivers/mtd/nand/denali.h
index cec5712..5feb466 100644
--- a/drivers/mtd/nand/denali.h
+++ b/drivers/mtd/nand/denali.h
@@ -455,7 +455,7 @@
 
 #define ECC_SECTOR_SIZE     512
 
-#define DENALI_BUF_SIZE                (NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE)
+#define DENALI_BUF_SIZE                (8192 + 744)
 
 struct nand_buf {
        int head;
diff --git a/drivers/mtd/nand/fsmc_nand.c b/drivers/mtd/nand/fsmc_nand.c
index 8b27522..082c880 100644
--- a/drivers/mtd/nand/fsmc_nand.c
+++ b/drivers/mtd/nand/fsmc_nand.c
@@ -719,8 +719,8 @@ static int fsmc_read_page_hwecc(struct mtd_info *mtd, 
struct nand_chip *chip,
        int eccbytes = chip->ecc.bytes;
        int eccsteps = chip->ecc.steps;
        uint8_t *p = buf;
-       uint8_t *ecc_calc = chip->buffers->ecccalc;
-       uint8_t *ecc_code = chip->buffers->ecccode;
+       uint8_t *ecc_calc = chip->buffers.ecccalc;
+       uint8_t *ecc_code = chip->buffers.ecccode;
        int off, len, group = 0;
        /*
         * ecc_oob is intentionally taken as uint16_t. In 16bit devices, we
diff --git a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c 
b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
index e2f5820..7618e71 100644
--- a/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
+++ b/drivers/mtd/nand/gpmi-nand/gpmi-nand.c
@@ -1298,7 +1298,7 @@ static int mx23_check_transcription_stamp(struct 
gpmi_nand_data *this)
        unsigned int search_area_size_in_strides;
        unsigned int stride;
        unsigned int page;
-       uint8_t *buffer = chip->buffers->databuf;
+       uint8_t *buffer = chip->buffers.databuf;
        int saved_chip_number;
        int found_an_ncb_fingerprint = false;
 
@@ -1357,7 +1357,7 @@ static int mx23_write_transcription_stamp(struct 
gpmi_nand_data *this)
        unsigned int block;
        unsigned int stride;
        unsigned int page;
-       uint8_t      *buffer = chip->buffers->databuf;
+       uint8_t      *buffer = chip->buffers.databuf;
        int saved_chip_number;
        int status;
 
diff --git a/drivers/mtd/nand/mxc_nand.c b/drivers/mtd/nand/mxc_nand.c
index 567a5e5..5343c4f 100644
--- a/drivers/mtd/nand/mxc_nand.c
+++ b/drivers/mtd/nand/mxc_nand.c
@@ -137,6 +137,9 @@
 
 #define NFC_V3_DELAY_LINE              (host->regs_ip + 0x34)
 
+#define MXC_MAX_OOBSIZE                        744
+#define MXC_MAX_PAGESIZE               8192
+
 struct mxc_nand_host;
 
 struct mxc_nand_devtype_data {
@@ -1400,7 +1403,7 @@ static int mxcnd_probe(struct platform_device *pdev)
 
        /* Allocate memory for MTD device structure and private data */
        host = devm_kzalloc(&pdev->dev, sizeof(struct mxc_nand_host) +
-                       NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE, GFP_KERNEL);
+                           MXC_MAX_PAGESIZE + MXC_MAX_OOBSIZE, GFP_KERNEL);
        if (!host)
                return -ENOMEM;
 
diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
index 9b3bb3c..57c1b57a 100644
--- a/drivers/mtd/nand/nand_base.c
+++ b/drivers/mtd/nand/nand_base.c
@@ -1078,8 +1078,8 @@ static int nand_read_page_swecc(struct mtd_info *mtd, 
struct nand_chip *chip,
        int eccbytes = chip->ecc.bytes;
        int eccsteps = chip->ecc.steps;
        uint8_t *p = buf;
-       uint8_t *ecc_calc = chip->buffers->ecccalc;
-       uint8_t *ecc_code = chip->buffers->ecccode;
+       uint8_t *ecc_calc = chip->buffers.ecccalc;
+       uint8_t *ecc_code = chip->buffers.ecccode;
        uint32_t *eccpos = chip->ecc.layout->eccpos;
        unsigned int max_bitflips = 0;
 
@@ -1147,7 +1147,7 @@ static int nand_read_subpage(struct mtd_info *mtd, struct 
nand_chip *chip,
 
        /* Calculate ECC */
        for (i = 0; i < eccfrag_len ; i += chip->ecc.bytes, p += chip->ecc.size)
-               chip->ecc.calculate(mtd, p, &chip->buffers->ecccalc[i]);
+               chip->ecc.calculate(mtd, p, &chip->buffers.ecccalc[i]);
 
        /*
         * The performance is faster if we position offsets according to
@@ -1183,14 +1183,14 @@ static int nand_read_subpage(struct mtd_info *mtd, 
struct nand_chip *chip,
        }
 
        for (i = 0; i < eccfrag_len; i++)
-               chip->buffers->ecccode[i] = chip->oob_poi[eccpos[i + index]];
+               chip->buffers.ecccode[i] = chip->oob_poi[eccpos[i + index]];
 
        p = bufpoi + data_col_addr;
        for (i = 0; i < eccfrag_len ; i += chip->ecc.bytes, p += 
chip->ecc.size) {
                int stat;
 
                stat = chip->ecc.correct(mtd, p,
-                       &chip->buffers->ecccode[i], &chip->buffers->ecccalc[i]);
+                       &chip->buffers.ecccode[i], &chip->buffers.ecccalc[i]);
                if (stat < 0) {
                        mtd->ecc_stats.failed++;
                } else {
@@ -1218,8 +1218,8 @@ static int nand_read_page_hwecc(struct mtd_info *mtd, 
struct nand_chip *chip,
        int eccbytes = chip->ecc.bytes;
        int eccsteps = chip->ecc.steps;
        uint8_t *p = buf;
-       uint8_t *ecc_calc = chip->buffers->ecccalc;
-       uint8_t *ecc_code = chip->buffers->ecccode;
+       uint8_t *ecc_calc = chip->buffers.ecccalc;
+       uint8_t *ecc_code = chip->buffers.ecccode;
        uint32_t *eccpos = chip->ecc.layout->eccpos;
        unsigned int max_bitflips = 0;
 
@@ -1271,9 +1271,9 @@ static int nand_read_page_hwecc_oob_first(struct mtd_info 
*mtd,
        int eccbytes = chip->ecc.bytes;
        int eccsteps = chip->ecc.steps;
        uint8_t *p = buf;
-       uint8_t *ecc_code = chip->buffers->ecccode;
+       uint8_t *ecc_code = chip->buffers.ecccode;
        uint32_t *eccpos = chip->ecc.layout->eccpos;
-       uint8_t *ecc_calc = chip->buffers->ecccalc;
+       uint8_t *ecc_calc = chip->buffers.ecccalc;
        unsigned int max_bitflips = 0;
 
        /* Read the OOB area first */
@@ -1452,7 +1452,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t 
from,
 
                /* Is the current page in the buffer? */
                if (realpage != chip->pagebuf || oob) {
-                       bufpoi = aligned ? buf : chip->buffers->databuf;
+                       bufpoi = aligned ? buf : chip->buffers.databuf;
 
                        chip->cmdfunc(mtd, NAND_CMD_READ0, 0x00, page);
 
@@ -1491,7 +1491,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t 
from,
                                        /* Invalidate page cache */
                                        chip->pagebuf = -1;
                                }
-                               memcpy(buf, chip->buffers->databuf + col, 
bytes);
+                               memcpy(buf, chip->buffers.databuf + col, bytes);
                        }
 
                        buf += bytes;
@@ -1514,7 +1514,7 @@ static int nand_do_read_ops(struct mtd_info *mtd, loff_t 
from,
                                        nand_wait_ready(mtd);
                        }
                } else {
-                       memcpy(buf, chip->buffers->databuf + col, bytes);
+                       memcpy(buf, chip->buffers.databuf + col, bytes);
                        buf += bytes;
                        max_bitflips = max_t(unsigned int, max_bitflips,
                                             chip->pagebuf_bitflips);
@@ -1932,7 +1932,7 @@ static int nand_write_page_swecc(struct mtd_info *mtd, 
struct nand_chip *chip,
        int i, eccsize = chip->ecc.size;
        int eccbytes = chip->ecc.bytes;
        int eccsteps = chip->ecc.steps;
-       uint8_t *ecc_calc = chip->buffers->ecccalc;
+       uint8_t *ecc_calc = chip->buffers.ecccalc;
        const uint8_t *p = buf;
        uint32_t *eccpos = chip->ecc.layout->eccpos;
 
@@ -1959,7 +1959,7 @@ static int nand_write_page_hwecc(struct mtd_info *mtd, 
struct nand_chip *chip,
        int i, eccsize = chip->ecc.size;
        int eccbytes = chip->ecc.bytes;
        int eccsteps = chip->ecc.steps;
-       uint8_t *ecc_calc = chip->buffers->ecccalc;
+       uint8_t *ecc_calc = chip->buffers.ecccalc;
        const uint8_t *p = buf;
        uint32_t *eccpos = chip->ecc.layout->eccpos;
 
@@ -1993,7 +1993,7 @@ static int nand_write_subpage_hwecc(struct mtd_info *mtd,
                                int oob_required)
 {
        uint8_t *oob_buf  = chip->oob_poi;
-       uint8_t *ecc_calc = chip->buffers->ecccalc;
+       uint8_t *ecc_calc = chip->buffers.ecccalc;
        int ecc_size      = chip->ecc.size;
        int ecc_bytes     = chip->ecc.bytes;
        int ecc_steps     = chip->ecc.steps;
@@ -2028,7 +2028,7 @@ static int nand_write_subpage_hwecc(struct mtd_info *mtd,
 
        /* copy calculated ECC for whole page to chip->buffer->oob */
        /* this include masked-value(0xFF) for unwritten subpages */
-       ecc_calc = chip->buffers->ecccalc;
+       ecc_calc = chip->buffers.ecccalc;
        for (i = 0; i < chip->ecc.total; i++)
                chip->oob_poi[eccpos[i]] = ecc_calc[i];
 
@@ -2282,9 +2282,9 @@ static int nand_do_write_ops(struct mtd_info *mtd, loff_t 
to,
                        cached = 0;
                        bytes = min_t(int, bytes - column, (int) writelen);
                        chip->pagebuf = -1;
-                       memset(chip->buffers->databuf, 0xff, mtd->writesize);
-                       memcpy(&chip->buffers->databuf[column], buf, bytes);
-                       wbuf = chip->buffers->databuf;
+                       memset(chip->buffers.databuf, 0xff, mtd->writesize);
+                       memcpy(&chip->buffers.databuf[column], buf, bytes);
+                       wbuf = chip->buffers.databuf;
                }
 
                if (unlikely(oob)) {
@@ -3564,13 +3564,21 @@ int nand_scan_tail(struct mtd_info *mtd)
        BUG_ON((chip->bbt_options & NAND_BBT_NO_OOB_BBM) &&
                        !(chip->bbt_options & NAND_BBT_USE_FLASH));
 
-       if (!(chip->options & NAND_OWN_BUFFERS))
-               chip->buffers = kmalloc(sizeof(*chip->buffers), GFP_KERNEL);
-       if (!chip->buffers)
+       if (!(chip->options & NAND_OWN_BUFFERS)) {
+               chip->buffers.buffer =
+                       kmalloc(mtd->oobsize * 3 + mtd->writesize, GFP_KERNEL);
+               if (!chip->buffers.buffer)
+                       return -ENOMEM;
+
+               chip->buffers.ecccalc = chip->buffers.buffer;
+               chip->buffers.ecccode = chip->buffers.ecccalc + mtd->oobsize;
+               chip->buffers.databuf = chip->buffers.ecccode + mtd->oobsize;
+       }
+       if (!chip->buffers.buffer)
                return -ENOMEM;
 
        /* Set the internal oob buffer location, just after the page data */
-       chip->oob_poi = chip->buffers->databuf + mtd->writesize;
+       chip->oob_poi = chip->buffers.databuf + mtd->writesize;
 
        /*
         * If no default placement scheme is given, select an appropriate one.
@@ -3886,8 +3894,10 @@ void nand_release(struct mtd_info *mtd)
 
        /* Free bad block table memory */
        kfree(chip->bbt);
-       if (!(chip->options & NAND_OWN_BUFFERS))
-               kfree(chip->buffers);
+       if (!(chip->options & NAND_OWN_BUFFERS)) {
+               kfree(chip->buffers.buffer);
+               chip->buffers.buffer = NULL;
+       }
 
        /* Free bad block descriptor memory */
        if (chip->badblock_pattern && chip->badblock_pattern->options
diff --git a/drivers/mtd/nand/nand_bbt.c b/drivers/mtd/nand/nand_bbt.c
index c0615d1..5cc4253 100644
--- a/drivers/mtd/nand/nand_bbt.c
+++ b/drivers/mtd/nand/nand_bbt.c
@@ -829,7 +829,7 @@ static inline int nand_memory_bbt(struct mtd_info *mtd, 
struct nand_bbt_descr *b
 {
        struct nand_chip *this = mtd->priv;
 
-       return create_bbt(mtd, this->buffers->databuf, bd, -1);
+       return create_bbt(mtd, this->buffers.databuf, bd, -1);
 }
 
 /**
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index f777250..c67986d 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -1519,7 +1519,7 @@ static int omap_write_page_bch(struct mtd_info *mtd, 
struct nand_chip *chip,
                                  const uint8_t *buf, int oob_required)
 {
        int i;
-       uint8_t *ecc_calc = chip->buffers->ecccalc;
+       uint8_t *ecc_calc = chip->buffers.ecccalc;
        uint32_t *eccpos = chip->ecc.layout->eccpos;
 
        /* Enable GPMC ecc engine */
@@ -1557,8 +1557,8 @@ static int omap_write_page_bch(struct mtd_info *mtd, 
struct nand_chip *chip,
 static int omap_read_page_bch(struct mtd_info *mtd, struct nand_chip *chip,
                                uint8_t *buf, int oob_required, int page)
 {
-       uint8_t *ecc_calc = chip->buffers->ecccalc;
-       uint8_t *ecc_code = chip->buffers->ecccode;
+       uint8_t *ecc_calc = chip->buffers.ecccalc;
+       uint8_t *ecc_code = chip->buffers.ecccode;
        uint32_t *eccpos = chip->ecc.layout->eccpos;
        uint8_t *oob = &chip->oob_poi[eccpos[0]];
        uint32_t oob_pos = mtd->writesize + chip->ecc.layout->eccpos[0];
diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h
index f3ea8da..ce9466f 100644
--- a/include/linux/mtd/nand.h
+++ b/include/linux/mtd/nand.h
@@ -52,14 +52,6 @@ extern int nand_unlock(struct mtd_info *mtd, loff_t ofs, 
uint64_t len);
 #define NAND_MAX_CHIPS         8
 
 /*
- * This constant declares the max. oobsize / page, which
- * is supported now. If you add a chip with bigger oobsize/page
- * adjust this accordingly.
- */
-#define NAND_MAX_OOBSIZE       744
-#define NAND_MAX_PAGESIZE      8192
-
-/*
  * Constants for hardware specific CLE/ALE/NCE function
  *
  * These are bits which can be or'ed to set/clear multiple
@@ -419,9 +411,10 @@ struct nand_ecc_ctrl {
  * consecutive order.
  */
 struct nand_buffers {
-       uint8_t ecccalc[NAND_MAX_OOBSIZE];
-       uint8_t ecccode[NAND_MAX_OOBSIZE];
-       uint8_t databuf[NAND_MAX_PAGESIZE + NAND_MAX_OOBSIZE];
+       uint8_t *buffer;
+       uint8_t *ecccalc;
+       uint8_t *ecccode;
+       uint8_t *databuf;
 };
 
 /**
@@ -574,7 +567,7 @@ struct nand_chip {
        struct nand_hw_control *controller;
 
        struct nand_ecc_ctrl ecc;
-       struct nand_buffers *buffers;
+       struct nand_buffers buffers;
        struct nand_hw_control hwcontrol;
 
        uint8_t *bbt;
-- 
1.8.1.5

--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Reply via email to