Commit cc548740 authored by Linus Torvalds's avatar Linus Torvalds

Merge tag 'for-linus-20170602' of git://git.infradead.org/linux-mtd

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