4fd4be6bbe
The series was merged for Linux v6.9, so move it to backports. Signed-off-by: Daniel Golle <daniel@makrotopia.org>
206 lines
5.0 KiB
Diff
206 lines
5.0 KiB
Diff
From 6e331888643887ce85657527bc03f97d46235e71 Mon Sep 17 00:00:00 2001
|
|
From: Daniel Golle <daniel@makrotopia.org>
|
|
Date: Tue, 19 Dec 2023 02:33:14 +0000
|
|
Subject: [PATCH 4/8] 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 <daniel@makrotopia.org>
|
|
Signed-off-by: Richard Weinberger <richard@nod.at>
|
|
---
|
|
drivers/mtd/ubi/build.c | 135 ++++++++++++++++++++++++++++------------
|
|
1 file changed, 96 insertions(+), 39 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"
|
|
@@ -1214,43 +1215,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)
|
|
+{
|
|
+ /* do nothing for now */
|
|
+}
|
|
|
|
- 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++) {
|
|
@@ -1298,25 +1299,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);
|
|
+ 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:
|
|
@@ -1326,13 +1381,15 @@ 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]) {
|