From: Richard Weinberger <rich...@nod.at> Provide a __nand_release() function for drivers which can deal with a failing nand release operation. Most drivers should be safe since they rely on module refcounting. To catch outliers implement a nand_release() with a WARN_ON().
Signed-off-by: Richard Weinberger <rich...@nod.at> --- drivers/mtd/nand/nand_base.c | 15 ++++++++++----- include/linux/mtd/nand.h | 12 +++++++++++- 2 files changed, 21 insertions(+), 6 deletions(-) diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c index 77533f7..d5608dd 100644 --- a/drivers/mtd/nand/nand_base.c +++ b/drivers/mtd/nand/nand_base.c @@ -4601,19 +4601,22 @@ int nand_scan(struct mtd_info *mtd, int maxchips) EXPORT_SYMBOL(nand_scan); /** - * nand_release - [NAND Interface] Free resources held by the NAND device + * __nand_release - [NAND Interface] Free resources held by the NAND device * @mtd: MTD device structure */ -void nand_release(struct mtd_info *mtd) +int __nand_release(struct mtd_info *mtd) { + int ret; struct nand_chip *chip = mtd_to_nand(mtd); + ret = mtd_device_unregister(mtd); + if (ret) + return ret; + if (chip->ecc.mode == NAND_ECC_SOFT && chip->ecc.algo == NAND_ECC_BCH) nand_bch_free((struct nand_bch_control *)chip->ecc.priv); - mtd_device_unregister(mtd); - /* Free bad block table memory */ kfree(chip->bbt); if (!(chip->options & NAND_OWN_BUFFERS)) @@ -4623,8 +4626,10 @@ void nand_release(struct mtd_info *mtd) if (chip->badblock_pattern && chip->badblock_pattern->options & NAND_BBT_DYNAMICSTRUCT) kfree(chip->badblock_pattern); + + return 0; } -EXPORT_SYMBOL_GPL(nand_release); +EXPORT_SYMBOL_GPL(__nand_release); MODULE_LICENSE("GPL"); MODULE_AUTHOR("Steven J. Hill <sjh...@realitydiluted.com>"); diff --git a/include/linux/mtd/nand.h b/include/linux/mtd/nand.h index 8dd6e01..06be25e 100644 --- a/include/linux/mtd/nand.h +++ b/include/linux/mtd/nand.h @@ -39,7 +39,7 @@ extern int nand_scan_ident(struct mtd_info *mtd, int max_chips, extern int nand_scan_tail(struct mtd_info *mtd); /* Free resources held by the NAND device */ -extern void nand_release(struct mtd_info *mtd); +extern int __nand_release(struct mtd_info *mtd); /* Internal helper for board drivers which need to override command function */ extern void nand_wait_ready(struct mtd_info *mtd); @@ -1023,6 +1023,16 @@ static inline int jedec_feature(struct nand_chip *chip) : 0; } +static inline void nand_release(struct mtd_info *mtd) +{ + /* + * If you face this warning your driver is doing something bad. + * Don't issue nand_release() when your MTD is in use. + * Use __nand_release() and handle the error correctly. + */ + WARN_ON(__nand_release(mtd) != 0); +} + /* * struct nand_sdr_timings - SDR NAND chip timings * -- 2.8.3