kernel: bump 4.4 to 4.4.167
[openwrt/openwrt.git] / target / linux / mediatek / patches-4.4 / 0072-mtd-backport-v4.7-0day-patches-from-Boris.patch
index 8ad59dfb332c1e252fd308b29096ef0f2ccd55f1..8881dcd485cb8a3215647a90089c538a8b72ef4f 100644 (file)
@@ -212,7 +212,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
        kfree(mtd_list);
 --- a/drivers/mtd/mtdchar.c
 +++ b/drivers/mtd/mtdchar.c
-@@ -465,38 +465,111 @@ static int mtdchar_readoob(struct file *
+@@ -469,38 +469,111 @@ static int mtdchar_readoob(struct file *
  }
  
  /*
@@ -341,7 +341,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
  static int mtdchar_blkpg_ioctl(struct mtd_info *mtd,
                               struct blkpg_ioctl_arg *arg)
  {
-@@ -815,16 +888,12 @@ static int mtdchar_ioctl(struct file *fi
+@@ -819,16 +892,12 @@ static int mtdchar_ioctl(struct file *fi
        {
                struct nand_oobinfo oi;
  
@@ -362,7 +362,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
  
                if (copy_to_user(argp, &oi, sizeof(struct nand_oobinfo)))
                        return -EFAULT;
-@@ -913,14 +982,14 @@ static int mtdchar_ioctl(struct file *fi
+@@ -917,14 +986,14 @@ static int mtdchar_ioctl(struct file *fi
        {
                struct nand_ecclayout_user *usrlay;
  
@@ -1954,7 +1954,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
        int ctrl = NAND_CTRL_CLE | NAND_CTRL_CHANGE;
  
        /* Write out the command to the device */
-@@ -708,7 +733,7 @@ static void nand_command(struct mtd_info
+@@ -710,7 +735,7 @@ static void nand_command(struct mtd_info
  static void nand_command_lp(struct mtd_info *mtd, unsigned int command,
                            int column, int page_addr)
  {
@@ -1963,7 +1963,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
  
        /* Emulate NAND_CMD_READOOB */
        if (command == NAND_CMD_READOOB) {
-@@ -832,7 +857,7 @@ static void panic_nand_get_device(struct
+@@ -837,7 +862,7 @@ static void panic_nand_get_device(struct
  static int
  nand_get_device(struct mtd_info *mtd, int new_state)
  {
@@ -1972,7 +1972,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
        spinlock_t *lock = &chip->controller->lock;
        wait_queue_head_t *wq = &chip->controller->wq;
        DECLARE_WAITQUEUE(wait, current);
-@@ -952,7 +977,7 @@ static int __nand_unlock(struct mtd_info
+@@ -957,7 +982,7 @@ static int __nand_unlock(struct mtd_info
  {
        int ret = 0;
        int status, page;
@@ -1981,7 +1981,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
  
        /* Submit address of first page to unlock */
        page = ofs >> chip->page_shift;
-@@ -987,7 +1012,7 @@ int nand_unlock(struct mtd_info *mtd, lo
+@@ -992,7 +1017,7 @@ int nand_unlock(struct mtd_info *mtd, lo
  {
        int ret = 0;
        int chipnr;
@@ -1990,7 +1990,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
  
        pr_debug("%s: start = 0x%012llx, len = %llu\n",
                        __func__, (unsigned long long)ofs, len);
-@@ -1050,7 +1075,7 @@ int nand_lock(struct mtd_info *mtd, loff
+@@ -1055,7 +1080,7 @@ int nand_lock(struct mtd_info *mtd, loff
  {
        int ret = 0;
        int chipnr, status, page;
@@ -1999,7 +1999,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
  
        pr_debug("%s: start = 0x%012llx, len = %llu\n",
                        __func__, (unsigned long long)ofs, len);
-@@ -1309,13 +1334,12 @@ static int nand_read_page_raw_syndrome(s
+@@ -1314,13 +1339,12 @@ static int nand_read_page_raw_syndrome(s
  static int nand_read_page_swecc(struct mtd_info *mtd, struct nand_chip *chip,
                                uint8_t *buf, int oob_required, int page)
  {
@@ -2014,7 +2014,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
        unsigned int max_bitflips = 0;
  
        chip->ecc.read_page_raw(mtd, chip, buf, 1, page);
-@@ -1323,8 +1347,10 @@ static int nand_read_page_swecc(struct m
+@@ -1328,8 +1352,10 @@ static int nand_read_page_swecc(struct m
        for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize)
                chip->ecc.calculate(mtd, p, &ecc_calc[i]);
  
@@ -2027,7 +2027,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
  
        eccsteps = chip->ecc.steps;
        p = buf;
-@@ -1356,14 +1382,14 @@ static int nand_read_subpage(struct mtd_
+@@ -1361,14 +1387,14 @@ static int nand_read_subpage(struct mtd_
                        uint32_t data_offs, uint32_t readlen, uint8_t *bufpoi,
                        int page)
  {
@@ -2045,7 +2045,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
  
        /* Column address within the page aligned to ECC size (256bytes) */
        start_step = data_offs / chip->ecc.size;
-@@ -1391,12 +1417,13 @@ static int nand_read_subpage(struct mtd_
+@@ -1396,12 +1422,13 @@ static int nand_read_subpage(struct mtd_
         * The performance is faster if we position offsets according to
         * ecc.pos. Let's make sure that there are no gaps in ECC positions.
         */
@@ -2065,7 +2065,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
        if (gaps) {
                chip->cmdfunc(mtd, NAND_CMD_RNDOUT, mtd->writesize, -1);
                chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
-@@ -1405,20 +1432,23 @@ static int nand_read_subpage(struct mtd_
+@@ -1410,20 +1437,23 @@ static int nand_read_subpage(struct mtd_
                 * Send the command to read the particular ECC bytes take care
                 * about buswidth alignment in read_buf.
                 */
@@ -2095,7 +2095,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
  
        p = bufpoi + data_col_addr;
        for (i = 0; i < eccfrag_len ; i += chip->ecc.bytes, p += chip->ecc.size) {
-@@ -1426,6 +1456,16 @@ static int nand_read_subpage(struct mtd_
+@@ -1431,6 +1461,16 @@ static int nand_read_subpage(struct mtd_
  
                stat = chip->ecc.correct(mtd, p,
                        &chip->buffers->ecccode[i], &chip->buffers->ecccalc[i]);
@@ -2112,7 +2112,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
                if (stat < 0) {
                        mtd->ecc_stats.failed++;
                } else {
-@@ -1449,13 +1489,12 @@ static int nand_read_subpage(struct mtd_
+@@ -1454,13 +1494,12 @@ static int nand_read_subpage(struct mtd_
  static int nand_read_page_hwecc(struct mtd_info *mtd, struct nand_chip *chip,
                                uint8_t *buf, int oob_required, int page)
  {
@@ -2127,7 +2127,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
        unsigned int max_bitflips = 0;
  
        for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
-@@ -1465,8 +1504,10 @@ static int nand_read_page_hwecc(struct m
+@@ -1470,8 +1509,10 @@ static int nand_read_page_hwecc(struct m
        }
        chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
  
@@ -2140,7 +2140,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
  
        eccsteps = chip->ecc.steps;
        p = buf;
-@@ -1475,6 +1516,15 @@ static int nand_read_page_hwecc(struct m
+@@ -1480,6 +1521,15 @@ static int nand_read_page_hwecc(struct m
                int stat;
  
                stat = chip->ecc.correct(mtd, p, &ecc_code[i], &ecc_calc[i]);
@@ -2156,7 +2156,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
                if (stat < 0) {
                        mtd->ecc_stats.failed++;
                } else {
-@@ -1502,12 +1552,11 @@ static int nand_read_page_hwecc(struct m
+@@ -1507,12 +1557,11 @@ static int nand_read_page_hwecc(struct m
  static int nand_read_page_hwecc_oob_first(struct mtd_info *mtd,
        struct nand_chip *chip, uint8_t *buf, int oob_required, int page)
  {
@@ -2170,7 +2170,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
        uint8_t *ecc_calc = chip->buffers->ecccalc;
        unsigned int max_bitflips = 0;
  
-@@ -1516,8 +1565,10 @@ static int nand_read_page_hwecc_oob_firs
+@@ -1521,8 +1570,10 @@ static int nand_read_page_hwecc_oob_firs
        chip->read_buf(mtd, chip->oob_poi, mtd->oobsize);
        chip->cmdfunc(mtd, NAND_CMD_READ0, 0, page);
  
@@ -2183,7 +2183,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
  
        for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
                int stat;
-@@ -1527,6 +1578,15 @@ static int nand_read_page_hwecc_oob_firs
+@@ -1532,6 +1583,15 @@ static int nand_read_page_hwecc_oob_firs
                chip->ecc.calculate(mtd, p, &ecc_calc[i]);
  
                stat = chip->ecc.correct(mtd, p, &ecc_code[i], NULL);
@@ -2199,7 +2199,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
                if (stat < 0) {
                        mtd->ecc_stats.failed++;
                } else {
-@@ -1554,6 +1614,7 @@ static int nand_read_page_syndrome(struc
+@@ -1559,6 +1619,7 @@ static int nand_read_page_syndrome(struc
        int i, eccsize = chip->ecc.size;
        int eccbytes = chip->ecc.bytes;
        int eccsteps = chip->ecc.steps;
@@ -2207,7 +2207,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
        uint8_t *p = buf;
        uint8_t *oob = chip->oob_poi;
        unsigned int max_bitflips = 0;
-@@ -1573,19 +1634,29 @@ static int nand_read_page_syndrome(struc
+@@ -1578,19 +1639,29 @@ static int nand_read_page_syndrome(struc
                chip->read_buf(mtd, oob, eccbytes);
                stat = chip->ecc.correct(mtd, p, oob, NULL);
  
@@ -2244,7 +2244,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
        }
  
        /* Calculate remaining oob bytes */
-@@ -1598,14 +1669,17 @@ static int nand_read_page_syndrome(struc
+@@ -1603,14 +1674,17 @@ static int nand_read_page_syndrome(struc
  
  /**
   * nand_transfer_oob - [INTERN] Transfer oob to client buffer
@@ -2264,7 +2264,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
        switch (ops->mode) {
  
        case MTD_OPS_PLACE_OOB:
-@@ -1613,31 +1687,12 @@ static uint8_t *nand_transfer_oob(struct
+@@ -1618,31 +1692,12 @@ static uint8_t *nand_transfer_oob(struct
                memcpy(oob, chip->oob_poi + ops->ooboffs, len);
                return oob + len;
  
@@ -2302,7 +2302,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
        default:
                BUG();
        }
-@@ -1655,7 +1710,7 @@ static uint8_t *nand_transfer_oob(struct
+@@ -1660,7 +1715,7 @@ static uint8_t *nand_transfer_oob(struct
   */
  static int nand_setup_read_retry(struct mtd_info *mtd, int retry_mode)
  {
@@ -2311,7 +2311,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
  
        pr_debug("setting READ RETRY mode %d\n", retry_mode);
  
-@@ -1680,12 +1735,11 @@ static int nand_do_read_ops(struct mtd_i
+@@ -1685,12 +1740,11 @@ static int nand_do_read_ops(struct mtd_i
                            struct mtd_oob_ops *ops)
  {
        int chipnr, page, realpage, col, bytes, aligned, oob_required;
@@ -2326,7 +2326,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
  
        uint8_t *bufpoi, *oob, *buf;
        int use_bufpoi;
-@@ -1772,7 +1826,7 @@ read_retry:
+@@ -1777,7 +1831,7 @@ read_retry:
                                int toread = min(oobreadlen, max_oobsize);
  
                                if (toread) {
@@ -2335,16 +2335,16 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
                                                oob, ops, toread);
                                        oobreadlen -= toread;
                                }
-@@ -2024,7 +2078,7 @@ static int nand_do_read_oob(struct mtd_i
-                           struct mtd_oob_ops *ops)
+@@ -2030,7 +2084,7 @@ static int nand_do_read_oob(struct mtd_i
  {
+       unsigned int max_bitflips = 0;
        int page, realpage, chipnr;
 -      struct nand_chip *chip = mtd->priv;
 +      struct nand_chip *chip = mtd_to_nand(mtd);
        struct mtd_ecc_stats stats;
        int readlen = ops->ooblen;
        int len;
-@@ -2036,10 +2090,7 @@ static int nand_do_read_oob(struct mtd_i
+@@ -2042,10 +2096,7 @@ static int nand_do_read_oob(struct mtd_i
  
        stats = mtd->ecc_stats;
  
@@ -2356,7 +2356,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
  
        if (unlikely(ops->ooboffs >= len)) {
                pr_debug("%s: attempt to start read outside oob\n",
-@@ -2073,7 +2124,7 @@ static int nand_do_read_oob(struct mtd_i
+@@ -2079,7 +2130,7 @@ static int nand_do_read_oob(struct mtd_i
                        break;
  
                len = min(len, readlen);
@@ -2365,7 +2365,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
  
                if (chip->options & NAND_NEED_READRDY) {
                        /* Apply delay or wait for ready/busy pin */
-@@ -2232,19 +2283,20 @@ static int nand_write_page_swecc(struct
+@@ -2240,19 +2291,20 @@ static int nand_write_page_swecc(struct
                                 const uint8_t *buf, int oob_required,
                                 int page)
  {
@@ -2390,7 +2390,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
  
        return chip->ecc.write_page_raw(mtd, chip, buf, 1, page);
  }
-@@ -2261,12 +2313,11 @@ static int nand_write_page_hwecc(struct
+@@ -2269,12 +2321,11 @@ static int nand_write_page_hwecc(struct
                                  const uint8_t *buf, int oob_required,
                                  int page)
  {
@@ -2404,7 +2404,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
  
        for (i = 0; eccsteps; eccsteps--, i += eccbytes, p += eccsize) {
                chip->ecc.hwctl(mtd, NAND_ECC_WRITE);
-@@ -2274,8 +2325,10 @@ static int nand_write_page_hwecc(struct
+@@ -2282,8 +2333,10 @@ static int nand_write_page_hwecc(struct
                chip->ecc.calculate(mtd, p, &ecc_calc[i]);
        }
  
@@ -2417,7 +2417,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
  
        chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
  
-@@ -2303,11 +2356,10 @@ static int nand_write_subpage_hwecc(stru
+@@ -2311,11 +2364,10 @@ static int nand_write_subpage_hwecc(stru
        int ecc_size      = chip->ecc.size;
        int ecc_bytes     = chip->ecc.bytes;
        int ecc_steps     = chip->ecc.steps;
@@ -2430,7 +2430,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
  
        for (step = 0; step < ecc_steps; step++) {
                /* configure controller for WRITE access */
-@@ -2335,8 +2387,10 @@ static int nand_write_subpage_hwecc(stru
+@@ -2343,8 +2395,10 @@ static int nand_write_subpage_hwecc(stru
        /* copy calculated ECC for whole page to chip->buffer->oob */
        /* this include masked-value(0xFF) for unwritten subpages */
        ecc_calc = chip->buffers->ecccalc;
@@ -2443,7 +2443,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
  
        /* write OOB buffer to NAND device */
        chip->write_buf(mtd, chip->oob_poi, mtd->oobsize);
-@@ -2472,7 +2526,8 @@ static int nand_write_page(struct mtd_in
+@@ -2480,7 +2534,8 @@ static int nand_write_page(struct mtd_in
  static uint8_t *nand_fill_oob(struct mtd_info *mtd, uint8_t *oob, size_t len,
                              struct mtd_oob_ops *ops)
  {
@@ -2453,7 +2453,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
  
        /*
         * Initialise to all 0xFF, to avoid the possibility of left over OOB
-@@ -2487,31 +2542,12 @@ static uint8_t *nand_fill_oob(struct mtd
+@@ -2495,31 +2550,12 @@ static uint8_t *nand_fill_oob(struct mtd
                memcpy(chip->oob_poi + ops->ooboffs, oob, len);
                return oob + len;
  
@@ -2491,7 +2491,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
        default:
                BUG();
        }
-@@ -2532,12 +2568,11 @@ static int nand_do_write_ops(struct mtd_
+@@ -2540,12 +2576,11 @@ static int nand_do_write_ops(struct mtd_
                             struct mtd_oob_ops *ops)
  {
        int chipnr, realpage, page, blockmask, column;
@@ -2506,16 +2506,16 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
  
        uint8_t *oob = ops->oobbuf;
        uint8_t *buf = ops->datbuf;
-@@ -2662,7 +2697,7 @@ err_out:
+@@ -2670,7 +2705,7 @@ err_out:
  static int panic_nand_write(struct mtd_info *mtd, loff_t to, size_t len,
                            size_t *retlen, const uint8_t *buf)
  {
 -      struct nand_chip *chip = mtd->priv;
 +      struct nand_chip *chip = mtd_to_nand(mtd);
+       int chipnr = (int)(to >> chip->chip_shift);
        struct mtd_oob_ops ops;
        int ret;
-@@ -2722,15 +2757,12 @@ static int nand_do_write_oob(struct mtd_
+@@ -2733,15 +2768,12 @@ static int nand_do_write_oob(struct mtd_
                             struct mtd_oob_ops *ops)
  {
        int chipnr, page, status, len;
@@ -2533,7 +2533,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
  
        /* Do not allow write past end of page */
        if ((ops->ooboffs + ops->ooblen) > len) {
-@@ -2847,7 +2879,7 @@ out:
+@@ -2858,7 +2890,7 @@ out:
   */
  static int single_erase(struct mtd_info *mtd, int page)
  {
@@ -2542,7 +2542,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
        /* Send commands to erase a block */
        chip->cmdfunc(mtd, NAND_CMD_ERASE1, -1, page);
        chip->cmdfunc(mtd, NAND_CMD_ERASE2, -1, -1);
-@@ -2879,7 +2911,7 @@ int nand_erase_nand(struct mtd_info *mtd
+@@ -2890,7 +2922,7 @@ int nand_erase_nand(struct mtd_info *mtd
                    int allowbbt)
  {
        int page, status, pages_per_block, ret, chipnr;
@@ -2551,7 +2551,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
        loff_t len;
  
        pr_debug("%s: start = 0x%012llx, len = %llu\n",
-@@ -2918,7 +2950,7 @@ int nand_erase_nand(struct mtd_info *mtd
+@@ -2929,7 +2961,7 @@ int nand_erase_nand(struct mtd_info *mtd
        while (len) {
                /* Check if we have a bad block, we do not erase bad blocks! */
                if (nand_block_checkbad(mtd, ((loff_t) page) <<
@@ -2560,7 +2560,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
                        pr_warn("%s: attempt to erase a bad block at page 0x%08x\n",
                                    __func__, page);
                        instr->state = MTD_ERASE_FAILED;
-@@ -3005,7 +3037,20 @@ static void nand_sync(struct mtd_info *m
+@@ -3016,7 +3048,20 @@ static void nand_sync(struct mtd_info *m
   */
  static int nand_block_isbad(struct mtd_info *mtd, loff_t offs)
  {
@@ -2582,7 +2582,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
  }
  
  /**
-@@ -3094,7 +3139,7 @@ static int nand_suspend(struct mtd_info
+@@ -3105,7 +3150,7 @@ static int nand_suspend(struct mtd_info
   */
  static void nand_resume(struct mtd_info *mtd)
  {
@@ -2591,7 +2591,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
  
        if (chip->state == FL_PM_SUSPENDED)
                nand_release_device(mtd);
-@@ -3266,7 +3311,7 @@ ext_out:
+@@ -3277,7 +3322,7 @@ ext_out:
  
  static int nand_setup_read_retry_micron(struct mtd_info *mtd, int retry_mode)
  {
@@ -2600,7 +2600,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
        uint8_t feature[ONFI_SUBFEATURE_PARAM_LEN] = {retry_mode};
  
        return chip->onfi_set_features(mtd, chip, ONFI_FEATURE_ADDR_READ_RETRY,
-@@ -3937,10 +3982,13 @@ ident_done:
+@@ -3948,10 +3993,13 @@ ident_done:
        return type;
  }
  
@@ -2617,7 +2617,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
  
        if (of_get_nand_bus_width(dn) == 16)
                chip->options |= NAND_BUSWIDTH_16;
-@@ -3949,6 +3997,7 @@ static int nand_dt_init(struct mtd_info
+@@ -3960,6 +4008,7 @@ static int nand_dt_init(struct mtd_info
                chip->bbt_options |= NAND_BBT_USE_FLASH;
  
        ecc_mode = of_get_nand_ecc_mode(dn);
@@ -2625,7 +2625,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
        ecc_strength = of_get_nand_ecc_strength(dn);
        ecc_step = of_get_nand_ecc_step_size(dn);
  
-@@ -3961,6 +4010,9 @@ static int nand_dt_init(struct mtd_info
+@@ -3972,6 +4021,9 @@ static int nand_dt_init(struct mtd_info
        if (ecc_mode >= 0)
                chip->ecc.mode = ecc_mode;
  
@@ -2635,7 +2635,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
        if (ecc_strength >= 0)
                chip->ecc.strength = ecc_strength;
  
-@@ -3984,15 +4036,16 @@ int nand_scan_ident(struct mtd_info *mtd
+@@ -3995,15 +4047,16 @@ int nand_scan_ident(struct mtd_info *mtd
                    struct nand_flash_dev *table)
  {
        int i, nand_maf_id, nand_dev_id;
@@ -2658,7 +2658,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
  
        if (!mtd->name && mtd->dev.parent)
                mtd->name = dev_name(mtd->dev.parent);
-@@ -4055,7 +4108,7 @@ EXPORT_SYMBOL(nand_scan_ident);
+@@ -4066,7 +4119,7 @@ EXPORT_SYMBOL(nand_scan_ident);
   */
  static bool nand_ecc_strength_good(struct mtd_info *mtd)
  {
@@ -2667,7 +2667,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
        struct nand_ecc_ctrl *ecc = &chip->ecc;
        int corr, ds_corr;
  
-@@ -4083,10 +4136,10 @@ static bool nand_ecc_strength_good(struc
+@@ -4094,10 +4147,10 @@ static bool nand_ecc_strength_good(struc
   */
  int nand_scan_tail(struct mtd_info *mtd)
  {
@@ -2680,7 +2680,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
  
        /* New bad blocks should be marked in OOB, flash-based BBT, or both */
        BUG_ON((chip->bbt_options & NAND_BBT_NO_OOB_BBM) &&
-@@ -4113,19 +4166,15 @@ int nand_scan_tail(struct mtd_info *mtd)
+@@ -4124,19 +4177,15 @@ int nand_scan_tail(struct mtd_info *mtd)
        /*
         * If no default placement scheme is given, select an appropriate one.
         */
@@ -2703,7 +2703,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
                        break;
                default:
                        pr_warn("No oob scheme defined for oobsize %d\n",
-@@ -4168,7 +4217,7 @@ int nand_scan_tail(struct mtd_info *mtd)
+@@ -4179,7 +4228,7 @@ int nand_scan_tail(struct mtd_info *mtd)
                        ecc->write_oob = nand_write_oob_std;
                if (!ecc->read_subpage)
                        ecc->read_subpage = nand_read_subpage;
@@ -2712,7 +2712,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
                        ecc->write_subpage = nand_write_subpage_hwecc;
  
        case NAND_ECC_HW_SYNDROME:
-@@ -4246,10 +4295,8 @@ int nand_scan_tail(struct mtd_info *mtd)
+@@ -4257,10 +4306,8 @@ int nand_scan_tail(struct mtd_info *mtd)
                }
  
                /* See nand_bch_init() for details. */
@@ -2725,7 +2725,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
                if (!ecc->priv) {
                        pr_warn("BCH ECC initialization failed!\n");
                        BUG();
-@@ -4280,20 +4327,9 @@ int nand_scan_tail(struct mtd_info *mtd)
+@@ -4291,20 +4338,9 @@ int nand_scan_tail(struct mtd_info *mtd)
        if (!ecc->write_oob_raw)
                ecc->write_oob_raw = ecc->write_oob;
  
@@ -2749,7 +2749,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
  
        /*
         * Set the number of read / write steps for one page depending on ECC
-@@ -4306,6 +4342,21 @@ int nand_scan_tail(struct mtd_info *mtd)
+@@ -4317,6 +4353,21 @@ int nand_scan_tail(struct mtd_info *mtd)
        }
        ecc->total = ecc->steps * ecc->bytes;
  
@@ -2771,7 +2771,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
        /* Allow subpage writes up to ecc.steps. Not possible for MLC flash */
        if (!(chip->options & NAND_NO_SUBPAGE_WRITE) && nand_is_slc(chip)) {
                switch (ecc->steps) {
-@@ -4362,10 +4413,6 @@ int nand_scan_tail(struct mtd_info *mtd)
+@@ -4373,10 +4424,6 @@ int nand_scan_tail(struct mtd_info *mtd)
        mtd->_block_markbad = nand_block_markbad;
        mtd->writebufsize = mtd->writesize;
  
@@ -2782,7 +2782,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
        /*
         * Initialize bitflip_threshold to its default prior scan_bbt() call.
         * scan_bbt() might invoke mtd_read(), thus bitflip_threshold must be
-@@ -4421,7 +4468,7 @@ EXPORT_SYMBOL(nand_scan);
+@@ -4432,7 +4479,7 @@ EXPORT_SYMBOL(nand_scan);
   */
  void nand_release(struct mtd_info *mtd)
  {
@@ -3942,7 +3942,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
  
  struct flash_info {
        char            *name;
-@@ -60,14 +61,20 @@ struct flash_info {
+@@ -60,15 +61,20 @@ struct flash_info {
        u16             addr_width;
  
        u16             flags;
@@ -3954,6 +3954,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
 -#define       SPI_NOR_DUAL_READ       0x20    /* Flash supports Dual Read */
 -#define       SPI_NOR_QUAD_READ       0x40    /* Flash supports Quad Read */
 -#define       USE_FSR                 0x80    /* use flag status register */
+-#define       SPI_NOR_HAS_LOCK        0x100   /* Flash supports lock/unlock via SR */
 +#define SECT_4K                       BIT(0)  /* SPINOR_OP_BE_4K works uniformly */
 +#define SPI_NOR_NO_ERASE      BIT(1)  /* No erase command needed */
 +#define SST_WRITE             BIT(2)  /* use SST byte programming */
@@ -3971,7 +3972,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
  };
  
  #define JEDEC_MFR(info)       ((info)->id[0])
-@@ -313,6 +320,29 @@ static void spi_nor_unlock_and_unprep(st
+@@ -314,6 +320,29 @@ static void spi_nor_unlock_and_unprep(st
  }
  
  /*
@@ -4001,7 +4002,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
   * Erase an address range on the nor chip.  The address range may extend
   * one or more erase sectors.  Return an error is there is a problem erasing.
   */
-@@ -371,10 +401,9 @@ static int spi_nor_erase(struct mtd_info
+@@ -372,10 +401,9 @@ static int spi_nor_erase(struct mtd_info
                while (len) {
                        write_enable(nor);
  
@@ -4014,7 +4015,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
  
                        addr += mtd->erasesize;
                        len -= mtd->erasesize;
-@@ -387,17 +416,13 @@ static int spi_nor_erase(struct mtd_info
+@@ -388,17 +416,13 @@ static int spi_nor_erase(struct mtd_info
  
        write_disable(nor);
  
@@ -4034,7 +4035,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
  }
  
  static void stm_get_locked_range(struct spi_nor *nor, u8 sr, loff_t *ofs,
-@@ -415,32 +440,58 @@ static void stm_get_locked_range(struct
+@@ -416,32 +440,58 @@ static void stm_get_locked_range(struct
        } else {
                pow = ((sr & mask) ^ mask) >> shift;
                *len = mtd->size >> pow;
@@ -4100,7 +4101,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
   * Sample table portion for 8MB flash (Winbond w25q64fw):
   *
   *   SEC  |  TB   |  BP2  |  BP1  |  BP0  |  Prot Length  | Protected Portion
-@@ -453,26 +504,55 @@ static int stm_is_locked_sr(struct spi_n
+@@ -454,26 +504,55 @@ static int stm_is_locked_sr(struct spi_n
   *    0   |   0   |   1   |   0   |   1   |  2 MB         | Upper 1/4
   *    0   |   0   |   1   |   1   |   0   |  4 MB         | Upper 1/2
   *    X   |   X   |   1   |   1   |   1   |  8 MB         | ALL
@@ -4165,7 +4166,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
  
        /*
         * Need smallest pow such that:
-@@ -483,7 +563,7 @@ static int stm_lock(struct spi_nor *nor,
+@@ -484,7 +563,7 @@ static int stm_lock(struct spi_nor *nor,
         *
         *   pow = ceil(log2(size / len)) = log2(size) - floor(log2(len))
         */
@@ -4174,7 +4175,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
        val = mask - (pow << shift);
        if (val & ~mask)
                return -EINVAL;
-@@ -491,14 +571,27 @@ static int stm_lock(struct spi_nor *nor,
+@@ -492,14 +571,27 @@ static int stm_lock(struct spi_nor *nor,
        if (!(val & mask))
                return -EINVAL;
  
@@ -4205,7 +4206,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
  }
  
  /*
-@@ -509,17 +602,43 @@ static int stm_lock(struct spi_nor *nor,
+@@ -510,17 +602,43 @@ static int stm_lock(struct spi_nor *nor,
  static int stm_unlock(struct spi_nor *nor, loff_t ofs, uint64_t len)
  {
        struct mtd_info *mtd = &nor->mtd;
@@ -4253,7 +4254,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
        /*
         * Need largest pow such that:
         *
-@@ -529,8 +648,8 @@ static int stm_unlock(struct spi_nor *no
+@@ -530,8 +648,8 @@ static int stm_unlock(struct spi_nor *no
         *
         *   pow = floor(log2(size / len)) = log2(size) - ceil(log2(len))
         */
@@ -4264,7 +4265,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
                val = 0; /* fully unlocked */
        } else {
                val = mask - (pow << shift);
-@@ -539,14 +658,28 @@ static int stm_unlock(struct spi_nor *no
+@@ -540,14 +658,28 @@ static int stm_unlock(struct spi_nor *no
                        return -EINVAL;
        }
  
@@ -4296,19 +4297,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
  }
  
  /*
-@@ -716,9 +849,9 @@ static const struct flash_info spi_nor_i
-       { "mx25l4005a",  INFO(0xc22013, 0, 64 * 1024,   8, SECT_4K) },
-       { "mx25l8005",   INFO(0xc22014, 0, 64 * 1024,  16, 0) },
-       { "mx25l1606e",  INFO(0xc22015, 0, 64 * 1024,  32, SECT_4K) },
--      { "mx25l3205d",  INFO(0xc22016, 0, 64 * 1024,  64, 0) },
-+      { "mx25l3205d",  INFO(0xc22016, 0, 64 * 1024,  64, SECT_4K) },
-       { "mx25l3255e",  INFO(0xc29e16, 0, 64 * 1024,  64, SECT_4K) },
--      { "mx25l6405d",  INFO(0xc22017, 0, 64 * 1024, 128, 0) },
-+      { "mx25l6405d",  INFO(0xc22017, 0, 64 * 1024, 128, SECT_4K) },
-       { "mx25u6435f",  INFO(0xc22537, 0, 64 * 1024, 128, SECT_4K) },
-       { "mx25l12805d", INFO(0xc22018, 0, 64 * 1024, 256, 0) },
-       { "mx25l12855e", INFO(0xc22618, 0, 64 * 1024, 256, 0) },
-@@ -733,8 +866,8 @@ static const struct flash_info spi_nor_i
+@@ -743,8 +875,8 @@ static const struct flash_info spi_nor_i
        { "n25q032a",    INFO(0x20bb16, 0, 64 * 1024,   64, SPI_NOR_QUAD_READ) },
        { "n25q064",     INFO(0x20ba17, 0, 64 * 1024,  128, SECT_4K | SPI_NOR_QUAD_READ) },
        { "n25q064a",    INFO(0x20bb17, 0, 64 * 1024,  128, SECT_4K | SPI_NOR_QUAD_READ) },
@@ -4319,7 +4308,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
        { "n25q256a",    INFO(0x20ba19, 0, 64 * 1024,  512, SECT_4K | SPI_NOR_QUAD_READ) },
        { "n25q512a",    INFO(0x20bb20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
        { "n25q512ax3",  INFO(0x20ba20, 0, 64 * 1024, 1024, SECT_4K | USE_FSR | SPI_NOR_QUAD_READ) },
-@@ -768,6 +901,7 @@ static const struct flash_info spi_nor_i
+@@ -778,6 +910,7 @@ static const struct flash_info spi_nor_i
        { "s25fl008k",  INFO(0xef4014,      0,  64 * 1024,  16, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
        { "s25fl016k",  INFO(0xef4015,      0,  64 * 1024,  32, SECT_4K | SPI_NOR_DUAL_READ | SPI_NOR_QUAD_READ) },
        { "s25fl064k",  INFO(0xef4017,      0,  64 * 1024, 128, SECT_4K) },
@@ -4327,7 +4316,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
        { "s25fl132k",  INFO(0x014016,      0,  64 * 1024,  64, SECT_4K) },
        { "s25fl164k",  INFO(0x014017,      0,  64 * 1024, 128, SECT_4K) },
        { "s25fl204k",  INFO(0x014013,      0,  64 * 1024,   8, SECT_4K | SPI_NOR_DUAL_READ) },
-@@ -831,11 +965,23 @@ static const struct flash_info spi_nor_i
+@@ -841,11 +974,23 @@ static const struct flash_info spi_nor_i
        { "w25x16", INFO(0xef3015, 0, 64 * 1024,  32, SECT_4K) },
        { "w25x32", INFO(0xef3016, 0, 64 * 1024,  64, SECT_4K) },
        { "w25q32", INFO(0xef4016, 0, 64 * 1024,  64, SECT_4K) },
@@ -4354,7 +4343,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
        { "w25q80", INFO(0xef5014, 0, 64 * 1024,  16, SECT_4K) },
        { "w25q80bl", INFO(0xef4014, 0, 64 * 1024,  16, SECT_4K) },
        { "w25q128", INFO(0xef4018, 0, 64 * 1024, 256, SECT_4K) },
-@@ -858,7 +1004,7 @@ static const struct flash_info *spi_nor_
+@@ -868,7 +1013,7 @@ static const struct flash_info *spi_nor_
  
        tmp = nor->read_reg(nor, SPINOR_OP_RDID, id, SPI_NOR_MAX_ID_LEN);
        if (tmp < 0) {
@@ -4363,7 +4352,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
                return ERR_PTR(tmp);
        }
  
-@@ -869,7 +1015,7 @@ static const struct flash_info *spi_nor_
+@@ -879,7 +1024,7 @@ static const struct flash_info *spi_nor_
                                return &spi_nor_ids[tmp];
                }
        }
@@ -4372,7 +4361,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
                id[0], id[1], id[2]);
        return ERR_PTR(-ENODEV);
  }
-@@ -1015,6 +1161,8 @@ static int macronix_quad_enable(struct s
+@@ -1025,6 +1170,8 @@ static int macronix_quad_enable(struct s
        int ret, val;
  
        val = read_sr(nor);
@@ -4381,7 +4370,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
        write_enable(nor);
  
        write_sr(nor, val | SR_QUAD_EN_MX);
-@@ -1096,7 +1244,7 @@ static int set_quad_mode(struct spi_nor
+@@ -1113,7 +1260,7 @@ static int set_quad_mode(struct spi_nor
  static int spi_nor_check(struct spi_nor *nor)
  {
        if (!nor->dev || !nor->read || !nor->write ||
@@ -4390,7 +4379,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
                pr_err("spi-nor: please fill all the necessary fields!\n");
                return -EINVAL;
        }
-@@ -1109,7 +1257,7 @@ int spi_nor_scan(struct spi_nor *nor, co
+@@ -1126,7 +1273,7 @@ int spi_nor_scan(struct spi_nor *nor, co
        const struct flash_info *info = NULL;
        struct device *dev = nor->dev;
        struct mtd_info *mtd = &nor->mtd;
@@ -4399,30 +4388,15 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
        int ret;
        int i;
  
-@@ -1159,9 +1307,11 @@ int spi_nor_scan(struct spi_nor *nor, co
-       if (JEDEC_MFR(info) == SNOR_MFR_ATMEL ||
-           JEDEC_MFR(info) == SNOR_MFR_INTEL ||
-           JEDEC_MFR(info) == SNOR_MFR_MACRONIX ||
--          JEDEC_MFR(info) == SNOR_MFR_SST) {
-+          JEDEC_MFR(info) == SNOR_MFR_SST ||
-+          info->flags & SPI_NOR_HAS_LOCK) {
+@@ -1180,6 +1327,7 @@ int spi_nor_scan(struct spi_nor *nor, co
+           info->flags & SPI_NOR_HAS_LOCK) {
                write_enable(nor);
                write_sr(nor, 0);
 +              spi_nor_wait_till_ready(nor);
        }
  
        if (!mtd->name)
-@@ -1175,7 +1325,8 @@ int spi_nor_scan(struct spi_nor *nor, co
-       mtd->_read = spi_nor_read;
-       /* NOR protection support for STmicro/Micron chips and similar */
--      if (JEDEC_MFR(info) == SNOR_MFR_MICRON) {
-+      if (JEDEC_MFR(info) == SNOR_MFR_MICRON ||
-+                      info->flags & SPI_NOR_HAS_LOCK) {
-               nor->flash_lock = stm_lock;
-               nor->flash_unlock = stm_unlock;
-               nor->flash_is_locked = stm_is_locked;
-@@ -1195,6 +1346,8 @@ int spi_nor_scan(struct spi_nor *nor, co
+@@ -1214,6 +1362,8 @@ int spi_nor_scan(struct spi_nor *nor, co
  
        if (info->flags & USE_FSR)
                nor->flags |= SNOR_F_USE_FSR;
@@ -4431,7 +4405,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
  
  #ifdef CONFIG_MTD_SPI_NOR_USE_4K_SECTORS
        /* prefer "small sector" erase if possible */
-@@ -1297,6 +1450,12 @@ int spi_nor_scan(struct spi_nor *nor, co
+@@ -1316,6 +1466,12 @@ int spi_nor_scan(struct spi_nor *nor, co
                nor->addr_width = 3;
        }
  
@@ -4698,7 +4672,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
  int INFTL_mount(struct INFTLrecord *s);
 --- a/include/linux/mtd/map.h
 +++ b/include/linux/mtd/map.h
-@@ -142,7 +142,9 @@
+@@ -137,7 +137,9 @@
  #endif
  
  #ifndef map_bankwidth
@@ -4708,7 +4682,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
  static inline int map_bankwidth(void *map)
  {
        BUG();
-@@ -238,8 +240,11 @@ struct map_info {
+@@ -233,8 +235,11 @@ struct map_info {
           If there is no cache to care about this can be set to NULL. */
        void (*inval_cache)(struct map_info *, unsigned long, ssize_t);
  
@@ -5168,7 +5142,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
                      long long offset, long long length);
 --- a/include/linux/mtd/sh_flctl.h
 +++ b/include/linux/mtd/sh_flctl.h
-@@ -143,11 +143,11 @@ enum flctl_ecc_res_t {
+@@ -143,7 +143,6 @@ enum flctl_ecc_res_t {
  struct dma_chan;
  
  struct sh_flctl {
@@ -5176,12 +5150,7 @@ Signed-off-by: John Crispin <blogic@openwrt.org>
        struct nand_chip        chip;
        struct platform_device  *pdev;
        struct dev_pm_qos_request pm_qos;
-       void __iomem            *reg;
-+      resource_size_t         fifo;
-       uint8_t done_buff[2048 + 64];   /* max size 2048 + 64 */
-       int     read_bytes;
-@@ -186,7 +186,7 @@ struct sh_flctl_platform_data {
+@@ -187,7 +186,7 @@ struct sh_flctl_platform_data {
  
  static inline struct sh_flctl *mtd_to_flctl(struct mtd_info *mtdinfo)
  {