kernel: import pending patches adding support for NVMEM on UBI and MMC
[openwrt/staging/dangole.git] / target / linux / generic / pending-6.1 / 450-04-mtd-ubi-attach-from-device-tree.patch
1 From 471a17d8d1b838092d1a76e48cdce8b5b67ff809 Mon Sep 17 00:00:00 2001
2 From: Daniel Golle <daniel@makrotopia.org>
3 Date: Mon, 27 Nov 2023 01:54:28 +0000
4 Subject: [PATCH 04/15] mtd: ubi: attach from device tree
5
6 Introduce device tree compatible 'linux,ubi' and attach compatible MTD
7 devices using the MTD add notifier. This is needed for a UBI device to
8 be available early at boot (and not only after late_initcall), so
9 volumes on them can be used eg. as NVMEM providers for other drivers.
10
11 Signed-off-by: Daniel Golle <daniel@makrotopia.org>
12 ---
13 drivers/mtd/ubi/build.c | 146 ++++++++++++++++++++++++++++------------
14 drivers/mtd/ubi/cdev.c | 2 +-
15 drivers/mtd/ubi/ubi.h | 2 +-
16 3 files changed, 106 insertions(+), 44 deletions(-)
17
18 --- a/drivers/mtd/ubi/build.c
19 +++ b/drivers/mtd/ubi/build.c
20 @@ -27,6 +27,7 @@
21 #include <linux/log2.h>
22 #include <linux/kthread.h>
23 #include <linux/kernel.h>
24 +#include <linux/of.h>
25 #include <linux/slab.h>
26 #include <linux/major.h>
27 #include "ubi.h"
28 @@ -1071,6 +1072,7 @@ out_free:
29 * ubi_detach_mtd_dev - detach an MTD device.
30 * @ubi_num: UBI device number to detach from
31 * @anyway: detach MTD even if device reference count is not zero
32 + * @have_lock: called by MTD notifier holding mtd_table_mutex
33 *
34 * This function destroys an UBI device number @ubi_num and detaches the
35 * underlying MTD device. Returns zero in case of success and %-EBUSY if the
36 @@ -1080,7 +1082,7 @@ out_free:
37 * Note, the invocations of this function has to be serialized by the
38 * @ubi_devices_mutex.
39 */
40 -int ubi_detach_mtd_dev(int ubi_num, int anyway)
41 +int ubi_detach_mtd_dev(int ubi_num, int anyway, bool have_lock)
42 {
43 struct ubi_device *ubi;
44
45 @@ -1136,7 +1138,11 @@ int ubi_detach_mtd_dev(int ubi_num, int
46 vfree(ubi->peb_buf);
47 vfree(ubi->fm_buf);
48 ubi_msg(ubi, "mtd%d is detached", ubi->mtd->index);
49 - put_mtd_device(ubi->mtd);
50 + if (have_lock)
51 + __put_mtd_device(ubi->mtd);
52 + else
53 + put_mtd_device(ubi->mtd);
54 +
55 put_device(&ubi->dev);
56 return 0;
57 }
58 @@ -1213,43 +1219,43 @@ static struct mtd_info * __init open_mtd
59 return mtd;
60 }
61
62 -static int __init ubi_init(void)
63 +static void ubi_notify_add(struct mtd_info *mtd)
64 {
65 - int err, i, k;
66 + struct device_node *np = mtd_get_of_node(mtd);
67 + int err;
68
69 - /* Ensure that EC and VID headers have correct size */
70 - BUILD_BUG_ON(sizeof(struct ubi_ec_hdr) != 64);
71 - BUILD_BUG_ON(sizeof(struct ubi_vid_hdr) != 64);
72 + if (!of_device_is_compatible(np, "linux,ubi"))
73 + return;
74
75 - if (mtd_devs > UBI_MAX_DEVICES) {
76 - pr_err("UBI error: too many MTD devices, maximum is %d\n",
77 - UBI_MAX_DEVICES);
78 - return -EINVAL;
79 - }
80 + /*
81 + * we are already holding &mtd_table_mutex, but still need
82 + * to bump refcount
83 + */
84 + err = __get_mtd_device(mtd);
85 + if (err)
86 + return;
87
88 - /* Create base sysfs directory and sysfs files */
89 - err = class_register(&ubi_class);
90 + /* called while holding mtd_table_mutex */
91 + mutex_lock_nested(&ubi_devices_mutex, SINGLE_DEPTH_NESTING);
92 + err = ubi_attach_mtd_dev(mtd, UBI_DEV_NUM_AUTO, 0, 0, false);
93 + mutex_unlock(&ubi_devices_mutex);
94 if (err < 0)
95 - return err;
96 -
97 - err = misc_register(&ubi_ctrl_cdev);
98 - if (err) {
99 - pr_err("UBI error: cannot register device\n");
100 - goto out;
101 - }
102 + __put_mtd_device(mtd);
103 +}
104
105 - ubi_wl_entry_slab = kmem_cache_create("ubi_wl_entry_slab",
106 - sizeof(struct ubi_wl_entry),
107 - 0, 0, NULL);
108 - if (!ubi_wl_entry_slab) {
109 - err = -ENOMEM;
110 - goto out_dev_unreg;
111 - }
112 +static void ubi_notify_remove(struct mtd_info *mtd)
113 +{
114 + WARN(1, "mtd%d removed despite UBI still being attached", mtd->index);
115 +}
116
117 - err = ubi_debugfs_init();
118 - if (err)
119 - goto out_slab;
120 +static struct mtd_notifier ubi_mtd_notifier = {
121 + .add = ubi_notify_add,
122 + .remove = ubi_notify_remove,
123 +};
124
125 +static int __init ubi_init_attach(void)
126 +{
127 + int err, i, k;
128
129 /* Attach MTD devices */
130 for (i = 0; i < mtd_devs; i++) {
131 @@ -1297,25 +1303,79 @@ static int __init ubi_init(void)
132 }
133 }
134
135 + return 0;
136 +
137 +out_detach:
138 + for (k = 0; k < i; k++)
139 + if (ubi_devices[k]) {
140 + mutex_lock(&ubi_devices_mutex);
141 + ubi_detach_mtd_dev(ubi_devices[k]->ubi_num, 1, false);
142 + mutex_unlock(&ubi_devices_mutex);
143 + }
144 + return err;
145 +}
146 +#ifndef CONFIG_MTD_UBI_MODULE
147 +late_initcall(ubi_init_attach);
148 +#endif
149 +
150 +static int __init ubi_init(void)
151 +{
152 + int err;
153 +
154 + /* Ensure that EC and VID headers have correct size */
155 + BUILD_BUG_ON(sizeof(struct ubi_ec_hdr) != 64);
156 + BUILD_BUG_ON(sizeof(struct ubi_vid_hdr) != 64);
157 +
158 + if (mtd_devs > UBI_MAX_DEVICES) {
159 + pr_err("UBI error: too many MTD devices, maximum is %d\n",
160 + UBI_MAX_DEVICES);
161 + return -EINVAL;
162 + }
163 +
164 + /* Create base sysfs directory and sysfs files */
165 + err = class_register(&ubi_class);
166 + if (err < 0)
167 + return err;
168 +
169 + err = misc_register(&ubi_ctrl_cdev);
170 + if (err) {
171 + pr_err("UBI error: cannot register device\n");
172 + goto out;
173 + }
174 +
175 + ubi_wl_entry_slab = kmem_cache_create("ubi_wl_entry_slab",
176 + sizeof(struct ubi_wl_entry),
177 + 0, 0, NULL);
178 + if (!ubi_wl_entry_slab) {
179 + err = -ENOMEM;
180 + goto out_dev_unreg;
181 + }
182 +
183 + err = ubi_debugfs_init();
184 + if (err)
185 + goto out_slab;
186 +
187 err = ubiblock_init();
188 if (err) {
189 pr_err("UBI error: block: cannot initialize, error %d\n", err);
190
191 /* See comment above re-ubi_is_module(). */
192 if (ubi_is_module())
193 - goto out_detach;
194 + goto out_slab;
195 + }
196 +
197 + register_mtd_user(&ubi_mtd_notifier);
198 +
199 + if (ubi_is_module()) {
200 + err = ubi_init_attach();
201 + if (err)
202 + goto out_mtd_notifier;
203 }
204
205 return 0;
206
207 -out_detach:
208 - for (k = 0; k < i; k++)
209 - if (ubi_devices[k]) {
210 - mutex_lock(&ubi_devices_mutex);
211 - ubi_detach_mtd_dev(ubi_devices[k]->ubi_num, 1);
212 - mutex_unlock(&ubi_devices_mutex);
213 - }
214 - ubi_debugfs_exit();
215 +out_mtd_notifier:
216 + unregister_mtd_user(&ubi_mtd_notifier);
217 out_slab:
218 kmem_cache_destroy(ubi_wl_entry_slab);
219 out_dev_unreg:
220 @@ -1325,18 +1385,20 @@ out:
221 pr_err("UBI error: cannot initialize UBI, error %d\n", err);
222 return err;
223 }
224 -late_initcall(ubi_init);
225 +device_initcall(ubi_init);
226 +
227
228 static void __exit ubi_exit(void)
229 {
230 int i;
231
232 ubiblock_exit();
233 + unregister_mtd_user(&ubi_mtd_notifier);
234
235 for (i = 0; i < UBI_MAX_DEVICES; i++)
236 if (ubi_devices[i]) {
237 mutex_lock(&ubi_devices_mutex);
238 - ubi_detach_mtd_dev(ubi_devices[i]->ubi_num, 1);
239 + ubi_detach_mtd_dev(ubi_devices[i]->ubi_num, 1, false);
240 mutex_unlock(&ubi_devices_mutex);
241 }
242 ubi_debugfs_exit();
243 --- a/drivers/mtd/ubi/cdev.c
244 +++ b/drivers/mtd/ubi/cdev.c
245 @@ -1065,7 +1065,7 @@ static long ctrl_cdev_ioctl(struct file
246 }
247
248 mutex_lock(&ubi_devices_mutex);
249 - err = ubi_detach_mtd_dev(ubi_num, 0);
250 + err = ubi_detach_mtd_dev(ubi_num, 0, false);
251 mutex_unlock(&ubi_devices_mutex);
252 break;
253 }
254 --- a/drivers/mtd/ubi/ubi.h
255 +++ b/drivers/mtd/ubi/ubi.h
256 @@ -939,7 +939,7 @@ int ubi_io_write_vid_hdr(struct ubi_devi
257 int ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
258 int vid_hdr_offset, int max_beb_per1024,
259 bool disable_fm);
260 -int ubi_detach_mtd_dev(int ubi_num, int anyway);
261 +int ubi_detach_mtd_dev(int ubi_num, int anyway, bool have_lock);
262 struct ubi_device *ubi_get_device(int ubi_num);
263 void ubi_put_device(struct ubi_device *ubi);
264 struct ubi_device *ubi_get_by_major(int major);