mtd: nand: don't leak buffers when ->scan_bbt() fails
Subsystems (2)
PATCH 1/1 mtd: nand: don't leak buffers when ->scan_bbt() fails
This bug seems to have been here forever, although we came close to fixing all of them in [1]!
[1] 11eaf6df1cce ("mtd: nand: Remove BUG() abuse in nand_scan_tail")
---
The goto isn't *really* necessary, but I thought it'd be more consistent.
Compile tested only
drivers/mtd/nand/nand_base.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)
drivers/mtd/nand/nand_base.c +5 -1
@@ -4794,7 +4794,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);
Signature · 1 line
2.13.0.rc1.294.g07d810a77f-goog
PATCH 1/1 mtd: nand: samsung: warn about un-parseable ECC info
We don't handle cases larger than 7. We probably shouldn't pretend we know the ECC step size in this case, and it's probably also good to WARN() like we do in many other similar cases.
---
Compile tested only
drivers/mtd/nand/nand_samsung.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/mtd/nand/nand_samsung.c +3 -0
@@ -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 {
Signature · 1 line
2.13.0.rc1.294.g07d810a77f-goog
Re: [PATCH] mtd: nand: samsung: warn about un-parseable ECC info
Quoted 7 lines · On Mon, 1 May 2017 17:04:55 -0700 Brian Norris <[email protected]>…
We don't handle cases larger than 7. We probably shouldn't pretend we know the ECC step size in this case, and it's probably also good to
WARN()like we do in many other similar cases.Cc Hans de Goede <[email protected]>Fixes 8fc82d456e40 ("mtd: nand: samsung: Retrieve ECC requirements from extended ID")Signed-off-by Brian Norris <[email protected]>
Quoted 20 lines
---
Compile tested onlydrivers/mtd/nand/nand_samsung.c | 3 +++ 1 file changed, 3 insertions(+)drivers/mtd/nand/nand_samsung.c +3
-0@@ -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 {
Boris Brezillon
AppliedRe: [PATCH] mtd: nand: samsung: warn about un-parseable ECC info
In reply to Brian NorrisQuoted 7 lines · On Mon, 1 May 2017 17:04:55 -0700 Brian Norris <[email protected]>…
We don't handle cases larger than 7. We probably shouldn't pretend we know the ECC step size in this case, and it's probably also good to
WARN()like we do in many other similar cases.Cc Hans de Goede <[email protected]>Fixes 8fc82d456e40 ("mtd: nand: samsung: Retrieve ECC requirements from extended ID")Signed-off-by Brian Norris <[email protected]>
Applied to nand/fixes.
Thanks,
Boris
Quoted 20 lines
---
Compile tested onlydrivers/mtd/nand/nand_samsung.c | 3 +++ 1 file changed, 3 insertions(+)drivers/mtd/nand/nand_samsung.c +3
-0@@ -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 {
PATCH 1/1 mtd: nand: don't make vendor-specific code un-set their data pointer
In reply to Brian NorrisIt makes sense to do this in nand_base.
(Alternatively: we don't really need to do this at all.)
---
Compile tested only
drivers/mtd/nand/nand_base.c | 11 +++++++++-- drivers/mtd/nand/nand_hynix.c | 1 - 2 files changed, 9 insertions(+), 3 deletions(-)
drivers/mtd/nand/nand_base.c +9 -2
@@ -3910,11 +3910,16 @@ static void nand_manufacturer_detect(struct nand_chip *chip)*/ static int nand_manufacturer_init (struct nand_chip *chip) { +int ret; +if (!chip->manufacturer.desc || !chip->manufacturer.desc->ops || !chip->manufacturer.desc->ops->init)return 0 ; -return chip->manufacturer.desc->ops->init (chip); + ret = chip->manufacturer.desc->ops->init (chip); +if (ret) +nand_set_manufacturer_data (chip,NULL ); +return ret; }/*
@@ -3927,8 +3932,10 @@ static void nand_manufacturer_cleanup(struct nand_chip *chip) {/* Release manufacturer private data */ if (chip->manufacturer.desc && chip->manufacturer.desc->ops && - chip->manufacturer.desc->ops->cleanup) + chip->manufacturer.desc->ops->cleanup) { chip->manufacturer.desc->ops->cleanup (chip); +nand_set_manufacturer_data (chip,NULL ); + } }/*
drivers/mtd/nand/nand_hynix.c +0 -1
@@ -598,7 +598,6 @@ static void hynix_nand_cleanup(struct nand_chip *chip)kfree (hynix->read_retry);kfree (hynix); -nand_set_manufacturer_data (chip,NULL ); }static int hynix_nand_init (struct nand_chip *chip)
Signature · 1 line
2.13.0.rc1.294.g07d810a77f-goog
Re: [PATCH] mtd: nand: don't make vendor-specific code un-set their data pointer
Quoted 3 lines · On Mon, 1 May 2017 17:04:51 -0700 Brian Norris <[email protected]>…
It makes sense to do this in
nand_base.(Alternatively: we don't really need to do this at all.)
Actually, I was just trying to handle a potential 'double-free' error nicely (see the 'if (hynix) return;' statement at the beginning of hynix_nand_cleanup(), but I'm not sure this was a good idea.
Let's drop this assignment.
Quoted 55 lines
Signed-off-by Brian Norris <[email protected]>---
Compile tested onlydrivers/mtd/nand/nand_base.c | 11 +++++++++-- drivers/mtd/nand/nand_hynix.c | 1 - 2 files changed, 9 insertions(+), 3 deletions(-)drivers/mtd/nand/nand_base.c +9
-2@@ -3910,11 +3910,16 @@ static void nand_manufacturer_detect(struct nand_chip *chip)*/ static int nand_manufacturer_init (struct nand_chip *chip) { +int ret; +if (!chip->manufacturer.desc || !chip->manufacturer.desc->ops || !chip->manufacturer.desc->ops->init)return 0 ; -return chip->manufacturer.desc->ops->init (chip); + ret = chip->manufacturer.desc->ops->init (chip); +if (ret) +nand_set_manufacturer_data (chip,NULL ); +return ret; }/* @@ -3927,8 +3932,10 @@ static void nand_manufacturer_cleanup(struct nand_chip *chip) {/* Release manufacturer private data */ if (chip->manufacturer.desc && chip->manufacturer.desc->ops && - chip->manufacturer.desc->ops->cleanup) + chip->manufacturer.desc->ops->cleanup) { chip->manufacturer.desc->ops->cleanup (chip); +nand_set_manufacturer_data (chip,NULL ); + } }/* drivers/mtd/nand/nand_hynix.c +0
-1@@ -598,7 +598,6 @@ static void hynix_nand_cleanup(struct nand_chip *chip)kfree (hynix->read_retry);kfree (hynix); -nand_set_manufacturer_data (chip,NULL ); }static int hynix_nand_init (struct nand_chip *chip)
PATCH 1/1 mtd: nand: drop unneeded module.h include
In reply to Brian Norrisnand_ids isn't a separate module anymore and doesn't need this header.
--- drivers/mtd/nand/nand_ids.c | 1 - 1 file changed, 1 deletion(-)
drivers/mtd/nand/nand_ids.c +0 -1
@@ -6,7 +6,6 @@* published by the Free Software Foundation. * */ -#include <linux/module.h> #include <linux/mtd/nand.h> #include <linux/sizes.h>
Signature · 1 line
2.13.0.rc1.294.g07d810a77f-goog
Re: [PATCH] mtd: nand: drop unneeded module.h include
Quoted 3 lines · On Mon, 1 May 2017 17:04:52 -0700 Brian Norris <[email protected]>…
nand_idsisn't a separate module anymore and doesn't need this header.Signed-off-by Brian Norris <[email protected]>
Quoted 16 lines
--- drivers/mtd/nand/nand_ids.c | 1 - 1 file changed, 1 deletion(-)drivers/mtd/nand/nand_ids.c +0
-1@@ -6,7 +6,6 @@* published by the Free Software Foundation. * */ -#include <linux/module.h> #include <linux/mtd/nand.h> #include <linux/sizes.h>
Boris Brezillon
AppliedRe: [PATCH] mtd: nand: drop unneeded module.h include
In reply to Brian NorrisQuoted 3 lines · On Mon, 1 May 2017 17:04:52 -0700 Brian Norris <[email protected]>…
nand_idsisn't a separate module anymore and doesn't need this header.Signed-off-by Brian Norris <[email protected]>
Applied to nand/fixes.
Thanks,
Boris
Quoted 16 lines
--- drivers/mtd/nand/nand_ids.c | 1 - 1 file changed, 1 deletion(-)drivers/mtd/nand/nand_ids.c +0
-1@@ -6,7 +6,6 @@* published by the Free Software Foundation. * */ -#include <linux/module.h> #include <linux/mtd/nand.h> #include <linux/sizes.h>
PATCH 1/1 mtd: nand: free vendor-specific resources in init failure paths
In reply to Brian NorrisIf we fail any time after calling nand_detect(), then we don't call the vendor-specific ->cleanup() callback, and we'll leak any resources the vendor-specific code might have allocated.
Mark the "fix" against the first commit that started allocating anything in ->init().
---
Compile tested only
drivers/mtd/nand/nand_base.c | 38 +++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-)
drivers/mtd/nand/nand_base.c +29 -9
@@ -4300,7 +4300,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.
@@ -4312,7 +4312,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 ];
@@ -4343,6 +4343,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);
@@ -4513,18 +4519,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) {
@@ -4547,8 +4558,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 */
@@ -4789,6 +4802,13 @@ int nand_scan_tail(struct mtd_info *mtd)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);
Signature · 1 line
2.13.0.rc1.294.g07d810a77f-goog
Re: [PATCH] mtd: nand: free vendor-specific resources in init failure paths
Quoted 6 lines · On Mon, 1 May 2017 17:04:53 -0700 Brian Norris <[email protected]>…
If we fail any time after calling
nand_detect(), then we don't call the vendor-specific ->cleanup() callback, and we'll leak any resources the vendor-specific code might have allocated.Mark the "fix" against the first commit that started allocating anything in ->init().
Yep, I noticed this leak while reviewing/applying Masahiro's series [1], and forgot to send a fix for this bug.
Actually, I'm not sure we should keep nand_manufacturer_init() in nand_scan_ident(), especially if we consider that nand_scan_ident() is not supposed to allocate resources and does not require a nand_cleanup() when something fails between nand_scan_ident() and nand_scan_tail().
Note that nand_scan_ident() is already allocating resources through nand_init_data_interface() which are also leaked if nand_cleanup() is not called. Again, we could solve the problem by moving data-iface initialization steps in nand_scan_tail() (which shouldn't be a problem AFAICS). Alternatively, we could could consider that nand_cleanup() is smart enough to know what to not release (which seems to be the case already), and force drivers to call nand_cleanup() as soon as nand_scan_ident() has returned 0.
Brian, any opinion?
Anyway, this is a bit off-topic, so for this patch
Quoted 101 lines
Cc Boris Brezillon <[email protected]>Fixes 626994e07480 ("mtd: nand: hynix: Add read-retry support for 1x nm MLC NANDs")Signed-off-by Brian Norris <[email protected]>---
Compile tested onlydrivers/mtd/nand/nand_base.c | 38 +++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-)drivers/mtd/nand/nand_base.c +29
-9@@ -4300,7 +4300,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. @@ -4312,7 +4312,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 ];@@ -4343,6 +4343,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);@@ -4513,18 +4519,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) {@@ -4547,8 +4558,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 */ @@ -4789,6 +4802,13 @@ int nand_scan_tail(struct mtd_info *mtd)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);
Re: [PATCH] mtd: nand: free vendor-specific resources in init failure paths
Quoted 10 lines · On Tue, 2 May 2017 09:52:30 +0200 Boris Brezillon…
Quoted 6 lines · On Mon, 1 May 2017 17:04:53 -0700 Brian Norris <[email protected]>…
If we fail any time after calling
nand_detect(), then we don't call the vendor-specific ->cleanup() callback, and we'll leak any resources the vendor-specific code might have allocated.Mark the "fix" against the first commit that started allocating anything in ->init().
Quoted 9 lines
Yep, I noticed this leak while reviewing/applying Masahiro's series [1], and forgot to send a fix for this bug.
Actually, I'm not sure we should keep
nand_manufacturer_init()innand_scan_ident(), especially if we consider thatnand_scan_ident()is not supposed to allocate resources and does not require anand_cleanup()when something fails betweennand_scan_ident()andnand_scan_tail().
Just for the record, this is the kind of fix I had in mind, but it can still be applied on top of your patch.
--->8---
From fd918ec7ed960792f020227b675838fee6f710d9 Mon Sep 17 00:00:00 2001
From: Boris Brezillon <[email protected]>
Date: Tue, 2 May 2017 18:10:18 +0200
Subject: [PATCH] mtd: nand: Fix various memory leaks in core
The nand_scan_ident() function is not expected to allocate resources, and people are usually not calling nand_cleanup() if something fails between nand_scan_ident() and nand_scan_tail().
Move all functions that may allocate resource to the nand_scan_tail() path to prevent such resource leaks.
---
Only compile tested.
--- drivers/mtd/nand/nand_base.c | 79 ++++++++++++++++++++++++-------------------- 1 file changed, 44 insertions(+), 35 deletions(-)
drivers/mtd/nand/nand_base.c +44 -35
@@ -3939,7 +3939,7 @@ static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type)const struct nand_manufacturer *manufacturer;struct mtd_info *mtd =nand_to_mtd (chip);int busw; -int i, ret; +int i;u8 *id_data = chip->id.data;u8 maf_id, dev_id;
@@ -4080,10 +4080,6 @@ static int nand_detect(struct nand_chip *chip, struct nand_flash_dev *type)if (mtd->writesize >512 && chip->cmdfunc == nand_command) chip->cmdfunc = nand_command_lp; - ret =nand_manufacturer_init (chip); -if (ret) -return ret; -pr_info ("device found, Manufacturer ID: 0x%02x, Chip ID: 0x%02x\n" , maf_id, dev_id);
@@ -4290,23 +4286,6 @@ int nand_scan_ident(struct mtd_info *mtd, int maxchips,return ret; } -/* Initialize the ->data_interface field. */ - ret =nand_init_data_interface (chip); -if (ret) -return ret; - -/* -* Setup the data interface correctly on the chip and controller side. -* This explicit call to nand_setup_data_interface() is only required -* for the first die, because nand_reset() has been called before -* ->data_interface and ->default_onfi_timing_mode were set. -* For the other dies, nand_reset() will automatically switch to the -* best mode for us. -*/ - ret =nand_setup_data_interface (chip); -if (ret) -return ret; - nand_maf_id = chip->id.data[0 ]; nand_dev_id = chip->id.data[1 ];
@@ -4502,7 +4481,7 @@ int nand_scan_tail(struct mtd_info *mtd)struct nand_chip *chip =mtd_to_nand (mtd);struct nand_ecc_ctrl *ecc = &chip->ecc;struct nand_buffers *nbuf =NULL ; -int ret; +int ret, i;/* New bad blocks should be marked in OOB, flash-based BBT, or both */ if (WARN_ON((chip->bbt_options & NAND_BBT_NO_OOB_BBM) &&
@@ -4522,20 +4501,20 @@ int nand_scan_tail(struct mtd_info *mtd) nbuf->ecccalc =kmalloc (mtd->oobsize,GFP_KERNEL );if (!nbuf->ecccalc) { ret = -ENOMEM ; - goto err_free; + goto err_free_nbuf; } nbuf->ecccode =kmalloc (mtd->oobsize,GFP_KERNEL );if (!nbuf->ecccode) { ret = -ENOMEM ; - goto err_free; + goto err_free_nbuf; } nbuf->databuf =kmalloc (mtd->writesize + mtd->oobsize,GFP_KERNEL );if (!nbuf->databuf) { ret = -ENOMEM ; - goto err_free; + goto err_free_nbuf; } chip->buffers = nbuf;
@@ -4544,6 +4523,10 @@ int nand_scan_tail(struct mtd_info *mtd)return -ENOMEM ; } + ret =nand_manufacturer_init (chip); +if (ret) + goto err_free_nbuf; +/* Set the internal oob buffer location, just after the page data */ chip->oob_poi = chip->buffers->databuf + mtd->writesize;
@@ -4565,7 +4548,7 @@ int nand_scan_tail(struct mtd_info *mtd)WARN (1 ,"No oob scheme defined for oobsize %d\n" , mtd->oobsize); ret = -EINVAL ; - goto err_free; + goto err_nand_manuf_cleanup; } }
@@ -4580,7 +4563,7 @@ int nand_scan_tail(struct mtd_info *mtd)if (!ecc->calculate || !ecc->correct || !ecc->hwctl) {WARN (1 ,"No ECC functions supplied; hardware ECC not possible\n" ); ret = -EINVAL ; - goto err_free; + goto err_nand_manuf_cleanup; }if (!ecc->read_page) ecc->read_page = nand_read_page_hwecc_oob_first;
@@ -4612,7 +4595,7 @@ int nand_scan_tail(struct mtd_info *mtd) ecc->write_page == nand_write_page_hwecc)) {WARN (1 ,"No ECC functions supplied; hardware ECC not possible\n" ); ret = -EINVAL ; - goto err_free; + goto err_nand_manuf_cleanup; }/* Use standard syndrome read/write page function? */ if (!ecc->read_page)
@@ -4632,7 +4615,7 @@ int nand_scan_tail(struct mtd_info *mtd)if (!ecc->strength) {WARN (1 ,"Driver must set ecc.strength when using hardware ECC\n" ); ret = -EINVAL ; - goto err_free; + goto err_nand_manuf_cleanup; }break ; }
@@ -4645,7 +4628,7 @@ int nand_scan_tail(struct mtd_info *mtd) ret =nand_set_ecc_soft_ops (mtd);if (ret) { ret = -EINVAL ; - goto err_free; + goto err_nand_manuf_cleanup; }break ;
@@ -4665,7 +4648,7 @@ int nand_scan_tail(struct mtd_info *mtd)default :WARN (1 ,"Invalid NAND_ECC_MODE %d\n" , ecc->mode); ret = -EINVAL ; - goto err_free; + goto err_nand_manuf_cleanup; }/* For many systems, the standard OOB write also works for raw */
@@ -4686,7 +4669,7 @@ int nand_scan_tail(struct mtd_info *mtd)if (ecc->steps * ecc->size != mtd->writesize) {WARN (1 ,"Invalid ECC parameters\n" ); ret = -EINVAL ; - goto err_free; + goto err_nand_manuf_cleanup; } ecc->total = ecc->steps * ecc->bytes;
@@ -4769,13 +4752,39 @@ int nand_scan_tail(struct mtd_info *mtd)if (!mtd->bitflip_threshold) mtd->bitflip_threshold =DIV_ROUND_UP (mtd->ecc_strength *3 ,4 ); +/* Initialize the ->data_interface field. */ + ret =nand_init_data_interface (chip); +if (ret) + goto err_nand_manuf_cleanup; + +/* Enter fastest possible mode on all dies. */ +for (i =0 ; i < chip->numchips; i++) { + chip->select_chip (mtd, i); + ret =nand_setup_data_interface (chip); + chip->select_chip (mtd,-1 ); + +if (ret) + goto err_nand_data_iface_cleanup; + } +/* Check, if we should skip the bad block table scan */ if (chip->options &NAND_SKIP_BBTSCAN )return 0 ;/* Build bad block table */ -return chip->scan_bbt (mtd); -err_free: + ret = chip->scan_bbt (mtd); +if (ret) + goto err_nand_data_iface_cleanup; + +return 0 ; + +err_nand_data_iface_cleanup: +nand_release_data_interface (chip); + +err_nand_manuf_cleanup: +nand_manufacturer_cleanup (chip); + +err_free_nbuf:if (nbuf) {kfree (nbuf->databuf);kfree (nbuf->ecccode);
Boris Brezillon
AppliedRe: [PATCH] mtd: nand: free vendor-specific resources in init failure paths
In reply to Brian NorrisQuoted 10 lines · On Mon, 1 May 2017 17:04:53 -0700 Brian Norris <[email protected]>…
If we fail any time after calling
nand_detect(), then we don't call the vendor-specific ->cleanup() callback, and we'll leak any resources the vendor-specific code might have allocated.Mark the "fix" against the first commit that started allocating anything in ->init().
Cc Boris Brezillon <[email protected]>Fixes 626994e07480 ("mtd: nand: hynix: Add read-retry support for 1x nm MLC NANDs")Signed-off-by Brian Norris <[email protected]>
Applied to nand/fixes.
Thanks,
Boris
Quoted 97 lines
---
Compile tested onlydrivers/mtd/nand/nand_base.c | 38 +++++++++++++++++++++++++++++--------- 1 file changed, 29 insertions(+), 9 deletions(-)drivers/mtd/nand/nand_base.c +29
-9@@ -4300,7 +4300,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. @@ -4312,7 +4312,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 ];@@ -4343,6 +4343,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);@@ -4513,18 +4519,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) {@@ -4547,8 +4558,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 */ @@ -4789,6 +4802,13 @@ int nand_scan_tail(struct mtd_info *mtd)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);
PATCH 1/1 mtd: nand: orion: don't complain for probe deferral
In reply to Brian NorrisRecent patches to this driver changed the error handling for missing clocks. Now we'll print an error if the clock causes us to defer probing. Let's not do that.
---
Compile tested only
drivers/mtd/nand/orion_nand.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)
drivers/mtd/nand/orion_nand.c +2 -1
@@ -161,7 +161,8 @@ static int __init orion_nand_probe(struct platform_device *pdev)if (ret == -ENOENT ) { info->clk =NULL ; }else { -dev_err (&pdev->dev,"failed to get clock!\n" ); +if (ret != -EPROBE_DEFER ) +dev_err (&pdev->dev,"failed to get clock!\n" );return ret; } }
Signature · 1 line
2.13.0.rc1.294.g07d810a77f-goog
Re: [PATCH] mtd: nand: orion: don't complain for probe deferral
Quoted 6 lines · On Mon, 1 May 2017 17:04:54 -0700 Brian Norris <[email protected]>…
Recent patches to this driver changed the error handling for missing clocks. Now we'll print an error if the clock causes us to defer probing. Let's not do that.
Cc Simon Baatz <[email protected]>Signed-off-by Brian Norris <[email protected]>
Quoted 20 lines
---
Compile tested onlydrivers/mtd/nand/orion_nand.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-)drivers/mtd/nand/orion_nand.c +2
-1@@ -161,7 +161,8 @@ static int __init orion_nand_probe(struct platform_device *pdev)if (ret == -ENOENT ) { info->clk =NULL ; }else { -dev_err (&pdev->dev,"failed to get clock!\n" ); +if (ret != -EPROBE_DEFER ) +dev_err (&pdev->dev,"failed to get clock!\n" );return ret; } }
Re: [PATCH] mtd: nand: orion: don't complain for probe deferral
In reply to Brian NorrisHi Brian,
Quoted 4 lines · Brian Norris
Recent patches to this driver changed the error handling for missing clocks. Now we'll print an error if the clock causes us to defer probing. Let's not do that.
This is by intention. Probe deferral is not supported by drivers using module_platform_driver_probe(). EPROBE_DEFER results in not being able to get the clock and, thus, is handled like any other error.
- Simon
Re: [PATCH] mtd: nand: orion: don't complain for probe deferral
Quoted 8 lines · Simon Baatz
Hi Brian,
Quoted 4 lines · Brian Norris
Recent patches to this driver changed the error handling for missing clocks. Now we'll print an error if the clock causes us to defer probing. Let's not do that.
Quoted 4 lines
This is by intention. Probe deferral is not supported by drivers using
module_platform_driver_probe().EPROBE_DEFERresults in not being able to get the clock and, thus, is handled like any other error.
Ah, good point. I overlooked that part.
Seems kind of inconsistent driver writing (what happens if someone wants to use this driver on a more complex system, where some of the dependent resources are not available at init time?), but I see in the git logs that apparently this is intentional (to save memory?).
So, I'll NAK this patch.
Brian
Quoted 5 lines · Brian Norris
This bug seems to have been here forever, although we came close to fixing all of them in [1]!
[1]
11eaf6df1cce("mtd: nand: RemoveBUG()abuse innand_scan_tail")
Well, we came even closer. See [1] for a patch that fixes this by cleaning BBT init and release.
Back then Boris suggested on IRC to wait for Peter Pan's BBT, which would address this too.
It's interesting to note that: (1) the patch never got any formal feedback, despite it was a fix; and (2) Peter Pan's work is still under development.
Guess I should have pressed the upstream buttons harder :-)
[1] http://lists.infradead.org/pipermail/linux-mtd/2016-April/066834.html,
[2] http://lists.infradead.org/pipermail/linux-mtd/2016-April/066835.html
Signature · 2 lines
Ezequiel García, VanguardiaSur www.vanguardiasur.com.ar
Quoted 9 lines · Ezequiel Garcia
Quoted 5 lines · Brian Norris
This bug seems to have been here forever, although we came close to fixing all of them in [1]!
[1]
11eaf6df1cce("mtd: nand: RemoveBUG()abuse innand_scan_tail")Well, we came even closer. See [1] for a patch that fixes this by cleaning BBT init and release.
That's a different bug(fix), no?
Quoted 2 lines
Back then Boris suggested on IRC to wait for Peter Pan's BBT, which would address this too.
Haha, well bad strategy I guess :)
Quoted 2 lines
It's interesting to note that: (1) the patch never got any formal feedback, despite it was a fix; and (2) Peter Pan's work is still under development.
Yes, well you kinda nacked yourself, so (1) isn't that surprising. And
(2) is well...no comment.
Quoted 1 line
Guess I should have pressed the upstream buttons harder :-)
I suppose.
I'd be happy to see you resubmit, since I definitely would prioritize bugfixes over years-long refactoring. But I guess I'd defer to Boris, et al, who are paying much more attention to NAND stuff these days than I am. I just noticed this when bugfixing some things I noticed in Boris's pull request.
Brian
Quoted 5 lines
[1] http://lists.infradead.org/pipermail/linux-mtd/2016-April/066834.html,
[2] http://lists.infradead.org/pipermail/linux-mtd/2016-April/066835.htmlSignature · 2 lines
Ezequiel García, VanguardiaSur www.vanguardiasur.com.ar
Ezequiel Garcia
Acked-byQuoted 5 lines · Brian Norris
Quoted 4 lines · Ezequiel Garcia
Quoted 3 lines · Brian Norris
This bug seems to have been here forever, although we came close to fixing all of them in [1]!
Quoted 8 lines
Quoted 5 lines
Quoted 2 lines
[1]
11eaf6df1cce("mtd: nand: RemoveBUG()abuse innand_scan_tail")Well, we came even closer. See [1] for a patch that fixes this by cleaning BBT init and release.
That's a different bug(fix), no?
Oops, I really jumped on the gun here. The patch looks good.
Signature · 2 lines
Ezequiel García, VanguardiaSur www.vanguardiasur.com.ar
Quoted 7 lines · On Mon, 1 May 2017 17:04:50 -0700 Brian Norris <[email protected]>…
This bug seems to have been here forever, although we came close to fixing all of them in [1]!
[1]
11eaf6df1cce("mtd: nand: RemoveBUG()abuse innand_scan_tail")Cc Ezequiel Garcia <[email protected]>Signed-off-by Brian Norris <[email protected]>
Quoted 25 lines
---
The goto isn't *really* necessary, but I thought it'd be more consistent.Compile tested only
drivers/mtd/nand/nand_base.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)drivers/mtd/nand/nand_base.c +5
-1@@ -4794,7 +4794,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);
Boris Brezillon
AppliedQuoted 7 lines · On Mon, 1 May 2017 17:04:50 -0700 Brian Norris <[email protected]>…
This bug seems to have been here forever, although we came close to fixing all of them in [1]!
[1]
11eaf6df1cce("mtd: nand: RemoveBUG()abuse innand_scan_tail")Cc Ezequiel Garcia <[email protected]>Signed-off-by Brian Norris <[email protected]>
Applied to nand/fixes.
Thanks,
Boris
Quoted 25 lines
---
The goto isn't *really* necessary, but I thought it'd be more consistent.Compile tested only
drivers/mtd/nand/nand_base.c | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-)drivers/mtd/nand/nand_base.c +5
-1@@ -4794,7 +4794,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);