forked from Minki/linux
MTD fixes for 4.12:
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 """ -----BEGIN PGP SIGNATURE----- Version: GnuPG v1 iQIcBAABAgAGBQJZMhESAAoJEFySrpd9RFgtZVMP/37yR+PzpS1MPLyQNPalVgFs qHH5pQHLnDRikgeQAMQacQK9/Du/7ei9RsFOfPyvaGQhRJDej9M6Vp8VKb63LgKz LfQXt/KrUiGyJa929Ew7QGXvxWHKsapPZMx9UiGxMMT/qUwyv4Gfcys/GfJEK2aO Sb5stx8WckRZr4j8dL2EX0Q6yB+BtAKavNWakEbaJYPwQSapsCgTejse7x+hjZDT cpcE3EXK/yLaQM21K3GD/g2gqeMKX6k/phxnYnt3kBBO8XVgH8MpimglRuo1/cZq H9y56GMamiBLX03XflsooLV6vHx7MWNOtUPRAHey1hilj7VuKfRj66zx1oVv/4iw PenKe7mS1Y3Eg1eXM+/0m30/X3tA0xUCWpJsoPdXn3lWcxhnfN8wXwQb0JJNulqE 9Msw1w7OswmtMnbX/YTamYMO0SLgY2Kv7BBGBp8YeXujIgpDBlVGaf3cjIo6U6sp 3IkllIMHEHFPxKdpxYMMzZ9O/kg6YdiX76IhnmNFt1Y2RZKn0f/9j+dNoMqBjC2A w++PJWJYrmibDYLP1dTiFR1u58j9HHJBkIlUstj/HkTNjsf/E1MLqF9P01EqEnnm gfzmwt7q/8ahE7mJQ84iA6H+GvFCpzay6T26ZnXEd1LequslVpNtQgUuDZhDo4FV rtDnrca0h3ZP1MsniP0d =y6Ps -----END PGP SIGNATURE----- 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
This commit is contained in:
commit
cc54874055
@ -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);
|
||||
|
@ -6,7 +6,6 @@
|
||||
* published by the Free Software Foundation.
|
||||
*
|
||||
*/
|
||||
#include <linux/module.h>
|
||||
#include <linux/mtd/nand.h>
|
||||
#include <linux/sizes.h>
|
||||
|
||||
|
@ -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 {
|
||||
|
@ -55,10 +55,10 @@
|
||||
* 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;
|
||||
|
||||
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 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,
|
||||
|
Loading…
Reference in New Issue
Block a user