[PATCH] mtd: add reboot notifier to mtdcore and register nand_shutdown with notifier
Scott Branden
sbranden at broadcom.com
Thu Dec 4 16:13:01 PST 2014
Apologies: patch fails checkpatch due to spaces instead of tabs during
cut and paste.
But, please comment on this patch before I create a new version.
On 14-12-04 02:37 PM, Scott Branden wrote:
> add (optional) reboot notifier field to struct mtd_info, and use it to
> register a system reboot notifier on behalf of the lower layers.
>
> Add nand_shutdown to wait for current nand operations to finish and prevent
> further operations by changing the nand flash state to FL_SHUTDOWN.
> Register the nand_shutdown with the reboot notifier in nand_base.c
>
> This is addressing a problem observed during reboot tests using UBIFS
> root file system: NAND erase operations that are in progress during
> system reboot/shutdown are causing partial erased blocks. Although UBI should
> be able to detect and recover from this error, this change will avoid
> the creation of partial erased blocks on reboot in the middle of a NAND erase
> operation.
>
> Signed-off-by: Brian Norris <computersforpeace at gmail.com>
> Signed-off-by: Corneliu Doban <cdoban at broadcom.com>
> Signed-off-by: Scott Branden <sbranden at broadcom.com>
> ---
> drivers/mtd/mtdcore.c | 20 ++++++++++++++++++++
> drivers/mtd/nand/nand_base.c | 11 +++++++++++
> include/linux/mtd/mtd.h | 1 +
> 3 files changed, 32 insertions(+)
>
> diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
> index 4c61187..b80d44f 100644
> --- a/drivers/mtd/mtdcore.c
> +++ b/drivers/mtd/mtdcore.c
> @@ -37,6 +37,7 @@
> #include <linux/backing-dev.h>
> #include <linux/gfp.h>
> #include <linux/slab.h>
> +#include <linux/reboot.h>
>
> #include <linux/mtd/mtd.h>
> #include <linux/mtd/partitions.h>
> @@ -365,6 +366,17 @@ static struct device_type mtd_devtype = {
> .release = mtd_release,
> };
>
> +static int mtd_reboot_notifier(struct notifier_block *n, unsigned long state,
> + void *cmd)
> +{
> + struct mtd_info *mtd;
> +
> + mtd = container_of(n, struct mtd_info, reboot_notifier);
> + mtd->_reboot(mtd);
> +
> + return NOTIFY_DONE;
> +}
> +
> /**
> * add_mtd_device - register an MTD device
> * @mtd: pointer to new MTD device info structure
> @@ -565,6 +577,11 @@ int mtd_device_parse_register(struct mtd_info *mtd, const char * const *types,
> err = -ENODEV;
> }
>
> + if (mtd->_reboot) {
> + mtd->reboot_notifier.notifier_call = mtd_reboot_notifier;
> + register_reboot_notifier(&mtd->reboot_notifier);
> + }
> +
> return err;
> }
> EXPORT_SYMBOL_GPL(mtd_device_parse_register);
> @@ -579,6 +596,9 @@ int mtd_device_unregister(struct mtd_info *master)
> {
> int err;
>
> + if (master->_reboot)
> + unregister_reboot_notifier(&master->reboot_notifier);
> +
> err = del_mtd_partitions(master);
> if (err)
> return err;
> diff --git a/drivers/mtd/nand/nand_base.c b/drivers/mtd/nand/nand_base.c
> index 5b5c627..e18165b 100644
> --- a/drivers/mtd/nand/nand_base.c
> +++ b/drivers/mtd/nand/nand_base.c
> @@ -2944,6 +2944,16 @@ static void nand_resume(struct mtd_info *mtd)
> __func__);
> }
>
> +/**
> + * nand_shutdown - [MTD Interface] Finish the current NAND operation and
> + * prevent further operations
> + * @mtd: MTD device structure
> + */
> +static void nand_shutdown(struct mtd_info *mtd)
> +{
> + nand_get_device(mtd, FL_SHUTDOWN);
> +}
> +
> /* Set default functions */
> static void nand_set_defaults(struct nand_chip *chip, int busw)
> {
> @@ -4146,6 +4156,7 @@ int nand_scan_tail(struct mtd_info *mtd)
> mtd->_unlock = NULL;
> mtd->_suspend = nand_suspend;
> mtd->_resume = nand_resume;
> + mtd->_reboot = nand_shutdown;
> mtd->_block_isreserved = nand_block_isreserved;
> mtd->_block_isbad = nand_block_isbad;
> mtd->_block_markbad = nand_block_markbad;
> diff --git a/include/linux/mtd/mtd.h b/include/linux/mtd/mtd.h
> index 031ff3a..c06f537 100644
> --- a/include/linux/mtd/mtd.h
> +++ b/include/linux/mtd/mtd.h
> @@ -227,6 +227,7 @@ struct mtd_info {
> int (*_block_markbad) (struct mtd_info *mtd, loff_t ofs);
> int (*_suspend) (struct mtd_info *mtd);
> void (*_resume) (struct mtd_info *mtd);
> + void (*_reboot) (struct mtd_info *mtd);
> /*
> * If the driver is something smart, like UBI, it may need to maintain
> * its own reference counting. The below functions are only for driver.
>
More information about the linux-mtd
mailing list