]> git.karo-electronics.de Git - karo-tx-linux.git/commitdiff
Merge tag 'for-linus-20170602' of git://git.infradead.org/linux-mtd
authorLinus Torvalds <torvalds@linux-foundation.org>
Sat, 3 Jun 2017 15:42:30 +0000 (08:42 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Sat, 3 Jun 2017 15:42:30 +0000 (08:42 -0700)
Pull MTD fixes from Brian Norris:
 "NAND updates from Boris:

  tango fixes:
   - Add missing MODULE_DEVICE_TABLE() in tango_nand.c
   - Update the number of corrected bitflips

  core fixes:
   - Fix a long standing memory leak in nand_scan_tail()
   - Fix several bugs introduced by the per-vendor init/detection
     infrastructure (introduced in 4.12)
   - Add a static specifier to nand_ooblayout_lp_hamming_ops definition"

* tag 'for-linus-20170602' of git://git.infradead.org/linux-mtd:
  mtd: nand: make nand_ooblayout_lp_hamming_ops static
  mtd: nand: tango: Update ecc_stats.corrected
  mtd: nand: tango: Export OF device ID table as module aliases
  mtd: nand: samsung: warn about un-parseable ECC info
  mtd: nand: free vendor-specific resources in init failure paths
  mtd: nand: drop unneeded module.h include
  mtd: nand: don't leak buffers when ->scan_bbt() fails

drivers/mtd/nand/nand_base.c
drivers/mtd/nand/nand_ids.c
drivers/mtd/nand/nand_samsung.c
drivers/mtd/nand/tango_nand.c

index d474378ed810b3c3ab19d8a4e85e77e0eb15511c..b1dd12729f19b29ea8f35886aba02cc986990661 100644 (file)
@@ -202,7 +202,7 @@ static int nand_ooblayout_free_lp_hamming(struct mtd_info *mtd, int section,
        return 0;
 }
 
-const struct mtd_ooblayout_ops nand_ooblayout_lp_hamming_ops = {
+static const struct mtd_ooblayout_ops nand_ooblayout_lp_hamming_ops = {
        .ecc = nand_ooblayout_ecc_lp_hamming,
        .free = nand_ooblayout_free_lp_hamming,
 };
@@ -4361,7 +4361,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
        /* Initialize the ->data_interface field. */
        ret = nand_init_data_interface(chip);
        if (ret)
-               return ret;
+               goto err_nand_init;
 
        /*
         * Setup the data interface correctly on the chip and controller side.
@@ -4373,7 +4373,7 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
         */
        ret = nand_setup_data_interface(chip);
        if (ret)
-               return ret;
+               goto err_nand_init;
 
        nand_maf_id = chip->id.data[0];
        nand_dev_id = chip->id.data[1];
@@ -4404,6 +4404,12 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,
        mtd->size = i * chip->chipsize;
 
        return 0;
+
+err_nand_init:
+       /* Free manufacturer priv data. */
+       nand_manufacturer_cleanup(chip);
+
+       return ret;
 }
 EXPORT_SYMBOL(nand_scan_ident);
 
@@ -4574,18 +4580,23 @@ int nand_scan_tail(struct mtd_info *mtd)
 
        /* New bad blocks should be marked in OOB, flash-based BBT, or both */
        if (WARN_ON((chip->bbt_options & NAND_BBT_NO_OOB_BBM) &&
-                  !(chip->bbt_options & NAND_BBT_USE_FLASH)))
-               return -EINVAL;
+                  !(chip->bbt_options & NAND_BBT_USE_FLASH))) {
+               ret = -EINVAL;
+               goto err_ident;
+       }
 
        if (invalid_ecc_page_accessors(chip)) {
                pr_err("Invalid ECC page accessors setup\n");
-               return -EINVAL;
+               ret = -EINVAL;
+               goto err_ident;
        }
 
        if (!(chip->options & NAND_OWN_BUFFERS)) {
                nbuf = kzalloc(sizeof(*nbuf), GFP_KERNEL);
-               if (!nbuf)
-                       return -ENOMEM;
+               if (!nbuf) {
+                       ret = -ENOMEM;
+                       goto err_ident;
+               }
 
                nbuf->ecccalc = kmalloc(mtd->oobsize, GFP_KERNEL);
                if (!nbuf->ecccalc) {
@@ -4608,8 +4619,10 @@ int nand_scan_tail(struct mtd_info *mtd)
 
                chip->buffers = nbuf;
        } else {
-               if (!chip->buffers)
-                       return -ENOMEM;
+               if (!chip->buffers) {
+                       ret = -ENOMEM;
+                       goto err_ident;
+               }
        }
 
        /* Set the internal oob buffer location, just after the page data */
@@ -4842,7 +4855,11 @@ int nand_scan_tail(struct mtd_info *mtd)
                return 0;
 
        /* Build bad block table */
-       return chip->scan_bbt(mtd);
+       ret = chip->scan_bbt(mtd);
+       if (ret)
+               goto err_free;
+       return 0;
+
 err_free:
        if (nbuf) {
                kfree(nbuf->databuf);
@@ -4850,6 +4867,13 @@ err_free:
                kfree(nbuf->ecccalc);
                kfree(nbuf);
        }
+
+err_ident:
+       /* Clean up nand_scan_ident(). */
+
+       /* Free manufacturer priv data. */
+       nand_manufacturer_cleanup(chip);
+
        return ret;
 }
 EXPORT_SYMBOL(nand_scan_tail);
index 9d5ca0e540b5bc5c9e3be9a6a3b476624e63be14..92e2cf8e9ff9066860973caaf60ecb95e2d4a599 100644 (file)
@@ -6,7 +6,6 @@
  * published by the Free Software Foundation.
  *
  */
-#include <linux/module.h>
 #include <linux/mtd/nand.h>
 #include <linux/sizes.h>
 
index 9cfc4035a420a3eae2d2a451c97f5300f8bc8b80..1e0755997762aa23ee953ad20f2a88d24dc7139c 100644 (file)
@@ -84,6 +84,9 @@ static void samsung_nand_decode_id(struct nand_chip *chip)
                        case 7:
                                chip->ecc_strength_ds = 60;
                                break;
+                       default:
+                               WARN(1, "Could not decode ECC info");
+                               chip->ecc_step_ds = 0;
                        }
                }
        } else {
index 05b6e106520331ddd48f619f798d21c4cfeb2059..49b286c6c10fc85e5ee7e75f4dd10d231c86c73f 100644 (file)
  * byte 1 for other packets in the page (PKT_N, for N > 0)
  * ERR_COUNT_PKT_N is the max error count over all but the first packet.
  */
-#define DECODE_OK_PKT_0(v)     ((v) & BIT(7))
-#define DECODE_OK_PKT_N(v)     ((v) & BIT(15))
 #define ERR_COUNT_PKT_0(v)     (((v) >> 0) & 0x3f)
 #define ERR_COUNT_PKT_N(v)     (((v) >> 8) & 0x3f)
+#define DECODE_FAIL_PKT_0(v)   (((v) & BIT(7)) == 0)
+#define DECODE_FAIL_PKT_N(v)   (((v) & BIT(15)) == 0)
 
 /* Offsets relative to pbus_base */
 #define PBUS_CS_CTRL   0x83c
@@ -193,6 +193,8 @@ static int check_erased_page(struct nand_chip *chip, u8 *buf)
                                                  chip->ecc.strength);
                if (res < 0)
                        mtd->ecc_stats.failed++;
+               else
+                       mtd->ecc_stats.corrected += res;
 
                bitflips = max(res, bitflips);
                buf += pkt_size;
@@ -202,9 +204,11 @@ static int check_erased_page(struct nand_chip *chip, u8 *buf)
        return bitflips;
 }
 
-static int decode_error_report(struct tango_nfc *nfc)
+static int decode_error_report(struct nand_chip *chip)
 {
        u32 status, res;
+       struct mtd_info *mtd = nand_to_mtd(chip);
+       struct tango_nfc *nfc = to_tango_nfc(chip->controller);
 
        status = readl_relaxed(nfc->reg_base + NFC_XFER_STATUS);
        if (status & PAGE_IS_EMPTY)
@@ -212,10 +216,14 @@ static int decode_error_report(struct tango_nfc *nfc)
 
        res = readl_relaxed(nfc->mem_base + ERROR_REPORT);
 
-       if (DECODE_OK_PKT_0(res) && DECODE_OK_PKT_N(res))
-               return max(ERR_COUNT_PKT_0(res), ERR_COUNT_PKT_N(res));
+       if (DECODE_FAIL_PKT_0(res) || DECODE_FAIL_PKT_N(res))
+               return -EBADMSG;
+
+       /* ERR_COUNT_PKT_N is max, not sum, but that's all we have */
+       mtd->ecc_stats.corrected +=
+               ERR_COUNT_PKT_0(res) + ERR_COUNT_PKT_N(res);
 
-       return -EBADMSG;
+       return max(ERR_COUNT_PKT_0(res), ERR_COUNT_PKT_N(res));
 }
 
 static void tango_dma_callback(void *arg)
@@ -282,7 +290,7 @@ static int tango_read_page(struct mtd_info *mtd, struct nand_chip *chip,
        if (err)
                return err;
 
-       res = decode_error_report(nfc);
+       res = decode_error_report(chip);
        if (res < 0) {
                chip->ecc.read_oob_raw(mtd, chip, page);
                res = check_erased_page(chip, buf);
@@ -663,6 +671,7 @@ static const struct of_device_id tango_nand_ids[] = {
        { .compatible = "sigma,smp8758-nand" },
        { /* sentinel */ }
 };
+MODULE_DEVICE_TABLE(of, tango_nand_ids);
 
 static struct platform_driver tango_nand_driver = {
        .probe  = tango_nand_probe,