Commit 927c1452 authored by Daniel Golle's avatar Daniel Golle Committed by Richard Weinberger
Browse files

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: default avatarDaniel Golle <daniel@makrotopia.org>
Signed-off-by: default avatarRichard Weinberger <richard@nod.at>
parent 762d73cd
Loading
Loading
Loading
Loading
+96 −39
Original line number Diff line number Diff line
@@ -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,43 +1220,43 @@ 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)
{
	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, 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++) {
@@ -1304,25 +1305,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;
	}

	return 0;
	register_mtd_user(&ubi_mtd_notifier);

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);
	if (ubi_is_module()) {
		err = ubi_init_attach();
		if (err)
			goto out_mtd_notifier;
	}
	ubi_debugfs_exit();

	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 @@ static int __init ubi_init(void)
	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]) {