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>
This commit is contained in:
parent
762d73cd93
commit
927c145208
@ -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"
|
||||
@ -1219,44 +1220,44 @@ static struct mtd_info * __init open_mtd_device(const char *mtd_dev)
|
||||
return mtd;
|
||||
}
|
||||
|
||||
static int __init ubi_init(void)
|
||||
static void ubi_notify_add(struct mtd_info *mtd)
|
||||
{
|
||||
struct device_node *np = mtd_get_of_node(mtd);
|
||||
int err;
|
||||
|
||||
if (!of_device_is_compatible(np, "linux,ubi"))
|
||||
return;
|
||||
|
||||
/*
|
||||
* we are already holding &mtd_table_mutex, but still need
|
||||
* to bump refcount
|
||||
*/
|
||||
err = __get_mtd_device(mtd);
|
||||
if (err)
|
||||
return;
|
||||
|
||||
/* 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, false);
|
||||
mutex_unlock(&ubi_devices_mutex);
|
||||
if (err < 0)
|
||||
__put_mtd_device(mtd);
|
||||
}
|
||||
|
||||
static void ubi_notify_remove(struct mtd_info *mtd)
|
||||
{
|
||||
/* do nothing for now */
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
/* 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;
|
||||
|
||||
|
||||
/* Attach MTD devices */
|
||||
for (i = 0; i < mtd_devs; i++) {
|
||||
struct mtd_dev_param *p = &mtd_dev_param[i];
|
||||
@ -1304,15 +1305,6 @@ static int __init ubi_init(void)
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out_detach:
|
||||
@ -1322,7 +1314,70 @@ out_detach:
|
||||
ubi_detach_mtd_dev(ubi_devices[k]->ubi_num, 1);
|
||||
mutex_unlock(&ubi_devices_mutex);
|
||||
}
|
||||
ubi_debugfs_exit();
|
||||
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_slab;
|
||||
}
|
||||
|
||||
register_mtd_user(&ubi_mtd_notifier);
|
||||
|
||||
if (ubi_is_module()) {
|
||||
err = ubi_init_attach();
|
||||
if (err)
|
||||
goto out_mtd_notifier;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
out_mtd_notifier:
|
||||
unregister_mtd_user(&ubi_mtd_notifier);
|
||||
out_slab:
|
||||
kmem_cache_destroy(ubi_wl_entry_slab);
|
||||
out_dev_unreg:
|
||||
@ -1332,13 +1387,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]) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user