123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264 |
- From 471a17d8d1b838092d1a76e48cdce8b5b67ff809 Mon Sep 17 00:00:00 2001
- From: Daniel Golle <[email protected]>
- Date: Mon, 27 Nov 2023 01:54:28 +0000
- Subject: [PATCH 04/15] mtd: ubi: attach from device tree
- Introduce device tree compatible 'linux,ubi' and attach compatible MTD
- devices using the MTD add notifier. This is needed for a UBI device to
- be available early at boot (and not only after late_initcall), so
- volumes on them can be used eg. as NVMEM providers for other drivers.
- Signed-off-by: Daniel Golle <[email protected]>
- ---
- drivers/mtd/ubi/build.c | 146 ++++++++++++++++++++++++++++------------
- drivers/mtd/ubi/cdev.c | 2 +-
- drivers/mtd/ubi/ubi.h | 2 +-
- 3 files changed, 106 insertions(+), 44 deletions(-)
- --- 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"
- @@ -1071,6 +1072,7 @@ out_free:
- * 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
- @@ -1080,7 +1082,7 @@ out_free:
- * 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;
-
- @@ -1136,7 +1138,11 @@ int ubi_detach_mtd_dev(int ubi_num, int
- vfree(ubi->peb_buf);
- vfree(ubi->fm_buf);
- ubi_msg(ubi, "mtd%d is detached", ubi->mtd->index);
- - put_mtd_device(ubi->mtd);
- + if (have_lock)
- + __put_mtd_device(ubi->mtd);
- + else
- + put_mtd_device(ubi->mtd);
- +
- put_device(&ubi->dev);
- return 0;
- }
- @@ -1213,43 +1219,43 @@ static struct mtd_info * __init open_mtd
- return mtd;
- }
-
- -static int __init ubi_init(void)
- +static void ubi_notify_add(struct mtd_info *mtd)
- {
- - int err, i, k;
- + struct device_node *np = mtd_get_of_node(mtd);
- + int err;
-
- - /* Ensure that EC and VID headers have correct size */
- - BUILD_BUG_ON(sizeof(struct ubi_ec_hdr) != 64);
- - BUILD_BUG_ON(sizeof(struct ubi_vid_hdr) != 64);
- + if (!of_device_is_compatible(np, "linux,ubi"))
- + return;
-
- - if (mtd_devs > UBI_MAX_DEVICES) {
- - pr_err("UBI error: too many MTD devices, maximum is %d\n",
- - UBI_MAX_DEVICES);
- - return -EINVAL;
- - }
- + /*
- + * we are already holding &mtd_table_mutex, but still need
- + * to bump refcount
- + */
- + err = __get_mtd_device(mtd);
- + if (err)
- + return;
-
- - /* Create base sysfs directory and sysfs files */
- - err = class_register(&ubi_class);
- + /* called while holding mtd_table_mutex */
- + mutex_lock_nested(&ubi_devices_mutex, SINGLE_DEPTH_NESTING);
- + err = ubi_attach_mtd_dev(mtd, UBI_DEV_NUM_AUTO, 0, 0, false);
- + mutex_unlock(&ubi_devices_mutex);
- if (err < 0)
- - return err;
- -
- - err = misc_register(&ubi_ctrl_cdev);
- - if (err) {
- - pr_err("UBI error: cannot register device\n");
- - goto out;
- - }
- + __put_mtd_device(mtd);
- +}
-
- - 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;
- - }
- +static void ubi_notify_remove(struct mtd_info *mtd)
- +{
- + WARN(1, "mtd%d removed despite UBI still being attached", mtd->index);
- +}
-
- - err = ubi_debugfs_init();
- - if (err)
- - goto out_slab;
- +static struct mtd_notifier ubi_mtd_notifier = {
- + .add = ubi_notify_add,
- + .remove = ubi_notify_remove,
- +};
-
- +static int __init ubi_init_attach(void)
- +{
- + int err, i, k;
-
- /* Attach MTD devices */
- for (i = 0; i < mtd_devs; i++) {
- @@ -1297,25 +1303,79 @@ static int __init ubi_init(void)
- }
- }
-
- + return 0;
- +
- +out_detach:
- + for (k = 0; k < i; k++)
- + if (ubi_devices[k]) {
- + mutex_lock(&ubi_devices_mutex);
- + ubi_detach_mtd_dev(ubi_devices[k]->ubi_num, 1, false);
- + mutex_unlock(&ubi_devices_mutex);
- + }
- + return err;
- +}
- +#ifndef CONFIG_MTD_UBI_MODULE
- +late_initcall(ubi_init_attach);
- +#endif
- +
- +static int __init ubi_init(void)
- +{
- + int err;
- +
- + /* Ensure that EC and VID headers have correct size */
- + BUILD_BUG_ON(sizeof(struct ubi_ec_hdr) != 64);
- + BUILD_BUG_ON(sizeof(struct ubi_vid_hdr) != 64);
- +
- + if (mtd_devs > UBI_MAX_DEVICES) {
- + pr_err("UBI error: too many MTD devices, maximum is %d\n",
- + UBI_MAX_DEVICES);
- + return -EINVAL;
- + }
- +
- + /* Create base sysfs directory and sysfs files */
- + err = class_register(&ubi_class);
- + if (err < 0)
- + return err;
- +
- + err = misc_register(&ubi_ctrl_cdev);
- + if (err) {
- + pr_err("UBI error: cannot register device\n");
- + goto out;
- + }
- +
- + 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;
- + }
- +
- + err = ubi_debugfs_init();
- + if (err)
- + goto out_slab;
- +
- err = ubiblock_init();
- if (err) {
- pr_err("UBI error: block: cannot initialize, error %d\n", err);
-
- /* See comment above re-ubi_is_module(). */
- if (ubi_is_module())
- - goto out_detach;
- + goto out_slab;
- + }
- +
- + register_mtd_user(&ubi_mtd_notifier);
- +
- + if (ubi_is_module()) {
- + err = ubi_init_attach();
- + if (err)
- + goto out_mtd_notifier;
- }
-
- return 0;
-
- -out_detach:
- - for (k = 0; k < i; k++)
- - if (ubi_devices[k]) {
- - mutex_lock(&ubi_devices_mutex);
- - ubi_detach_mtd_dev(ubi_devices[k]->ubi_num, 1);
- - mutex_unlock(&ubi_devices_mutex);
- - }
- - ubi_debugfs_exit();
- +out_mtd_notifier:
- + unregister_mtd_user(&ubi_mtd_notifier);
- out_slab:
- kmem_cache_destroy(ubi_wl_entry_slab);
- out_dev_unreg:
- @@ -1325,18 +1385,20 @@ out:
- pr_err("UBI error: cannot initialize UBI, error %d\n", err);
- return err;
- }
- -late_initcall(ubi_init);
- +device_initcall(ubi_init);
- +
-
- static void __exit ubi_exit(void)
- {
- int i;
-
- ubiblock_exit();
- + unregister_mtd_user(&ubi_mtd_notifier);
-
- for (i = 0; i < UBI_MAX_DEVICES; i++)
- if (ubi_devices[i]) {
- mutex_lock(&ubi_devices_mutex);
- - ubi_detach_mtd_dev(ubi_devices[i]->ubi_num, 1);
- + ubi_detach_mtd_dev(ubi_devices[i]->ubi_num, 1, false);
- mutex_unlock(&ubi_devices_mutex);
- }
- ubi_debugfs_exit();
- --- a/drivers/mtd/ubi/cdev.c
- +++ b/drivers/mtd/ubi/cdev.c
- @@ -1065,7 +1065,7 @@ static long ctrl_cdev_ioctl(struct file
- }
-
- mutex_lock(&ubi_devices_mutex);
- - err = ubi_detach_mtd_dev(ubi_num, 0);
- + err = ubi_detach_mtd_dev(ubi_num, 0, false);
- mutex_unlock(&ubi_devices_mutex);
- break;
- }
- --- a/drivers/mtd/ubi/ubi.h
- +++ b/drivers/mtd/ubi/ubi.h
- @@ -939,7 +939,7 @@ int ubi_io_write_vid_hdr(struct ubi_devi
- int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
- int vid_hdr_offset, int max_beb_per1024,
- bool disable_fm);
- -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_get_device(int ubi_num);
- void ubi_put_device(struct ubi_device *ubi);
- struct ubi_device *ubi_get_by_major(int major);
|