[PATCH] mtd: ubi: attach MTD partition from device-tree
Zhihao Cheng
chengzhihao1 at huawei.com
Sun Apr 23 01:35:28 PDT 2023
Hi Daniel,
> Split ubi_init() function into early function to be called by
> device_initcall() and keep cmdline attachment in late_initcall().
> (when building ubi as module, both is still done in a single
> module_init() call)
>
> Register MTD notifier and attach MTD devices which are marked as
> compatible with 'linux,ubi' in OF device-tree when being added, detach
> UBI device from MTD device when it is being removed.
>
> Keep behavior regarding ubiblock creation and attaching of UBI device
> from kernel or module cmdline unchanged.
>
> For existing users this should not change anything besides automatic
> removal of (dead) UBI devices when their underlying MTD devices are
> already gone, e.g. in case of MTD driver module or (SPI) bus driver
> module being removed.
>
> For new users this opens up the option to attach UBI using device-tree
> which then happens early and in parallel with other drivers being
> probed which slightly reduces the total boot time.
>
> Attachment no longer happening late is also a requirement for other
> drivers to make use of UBI, e.g. drivers/nvmem/u-boot-env.c can now
> be extended to support U-Boot environment stored in UBI volumes.
>
Let me try to understand this patch, the main purpose is to add a new
way to load ubi according to device tree, am I right?
> Signed-off-by: Daniel Golle <daniel at makrotopia.org>
> ---
> drivers/mtd/ubi/block.c | 20 ++---
> drivers/mtd/ubi/build.c | 163 +++++++++++++++++++++++++++++-----------
> drivers/mtd/ubi/cdev.c | 2 +-
> drivers/mtd/ubi/ubi.h | 4 +-
> 4 files changed, 132 insertions(+), 57 deletions(-)
>
> diff --git a/drivers/mtd/ubi/block.c b/drivers/mtd/ubi/block.c
> index 3711d7f746003..b24b8b8f54b77 100644
> --- a/drivers/mtd/ubi/block.c
> +++ b/drivers/mtd/ubi/block.c
> @@ -65,10 +65,10 @@ struct ubiblock_pdu {
> };
>
> /* Numbers of elements set in the @ubiblock_param array */
> -static int ubiblock_devs __initdata;
> +static int ubiblock_devs;
>
> /* MTD devices specification parameters */
> -static struct ubiblock_param ubiblock_param[UBIBLOCK_MAX_DEVICES] __initdata;
> +static struct ubiblock_param ubiblock_param[UBIBLOCK_MAX_DEVICES];
>
> struct ubiblock {
> struct ubi_volume_desc *desc;
> @@ -582,7 +582,7 @@ open_volume_desc(const char *name, int ubi_num, int vol_id)
> return ubi_open_volume(ubi_num, vol_id, UBI_READONLY);
> }
>
> -static void __init ubiblock_create_from_param(void)
> +void ubiblock_create_from_param(void)
> {
> int i, ret = 0;
> struct ubiblock_param *p;
> @@ -611,9 +611,10 @@ static void __init ubiblock_create_from_param(void)
>
> ret = ubiblock_create(&vi);
> if (ret) {
> - pr_err(
> - "UBI: block: can't add '%s' volume on ubi%d_%d, err=%d\n",
> - vi.name, p->ubi_num, p->vol_id, ret);
> + if (ret != -EEXIST && ret != -ENOENT)
The EEXIST and ENOENT types of error messages are filtered, why? After
this patch applied, the user won't be aware of which ubi volume failed
to create ubiblock.
> + pr_err(
> + "UBI: block: can't add '%s' volume on ubi%d_%d, err=%d\n",
> + vi.name, p->ubi_num, p->vol_id, ret);
> continue;
> }
> }
> @@ -644,13 +645,6 @@ int __init ubiblock_init(void)
> if (ubiblock_major < 0)
> return ubiblock_major;
>
> - /*
> - * Attach block devices from 'block=' module param.
> - * Even if one block device in the param list fails to come up,
> - * still allow the module to load and leave any others up.
> - */
> - ubiblock_create_from_param();
> -
> /*
> * Block devices are only created upon user requests, so we ignore
> * existing volumes.
> diff --git a/drivers/mtd/ubi/build.c b/drivers/mtd/ubi/build.c
> index 9cd565daad368..a764f97eee791 100644
> --- a/drivers/mtd/ubi/build.c
> +++ b/drivers/mtd/ubi/build.c
> @@ -27,6 +27,7 @@
> #include <linux/log2.h>
> #include <linux/kthread.h>
> #include <linux/kernel.h>
> +#include <linux/of.h>
> #include <linux/slab.h>
> #include <linux/major.h>
> #include "ubi.h"
> @@ -1065,6 +1066,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
> * ubi_detach_mtd_dev - detach an MTD device.
> * @ubi_num: UBI device number to detach from
> * @anyway: detach MTD even if device reference count is not zero
> + * @have_lock: called by MTD notifier holding mtd_table_mutex
> *
> * This function destroys an UBI device number @ubi_num and detaches the
> * underlying MTD device. Returns zero in case of success and %-EBUSY if the
> @@ -1074,7 +1076,7 @@ int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
> * Note, the invocations of this function has to be serialized by the
> * @ubi_devices_mutex.
> */
> -int ubi_detach_mtd_dev(int ubi_num, int anyway)
> +int ubi_detach_mtd_dev(int ubi_num, int anyway, bool have_lock)
> {
> struct ubi_device *ubi;
>
> @@ -1108,7 +1110,7 @@ int ubi_detach_mtd_dev(int ubi_num, int anyway)
> * EC updates that have been made since the last written fastmap.
> * In case of fastmap debugging we omit the update to simulate an
> * unclean shutdown. */
> - if (!ubi_dbg_chk_fastmap(ubi))
> + if (!have_lock && !ubi_dbg_chk_fastmap(ubi))
> ubi_update_fastmap(ubi);
Why do you skip updating fastmap if ubi is detached in mtd notification way?
[...]> +static void ubi_notify_remove(struct mtd_info *mtd)
> +{
> + int i;
>
> - ubi_wl_entry_slab = kmem_cache_create("ubi_wl_entry_slab",
> - sizeof(struct ubi_wl_entry),
> - 0, 0, NULL);
> - if (!ubi_wl_entry_slab) {
> - err = -ENOMEM;
> - goto out_dev_unreg;
> - }
> + /* called while holding mtd_table_mutex */
> + mutex_lock_nested(&ubi_devices_mutex, SINGLE_DEPTH_NESTING);
> + for (i = 0; i < UBI_MAX_DEVICES; i++)
> + if (ubi_devices[i] &&
> + ubi_devices[i]->mtd->index == mtd->index)
> + ubi_detach_mtd_dev(ubi_devices[i]->ubi_num, 1, true);
Add a 'break'?
More information about the linux-mtd
mailing list