xref: /kernel/linux/linux-5.10/drivers/mtd/ubi/build.c (revision 8c2ecf20)
18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * Copyright (c) International Business Machines Corp., 2006
48c2ecf20Sopenharmony_ci * Copyright (c) Nokia Corporation, 2007
58c2ecf20Sopenharmony_ci *
68c2ecf20Sopenharmony_ci * Author: Artem Bityutskiy (Битюцкий Артём),
78c2ecf20Sopenharmony_ci *         Frank Haverkamp
88c2ecf20Sopenharmony_ci */
98c2ecf20Sopenharmony_ci
108c2ecf20Sopenharmony_ci/*
118c2ecf20Sopenharmony_ci * This file includes UBI initialization and building of UBI devices.
128c2ecf20Sopenharmony_ci *
138c2ecf20Sopenharmony_ci * When UBI is initialized, it attaches all the MTD devices specified as the
148c2ecf20Sopenharmony_ci * module load parameters or the kernel boot parameters. If MTD devices were
158c2ecf20Sopenharmony_ci * specified, UBI does not attach any MTD device, but it is possible to do
168c2ecf20Sopenharmony_ci * later using the "UBI control device".
178c2ecf20Sopenharmony_ci */
188c2ecf20Sopenharmony_ci
198c2ecf20Sopenharmony_ci#include <linux/err.h>
208c2ecf20Sopenharmony_ci#include <linux/module.h>
218c2ecf20Sopenharmony_ci#include <linux/moduleparam.h>
228c2ecf20Sopenharmony_ci#include <linux/stringify.h>
238c2ecf20Sopenharmony_ci#include <linux/namei.h>
248c2ecf20Sopenharmony_ci#include <linux/stat.h>
258c2ecf20Sopenharmony_ci#include <linux/miscdevice.h>
268c2ecf20Sopenharmony_ci#include <linux/mtd/partitions.h>
278c2ecf20Sopenharmony_ci#include <linux/log2.h>
288c2ecf20Sopenharmony_ci#include <linux/kthread.h>
298c2ecf20Sopenharmony_ci#include <linux/kernel.h>
308c2ecf20Sopenharmony_ci#include <linux/slab.h>
318c2ecf20Sopenharmony_ci#include <linux/major.h>
328c2ecf20Sopenharmony_ci#include "ubi.h"
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci/* Maximum length of the 'mtd=' parameter */
358c2ecf20Sopenharmony_ci#define MTD_PARAM_LEN_MAX 64
368c2ecf20Sopenharmony_ci
378c2ecf20Sopenharmony_ci/* Maximum number of comma-separated items in the 'mtd=' parameter */
388c2ecf20Sopenharmony_ci#define MTD_PARAM_MAX_COUNT 4
398c2ecf20Sopenharmony_ci
408c2ecf20Sopenharmony_ci/* Maximum value for the number of bad PEBs per 1024 PEBs */
418c2ecf20Sopenharmony_ci#define MAX_MTD_UBI_BEB_LIMIT 768
428c2ecf20Sopenharmony_ci
438c2ecf20Sopenharmony_ci#ifdef CONFIG_MTD_UBI_MODULE
448c2ecf20Sopenharmony_ci#define ubi_is_module() 1
458c2ecf20Sopenharmony_ci#else
468c2ecf20Sopenharmony_ci#define ubi_is_module() 0
478c2ecf20Sopenharmony_ci#endif
488c2ecf20Sopenharmony_ci
498c2ecf20Sopenharmony_ci/**
508c2ecf20Sopenharmony_ci * struct mtd_dev_param - MTD device parameter description data structure.
518c2ecf20Sopenharmony_ci * @name: MTD character device node path, MTD device name, or MTD device number
528c2ecf20Sopenharmony_ci *        string
538c2ecf20Sopenharmony_ci * @vid_hdr_offs: VID header offset
548c2ecf20Sopenharmony_ci * @max_beb_per1024: maximum expected number of bad PEBs per 1024 PEBs
558c2ecf20Sopenharmony_ci */
568c2ecf20Sopenharmony_cistruct mtd_dev_param {
578c2ecf20Sopenharmony_ci	char name[MTD_PARAM_LEN_MAX];
588c2ecf20Sopenharmony_ci	int ubi_num;
598c2ecf20Sopenharmony_ci	int vid_hdr_offs;
608c2ecf20Sopenharmony_ci	int max_beb_per1024;
618c2ecf20Sopenharmony_ci};
628c2ecf20Sopenharmony_ci
638c2ecf20Sopenharmony_ci/* Numbers of elements set in the @mtd_dev_param array */
648c2ecf20Sopenharmony_cistatic int mtd_devs;
658c2ecf20Sopenharmony_ci
668c2ecf20Sopenharmony_ci/* MTD devices specification parameters */
678c2ecf20Sopenharmony_cistatic struct mtd_dev_param mtd_dev_param[UBI_MAX_DEVICES];
688c2ecf20Sopenharmony_ci#ifdef CONFIG_MTD_UBI_FASTMAP
698c2ecf20Sopenharmony_ci/* UBI module parameter to enable fastmap automatically on non-fastmap images */
708c2ecf20Sopenharmony_cistatic bool fm_autoconvert;
718c2ecf20Sopenharmony_cistatic bool fm_debug;
728c2ecf20Sopenharmony_ci#endif
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci/* Slab cache for wear-leveling entries */
758c2ecf20Sopenharmony_cistruct kmem_cache *ubi_wl_entry_slab;
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_ci/* UBI control character device */
788c2ecf20Sopenharmony_cistatic struct miscdevice ubi_ctrl_cdev = {
798c2ecf20Sopenharmony_ci	.minor = MISC_DYNAMIC_MINOR,
808c2ecf20Sopenharmony_ci	.name = "ubi_ctrl",
818c2ecf20Sopenharmony_ci	.fops = &ubi_ctrl_cdev_operations,
828c2ecf20Sopenharmony_ci};
838c2ecf20Sopenharmony_ci
848c2ecf20Sopenharmony_ci/* All UBI devices in system */
858c2ecf20Sopenharmony_cistatic struct ubi_device *ubi_devices[UBI_MAX_DEVICES];
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_ci/* Serializes UBI devices creations and removals */
888c2ecf20Sopenharmony_ciDEFINE_MUTEX(ubi_devices_mutex);
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci/* Protects @ubi_devices and @ubi->ref_count */
918c2ecf20Sopenharmony_cistatic DEFINE_SPINLOCK(ubi_devices_lock);
928c2ecf20Sopenharmony_ci
938c2ecf20Sopenharmony_ci/* "Show" method for files in '/<sysfs>/class/ubi/' */
948c2ecf20Sopenharmony_ci/* UBI version attribute ('/<sysfs>/class/ubi/version') */
958c2ecf20Sopenharmony_cistatic ssize_t version_show(struct class *class, struct class_attribute *attr,
968c2ecf20Sopenharmony_ci			    char *buf)
978c2ecf20Sopenharmony_ci{
988c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", UBI_VERSION);
998c2ecf20Sopenharmony_ci}
1008c2ecf20Sopenharmony_cistatic CLASS_ATTR_RO(version);
1018c2ecf20Sopenharmony_ci
1028c2ecf20Sopenharmony_cistatic struct attribute *ubi_class_attrs[] = {
1038c2ecf20Sopenharmony_ci	&class_attr_version.attr,
1048c2ecf20Sopenharmony_ci	NULL,
1058c2ecf20Sopenharmony_ci};
1068c2ecf20Sopenharmony_ciATTRIBUTE_GROUPS(ubi_class);
1078c2ecf20Sopenharmony_ci
1088c2ecf20Sopenharmony_ci/* Root UBI "class" object (corresponds to '/<sysfs>/class/ubi/') */
1098c2ecf20Sopenharmony_cistruct class ubi_class = {
1108c2ecf20Sopenharmony_ci	.name		= UBI_NAME_STR,
1118c2ecf20Sopenharmony_ci	.owner		= THIS_MODULE,
1128c2ecf20Sopenharmony_ci	.class_groups	= ubi_class_groups,
1138c2ecf20Sopenharmony_ci};
1148c2ecf20Sopenharmony_ci
1158c2ecf20Sopenharmony_cistatic ssize_t dev_attribute_show(struct device *dev,
1168c2ecf20Sopenharmony_ci				  struct device_attribute *attr, char *buf);
1178c2ecf20Sopenharmony_ci
1188c2ecf20Sopenharmony_ci/* UBI device attributes (correspond to files in '/<sysfs>/class/ubi/ubiX') */
1198c2ecf20Sopenharmony_cistatic struct device_attribute dev_eraseblock_size =
1208c2ecf20Sopenharmony_ci	__ATTR(eraseblock_size, S_IRUGO, dev_attribute_show, NULL);
1218c2ecf20Sopenharmony_cistatic struct device_attribute dev_avail_eraseblocks =
1228c2ecf20Sopenharmony_ci	__ATTR(avail_eraseblocks, S_IRUGO, dev_attribute_show, NULL);
1238c2ecf20Sopenharmony_cistatic struct device_attribute dev_total_eraseblocks =
1248c2ecf20Sopenharmony_ci	__ATTR(total_eraseblocks, S_IRUGO, dev_attribute_show, NULL);
1258c2ecf20Sopenharmony_cistatic struct device_attribute dev_volumes_count =
1268c2ecf20Sopenharmony_ci	__ATTR(volumes_count, S_IRUGO, dev_attribute_show, NULL);
1278c2ecf20Sopenharmony_cistatic struct device_attribute dev_max_ec =
1288c2ecf20Sopenharmony_ci	__ATTR(max_ec, S_IRUGO, dev_attribute_show, NULL);
1298c2ecf20Sopenharmony_cistatic struct device_attribute dev_reserved_for_bad =
1308c2ecf20Sopenharmony_ci	__ATTR(reserved_for_bad, S_IRUGO, dev_attribute_show, NULL);
1318c2ecf20Sopenharmony_cistatic struct device_attribute dev_bad_peb_count =
1328c2ecf20Sopenharmony_ci	__ATTR(bad_peb_count, S_IRUGO, dev_attribute_show, NULL);
1338c2ecf20Sopenharmony_cistatic struct device_attribute dev_max_vol_count =
1348c2ecf20Sopenharmony_ci	__ATTR(max_vol_count, S_IRUGO, dev_attribute_show, NULL);
1358c2ecf20Sopenharmony_cistatic struct device_attribute dev_min_io_size =
1368c2ecf20Sopenharmony_ci	__ATTR(min_io_size, S_IRUGO, dev_attribute_show, NULL);
1378c2ecf20Sopenharmony_cistatic struct device_attribute dev_bgt_enabled =
1388c2ecf20Sopenharmony_ci	__ATTR(bgt_enabled, S_IRUGO, dev_attribute_show, NULL);
1398c2ecf20Sopenharmony_cistatic struct device_attribute dev_mtd_num =
1408c2ecf20Sopenharmony_ci	__ATTR(mtd_num, S_IRUGO, dev_attribute_show, NULL);
1418c2ecf20Sopenharmony_cistatic struct device_attribute dev_ro_mode =
1428c2ecf20Sopenharmony_ci	__ATTR(ro_mode, S_IRUGO, dev_attribute_show, NULL);
1438c2ecf20Sopenharmony_ci
1448c2ecf20Sopenharmony_ci/**
1458c2ecf20Sopenharmony_ci * ubi_volume_notify - send a volume change notification.
1468c2ecf20Sopenharmony_ci * @ubi: UBI device description object
1478c2ecf20Sopenharmony_ci * @vol: volume description object of the changed volume
1488c2ecf20Sopenharmony_ci * @ntype: notification type to send (%UBI_VOLUME_ADDED, etc)
1498c2ecf20Sopenharmony_ci *
1508c2ecf20Sopenharmony_ci * This is a helper function which notifies all subscribers about a volume
1518c2ecf20Sopenharmony_ci * change event (creation, removal, re-sizing, re-naming, updating). Returns
1528c2ecf20Sopenharmony_ci * zero in case of success and a negative error code in case of failure.
1538c2ecf20Sopenharmony_ci */
1548c2ecf20Sopenharmony_ciint ubi_volume_notify(struct ubi_device *ubi, struct ubi_volume *vol, int ntype)
1558c2ecf20Sopenharmony_ci{
1568c2ecf20Sopenharmony_ci	int ret;
1578c2ecf20Sopenharmony_ci	struct ubi_notification nt;
1588c2ecf20Sopenharmony_ci
1598c2ecf20Sopenharmony_ci	ubi_do_get_device_info(ubi, &nt.di);
1608c2ecf20Sopenharmony_ci	ubi_do_get_volume_info(ubi, vol, &nt.vi);
1618c2ecf20Sopenharmony_ci
1628c2ecf20Sopenharmony_ci	switch (ntype) {
1638c2ecf20Sopenharmony_ci	case UBI_VOLUME_ADDED:
1648c2ecf20Sopenharmony_ci	case UBI_VOLUME_REMOVED:
1658c2ecf20Sopenharmony_ci	case UBI_VOLUME_RESIZED:
1668c2ecf20Sopenharmony_ci	case UBI_VOLUME_RENAMED:
1678c2ecf20Sopenharmony_ci		ret = ubi_update_fastmap(ubi);
1688c2ecf20Sopenharmony_ci		if (ret)
1698c2ecf20Sopenharmony_ci			ubi_msg(ubi, "Unable to write a new fastmap: %i", ret);
1708c2ecf20Sopenharmony_ci	}
1718c2ecf20Sopenharmony_ci
1728c2ecf20Sopenharmony_ci	return blocking_notifier_call_chain(&ubi_notifiers, ntype, &nt);
1738c2ecf20Sopenharmony_ci}
1748c2ecf20Sopenharmony_ci
1758c2ecf20Sopenharmony_ci/**
1768c2ecf20Sopenharmony_ci * ubi_notify_all - send a notification to all volumes.
1778c2ecf20Sopenharmony_ci * @ubi: UBI device description object
1788c2ecf20Sopenharmony_ci * @ntype: notification type to send (%UBI_VOLUME_ADDED, etc)
1798c2ecf20Sopenharmony_ci * @nb: the notifier to call
1808c2ecf20Sopenharmony_ci *
1818c2ecf20Sopenharmony_ci * This function walks all volumes of UBI device @ubi and sends the @ntype
1828c2ecf20Sopenharmony_ci * notification for each volume. If @nb is %NULL, then all registered notifiers
1838c2ecf20Sopenharmony_ci * are called, otherwise only the @nb notifier is called. Returns the number of
1848c2ecf20Sopenharmony_ci * sent notifications.
1858c2ecf20Sopenharmony_ci */
1868c2ecf20Sopenharmony_ciint ubi_notify_all(struct ubi_device *ubi, int ntype, struct notifier_block *nb)
1878c2ecf20Sopenharmony_ci{
1888c2ecf20Sopenharmony_ci	struct ubi_notification nt;
1898c2ecf20Sopenharmony_ci	int i, count = 0;
1908c2ecf20Sopenharmony_ci
1918c2ecf20Sopenharmony_ci	ubi_do_get_device_info(ubi, &nt.di);
1928c2ecf20Sopenharmony_ci
1938c2ecf20Sopenharmony_ci	mutex_lock(&ubi->device_mutex);
1948c2ecf20Sopenharmony_ci	for (i = 0; i < ubi->vtbl_slots; i++) {
1958c2ecf20Sopenharmony_ci		/*
1968c2ecf20Sopenharmony_ci		 * Since the @ubi->device is locked, and we are not going to
1978c2ecf20Sopenharmony_ci		 * change @ubi->volumes, we do not have to lock
1988c2ecf20Sopenharmony_ci		 * @ubi->volumes_lock.
1998c2ecf20Sopenharmony_ci		 */
2008c2ecf20Sopenharmony_ci		if (!ubi->volumes[i])
2018c2ecf20Sopenharmony_ci			continue;
2028c2ecf20Sopenharmony_ci
2038c2ecf20Sopenharmony_ci		ubi_do_get_volume_info(ubi, ubi->volumes[i], &nt.vi);
2048c2ecf20Sopenharmony_ci		if (nb)
2058c2ecf20Sopenharmony_ci			nb->notifier_call(nb, ntype, &nt);
2068c2ecf20Sopenharmony_ci		else
2078c2ecf20Sopenharmony_ci			blocking_notifier_call_chain(&ubi_notifiers, ntype,
2088c2ecf20Sopenharmony_ci						     &nt);
2098c2ecf20Sopenharmony_ci		count += 1;
2108c2ecf20Sopenharmony_ci	}
2118c2ecf20Sopenharmony_ci	mutex_unlock(&ubi->device_mutex);
2128c2ecf20Sopenharmony_ci
2138c2ecf20Sopenharmony_ci	return count;
2148c2ecf20Sopenharmony_ci}
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_ci/**
2178c2ecf20Sopenharmony_ci * ubi_enumerate_volumes - send "add" notification for all existing volumes.
2188c2ecf20Sopenharmony_ci * @nb: the notifier to call
2198c2ecf20Sopenharmony_ci *
2208c2ecf20Sopenharmony_ci * This function walks all UBI devices and volumes and sends the
2218c2ecf20Sopenharmony_ci * %UBI_VOLUME_ADDED notification for each volume. If @nb is %NULL, then all
2228c2ecf20Sopenharmony_ci * registered notifiers are called, otherwise only the @nb notifier is called.
2238c2ecf20Sopenharmony_ci * Returns the number of sent notifications.
2248c2ecf20Sopenharmony_ci */
2258c2ecf20Sopenharmony_ciint ubi_enumerate_volumes(struct notifier_block *nb)
2268c2ecf20Sopenharmony_ci{
2278c2ecf20Sopenharmony_ci	int i, count = 0;
2288c2ecf20Sopenharmony_ci
2298c2ecf20Sopenharmony_ci	/*
2308c2ecf20Sopenharmony_ci	 * Since the @ubi_devices_mutex is locked, and we are not going to
2318c2ecf20Sopenharmony_ci	 * change @ubi_devices, we do not have to lock @ubi_devices_lock.
2328c2ecf20Sopenharmony_ci	 */
2338c2ecf20Sopenharmony_ci	for (i = 0; i < UBI_MAX_DEVICES; i++) {
2348c2ecf20Sopenharmony_ci		struct ubi_device *ubi = ubi_devices[i];
2358c2ecf20Sopenharmony_ci
2368c2ecf20Sopenharmony_ci		if (!ubi)
2378c2ecf20Sopenharmony_ci			continue;
2388c2ecf20Sopenharmony_ci		count += ubi_notify_all(ubi, UBI_VOLUME_ADDED, nb);
2398c2ecf20Sopenharmony_ci	}
2408c2ecf20Sopenharmony_ci
2418c2ecf20Sopenharmony_ci	return count;
2428c2ecf20Sopenharmony_ci}
2438c2ecf20Sopenharmony_ci
2448c2ecf20Sopenharmony_ci/**
2458c2ecf20Sopenharmony_ci * ubi_get_device - get UBI device.
2468c2ecf20Sopenharmony_ci * @ubi_num: UBI device number
2478c2ecf20Sopenharmony_ci *
2488c2ecf20Sopenharmony_ci * This function returns UBI device description object for UBI device number
2498c2ecf20Sopenharmony_ci * @ubi_num, or %NULL if the device does not exist. This function increases the
2508c2ecf20Sopenharmony_ci * device reference count to prevent removal of the device. In other words, the
2518c2ecf20Sopenharmony_ci * device cannot be removed if its reference count is not zero.
2528c2ecf20Sopenharmony_ci */
2538c2ecf20Sopenharmony_cistruct ubi_device *ubi_get_device(int ubi_num)
2548c2ecf20Sopenharmony_ci{
2558c2ecf20Sopenharmony_ci	struct ubi_device *ubi;
2568c2ecf20Sopenharmony_ci
2578c2ecf20Sopenharmony_ci	spin_lock(&ubi_devices_lock);
2588c2ecf20Sopenharmony_ci	ubi = ubi_devices[ubi_num];
2598c2ecf20Sopenharmony_ci	if (ubi) {
2608c2ecf20Sopenharmony_ci		ubi_assert(ubi->ref_count >= 0);
2618c2ecf20Sopenharmony_ci		ubi->ref_count += 1;
2628c2ecf20Sopenharmony_ci		get_device(&ubi->dev);
2638c2ecf20Sopenharmony_ci	}
2648c2ecf20Sopenharmony_ci	spin_unlock(&ubi_devices_lock);
2658c2ecf20Sopenharmony_ci
2668c2ecf20Sopenharmony_ci	return ubi;
2678c2ecf20Sopenharmony_ci}
2688c2ecf20Sopenharmony_ci
2698c2ecf20Sopenharmony_ci/**
2708c2ecf20Sopenharmony_ci * ubi_put_device - drop an UBI device reference.
2718c2ecf20Sopenharmony_ci * @ubi: UBI device description object
2728c2ecf20Sopenharmony_ci */
2738c2ecf20Sopenharmony_civoid ubi_put_device(struct ubi_device *ubi)
2748c2ecf20Sopenharmony_ci{
2758c2ecf20Sopenharmony_ci	spin_lock(&ubi_devices_lock);
2768c2ecf20Sopenharmony_ci	ubi->ref_count -= 1;
2778c2ecf20Sopenharmony_ci	put_device(&ubi->dev);
2788c2ecf20Sopenharmony_ci	spin_unlock(&ubi_devices_lock);
2798c2ecf20Sopenharmony_ci}
2808c2ecf20Sopenharmony_ci
2818c2ecf20Sopenharmony_ci/**
2828c2ecf20Sopenharmony_ci * ubi_get_by_major - get UBI device by character device major number.
2838c2ecf20Sopenharmony_ci * @major: major number
2848c2ecf20Sopenharmony_ci *
2858c2ecf20Sopenharmony_ci * This function is similar to 'ubi_get_device()', but it searches the device
2868c2ecf20Sopenharmony_ci * by its major number.
2878c2ecf20Sopenharmony_ci */
2888c2ecf20Sopenharmony_cistruct ubi_device *ubi_get_by_major(int major)
2898c2ecf20Sopenharmony_ci{
2908c2ecf20Sopenharmony_ci	int i;
2918c2ecf20Sopenharmony_ci	struct ubi_device *ubi;
2928c2ecf20Sopenharmony_ci
2938c2ecf20Sopenharmony_ci	spin_lock(&ubi_devices_lock);
2948c2ecf20Sopenharmony_ci	for (i = 0; i < UBI_MAX_DEVICES; i++) {
2958c2ecf20Sopenharmony_ci		ubi = ubi_devices[i];
2968c2ecf20Sopenharmony_ci		if (ubi && MAJOR(ubi->cdev.dev) == major) {
2978c2ecf20Sopenharmony_ci			ubi_assert(ubi->ref_count >= 0);
2988c2ecf20Sopenharmony_ci			ubi->ref_count += 1;
2998c2ecf20Sopenharmony_ci			get_device(&ubi->dev);
3008c2ecf20Sopenharmony_ci			spin_unlock(&ubi_devices_lock);
3018c2ecf20Sopenharmony_ci			return ubi;
3028c2ecf20Sopenharmony_ci		}
3038c2ecf20Sopenharmony_ci	}
3048c2ecf20Sopenharmony_ci	spin_unlock(&ubi_devices_lock);
3058c2ecf20Sopenharmony_ci
3068c2ecf20Sopenharmony_ci	return NULL;
3078c2ecf20Sopenharmony_ci}
3088c2ecf20Sopenharmony_ci
3098c2ecf20Sopenharmony_ci/**
3108c2ecf20Sopenharmony_ci * ubi_major2num - get UBI device number by character device major number.
3118c2ecf20Sopenharmony_ci * @major: major number
3128c2ecf20Sopenharmony_ci *
3138c2ecf20Sopenharmony_ci * This function searches UBI device number object by its major number. If UBI
3148c2ecf20Sopenharmony_ci * device was not found, this function returns -ENODEV, otherwise the UBI device
3158c2ecf20Sopenharmony_ci * number is returned.
3168c2ecf20Sopenharmony_ci */
3178c2ecf20Sopenharmony_ciint ubi_major2num(int major)
3188c2ecf20Sopenharmony_ci{
3198c2ecf20Sopenharmony_ci	int i, ubi_num = -ENODEV;
3208c2ecf20Sopenharmony_ci
3218c2ecf20Sopenharmony_ci	spin_lock(&ubi_devices_lock);
3228c2ecf20Sopenharmony_ci	for (i = 0; i < UBI_MAX_DEVICES; i++) {
3238c2ecf20Sopenharmony_ci		struct ubi_device *ubi = ubi_devices[i];
3248c2ecf20Sopenharmony_ci
3258c2ecf20Sopenharmony_ci		if (ubi && MAJOR(ubi->cdev.dev) == major) {
3268c2ecf20Sopenharmony_ci			ubi_num = ubi->ubi_num;
3278c2ecf20Sopenharmony_ci			break;
3288c2ecf20Sopenharmony_ci		}
3298c2ecf20Sopenharmony_ci	}
3308c2ecf20Sopenharmony_ci	spin_unlock(&ubi_devices_lock);
3318c2ecf20Sopenharmony_ci
3328c2ecf20Sopenharmony_ci	return ubi_num;
3338c2ecf20Sopenharmony_ci}
3348c2ecf20Sopenharmony_ci
3358c2ecf20Sopenharmony_ci/* "Show" method for files in '/<sysfs>/class/ubi/ubiX/' */
3368c2ecf20Sopenharmony_cistatic ssize_t dev_attribute_show(struct device *dev,
3378c2ecf20Sopenharmony_ci				  struct device_attribute *attr, char *buf)
3388c2ecf20Sopenharmony_ci{
3398c2ecf20Sopenharmony_ci	ssize_t ret;
3408c2ecf20Sopenharmony_ci	struct ubi_device *ubi;
3418c2ecf20Sopenharmony_ci
3428c2ecf20Sopenharmony_ci	/*
3438c2ecf20Sopenharmony_ci	 * The below code looks weird, but it actually makes sense. We get the
3448c2ecf20Sopenharmony_ci	 * UBI device reference from the contained 'struct ubi_device'. But it
3458c2ecf20Sopenharmony_ci	 * is unclear if the device was removed or not yet. Indeed, if the
3468c2ecf20Sopenharmony_ci	 * device was removed before we increased its reference count,
3478c2ecf20Sopenharmony_ci	 * 'ubi_get_device()' will return -ENODEV and we fail.
3488c2ecf20Sopenharmony_ci	 *
3498c2ecf20Sopenharmony_ci	 * Remember, 'struct ubi_device' is freed in the release function, so
3508c2ecf20Sopenharmony_ci	 * we still can use 'ubi->ubi_num'.
3518c2ecf20Sopenharmony_ci	 */
3528c2ecf20Sopenharmony_ci	ubi = container_of(dev, struct ubi_device, dev);
3538c2ecf20Sopenharmony_ci
3548c2ecf20Sopenharmony_ci	if (attr == &dev_eraseblock_size)
3558c2ecf20Sopenharmony_ci		ret = sprintf(buf, "%d\n", ubi->leb_size);
3568c2ecf20Sopenharmony_ci	else if (attr == &dev_avail_eraseblocks)
3578c2ecf20Sopenharmony_ci		ret = sprintf(buf, "%d\n", ubi->avail_pebs);
3588c2ecf20Sopenharmony_ci	else if (attr == &dev_total_eraseblocks)
3598c2ecf20Sopenharmony_ci		ret = sprintf(buf, "%d\n", ubi->good_peb_count);
3608c2ecf20Sopenharmony_ci	else if (attr == &dev_volumes_count)
3618c2ecf20Sopenharmony_ci		ret = sprintf(buf, "%d\n", ubi->vol_count - UBI_INT_VOL_COUNT);
3628c2ecf20Sopenharmony_ci	else if (attr == &dev_max_ec)
3638c2ecf20Sopenharmony_ci		ret = sprintf(buf, "%d\n", ubi->max_ec);
3648c2ecf20Sopenharmony_ci	else if (attr == &dev_reserved_for_bad)
3658c2ecf20Sopenharmony_ci		ret = sprintf(buf, "%d\n", ubi->beb_rsvd_pebs);
3668c2ecf20Sopenharmony_ci	else if (attr == &dev_bad_peb_count)
3678c2ecf20Sopenharmony_ci		ret = sprintf(buf, "%d\n", ubi->bad_peb_count);
3688c2ecf20Sopenharmony_ci	else if (attr == &dev_max_vol_count)
3698c2ecf20Sopenharmony_ci		ret = sprintf(buf, "%d\n", ubi->vtbl_slots);
3708c2ecf20Sopenharmony_ci	else if (attr == &dev_min_io_size)
3718c2ecf20Sopenharmony_ci		ret = sprintf(buf, "%d\n", ubi->min_io_size);
3728c2ecf20Sopenharmony_ci	else if (attr == &dev_bgt_enabled)
3738c2ecf20Sopenharmony_ci		ret = sprintf(buf, "%d\n", ubi->thread_enabled);
3748c2ecf20Sopenharmony_ci	else if (attr == &dev_mtd_num)
3758c2ecf20Sopenharmony_ci		ret = sprintf(buf, "%d\n", ubi->mtd->index);
3768c2ecf20Sopenharmony_ci	else if (attr == &dev_ro_mode)
3778c2ecf20Sopenharmony_ci		ret = sprintf(buf, "%d\n", ubi->ro_mode);
3788c2ecf20Sopenharmony_ci	else
3798c2ecf20Sopenharmony_ci		ret = -EINVAL;
3808c2ecf20Sopenharmony_ci
3818c2ecf20Sopenharmony_ci	return ret;
3828c2ecf20Sopenharmony_ci}
3838c2ecf20Sopenharmony_ci
3848c2ecf20Sopenharmony_cistatic struct attribute *ubi_dev_attrs[] = {
3858c2ecf20Sopenharmony_ci	&dev_eraseblock_size.attr,
3868c2ecf20Sopenharmony_ci	&dev_avail_eraseblocks.attr,
3878c2ecf20Sopenharmony_ci	&dev_total_eraseblocks.attr,
3888c2ecf20Sopenharmony_ci	&dev_volumes_count.attr,
3898c2ecf20Sopenharmony_ci	&dev_max_ec.attr,
3908c2ecf20Sopenharmony_ci	&dev_reserved_for_bad.attr,
3918c2ecf20Sopenharmony_ci	&dev_bad_peb_count.attr,
3928c2ecf20Sopenharmony_ci	&dev_max_vol_count.attr,
3938c2ecf20Sopenharmony_ci	&dev_min_io_size.attr,
3948c2ecf20Sopenharmony_ci	&dev_bgt_enabled.attr,
3958c2ecf20Sopenharmony_ci	&dev_mtd_num.attr,
3968c2ecf20Sopenharmony_ci	&dev_ro_mode.attr,
3978c2ecf20Sopenharmony_ci	NULL
3988c2ecf20Sopenharmony_ci};
3998c2ecf20Sopenharmony_ciATTRIBUTE_GROUPS(ubi_dev);
4008c2ecf20Sopenharmony_ci
4018c2ecf20Sopenharmony_cistatic void dev_release(struct device *dev)
4028c2ecf20Sopenharmony_ci{
4038c2ecf20Sopenharmony_ci	struct ubi_device *ubi = container_of(dev, struct ubi_device, dev);
4048c2ecf20Sopenharmony_ci
4058c2ecf20Sopenharmony_ci	kfree(ubi);
4068c2ecf20Sopenharmony_ci}
4078c2ecf20Sopenharmony_ci
4088c2ecf20Sopenharmony_ci/**
4098c2ecf20Sopenharmony_ci * kill_volumes - destroy all user volumes.
4108c2ecf20Sopenharmony_ci * @ubi: UBI device description object
4118c2ecf20Sopenharmony_ci */
4128c2ecf20Sopenharmony_cistatic void kill_volumes(struct ubi_device *ubi)
4138c2ecf20Sopenharmony_ci{
4148c2ecf20Sopenharmony_ci	int i;
4158c2ecf20Sopenharmony_ci
4168c2ecf20Sopenharmony_ci	for (i = 0; i < ubi->vtbl_slots; i++)
4178c2ecf20Sopenharmony_ci		if (ubi->volumes[i])
4188c2ecf20Sopenharmony_ci			ubi_free_volume(ubi, ubi->volumes[i]);
4198c2ecf20Sopenharmony_ci}
4208c2ecf20Sopenharmony_ci
4218c2ecf20Sopenharmony_ci/**
4228c2ecf20Sopenharmony_ci * uif_init - initialize user interfaces for an UBI device.
4238c2ecf20Sopenharmony_ci * @ubi: UBI device description object
4248c2ecf20Sopenharmony_ci *
4258c2ecf20Sopenharmony_ci * This function initializes various user interfaces for an UBI device. If the
4268c2ecf20Sopenharmony_ci * initialization fails at an early stage, this function frees all the
4278c2ecf20Sopenharmony_ci * resources it allocated, returns an error.
4288c2ecf20Sopenharmony_ci *
4298c2ecf20Sopenharmony_ci * This function returns zero in case of success and a negative error code in
4308c2ecf20Sopenharmony_ci * case of failure.
4318c2ecf20Sopenharmony_ci */
4328c2ecf20Sopenharmony_cistatic int uif_init(struct ubi_device *ubi)
4338c2ecf20Sopenharmony_ci{
4348c2ecf20Sopenharmony_ci	int i, err;
4358c2ecf20Sopenharmony_ci	dev_t dev;
4368c2ecf20Sopenharmony_ci
4378c2ecf20Sopenharmony_ci	sprintf(ubi->ubi_name, UBI_NAME_STR "%d", ubi->ubi_num);
4388c2ecf20Sopenharmony_ci
4398c2ecf20Sopenharmony_ci	/*
4408c2ecf20Sopenharmony_ci	 * Major numbers for the UBI character devices are allocated
4418c2ecf20Sopenharmony_ci	 * dynamically. Major numbers of volume character devices are
4428c2ecf20Sopenharmony_ci	 * equivalent to ones of the corresponding UBI character device. Minor
4438c2ecf20Sopenharmony_ci	 * numbers of UBI character devices are 0, while minor numbers of
4448c2ecf20Sopenharmony_ci	 * volume character devices start from 1. Thus, we allocate one major
4458c2ecf20Sopenharmony_ci	 * number and ubi->vtbl_slots + 1 minor numbers.
4468c2ecf20Sopenharmony_ci	 */
4478c2ecf20Sopenharmony_ci	err = alloc_chrdev_region(&dev, 0, ubi->vtbl_slots + 1, ubi->ubi_name);
4488c2ecf20Sopenharmony_ci	if (err) {
4498c2ecf20Sopenharmony_ci		ubi_err(ubi, "cannot register UBI character devices");
4508c2ecf20Sopenharmony_ci		return err;
4518c2ecf20Sopenharmony_ci	}
4528c2ecf20Sopenharmony_ci
4538c2ecf20Sopenharmony_ci	ubi->dev.devt = dev;
4548c2ecf20Sopenharmony_ci
4558c2ecf20Sopenharmony_ci	ubi_assert(MINOR(dev) == 0);
4568c2ecf20Sopenharmony_ci	cdev_init(&ubi->cdev, &ubi_cdev_operations);
4578c2ecf20Sopenharmony_ci	dbg_gen("%s major is %u", ubi->ubi_name, MAJOR(dev));
4588c2ecf20Sopenharmony_ci	ubi->cdev.owner = THIS_MODULE;
4598c2ecf20Sopenharmony_ci
4608c2ecf20Sopenharmony_ci	dev_set_name(&ubi->dev, UBI_NAME_STR "%d", ubi->ubi_num);
4618c2ecf20Sopenharmony_ci	err = cdev_device_add(&ubi->cdev, &ubi->dev);
4628c2ecf20Sopenharmony_ci	if (err)
4638c2ecf20Sopenharmony_ci		goto out_unreg;
4648c2ecf20Sopenharmony_ci
4658c2ecf20Sopenharmony_ci	for (i = 0; i < ubi->vtbl_slots; i++)
4668c2ecf20Sopenharmony_ci		if (ubi->volumes[i]) {
4678c2ecf20Sopenharmony_ci			err = ubi_add_volume(ubi, ubi->volumes[i]);
4688c2ecf20Sopenharmony_ci			if (err) {
4698c2ecf20Sopenharmony_ci				ubi_err(ubi, "cannot add volume %d", i);
4708c2ecf20Sopenharmony_ci				ubi->volumes[i] = NULL;
4718c2ecf20Sopenharmony_ci				goto out_volumes;
4728c2ecf20Sopenharmony_ci			}
4738c2ecf20Sopenharmony_ci		}
4748c2ecf20Sopenharmony_ci
4758c2ecf20Sopenharmony_ci	return 0;
4768c2ecf20Sopenharmony_ci
4778c2ecf20Sopenharmony_ciout_volumes:
4788c2ecf20Sopenharmony_ci	kill_volumes(ubi);
4798c2ecf20Sopenharmony_ci	cdev_device_del(&ubi->cdev, &ubi->dev);
4808c2ecf20Sopenharmony_ciout_unreg:
4818c2ecf20Sopenharmony_ci	unregister_chrdev_region(ubi->cdev.dev, ubi->vtbl_slots + 1);
4828c2ecf20Sopenharmony_ci	ubi_err(ubi, "cannot initialize UBI %s, error %d",
4838c2ecf20Sopenharmony_ci		ubi->ubi_name, err);
4848c2ecf20Sopenharmony_ci	return err;
4858c2ecf20Sopenharmony_ci}
4868c2ecf20Sopenharmony_ci
4878c2ecf20Sopenharmony_ci/**
4888c2ecf20Sopenharmony_ci * uif_close - close user interfaces for an UBI device.
4898c2ecf20Sopenharmony_ci * @ubi: UBI device description object
4908c2ecf20Sopenharmony_ci *
4918c2ecf20Sopenharmony_ci * Note, since this function un-registers UBI volume device objects (@vol->dev),
4928c2ecf20Sopenharmony_ci * the memory allocated voe the volumes is freed as well (in the release
4938c2ecf20Sopenharmony_ci * function).
4948c2ecf20Sopenharmony_ci */
4958c2ecf20Sopenharmony_cistatic void uif_close(struct ubi_device *ubi)
4968c2ecf20Sopenharmony_ci{
4978c2ecf20Sopenharmony_ci	kill_volumes(ubi);
4988c2ecf20Sopenharmony_ci	cdev_device_del(&ubi->cdev, &ubi->dev);
4998c2ecf20Sopenharmony_ci	unregister_chrdev_region(ubi->cdev.dev, ubi->vtbl_slots + 1);
5008c2ecf20Sopenharmony_ci}
5018c2ecf20Sopenharmony_ci
5028c2ecf20Sopenharmony_ci/**
5038c2ecf20Sopenharmony_ci * ubi_free_volumes_from - free volumes from specific index.
5048c2ecf20Sopenharmony_ci * @ubi: UBI device description object
5058c2ecf20Sopenharmony_ci * @from: the start index used for volume free.
5068c2ecf20Sopenharmony_ci */
5078c2ecf20Sopenharmony_cistatic void ubi_free_volumes_from(struct ubi_device *ubi, int from)
5088c2ecf20Sopenharmony_ci{
5098c2ecf20Sopenharmony_ci	int i;
5108c2ecf20Sopenharmony_ci
5118c2ecf20Sopenharmony_ci	for (i = from; i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) {
5128c2ecf20Sopenharmony_ci		if (!ubi->volumes[i])
5138c2ecf20Sopenharmony_ci			continue;
5148c2ecf20Sopenharmony_ci		ubi_eba_replace_table(ubi->volumes[i], NULL);
5158c2ecf20Sopenharmony_ci		ubi_fastmap_destroy_checkmap(ubi->volumes[i]);
5168c2ecf20Sopenharmony_ci		kfree(ubi->volumes[i]);
5178c2ecf20Sopenharmony_ci		ubi->volumes[i] = NULL;
5188c2ecf20Sopenharmony_ci	}
5198c2ecf20Sopenharmony_ci}
5208c2ecf20Sopenharmony_ci
5218c2ecf20Sopenharmony_ci/**
5228c2ecf20Sopenharmony_ci * ubi_free_all_volumes - free all volumes.
5238c2ecf20Sopenharmony_ci * @ubi: UBI device description object
5248c2ecf20Sopenharmony_ci */
5258c2ecf20Sopenharmony_civoid ubi_free_all_volumes(struct ubi_device *ubi)
5268c2ecf20Sopenharmony_ci{
5278c2ecf20Sopenharmony_ci	ubi_free_volumes_from(ubi, 0);
5288c2ecf20Sopenharmony_ci}
5298c2ecf20Sopenharmony_ci
5308c2ecf20Sopenharmony_ci/**
5318c2ecf20Sopenharmony_ci * ubi_free_internal_volumes - free internal volumes.
5328c2ecf20Sopenharmony_ci * @ubi: UBI device description object
5338c2ecf20Sopenharmony_ci */
5348c2ecf20Sopenharmony_civoid ubi_free_internal_volumes(struct ubi_device *ubi)
5358c2ecf20Sopenharmony_ci{
5368c2ecf20Sopenharmony_ci	ubi_free_volumes_from(ubi, ubi->vtbl_slots);
5378c2ecf20Sopenharmony_ci}
5388c2ecf20Sopenharmony_ci
5398c2ecf20Sopenharmony_cistatic int get_bad_peb_limit(const struct ubi_device *ubi, int max_beb_per1024)
5408c2ecf20Sopenharmony_ci{
5418c2ecf20Sopenharmony_ci	int limit, device_pebs;
5428c2ecf20Sopenharmony_ci	uint64_t device_size;
5438c2ecf20Sopenharmony_ci
5448c2ecf20Sopenharmony_ci	if (!max_beb_per1024) {
5458c2ecf20Sopenharmony_ci		/*
5468c2ecf20Sopenharmony_ci		 * Since max_beb_per1024 has not been set by the user in either
5478c2ecf20Sopenharmony_ci		 * the cmdline or Kconfig, use mtd_max_bad_blocks to set the
5488c2ecf20Sopenharmony_ci		 * limit if it is supported by the device.
5498c2ecf20Sopenharmony_ci		 */
5508c2ecf20Sopenharmony_ci		limit = mtd_max_bad_blocks(ubi->mtd, 0, ubi->mtd->size);
5518c2ecf20Sopenharmony_ci		if (limit < 0)
5528c2ecf20Sopenharmony_ci			return 0;
5538c2ecf20Sopenharmony_ci		return limit;
5548c2ecf20Sopenharmony_ci	}
5558c2ecf20Sopenharmony_ci
5568c2ecf20Sopenharmony_ci	/*
5578c2ecf20Sopenharmony_ci	 * Here we are using size of the entire flash chip and
5588c2ecf20Sopenharmony_ci	 * not just the MTD partition size because the maximum
5598c2ecf20Sopenharmony_ci	 * number of bad eraseblocks is a percentage of the
5608c2ecf20Sopenharmony_ci	 * whole device and bad eraseblocks are not fairly
5618c2ecf20Sopenharmony_ci	 * distributed over the flash chip. So the worst case
5628c2ecf20Sopenharmony_ci	 * is that all the bad eraseblocks of the chip are in
5638c2ecf20Sopenharmony_ci	 * the MTD partition we are attaching (ubi->mtd).
5648c2ecf20Sopenharmony_ci	 */
5658c2ecf20Sopenharmony_ci	device_size = mtd_get_device_size(ubi->mtd);
5668c2ecf20Sopenharmony_ci	device_pebs = mtd_div_by_eb(device_size, ubi->mtd);
5678c2ecf20Sopenharmony_ci	limit = mult_frac(device_pebs, max_beb_per1024, 1024);
5688c2ecf20Sopenharmony_ci
5698c2ecf20Sopenharmony_ci	/* Round it up */
5708c2ecf20Sopenharmony_ci	if (mult_frac(limit, 1024, max_beb_per1024) < device_pebs)
5718c2ecf20Sopenharmony_ci		limit += 1;
5728c2ecf20Sopenharmony_ci
5738c2ecf20Sopenharmony_ci	return limit;
5748c2ecf20Sopenharmony_ci}
5758c2ecf20Sopenharmony_ci
5768c2ecf20Sopenharmony_ci/**
5778c2ecf20Sopenharmony_ci * io_init - initialize I/O sub-system for a given UBI device.
5788c2ecf20Sopenharmony_ci * @ubi: UBI device description object
5798c2ecf20Sopenharmony_ci * @max_beb_per1024: maximum expected number of bad PEB per 1024 PEBs
5808c2ecf20Sopenharmony_ci *
5818c2ecf20Sopenharmony_ci * If @ubi->vid_hdr_offset or @ubi->leb_start is zero, default offsets are
5828c2ecf20Sopenharmony_ci * assumed:
5838c2ecf20Sopenharmony_ci *   o EC header is always at offset zero - this cannot be changed;
5848c2ecf20Sopenharmony_ci *   o VID header starts just after the EC header at the closest address
5858c2ecf20Sopenharmony_ci *     aligned to @io->hdrs_min_io_size;
5868c2ecf20Sopenharmony_ci *   o data starts just after the VID header at the closest address aligned to
5878c2ecf20Sopenharmony_ci *     @io->min_io_size
5888c2ecf20Sopenharmony_ci *
5898c2ecf20Sopenharmony_ci * This function returns zero in case of success and a negative error code in
5908c2ecf20Sopenharmony_ci * case of failure.
5918c2ecf20Sopenharmony_ci */
5928c2ecf20Sopenharmony_cistatic int io_init(struct ubi_device *ubi, int max_beb_per1024)
5938c2ecf20Sopenharmony_ci{
5948c2ecf20Sopenharmony_ci	dbg_gen("sizeof(struct ubi_ainf_peb) %zu", sizeof(struct ubi_ainf_peb));
5958c2ecf20Sopenharmony_ci	dbg_gen("sizeof(struct ubi_wl_entry) %zu", sizeof(struct ubi_wl_entry));
5968c2ecf20Sopenharmony_ci
5978c2ecf20Sopenharmony_ci	if (ubi->mtd->numeraseregions != 0) {
5988c2ecf20Sopenharmony_ci		/*
5998c2ecf20Sopenharmony_ci		 * Some flashes have several erase regions. Different regions
6008c2ecf20Sopenharmony_ci		 * may have different eraseblock size and other
6018c2ecf20Sopenharmony_ci		 * characteristics. It looks like mostly multi-region flashes
6028c2ecf20Sopenharmony_ci		 * have one "main" region and one or more small regions to
6038c2ecf20Sopenharmony_ci		 * store boot loader code or boot parameters or whatever. I
6048c2ecf20Sopenharmony_ci		 * guess we should just pick the largest region. But this is
6058c2ecf20Sopenharmony_ci		 * not implemented.
6068c2ecf20Sopenharmony_ci		 */
6078c2ecf20Sopenharmony_ci		ubi_err(ubi, "multiple regions, not implemented");
6088c2ecf20Sopenharmony_ci		return -EINVAL;
6098c2ecf20Sopenharmony_ci	}
6108c2ecf20Sopenharmony_ci
6118c2ecf20Sopenharmony_ci	if (ubi->vid_hdr_offset < 0)
6128c2ecf20Sopenharmony_ci		return -EINVAL;
6138c2ecf20Sopenharmony_ci
6148c2ecf20Sopenharmony_ci	/*
6158c2ecf20Sopenharmony_ci	 * Note, in this implementation we support MTD devices with 0x7FFFFFFF
6168c2ecf20Sopenharmony_ci	 * physical eraseblocks maximum.
6178c2ecf20Sopenharmony_ci	 */
6188c2ecf20Sopenharmony_ci
6198c2ecf20Sopenharmony_ci	ubi->peb_size   = ubi->mtd->erasesize;
6208c2ecf20Sopenharmony_ci	ubi->peb_count  = mtd_div_by_eb(ubi->mtd->size, ubi->mtd);
6218c2ecf20Sopenharmony_ci	ubi->flash_size = ubi->mtd->size;
6228c2ecf20Sopenharmony_ci
6238c2ecf20Sopenharmony_ci	if (mtd_can_have_bb(ubi->mtd)) {
6248c2ecf20Sopenharmony_ci		ubi->bad_allowed = 1;
6258c2ecf20Sopenharmony_ci		ubi->bad_peb_limit = get_bad_peb_limit(ubi, max_beb_per1024);
6268c2ecf20Sopenharmony_ci	}
6278c2ecf20Sopenharmony_ci
6288c2ecf20Sopenharmony_ci	if (ubi->mtd->type == MTD_NORFLASH) {
6298c2ecf20Sopenharmony_ci		ubi_assert(ubi->mtd->writesize == 1);
6308c2ecf20Sopenharmony_ci		ubi->nor_flash = 1;
6318c2ecf20Sopenharmony_ci	}
6328c2ecf20Sopenharmony_ci
6338c2ecf20Sopenharmony_ci	ubi->min_io_size = ubi->mtd->writesize;
6348c2ecf20Sopenharmony_ci	ubi->hdrs_min_io_size = ubi->mtd->writesize >> ubi->mtd->subpage_sft;
6358c2ecf20Sopenharmony_ci
6368c2ecf20Sopenharmony_ci	/*
6378c2ecf20Sopenharmony_ci	 * Make sure minimal I/O unit is power of 2. Note, there is no
6388c2ecf20Sopenharmony_ci	 * fundamental reason for this assumption. It is just an optimization
6398c2ecf20Sopenharmony_ci	 * which allows us to avoid costly division operations.
6408c2ecf20Sopenharmony_ci	 */
6418c2ecf20Sopenharmony_ci	if (!is_power_of_2(ubi->min_io_size)) {
6428c2ecf20Sopenharmony_ci		ubi_err(ubi, "min. I/O unit (%d) is not power of 2",
6438c2ecf20Sopenharmony_ci			ubi->min_io_size);
6448c2ecf20Sopenharmony_ci		return -EINVAL;
6458c2ecf20Sopenharmony_ci	}
6468c2ecf20Sopenharmony_ci
6478c2ecf20Sopenharmony_ci	ubi_assert(ubi->hdrs_min_io_size > 0);
6488c2ecf20Sopenharmony_ci	ubi_assert(ubi->hdrs_min_io_size <= ubi->min_io_size);
6498c2ecf20Sopenharmony_ci	ubi_assert(ubi->min_io_size % ubi->hdrs_min_io_size == 0);
6508c2ecf20Sopenharmony_ci
6518c2ecf20Sopenharmony_ci	ubi->max_write_size = ubi->mtd->writebufsize;
6528c2ecf20Sopenharmony_ci	/*
6538c2ecf20Sopenharmony_ci	 * Maximum write size has to be greater or equivalent to min. I/O
6548c2ecf20Sopenharmony_ci	 * size, and be multiple of min. I/O size.
6558c2ecf20Sopenharmony_ci	 */
6568c2ecf20Sopenharmony_ci	if (ubi->max_write_size < ubi->min_io_size ||
6578c2ecf20Sopenharmony_ci	    ubi->max_write_size % ubi->min_io_size ||
6588c2ecf20Sopenharmony_ci	    !is_power_of_2(ubi->max_write_size)) {
6598c2ecf20Sopenharmony_ci		ubi_err(ubi, "bad write buffer size %d for %d min. I/O unit",
6608c2ecf20Sopenharmony_ci			ubi->max_write_size, ubi->min_io_size);
6618c2ecf20Sopenharmony_ci		return -EINVAL;
6628c2ecf20Sopenharmony_ci	}
6638c2ecf20Sopenharmony_ci
6648c2ecf20Sopenharmony_ci	/* Calculate default aligned sizes of EC and VID headers */
6658c2ecf20Sopenharmony_ci	ubi->ec_hdr_alsize = ALIGN(UBI_EC_HDR_SIZE, ubi->hdrs_min_io_size);
6668c2ecf20Sopenharmony_ci	ubi->vid_hdr_alsize = ALIGN(UBI_VID_HDR_SIZE, ubi->hdrs_min_io_size);
6678c2ecf20Sopenharmony_ci
6688c2ecf20Sopenharmony_ci	dbg_gen("min_io_size      %d", ubi->min_io_size);
6698c2ecf20Sopenharmony_ci	dbg_gen("max_write_size   %d", ubi->max_write_size);
6708c2ecf20Sopenharmony_ci	dbg_gen("hdrs_min_io_size %d", ubi->hdrs_min_io_size);
6718c2ecf20Sopenharmony_ci	dbg_gen("ec_hdr_alsize    %d", ubi->ec_hdr_alsize);
6728c2ecf20Sopenharmony_ci	dbg_gen("vid_hdr_alsize   %d", ubi->vid_hdr_alsize);
6738c2ecf20Sopenharmony_ci
6748c2ecf20Sopenharmony_ci	if (ubi->vid_hdr_offset == 0)
6758c2ecf20Sopenharmony_ci		/* Default offset */
6768c2ecf20Sopenharmony_ci		ubi->vid_hdr_offset = ubi->vid_hdr_aloffset =
6778c2ecf20Sopenharmony_ci				      ubi->ec_hdr_alsize;
6788c2ecf20Sopenharmony_ci	else {
6798c2ecf20Sopenharmony_ci		ubi->vid_hdr_aloffset = ubi->vid_hdr_offset &
6808c2ecf20Sopenharmony_ci						~(ubi->hdrs_min_io_size - 1);
6818c2ecf20Sopenharmony_ci		ubi->vid_hdr_shift = ubi->vid_hdr_offset -
6828c2ecf20Sopenharmony_ci						ubi->vid_hdr_aloffset;
6838c2ecf20Sopenharmony_ci	}
6848c2ecf20Sopenharmony_ci
6858c2ecf20Sopenharmony_ci	/*
6868c2ecf20Sopenharmony_ci	 * Memory allocation for VID header is ubi->vid_hdr_alsize
6878c2ecf20Sopenharmony_ci	 * which is described in comments in io.c.
6888c2ecf20Sopenharmony_ci	 * Make sure VID header shift + UBI_VID_HDR_SIZE not exceeds
6898c2ecf20Sopenharmony_ci	 * ubi->vid_hdr_alsize, so that all vid header operations
6908c2ecf20Sopenharmony_ci	 * won't access memory out of bounds.
6918c2ecf20Sopenharmony_ci	 */
6928c2ecf20Sopenharmony_ci	if ((ubi->vid_hdr_shift + UBI_VID_HDR_SIZE) > ubi->vid_hdr_alsize) {
6938c2ecf20Sopenharmony_ci		ubi_err(ubi, "Invalid VID header offset %d, VID header shift(%d)"
6948c2ecf20Sopenharmony_ci			" + VID header size(%zu) > VID header aligned size(%d).",
6958c2ecf20Sopenharmony_ci			ubi->vid_hdr_offset, ubi->vid_hdr_shift,
6968c2ecf20Sopenharmony_ci			UBI_VID_HDR_SIZE, ubi->vid_hdr_alsize);
6978c2ecf20Sopenharmony_ci		return -EINVAL;
6988c2ecf20Sopenharmony_ci	}
6998c2ecf20Sopenharmony_ci
7008c2ecf20Sopenharmony_ci	/* Similar for the data offset */
7018c2ecf20Sopenharmony_ci	ubi->leb_start = ubi->vid_hdr_offset + UBI_VID_HDR_SIZE;
7028c2ecf20Sopenharmony_ci	ubi->leb_start = ALIGN(ubi->leb_start, ubi->min_io_size);
7038c2ecf20Sopenharmony_ci
7048c2ecf20Sopenharmony_ci	dbg_gen("vid_hdr_offset   %d", ubi->vid_hdr_offset);
7058c2ecf20Sopenharmony_ci	dbg_gen("vid_hdr_aloffset %d", ubi->vid_hdr_aloffset);
7068c2ecf20Sopenharmony_ci	dbg_gen("vid_hdr_shift    %d", ubi->vid_hdr_shift);
7078c2ecf20Sopenharmony_ci	dbg_gen("leb_start        %d", ubi->leb_start);
7088c2ecf20Sopenharmony_ci
7098c2ecf20Sopenharmony_ci	/* The shift must be aligned to 32-bit boundary */
7108c2ecf20Sopenharmony_ci	if (ubi->vid_hdr_shift % 4) {
7118c2ecf20Sopenharmony_ci		ubi_err(ubi, "unaligned VID header shift %d",
7128c2ecf20Sopenharmony_ci			ubi->vid_hdr_shift);
7138c2ecf20Sopenharmony_ci		return -EINVAL;
7148c2ecf20Sopenharmony_ci	}
7158c2ecf20Sopenharmony_ci
7168c2ecf20Sopenharmony_ci	/* Check sanity */
7178c2ecf20Sopenharmony_ci	if (ubi->vid_hdr_offset < UBI_EC_HDR_SIZE ||
7188c2ecf20Sopenharmony_ci	    ubi->leb_start < ubi->vid_hdr_offset + UBI_VID_HDR_SIZE ||
7198c2ecf20Sopenharmony_ci	    ubi->leb_start > ubi->peb_size - UBI_VID_HDR_SIZE ||
7208c2ecf20Sopenharmony_ci	    ubi->leb_start & (ubi->min_io_size - 1)) {
7218c2ecf20Sopenharmony_ci		ubi_err(ubi, "bad VID header (%d) or data offsets (%d)",
7228c2ecf20Sopenharmony_ci			ubi->vid_hdr_offset, ubi->leb_start);
7238c2ecf20Sopenharmony_ci		return -EINVAL;
7248c2ecf20Sopenharmony_ci	}
7258c2ecf20Sopenharmony_ci
7268c2ecf20Sopenharmony_ci	/*
7278c2ecf20Sopenharmony_ci	 * Set maximum amount of physical erroneous eraseblocks to be 10%.
7288c2ecf20Sopenharmony_ci	 * Erroneous PEB are those which have read errors.
7298c2ecf20Sopenharmony_ci	 */
7308c2ecf20Sopenharmony_ci	ubi->max_erroneous = ubi->peb_count / 10;
7318c2ecf20Sopenharmony_ci	if (ubi->max_erroneous < 16)
7328c2ecf20Sopenharmony_ci		ubi->max_erroneous = 16;
7338c2ecf20Sopenharmony_ci	dbg_gen("max_erroneous    %d", ubi->max_erroneous);
7348c2ecf20Sopenharmony_ci
7358c2ecf20Sopenharmony_ci	/*
7368c2ecf20Sopenharmony_ci	 * It may happen that EC and VID headers are situated in one minimal
7378c2ecf20Sopenharmony_ci	 * I/O unit. In this case we can only accept this UBI image in
7388c2ecf20Sopenharmony_ci	 * read-only mode.
7398c2ecf20Sopenharmony_ci	 */
7408c2ecf20Sopenharmony_ci	if (ubi->vid_hdr_offset + UBI_VID_HDR_SIZE <= ubi->hdrs_min_io_size) {
7418c2ecf20Sopenharmony_ci		ubi_warn(ubi, "EC and VID headers are in the same minimal I/O unit, switch to read-only mode");
7428c2ecf20Sopenharmony_ci		ubi->ro_mode = 1;
7438c2ecf20Sopenharmony_ci	}
7448c2ecf20Sopenharmony_ci
7458c2ecf20Sopenharmony_ci	ubi->leb_size = ubi->peb_size - ubi->leb_start;
7468c2ecf20Sopenharmony_ci
7478c2ecf20Sopenharmony_ci	if (!(ubi->mtd->flags & MTD_WRITEABLE)) {
7488c2ecf20Sopenharmony_ci		ubi_msg(ubi, "MTD device %d is write-protected, attach in read-only mode",
7498c2ecf20Sopenharmony_ci			ubi->mtd->index);
7508c2ecf20Sopenharmony_ci		ubi->ro_mode = 1;
7518c2ecf20Sopenharmony_ci	}
7528c2ecf20Sopenharmony_ci
7538c2ecf20Sopenharmony_ci	/*
7548c2ecf20Sopenharmony_ci	 * Note, ideally, we have to initialize @ubi->bad_peb_count here. But
7558c2ecf20Sopenharmony_ci	 * unfortunately, MTD does not provide this information. We should loop
7568c2ecf20Sopenharmony_ci	 * over all physical eraseblocks and invoke mtd->block_is_bad() for
7578c2ecf20Sopenharmony_ci	 * each physical eraseblock. So, we leave @ubi->bad_peb_count
7588c2ecf20Sopenharmony_ci	 * uninitialized so far.
7598c2ecf20Sopenharmony_ci	 */
7608c2ecf20Sopenharmony_ci
7618c2ecf20Sopenharmony_ci	return 0;
7628c2ecf20Sopenharmony_ci}
7638c2ecf20Sopenharmony_ci
7648c2ecf20Sopenharmony_ci/**
7658c2ecf20Sopenharmony_ci * autoresize - re-size the volume which has the "auto-resize" flag set.
7668c2ecf20Sopenharmony_ci * @ubi: UBI device description object
7678c2ecf20Sopenharmony_ci * @vol_id: ID of the volume to re-size
7688c2ecf20Sopenharmony_ci *
7698c2ecf20Sopenharmony_ci * This function re-sizes the volume marked by the %UBI_VTBL_AUTORESIZE_FLG in
7708c2ecf20Sopenharmony_ci * the volume table to the largest possible size. See comments in ubi-header.h
7718c2ecf20Sopenharmony_ci * for more description of the flag. Returns zero in case of success and a
7728c2ecf20Sopenharmony_ci * negative error code in case of failure.
7738c2ecf20Sopenharmony_ci */
7748c2ecf20Sopenharmony_cistatic int autoresize(struct ubi_device *ubi, int vol_id)
7758c2ecf20Sopenharmony_ci{
7768c2ecf20Sopenharmony_ci	struct ubi_volume_desc desc;
7778c2ecf20Sopenharmony_ci	struct ubi_volume *vol = ubi->volumes[vol_id];
7788c2ecf20Sopenharmony_ci	int err, old_reserved_pebs = vol->reserved_pebs;
7798c2ecf20Sopenharmony_ci
7808c2ecf20Sopenharmony_ci	if (ubi->ro_mode) {
7818c2ecf20Sopenharmony_ci		ubi_warn(ubi, "skip auto-resize because of R/O mode");
7828c2ecf20Sopenharmony_ci		return 0;
7838c2ecf20Sopenharmony_ci	}
7848c2ecf20Sopenharmony_ci
7858c2ecf20Sopenharmony_ci	/*
7868c2ecf20Sopenharmony_ci	 * Clear the auto-resize flag in the volume in-memory copy of the
7878c2ecf20Sopenharmony_ci	 * volume table, and 'ubi_resize_volume()' will propagate this change
7888c2ecf20Sopenharmony_ci	 * to the flash.
7898c2ecf20Sopenharmony_ci	 */
7908c2ecf20Sopenharmony_ci	ubi->vtbl[vol_id].flags &= ~UBI_VTBL_AUTORESIZE_FLG;
7918c2ecf20Sopenharmony_ci
7928c2ecf20Sopenharmony_ci	if (ubi->avail_pebs == 0) {
7938c2ecf20Sopenharmony_ci		struct ubi_vtbl_record vtbl_rec;
7948c2ecf20Sopenharmony_ci
7958c2ecf20Sopenharmony_ci		/*
7968c2ecf20Sopenharmony_ci		 * No available PEBs to re-size the volume, clear the flag on
7978c2ecf20Sopenharmony_ci		 * flash and exit.
7988c2ecf20Sopenharmony_ci		 */
7998c2ecf20Sopenharmony_ci		vtbl_rec = ubi->vtbl[vol_id];
8008c2ecf20Sopenharmony_ci		err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec);
8018c2ecf20Sopenharmony_ci		if (err)
8028c2ecf20Sopenharmony_ci			ubi_err(ubi, "cannot clean auto-resize flag for volume %d",
8038c2ecf20Sopenharmony_ci				vol_id);
8048c2ecf20Sopenharmony_ci	} else {
8058c2ecf20Sopenharmony_ci		desc.vol = vol;
8068c2ecf20Sopenharmony_ci		err = ubi_resize_volume(&desc,
8078c2ecf20Sopenharmony_ci					old_reserved_pebs + ubi->avail_pebs);
8088c2ecf20Sopenharmony_ci		if (err)
8098c2ecf20Sopenharmony_ci			ubi_err(ubi, "cannot auto-resize volume %d",
8108c2ecf20Sopenharmony_ci				vol_id);
8118c2ecf20Sopenharmony_ci	}
8128c2ecf20Sopenharmony_ci
8138c2ecf20Sopenharmony_ci	if (err)
8148c2ecf20Sopenharmony_ci		return err;
8158c2ecf20Sopenharmony_ci
8168c2ecf20Sopenharmony_ci	ubi_msg(ubi, "volume %d (\"%s\") re-sized from %d to %d LEBs",
8178c2ecf20Sopenharmony_ci		vol_id, vol->name, old_reserved_pebs, vol->reserved_pebs);
8188c2ecf20Sopenharmony_ci	return 0;
8198c2ecf20Sopenharmony_ci}
8208c2ecf20Sopenharmony_ci
8218c2ecf20Sopenharmony_ci/**
8228c2ecf20Sopenharmony_ci * ubi_attach_mtd_dev - attach an MTD device.
8238c2ecf20Sopenharmony_ci * @mtd: MTD device description object
8248c2ecf20Sopenharmony_ci * @ubi_num: number to assign to the new UBI device
8258c2ecf20Sopenharmony_ci * @vid_hdr_offset: VID header offset
8268c2ecf20Sopenharmony_ci * @max_beb_per1024: maximum expected number of bad PEB per 1024 PEBs
8278c2ecf20Sopenharmony_ci *
8288c2ecf20Sopenharmony_ci * This function attaches MTD device @mtd_dev to UBI and assign @ubi_num number
8298c2ecf20Sopenharmony_ci * to the newly created UBI device, unless @ubi_num is %UBI_DEV_NUM_AUTO, in
8308c2ecf20Sopenharmony_ci * which case this function finds a vacant device number and assigns it
8318c2ecf20Sopenharmony_ci * automatically. Returns the new UBI device number in case of success and a
8328c2ecf20Sopenharmony_ci * negative error code in case of failure.
8338c2ecf20Sopenharmony_ci *
8348c2ecf20Sopenharmony_ci * Note, the invocations of this function has to be serialized by the
8358c2ecf20Sopenharmony_ci * @ubi_devices_mutex.
8368c2ecf20Sopenharmony_ci */
8378c2ecf20Sopenharmony_ciint ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num,
8388c2ecf20Sopenharmony_ci		       int vid_hdr_offset, int max_beb_per1024)
8398c2ecf20Sopenharmony_ci{
8408c2ecf20Sopenharmony_ci	struct ubi_device *ubi;
8418c2ecf20Sopenharmony_ci	int i, err;
8428c2ecf20Sopenharmony_ci
8438c2ecf20Sopenharmony_ci	if (max_beb_per1024 < 0 || max_beb_per1024 > MAX_MTD_UBI_BEB_LIMIT)
8448c2ecf20Sopenharmony_ci		return -EINVAL;
8458c2ecf20Sopenharmony_ci
8468c2ecf20Sopenharmony_ci	if (!max_beb_per1024)
8478c2ecf20Sopenharmony_ci		max_beb_per1024 = CONFIG_MTD_UBI_BEB_LIMIT;
8488c2ecf20Sopenharmony_ci
8498c2ecf20Sopenharmony_ci	/*
8508c2ecf20Sopenharmony_ci	 * Check if we already have the same MTD device attached.
8518c2ecf20Sopenharmony_ci	 *
8528c2ecf20Sopenharmony_ci	 * Note, this function assumes that UBI devices creations and deletions
8538c2ecf20Sopenharmony_ci	 * are serialized, so it does not take the &ubi_devices_lock.
8548c2ecf20Sopenharmony_ci	 */
8558c2ecf20Sopenharmony_ci	for (i = 0; i < UBI_MAX_DEVICES; i++) {
8568c2ecf20Sopenharmony_ci		ubi = ubi_devices[i];
8578c2ecf20Sopenharmony_ci		if (ubi && mtd->index == ubi->mtd->index) {
8588c2ecf20Sopenharmony_ci			pr_err("ubi: mtd%d is already attached to ubi%d\n",
8598c2ecf20Sopenharmony_ci				mtd->index, i);
8608c2ecf20Sopenharmony_ci			return -EEXIST;
8618c2ecf20Sopenharmony_ci		}
8628c2ecf20Sopenharmony_ci	}
8638c2ecf20Sopenharmony_ci
8648c2ecf20Sopenharmony_ci	/*
8658c2ecf20Sopenharmony_ci	 * Make sure this MTD device is not emulated on top of an UBI volume
8668c2ecf20Sopenharmony_ci	 * already. Well, generally this recursion works fine, but there are
8678c2ecf20Sopenharmony_ci	 * different problems like the UBI module takes a reference to itself
8688c2ecf20Sopenharmony_ci	 * by attaching (and thus, opening) the emulated MTD device. This
8698c2ecf20Sopenharmony_ci	 * results in inability to unload the module. And in general it makes
8708c2ecf20Sopenharmony_ci	 * no sense to attach emulated MTD devices, so we prohibit this.
8718c2ecf20Sopenharmony_ci	 */
8728c2ecf20Sopenharmony_ci	if (mtd->type == MTD_UBIVOLUME) {
8738c2ecf20Sopenharmony_ci		pr_err("ubi: refuse attaching mtd%d - it is already emulated on top of UBI\n",
8748c2ecf20Sopenharmony_ci			mtd->index);
8758c2ecf20Sopenharmony_ci		return -EINVAL;
8768c2ecf20Sopenharmony_ci	}
8778c2ecf20Sopenharmony_ci
8788c2ecf20Sopenharmony_ci	/*
8798c2ecf20Sopenharmony_ci	 * Both UBI and UBIFS have been designed for SLC NAND and NOR flashes.
8808c2ecf20Sopenharmony_ci	 * MLC NAND is different and needs special care, otherwise UBI or UBIFS
8818c2ecf20Sopenharmony_ci	 * will die soon and you will lose all your data.
8828c2ecf20Sopenharmony_ci	 * Relax this rule if the partition we're attaching to operates in SLC
8838c2ecf20Sopenharmony_ci	 * mode.
8848c2ecf20Sopenharmony_ci	 */
8858c2ecf20Sopenharmony_ci	if (mtd->type == MTD_MLCNANDFLASH &&
8868c2ecf20Sopenharmony_ci	    !(mtd->flags & MTD_SLC_ON_MLC_EMULATION)) {
8878c2ecf20Sopenharmony_ci		pr_err("ubi: refuse attaching mtd%d - MLC NAND is not supported\n",
8888c2ecf20Sopenharmony_ci			mtd->index);
8898c2ecf20Sopenharmony_ci		return -EINVAL;
8908c2ecf20Sopenharmony_ci	}
8918c2ecf20Sopenharmony_ci
8928c2ecf20Sopenharmony_ci	/* UBI cannot work on flashes with zero erasesize. */
8938c2ecf20Sopenharmony_ci	if (!mtd->erasesize) {
8948c2ecf20Sopenharmony_ci		pr_err("ubi: refuse attaching mtd%d - zero erasesize flash is not supported\n",
8958c2ecf20Sopenharmony_ci			mtd->index);
8968c2ecf20Sopenharmony_ci		return -EINVAL;
8978c2ecf20Sopenharmony_ci	}
8988c2ecf20Sopenharmony_ci
8998c2ecf20Sopenharmony_ci	if (ubi_num == UBI_DEV_NUM_AUTO) {
9008c2ecf20Sopenharmony_ci		/* Search for an empty slot in the @ubi_devices array */
9018c2ecf20Sopenharmony_ci		for (ubi_num = 0; ubi_num < UBI_MAX_DEVICES; ubi_num++)
9028c2ecf20Sopenharmony_ci			if (!ubi_devices[ubi_num])
9038c2ecf20Sopenharmony_ci				break;
9048c2ecf20Sopenharmony_ci		if (ubi_num == UBI_MAX_DEVICES) {
9058c2ecf20Sopenharmony_ci			pr_err("ubi: only %d UBI devices may be created\n",
9068c2ecf20Sopenharmony_ci				UBI_MAX_DEVICES);
9078c2ecf20Sopenharmony_ci			return -ENFILE;
9088c2ecf20Sopenharmony_ci		}
9098c2ecf20Sopenharmony_ci	} else {
9108c2ecf20Sopenharmony_ci		if (ubi_num >= UBI_MAX_DEVICES)
9118c2ecf20Sopenharmony_ci			return -EINVAL;
9128c2ecf20Sopenharmony_ci
9138c2ecf20Sopenharmony_ci		/* Make sure ubi_num is not busy */
9148c2ecf20Sopenharmony_ci		if (ubi_devices[ubi_num]) {
9158c2ecf20Sopenharmony_ci			pr_err("ubi: ubi%i already exists\n", ubi_num);
9168c2ecf20Sopenharmony_ci			return -EEXIST;
9178c2ecf20Sopenharmony_ci		}
9188c2ecf20Sopenharmony_ci	}
9198c2ecf20Sopenharmony_ci
9208c2ecf20Sopenharmony_ci	ubi = kzalloc(sizeof(struct ubi_device), GFP_KERNEL);
9218c2ecf20Sopenharmony_ci	if (!ubi)
9228c2ecf20Sopenharmony_ci		return -ENOMEM;
9238c2ecf20Sopenharmony_ci
9248c2ecf20Sopenharmony_ci	device_initialize(&ubi->dev);
9258c2ecf20Sopenharmony_ci	ubi->dev.release = dev_release;
9268c2ecf20Sopenharmony_ci	ubi->dev.class = &ubi_class;
9278c2ecf20Sopenharmony_ci	ubi->dev.groups = ubi_dev_groups;
9288c2ecf20Sopenharmony_ci
9298c2ecf20Sopenharmony_ci	ubi->mtd = mtd;
9308c2ecf20Sopenharmony_ci	ubi->ubi_num = ubi_num;
9318c2ecf20Sopenharmony_ci	ubi->vid_hdr_offset = vid_hdr_offset;
9328c2ecf20Sopenharmony_ci	ubi->autoresize_vol_id = -1;
9338c2ecf20Sopenharmony_ci
9348c2ecf20Sopenharmony_ci#ifdef CONFIG_MTD_UBI_FASTMAP
9358c2ecf20Sopenharmony_ci	ubi->fm_pool.used = ubi->fm_pool.size = 0;
9368c2ecf20Sopenharmony_ci	ubi->fm_wl_pool.used = ubi->fm_wl_pool.size = 0;
9378c2ecf20Sopenharmony_ci
9388c2ecf20Sopenharmony_ci	/*
9398c2ecf20Sopenharmony_ci	 * fm_pool.max_size is 5% of the total number of PEBs but it's also
9408c2ecf20Sopenharmony_ci	 * between UBI_FM_MAX_POOL_SIZE and UBI_FM_MIN_POOL_SIZE.
9418c2ecf20Sopenharmony_ci	 */
9428c2ecf20Sopenharmony_ci	ubi->fm_pool.max_size = min(((int)mtd_div_by_eb(ubi->mtd->size,
9438c2ecf20Sopenharmony_ci		ubi->mtd) / 100) * 5, UBI_FM_MAX_POOL_SIZE);
9448c2ecf20Sopenharmony_ci	ubi->fm_pool.max_size = max(ubi->fm_pool.max_size,
9458c2ecf20Sopenharmony_ci		UBI_FM_MIN_POOL_SIZE);
9468c2ecf20Sopenharmony_ci
9478c2ecf20Sopenharmony_ci	ubi->fm_wl_pool.max_size = ubi->fm_pool.max_size / 2;
9488c2ecf20Sopenharmony_ci	ubi->fm_disabled = !fm_autoconvert;
9498c2ecf20Sopenharmony_ci	if (fm_debug)
9508c2ecf20Sopenharmony_ci		ubi_enable_dbg_chk_fastmap(ubi);
9518c2ecf20Sopenharmony_ci
9528c2ecf20Sopenharmony_ci	if (!ubi->fm_disabled && (int)mtd_div_by_eb(ubi->mtd->size, ubi->mtd)
9538c2ecf20Sopenharmony_ci	    <= UBI_FM_MAX_START) {
9548c2ecf20Sopenharmony_ci		ubi_err(ubi, "More than %i PEBs are needed for fastmap, sorry.",
9558c2ecf20Sopenharmony_ci			UBI_FM_MAX_START);
9568c2ecf20Sopenharmony_ci		ubi->fm_disabled = 1;
9578c2ecf20Sopenharmony_ci	}
9588c2ecf20Sopenharmony_ci
9598c2ecf20Sopenharmony_ci	ubi_msg(ubi, "default fastmap pool size: %d", ubi->fm_pool.max_size);
9608c2ecf20Sopenharmony_ci	ubi_msg(ubi, "default fastmap WL pool size: %d",
9618c2ecf20Sopenharmony_ci		ubi->fm_wl_pool.max_size);
9628c2ecf20Sopenharmony_ci#else
9638c2ecf20Sopenharmony_ci	ubi->fm_disabled = 1;
9648c2ecf20Sopenharmony_ci#endif
9658c2ecf20Sopenharmony_ci	mutex_init(&ubi->buf_mutex);
9668c2ecf20Sopenharmony_ci	mutex_init(&ubi->ckvol_mutex);
9678c2ecf20Sopenharmony_ci	mutex_init(&ubi->device_mutex);
9688c2ecf20Sopenharmony_ci	spin_lock_init(&ubi->volumes_lock);
9698c2ecf20Sopenharmony_ci	init_rwsem(&ubi->fm_protect);
9708c2ecf20Sopenharmony_ci	init_rwsem(&ubi->fm_eba_sem);
9718c2ecf20Sopenharmony_ci
9728c2ecf20Sopenharmony_ci	ubi_msg(ubi, "attaching mtd%d", mtd->index);
9738c2ecf20Sopenharmony_ci
9748c2ecf20Sopenharmony_ci	err = io_init(ubi, max_beb_per1024);
9758c2ecf20Sopenharmony_ci	if (err)
9768c2ecf20Sopenharmony_ci		goto out_free;
9778c2ecf20Sopenharmony_ci
9788c2ecf20Sopenharmony_ci	err = -ENOMEM;
9798c2ecf20Sopenharmony_ci	ubi->peb_buf = vmalloc(ubi->peb_size);
9808c2ecf20Sopenharmony_ci	if (!ubi->peb_buf)
9818c2ecf20Sopenharmony_ci		goto out_free;
9828c2ecf20Sopenharmony_ci
9838c2ecf20Sopenharmony_ci#ifdef CONFIG_MTD_UBI_FASTMAP
9848c2ecf20Sopenharmony_ci	ubi->fm_size = ubi_calc_fm_size(ubi);
9858c2ecf20Sopenharmony_ci	ubi->fm_buf = vzalloc(ubi->fm_size);
9868c2ecf20Sopenharmony_ci	if (!ubi->fm_buf)
9878c2ecf20Sopenharmony_ci		goto out_free;
9888c2ecf20Sopenharmony_ci#endif
9898c2ecf20Sopenharmony_ci	err = ubi_attach(ubi, 0);
9908c2ecf20Sopenharmony_ci	if (err) {
9918c2ecf20Sopenharmony_ci		ubi_err(ubi, "failed to attach mtd%d, error %d",
9928c2ecf20Sopenharmony_ci			mtd->index, err);
9938c2ecf20Sopenharmony_ci		goto out_free;
9948c2ecf20Sopenharmony_ci	}
9958c2ecf20Sopenharmony_ci
9968c2ecf20Sopenharmony_ci	if (ubi->autoresize_vol_id != -1) {
9978c2ecf20Sopenharmony_ci		err = autoresize(ubi, ubi->autoresize_vol_id);
9988c2ecf20Sopenharmony_ci		if (err)
9998c2ecf20Sopenharmony_ci			goto out_detach;
10008c2ecf20Sopenharmony_ci	}
10018c2ecf20Sopenharmony_ci
10028c2ecf20Sopenharmony_ci	err = uif_init(ubi);
10038c2ecf20Sopenharmony_ci	if (err)
10048c2ecf20Sopenharmony_ci		goto out_detach;
10058c2ecf20Sopenharmony_ci
10068c2ecf20Sopenharmony_ci	err = ubi_debugfs_init_dev(ubi);
10078c2ecf20Sopenharmony_ci	if (err)
10088c2ecf20Sopenharmony_ci		goto out_uif;
10098c2ecf20Sopenharmony_ci
10108c2ecf20Sopenharmony_ci	ubi->bgt_thread = kthread_create(ubi_thread, ubi, "%s", ubi->bgt_name);
10118c2ecf20Sopenharmony_ci	if (IS_ERR(ubi->bgt_thread)) {
10128c2ecf20Sopenharmony_ci		err = PTR_ERR(ubi->bgt_thread);
10138c2ecf20Sopenharmony_ci		ubi_err(ubi, "cannot spawn \"%s\", error %d",
10148c2ecf20Sopenharmony_ci			ubi->bgt_name, err);
10158c2ecf20Sopenharmony_ci		goto out_debugfs;
10168c2ecf20Sopenharmony_ci	}
10178c2ecf20Sopenharmony_ci
10188c2ecf20Sopenharmony_ci	ubi_msg(ubi, "attached mtd%d (name \"%s\", size %llu MiB)",
10198c2ecf20Sopenharmony_ci		mtd->index, mtd->name, ubi->flash_size >> 20);
10208c2ecf20Sopenharmony_ci	ubi_msg(ubi, "PEB size: %d bytes (%d KiB), LEB size: %d bytes",
10218c2ecf20Sopenharmony_ci		ubi->peb_size, ubi->peb_size >> 10, ubi->leb_size);
10228c2ecf20Sopenharmony_ci	ubi_msg(ubi, "min./max. I/O unit sizes: %d/%d, sub-page size %d",
10238c2ecf20Sopenharmony_ci		ubi->min_io_size, ubi->max_write_size, ubi->hdrs_min_io_size);
10248c2ecf20Sopenharmony_ci	ubi_msg(ubi, "VID header offset: %d (aligned %d), data offset: %d",
10258c2ecf20Sopenharmony_ci		ubi->vid_hdr_offset, ubi->vid_hdr_aloffset, ubi->leb_start);
10268c2ecf20Sopenharmony_ci	ubi_msg(ubi, "good PEBs: %d, bad PEBs: %d, corrupted PEBs: %d",
10278c2ecf20Sopenharmony_ci		ubi->good_peb_count, ubi->bad_peb_count, ubi->corr_peb_count);
10288c2ecf20Sopenharmony_ci	ubi_msg(ubi, "user volume: %d, internal volumes: %d, max. volumes count: %d",
10298c2ecf20Sopenharmony_ci		ubi->vol_count - UBI_INT_VOL_COUNT, UBI_INT_VOL_COUNT,
10308c2ecf20Sopenharmony_ci		ubi->vtbl_slots);
10318c2ecf20Sopenharmony_ci	ubi_msg(ubi, "max/mean erase counter: %d/%d, WL threshold: %d, image sequence number: %u",
10328c2ecf20Sopenharmony_ci		ubi->max_ec, ubi->mean_ec, CONFIG_MTD_UBI_WL_THRESHOLD,
10338c2ecf20Sopenharmony_ci		ubi->image_seq);
10348c2ecf20Sopenharmony_ci	ubi_msg(ubi, "available PEBs: %d, total reserved PEBs: %d, PEBs reserved for bad PEB handling: %d",
10358c2ecf20Sopenharmony_ci		ubi->avail_pebs, ubi->rsvd_pebs, ubi->beb_rsvd_pebs);
10368c2ecf20Sopenharmony_ci
10378c2ecf20Sopenharmony_ci	/*
10388c2ecf20Sopenharmony_ci	 * The below lock makes sure we do not race with 'ubi_thread()' which
10398c2ecf20Sopenharmony_ci	 * checks @ubi->thread_enabled. Otherwise we may fail to wake it up.
10408c2ecf20Sopenharmony_ci	 */
10418c2ecf20Sopenharmony_ci	spin_lock(&ubi->wl_lock);
10428c2ecf20Sopenharmony_ci	ubi->thread_enabled = 1;
10438c2ecf20Sopenharmony_ci	wake_up_process(ubi->bgt_thread);
10448c2ecf20Sopenharmony_ci	spin_unlock(&ubi->wl_lock);
10458c2ecf20Sopenharmony_ci
10468c2ecf20Sopenharmony_ci	ubi_devices[ubi_num] = ubi;
10478c2ecf20Sopenharmony_ci	ubi_notify_all(ubi, UBI_VOLUME_ADDED, NULL);
10488c2ecf20Sopenharmony_ci	return ubi_num;
10498c2ecf20Sopenharmony_ci
10508c2ecf20Sopenharmony_ciout_debugfs:
10518c2ecf20Sopenharmony_ci	ubi_debugfs_exit_dev(ubi);
10528c2ecf20Sopenharmony_ciout_uif:
10538c2ecf20Sopenharmony_ci	uif_close(ubi);
10548c2ecf20Sopenharmony_ciout_detach:
10558c2ecf20Sopenharmony_ci	ubi_wl_close(ubi);
10568c2ecf20Sopenharmony_ci	ubi_free_all_volumes(ubi);
10578c2ecf20Sopenharmony_ci	vfree(ubi->vtbl);
10588c2ecf20Sopenharmony_ciout_free:
10598c2ecf20Sopenharmony_ci	vfree(ubi->peb_buf);
10608c2ecf20Sopenharmony_ci	vfree(ubi->fm_buf);
10618c2ecf20Sopenharmony_ci	put_device(&ubi->dev);
10628c2ecf20Sopenharmony_ci	return err;
10638c2ecf20Sopenharmony_ci}
10648c2ecf20Sopenharmony_ci
10658c2ecf20Sopenharmony_ci/**
10668c2ecf20Sopenharmony_ci * ubi_detach_mtd_dev - detach an MTD device.
10678c2ecf20Sopenharmony_ci * @ubi_num: UBI device number to detach from
10688c2ecf20Sopenharmony_ci * @anyway: detach MTD even if device reference count is not zero
10698c2ecf20Sopenharmony_ci *
10708c2ecf20Sopenharmony_ci * This function destroys an UBI device number @ubi_num and detaches the
10718c2ecf20Sopenharmony_ci * underlying MTD device. Returns zero in case of success and %-EBUSY if the
10728c2ecf20Sopenharmony_ci * UBI device is busy and cannot be destroyed, and %-EINVAL if it does not
10738c2ecf20Sopenharmony_ci * exist.
10748c2ecf20Sopenharmony_ci *
10758c2ecf20Sopenharmony_ci * Note, the invocations of this function has to be serialized by the
10768c2ecf20Sopenharmony_ci * @ubi_devices_mutex.
10778c2ecf20Sopenharmony_ci */
10788c2ecf20Sopenharmony_ciint ubi_detach_mtd_dev(int ubi_num, int anyway)
10798c2ecf20Sopenharmony_ci{
10808c2ecf20Sopenharmony_ci	struct ubi_device *ubi;
10818c2ecf20Sopenharmony_ci
10828c2ecf20Sopenharmony_ci	if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES)
10838c2ecf20Sopenharmony_ci		return -EINVAL;
10848c2ecf20Sopenharmony_ci
10858c2ecf20Sopenharmony_ci	ubi = ubi_get_device(ubi_num);
10868c2ecf20Sopenharmony_ci	if (!ubi)
10878c2ecf20Sopenharmony_ci		return -EINVAL;
10888c2ecf20Sopenharmony_ci
10898c2ecf20Sopenharmony_ci	spin_lock(&ubi_devices_lock);
10908c2ecf20Sopenharmony_ci	put_device(&ubi->dev);
10918c2ecf20Sopenharmony_ci	ubi->ref_count -= 1;
10928c2ecf20Sopenharmony_ci	if (ubi->ref_count) {
10938c2ecf20Sopenharmony_ci		if (!anyway) {
10948c2ecf20Sopenharmony_ci			spin_unlock(&ubi_devices_lock);
10958c2ecf20Sopenharmony_ci			return -EBUSY;
10968c2ecf20Sopenharmony_ci		}
10978c2ecf20Sopenharmony_ci		/* This may only happen if there is a bug */
10988c2ecf20Sopenharmony_ci		ubi_err(ubi, "%s reference count %d, destroy anyway",
10998c2ecf20Sopenharmony_ci			ubi->ubi_name, ubi->ref_count);
11008c2ecf20Sopenharmony_ci	}
11018c2ecf20Sopenharmony_ci	ubi_devices[ubi_num] = NULL;
11028c2ecf20Sopenharmony_ci	spin_unlock(&ubi_devices_lock);
11038c2ecf20Sopenharmony_ci
11048c2ecf20Sopenharmony_ci	ubi_assert(ubi_num == ubi->ubi_num);
11058c2ecf20Sopenharmony_ci	ubi_notify_all(ubi, UBI_VOLUME_REMOVED, NULL);
11068c2ecf20Sopenharmony_ci	ubi_msg(ubi, "detaching mtd%d", ubi->mtd->index);
11078c2ecf20Sopenharmony_ci#ifdef CONFIG_MTD_UBI_FASTMAP
11088c2ecf20Sopenharmony_ci	/* If we don't write a new fastmap at detach time we lose all
11098c2ecf20Sopenharmony_ci	 * EC updates that have been made since the last written fastmap.
11108c2ecf20Sopenharmony_ci	 * In case of fastmap debugging we omit the update to simulate an
11118c2ecf20Sopenharmony_ci	 * unclean shutdown. */
11128c2ecf20Sopenharmony_ci	if (!ubi_dbg_chk_fastmap(ubi))
11138c2ecf20Sopenharmony_ci		ubi_update_fastmap(ubi);
11148c2ecf20Sopenharmony_ci#endif
11158c2ecf20Sopenharmony_ci	/*
11168c2ecf20Sopenharmony_ci	 * Before freeing anything, we have to stop the background thread to
11178c2ecf20Sopenharmony_ci	 * prevent it from doing anything on this device while we are freeing.
11188c2ecf20Sopenharmony_ci	 */
11198c2ecf20Sopenharmony_ci	if (ubi->bgt_thread)
11208c2ecf20Sopenharmony_ci		kthread_stop(ubi->bgt_thread);
11218c2ecf20Sopenharmony_ci
11228c2ecf20Sopenharmony_ci#ifdef CONFIG_MTD_UBI_FASTMAP
11238c2ecf20Sopenharmony_ci	cancel_work_sync(&ubi->fm_work);
11248c2ecf20Sopenharmony_ci#endif
11258c2ecf20Sopenharmony_ci	ubi_debugfs_exit_dev(ubi);
11268c2ecf20Sopenharmony_ci	uif_close(ubi);
11278c2ecf20Sopenharmony_ci
11288c2ecf20Sopenharmony_ci	ubi_wl_close(ubi);
11298c2ecf20Sopenharmony_ci	ubi_free_internal_volumes(ubi);
11308c2ecf20Sopenharmony_ci	vfree(ubi->vtbl);
11318c2ecf20Sopenharmony_ci	vfree(ubi->peb_buf);
11328c2ecf20Sopenharmony_ci	vfree(ubi->fm_buf);
11338c2ecf20Sopenharmony_ci	ubi_msg(ubi, "mtd%d is detached", ubi->mtd->index);
11348c2ecf20Sopenharmony_ci	put_mtd_device(ubi->mtd);
11358c2ecf20Sopenharmony_ci	put_device(&ubi->dev);
11368c2ecf20Sopenharmony_ci	return 0;
11378c2ecf20Sopenharmony_ci}
11388c2ecf20Sopenharmony_ci
11398c2ecf20Sopenharmony_ci/**
11408c2ecf20Sopenharmony_ci * open_mtd_by_chdev - open an MTD device by its character device node path.
11418c2ecf20Sopenharmony_ci * @mtd_dev: MTD character device node path
11428c2ecf20Sopenharmony_ci *
11438c2ecf20Sopenharmony_ci * This helper function opens an MTD device by its character node device path.
11448c2ecf20Sopenharmony_ci * Returns MTD device description object in case of success and a negative
11458c2ecf20Sopenharmony_ci * error code in case of failure.
11468c2ecf20Sopenharmony_ci */
11478c2ecf20Sopenharmony_cistatic struct mtd_info * __init open_mtd_by_chdev(const char *mtd_dev)
11488c2ecf20Sopenharmony_ci{
11498c2ecf20Sopenharmony_ci	int err, minor;
11508c2ecf20Sopenharmony_ci	struct path path;
11518c2ecf20Sopenharmony_ci	struct kstat stat;
11528c2ecf20Sopenharmony_ci
11538c2ecf20Sopenharmony_ci	/* Probably this is an MTD character device node path */
11548c2ecf20Sopenharmony_ci	err = kern_path(mtd_dev, LOOKUP_FOLLOW, &path);
11558c2ecf20Sopenharmony_ci	if (err)
11568c2ecf20Sopenharmony_ci		return ERR_PTR(err);
11578c2ecf20Sopenharmony_ci
11588c2ecf20Sopenharmony_ci	err = vfs_getattr(&path, &stat, STATX_TYPE, AT_STATX_SYNC_AS_STAT);
11598c2ecf20Sopenharmony_ci	path_put(&path);
11608c2ecf20Sopenharmony_ci	if (err)
11618c2ecf20Sopenharmony_ci		return ERR_PTR(err);
11628c2ecf20Sopenharmony_ci
11638c2ecf20Sopenharmony_ci	/* MTD device number is defined by the major / minor numbers */
11648c2ecf20Sopenharmony_ci	if (MAJOR(stat.rdev) != MTD_CHAR_MAJOR || !S_ISCHR(stat.mode))
11658c2ecf20Sopenharmony_ci		return ERR_PTR(-EINVAL);
11668c2ecf20Sopenharmony_ci
11678c2ecf20Sopenharmony_ci	minor = MINOR(stat.rdev);
11688c2ecf20Sopenharmony_ci
11698c2ecf20Sopenharmony_ci	if (minor & 1)
11708c2ecf20Sopenharmony_ci		/*
11718c2ecf20Sopenharmony_ci		 * Just do not think the "/dev/mtdrX" devices support is need,
11728c2ecf20Sopenharmony_ci		 * so do not support them to avoid doing extra work.
11738c2ecf20Sopenharmony_ci		 */
11748c2ecf20Sopenharmony_ci		return ERR_PTR(-EINVAL);
11758c2ecf20Sopenharmony_ci
11768c2ecf20Sopenharmony_ci	return get_mtd_device(NULL, minor / 2);
11778c2ecf20Sopenharmony_ci}
11788c2ecf20Sopenharmony_ci
11798c2ecf20Sopenharmony_ci/**
11808c2ecf20Sopenharmony_ci * open_mtd_device - open MTD device by name, character device path, or number.
11818c2ecf20Sopenharmony_ci * @mtd_dev: name, character device node path, or MTD device device number
11828c2ecf20Sopenharmony_ci *
11838c2ecf20Sopenharmony_ci * This function tries to open and MTD device described by @mtd_dev string,
11848c2ecf20Sopenharmony_ci * which is first treated as ASCII MTD device number, and if it is not true, it
11858c2ecf20Sopenharmony_ci * is treated as MTD device name, and if that is also not true, it is treated
11868c2ecf20Sopenharmony_ci * as MTD character device node path. Returns MTD device description object in
11878c2ecf20Sopenharmony_ci * case of success and a negative error code in case of failure.
11888c2ecf20Sopenharmony_ci */
11898c2ecf20Sopenharmony_cistatic struct mtd_info * __init open_mtd_device(const char *mtd_dev)
11908c2ecf20Sopenharmony_ci{
11918c2ecf20Sopenharmony_ci	struct mtd_info *mtd;
11928c2ecf20Sopenharmony_ci	int mtd_num;
11938c2ecf20Sopenharmony_ci	char *endp;
11948c2ecf20Sopenharmony_ci
11958c2ecf20Sopenharmony_ci	mtd_num = simple_strtoul(mtd_dev, &endp, 0);
11968c2ecf20Sopenharmony_ci	if (*endp != '\0' || mtd_dev == endp) {
11978c2ecf20Sopenharmony_ci		/*
11988c2ecf20Sopenharmony_ci		 * This does not look like an ASCII integer, probably this is
11998c2ecf20Sopenharmony_ci		 * MTD device name.
12008c2ecf20Sopenharmony_ci		 */
12018c2ecf20Sopenharmony_ci		mtd = get_mtd_device_nm(mtd_dev);
12028c2ecf20Sopenharmony_ci		if (PTR_ERR(mtd) == -ENODEV)
12038c2ecf20Sopenharmony_ci			/* Probably this is an MTD character device node path */
12048c2ecf20Sopenharmony_ci			mtd = open_mtd_by_chdev(mtd_dev);
12058c2ecf20Sopenharmony_ci	} else
12068c2ecf20Sopenharmony_ci		mtd = get_mtd_device(NULL, mtd_num);
12078c2ecf20Sopenharmony_ci
12088c2ecf20Sopenharmony_ci	return mtd;
12098c2ecf20Sopenharmony_ci}
12108c2ecf20Sopenharmony_ci
12118c2ecf20Sopenharmony_cistatic int __init ubi_init(void)
12128c2ecf20Sopenharmony_ci{
12138c2ecf20Sopenharmony_ci	int err, i, k;
12148c2ecf20Sopenharmony_ci
12158c2ecf20Sopenharmony_ci	/* Ensure that EC and VID headers have correct size */
12168c2ecf20Sopenharmony_ci	BUILD_BUG_ON(sizeof(struct ubi_ec_hdr) != 64);
12178c2ecf20Sopenharmony_ci	BUILD_BUG_ON(sizeof(struct ubi_vid_hdr) != 64);
12188c2ecf20Sopenharmony_ci
12198c2ecf20Sopenharmony_ci	if (mtd_devs > UBI_MAX_DEVICES) {
12208c2ecf20Sopenharmony_ci		pr_err("UBI error: too many MTD devices, maximum is %d\n",
12218c2ecf20Sopenharmony_ci		       UBI_MAX_DEVICES);
12228c2ecf20Sopenharmony_ci		return -EINVAL;
12238c2ecf20Sopenharmony_ci	}
12248c2ecf20Sopenharmony_ci
12258c2ecf20Sopenharmony_ci	/* Create base sysfs directory and sysfs files */
12268c2ecf20Sopenharmony_ci	err = class_register(&ubi_class);
12278c2ecf20Sopenharmony_ci	if (err < 0)
12288c2ecf20Sopenharmony_ci		return err;
12298c2ecf20Sopenharmony_ci
12308c2ecf20Sopenharmony_ci	err = misc_register(&ubi_ctrl_cdev);
12318c2ecf20Sopenharmony_ci	if (err) {
12328c2ecf20Sopenharmony_ci		pr_err("UBI error: cannot register device\n");
12338c2ecf20Sopenharmony_ci		goto out;
12348c2ecf20Sopenharmony_ci	}
12358c2ecf20Sopenharmony_ci
12368c2ecf20Sopenharmony_ci	ubi_wl_entry_slab = kmem_cache_create("ubi_wl_entry_slab",
12378c2ecf20Sopenharmony_ci					      sizeof(struct ubi_wl_entry),
12388c2ecf20Sopenharmony_ci					      0, 0, NULL);
12398c2ecf20Sopenharmony_ci	if (!ubi_wl_entry_slab) {
12408c2ecf20Sopenharmony_ci		err = -ENOMEM;
12418c2ecf20Sopenharmony_ci		goto out_dev_unreg;
12428c2ecf20Sopenharmony_ci	}
12438c2ecf20Sopenharmony_ci
12448c2ecf20Sopenharmony_ci	err = ubi_debugfs_init();
12458c2ecf20Sopenharmony_ci	if (err)
12468c2ecf20Sopenharmony_ci		goto out_slab;
12478c2ecf20Sopenharmony_ci
12488c2ecf20Sopenharmony_ci
12498c2ecf20Sopenharmony_ci	/* Attach MTD devices */
12508c2ecf20Sopenharmony_ci	for (i = 0; i < mtd_devs; i++) {
12518c2ecf20Sopenharmony_ci		struct mtd_dev_param *p = &mtd_dev_param[i];
12528c2ecf20Sopenharmony_ci		struct mtd_info *mtd;
12538c2ecf20Sopenharmony_ci
12548c2ecf20Sopenharmony_ci		cond_resched();
12558c2ecf20Sopenharmony_ci
12568c2ecf20Sopenharmony_ci		mtd = open_mtd_device(p->name);
12578c2ecf20Sopenharmony_ci		if (IS_ERR(mtd)) {
12588c2ecf20Sopenharmony_ci			err = PTR_ERR(mtd);
12598c2ecf20Sopenharmony_ci			pr_err("UBI error: cannot open mtd %s, error %d\n",
12608c2ecf20Sopenharmony_ci			       p->name, err);
12618c2ecf20Sopenharmony_ci			/* See comment below re-ubi_is_module(). */
12628c2ecf20Sopenharmony_ci			if (ubi_is_module())
12638c2ecf20Sopenharmony_ci				goto out_detach;
12648c2ecf20Sopenharmony_ci			continue;
12658c2ecf20Sopenharmony_ci		}
12668c2ecf20Sopenharmony_ci
12678c2ecf20Sopenharmony_ci		mutex_lock(&ubi_devices_mutex);
12688c2ecf20Sopenharmony_ci		err = ubi_attach_mtd_dev(mtd, p->ubi_num,
12698c2ecf20Sopenharmony_ci					 p->vid_hdr_offs, p->max_beb_per1024);
12708c2ecf20Sopenharmony_ci		mutex_unlock(&ubi_devices_mutex);
12718c2ecf20Sopenharmony_ci		if (err < 0) {
12728c2ecf20Sopenharmony_ci			pr_err("UBI error: cannot attach mtd%d\n",
12738c2ecf20Sopenharmony_ci			       mtd->index);
12748c2ecf20Sopenharmony_ci			put_mtd_device(mtd);
12758c2ecf20Sopenharmony_ci
12768c2ecf20Sopenharmony_ci			/*
12778c2ecf20Sopenharmony_ci			 * Originally UBI stopped initializing on any error.
12788c2ecf20Sopenharmony_ci			 * However, later on it was found out that this
12798c2ecf20Sopenharmony_ci			 * behavior is not very good when UBI is compiled into
12808c2ecf20Sopenharmony_ci			 * the kernel and the MTD devices to attach are passed
12818c2ecf20Sopenharmony_ci			 * through the command line. Indeed, UBI failure
12828c2ecf20Sopenharmony_ci			 * stopped whole boot sequence.
12838c2ecf20Sopenharmony_ci			 *
12848c2ecf20Sopenharmony_ci			 * To fix this, we changed the behavior for the
12858c2ecf20Sopenharmony_ci			 * non-module case, but preserved the old behavior for
12868c2ecf20Sopenharmony_ci			 * the module case, just for compatibility. This is a
12878c2ecf20Sopenharmony_ci			 * little inconsistent, though.
12888c2ecf20Sopenharmony_ci			 */
12898c2ecf20Sopenharmony_ci			if (ubi_is_module())
12908c2ecf20Sopenharmony_ci				goto out_detach;
12918c2ecf20Sopenharmony_ci		}
12928c2ecf20Sopenharmony_ci	}
12938c2ecf20Sopenharmony_ci
12948c2ecf20Sopenharmony_ci	err = ubiblock_init();
12958c2ecf20Sopenharmony_ci	if (err) {
12968c2ecf20Sopenharmony_ci		pr_err("UBI error: block: cannot initialize, error %d\n", err);
12978c2ecf20Sopenharmony_ci
12988c2ecf20Sopenharmony_ci		/* See comment above re-ubi_is_module(). */
12998c2ecf20Sopenharmony_ci		if (ubi_is_module())
13008c2ecf20Sopenharmony_ci			goto out_detach;
13018c2ecf20Sopenharmony_ci	}
13028c2ecf20Sopenharmony_ci
13038c2ecf20Sopenharmony_ci	return 0;
13048c2ecf20Sopenharmony_ci
13058c2ecf20Sopenharmony_ciout_detach:
13068c2ecf20Sopenharmony_ci	for (k = 0; k < i; k++)
13078c2ecf20Sopenharmony_ci		if (ubi_devices[k]) {
13088c2ecf20Sopenharmony_ci			mutex_lock(&ubi_devices_mutex);
13098c2ecf20Sopenharmony_ci			ubi_detach_mtd_dev(ubi_devices[k]->ubi_num, 1);
13108c2ecf20Sopenharmony_ci			mutex_unlock(&ubi_devices_mutex);
13118c2ecf20Sopenharmony_ci		}
13128c2ecf20Sopenharmony_ci	ubi_debugfs_exit();
13138c2ecf20Sopenharmony_ciout_slab:
13148c2ecf20Sopenharmony_ci	kmem_cache_destroy(ubi_wl_entry_slab);
13158c2ecf20Sopenharmony_ciout_dev_unreg:
13168c2ecf20Sopenharmony_ci	misc_deregister(&ubi_ctrl_cdev);
13178c2ecf20Sopenharmony_ciout:
13188c2ecf20Sopenharmony_ci	class_unregister(&ubi_class);
13198c2ecf20Sopenharmony_ci	pr_err("UBI error: cannot initialize UBI, error %d\n", err);
13208c2ecf20Sopenharmony_ci	return err;
13218c2ecf20Sopenharmony_ci}
13228c2ecf20Sopenharmony_cilate_initcall(ubi_init);
13238c2ecf20Sopenharmony_ci
13248c2ecf20Sopenharmony_cistatic void __exit ubi_exit(void)
13258c2ecf20Sopenharmony_ci{
13268c2ecf20Sopenharmony_ci	int i;
13278c2ecf20Sopenharmony_ci
13288c2ecf20Sopenharmony_ci	ubiblock_exit();
13298c2ecf20Sopenharmony_ci
13308c2ecf20Sopenharmony_ci	for (i = 0; i < UBI_MAX_DEVICES; i++)
13318c2ecf20Sopenharmony_ci		if (ubi_devices[i]) {
13328c2ecf20Sopenharmony_ci			mutex_lock(&ubi_devices_mutex);
13338c2ecf20Sopenharmony_ci			ubi_detach_mtd_dev(ubi_devices[i]->ubi_num, 1);
13348c2ecf20Sopenharmony_ci			mutex_unlock(&ubi_devices_mutex);
13358c2ecf20Sopenharmony_ci		}
13368c2ecf20Sopenharmony_ci	ubi_debugfs_exit();
13378c2ecf20Sopenharmony_ci	kmem_cache_destroy(ubi_wl_entry_slab);
13388c2ecf20Sopenharmony_ci	misc_deregister(&ubi_ctrl_cdev);
13398c2ecf20Sopenharmony_ci	class_unregister(&ubi_class);
13408c2ecf20Sopenharmony_ci}
13418c2ecf20Sopenharmony_cimodule_exit(ubi_exit);
13428c2ecf20Sopenharmony_ci
13438c2ecf20Sopenharmony_ci/**
13448c2ecf20Sopenharmony_ci * bytes_str_to_int - convert a number of bytes string into an integer.
13458c2ecf20Sopenharmony_ci * @str: the string to convert
13468c2ecf20Sopenharmony_ci *
13478c2ecf20Sopenharmony_ci * This function returns positive resulting integer in case of success and a
13488c2ecf20Sopenharmony_ci * negative error code in case of failure.
13498c2ecf20Sopenharmony_ci */
13508c2ecf20Sopenharmony_cistatic int bytes_str_to_int(const char *str)
13518c2ecf20Sopenharmony_ci{
13528c2ecf20Sopenharmony_ci	char *endp;
13538c2ecf20Sopenharmony_ci	unsigned long result;
13548c2ecf20Sopenharmony_ci
13558c2ecf20Sopenharmony_ci	result = simple_strtoul(str, &endp, 0);
13568c2ecf20Sopenharmony_ci	if (str == endp || result >= INT_MAX) {
13578c2ecf20Sopenharmony_ci		pr_err("UBI error: incorrect bytes count: \"%s\"\n", str);
13588c2ecf20Sopenharmony_ci		return -EINVAL;
13598c2ecf20Sopenharmony_ci	}
13608c2ecf20Sopenharmony_ci
13618c2ecf20Sopenharmony_ci	switch (*endp) {
13628c2ecf20Sopenharmony_ci	case 'G':
13638c2ecf20Sopenharmony_ci		result *= 1024;
13648c2ecf20Sopenharmony_ci		fallthrough;
13658c2ecf20Sopenharmony_ci	case 'M':
13668c2ecf20Sopenharmony_ci		result *= 1024;
13678c2ecf20Sopenharmony_ci		fallthrough;
13688c2ecf20Sopenharmony_ci	case 'K':
13698c2ecf20Sopenharmony_ci		result *= 1024;
13708c2ecf20Sopenharmony_ci		if (endp[1] == 'i' && endp[2] == 'B')
13718c2ecf20Sopenharmony_ci			endp += 2;
13728c2ecf20Sopenharmony_ci	case '\0':
13738c2ecf20Sopenharmony_ci		break;
13748c2ecf20Sopenharmony_ci	default:
13758c2ecf20Sopenharmony_ci		pr_err("UBI error: incorrect bytes count: \"%s\"\n", str);
13768c2ecf20Sopenharmony_ci		return -EINVAL;
13778c2ecf20Sopenharmony_ci	}
13788c2ecf20Sopenharmony_ci
13798c2ecf20Sopenharmony_ci	return result;
13808c2ecf20Sopenharmony_ci}
13818c2ecf20Sopenharmony_ci
13828c2ecf20Sopenharmony_ci/**
13838c2ecf20Sopenharmony_ci * ubi_mtd_param_parse - parse the 'mtd=' UBI parameter.
13848c2ecf20Sopenharmony_ci * @val: the parameter value to parse
13858c2ecf20Sopenharmony_ci * @kp: not used
13868c2ecf20Sopenharmony_ci *
13878c2ecf20Sopenharmony_ci * This function returns zero in case of success and a negative error code in
13888c2ecf20Sopenharmony_ci * case of error.
13898c2ecf20Sopenharmony_ci */
13908c2ecf20Sopenharmony_cistatic int ubi_mtd_param_parse(const char *val, const struct kernel_param *kp)
13918c2ecf20Sopenharmony_ci{
13928c2ecf20Sopenharmony_ci	int i, len;
13938c2ecf20Sopenharmony_ci	struct mtd_dev_param *p;
13948c2ecf20Sopenharmony_ci	char buf[MTD_PARAM_LEN_MAX];
13958c2ecf20Sopenharmony_ci	char *pbuf = &buf[0];
13968c2ecf20Sopenharmony_ci	char *tokens[MTD_PARAM_MAX_COUNT], *token;
13978c2ecf20Sopenharmony_ci
13988c2ecf20Sopenharmony_ci	if (!val)
13998c2ecf20Sopenharmony_ci		return -EINVAL;
14008c2ecf20Sopenharmony_ci
14018c2ecf20Sopenharmony_ci	if (mtd_devs == UBI_MAX_DEVICES) {
14028c2ecf20Sopenharmony_ci		pr_err("UBI error: too many parameters, max. is %d\n",
14038c2ecf20Sopenharmony_ci		       UBI_MAX_DEVICES);
14048c2ecf20Sopenharmony_ci		return -EINVAL;
14058c2ecf20Sopenharmony_ci	}
14068c2ecf20Sopenharmony_ci
14078c2ecf20Sopenharmony_ci	len = strnlen(val, MTD_PARAM_LEN_MAX);
14088c2ecf20Sopenharmony_ci	if (len == MTD_PARAM_LEN_MAX) {
14098c2ecf20Sopenharmony_ci		pr_err("UBI error: parameter \"%s\" is too long, max. is %d\n",
14108c2ecf20Sopenharmony_ci		       val, MTD_PARAM_LEN_MAX);
14118c2ecf20Sopenharmony_ci		return -EINVAL;
14128c2ecf20Sopenharmony_ci	}
14138c2ecf20Sopenharmony_ci
14148c2ecf20Sopenharmony_ci	if (len == 0) {
14158c2ecf20Sopenharmony_ci		pr_warn("UBI warning: empty 'mtd=' parameter - ignored\n");
14168c2ecf20Sopenharmony_ci		return 0;
14178c2ecf20Sopenharmony_ci	}
14188c2ecf20Sopenharmony_ci
14198c2ecf20Sopenharmony_ci	strcpy(buf, val);
14208c2ecf20Sopenharmony_ci
14218c2ecf20Sopenharmony_ci	/* Get rid of the final newline */
14228c2ecf20Sopenharmony_ci	if (buf[len - 1] == '\n')
14238c2ecf20Sopenharmony_ci		buf[len - 1] = '\0';
14248c2ecf20Sopenharmony_ci
14258c2ecf20Sopenharmony_ci	for (i = 0; i < MTD_PARAM_MAX_COUNT; i++)
14268c2ecf20Sopenharmony_ci		tokens[i] = strsep(&pbuf, ",");
14278c2ecf20Sopenharmony_ci
14288c2ecf20Sopenharmony_ci	if (pbuf) {
14298c2ecf20Sopenharmony_ci		pr_err("UBI error: too many arguments at \"%s\"\n", val);
14308c2ecf20Sopenharmony_ci		return -EINVAL;
14318c2ecf20Sopenharmony_ci	}
14328c2ecf20Sopenharmony_ci
14338c2ecf20Sopenharmony_ci	p = &mtd_dev_param[mtd_devs];
14348c2ecf20Sopenharmony_ci	strcpy(&p->name[0], tokens[0]);
14358c2ecf20Sopenharmony_ci
14368c2ecf20Sopenharmony_ci	token = tokens[1];
14378c2ecf20Sopenharmony_ci	if (token) {
14388c2ecf20Sopenharmony_ci		p->vid_hdr_offs = bytes_str_to_int(token);
14398c2ecf20Sopenharmony_ci
14408c2ecf20Sopenharmony_ci		if (p->vid_hdr_offs < 0)
14418c2ecf20Sopenharmony_ci			return p->vid_hdr_offs;
14428c2ecf20Sopenharmony_ci	}
14438c2ecf20Sopenharmony_ci
14448c2ecf20Sopenharmony_ci	token = tokens[2];
14458c2ecf20Sopenharmony_ci	if (token) {
14468c2ecf20Sopenharmony_ci		int err = kstrtoint(token, 10, &p->max_beb_per1024);
14478c2ecf20Sopenharmony_ci
14488c2ecf20Sopenharmony_ci		if (err) {
14498c2ecf20Sopenharmony_ci			pr_err("UBI error: bad value for max_beb_per1024 parameter: %s",
14508c2ecf20Sopenharmony_ci			       token);
14518c2ecf20Sopenharmony_ci			return -EINVAL;
14528c2ecf20Sopenharmony_ci		}
14538c2ecf20Sopenharmony_ci	}
14548c2ecf20Sopenharmony_ci
14558c2ecf20Sopenharmony_ci	token = tokens[3];
14568c2ecf20Sopenharmony_ci	if (token) {
14578c2ecf20Sopenharmony_ci		int err = kstrtoint(token, 10, &p->ubi_num);
14588c2ecf20Sopenharmony_ci
14598c2ecf20Sopenharmony_ci		if (err) {
14608c2ecf20Sopenharmony_ci			pr_err("UBI error: bad value for ubi_num parameter: %s",
14618c2ecf20Sopenharmony_ci			       token);
14628c2ecf20Sopenharmony_ci			return -EINVAL;
14638c2ecf20Sopenharmony_ci		}
14648c2ecf20Sopenharmony_ci	} else
14658c2ecf20Sopenharmony_ci		p->ubi_num = UBI_DEV_NUM_AUTO;
14668c2ecf20Sopenharmony_ci
14678c2ecf20Sopenharmony_ci	mtd_devs += 1;
14688c2ecf20Sopenharmony_ci	return 0;
14698c2ecf20Sopenharmony_ci}
14708c2ecf20Sopenharmony_ci
14718c2ecf20Sopenharmony_cimodule_param_call(mtd, ubi_mtd_param_parse, NULL, NULL, 0400);
14728c2ecf20Sopenharmony_ciMODULE_PARM_DESC(mtd, "MTD devices to attach. Parameter format: mtd=<name|num|path>[,<vid_hdr_offs>[,max_beb_per1024[,ubi_num]]].\n"
14738c2ecf20Sopenharmony_ci		      "Multiple \"mtd\" parameters may be specified.\n"
14748c2ecf20Sopenharmony_ci		      "MTD devices may be specified by their number, name, or path to the MTD character device node.\n"
14758c2ecf20Sopenharmony_ci		      "Optional \"vid_hdr_offs\" parameter specifies UBI VID header position to be used by UBI. (default value if 0)\n"
14768c2ecf20Sopenharmony_ci		      "Optional \"max_beb_per1024\" parameter specifies the maximum expected bad eraseblock per 1024 eraseblocks. (default value ("
14778c2ecf20Sopenharmony_ci		      __stringify(CONFIG_MTD_UBI_BEB_LIMIT) ") if 0)\n"
14788c2ecf20Sopenharmony_ci		      "Optional \"ubi_num\" parameter specifies UBI device number which have to be assigned to the newly created UBI device (assigned automatically by default)\n"
14798c2ecf20Sopenharmony_ci		      "\n"
14808c2ecf20Sopenharmony_ci		      "Example 1: mtd=/dev/mtd0 - attach MTD device /dev/mtd0.\n"
14818c2ecf20Sopenharmony_ci		      "Example 2: mtd=content,1984 mtd=4 - attach MTD device with name \"content\" using VID header offset 1984, and MTD device number 4 with default VID header offset.\n"
14828c2ecf20Sopenharmony_ci		      "Example 3: mtd=/dev/mtd1,0,25 - attach MTD device /dev/mtd1 using default VID header offset and reserve 25*nand_size_in_blocks/1024 erase blocks for bad block handling.\n"
14838c2ecf20Sopenharmony_ci		      "Example 4: mtd=/dev/mtd1,0,0,5 - attach MTD device /dev/mtd1 to UBI 5 and using default values for the other fields.\n"
14848c2ecf20Sopenharmony_ci		      "\t(e.g. if the NAND *chipset* has 4096 PEB, 100 will be reserved for this UBI device).");
14858c2ecf20Sopenharmony_ci#ifdef CONFIG_MTD_UBI_FASTMAP
14868c2ecf20Sopenharmony_cimodule_param(fm_autoconvert, bool, 0644);
14878c2ecf20Sopenharmony_ciMODULE_PARM_DESC(fm_autoconvert, "Set this parameter to enable fastmap automatically on images without a fastmap.");
14888c2ecf20Sopenharmony_cimodule_param(fm_debug, bool, 0);
14898c2ecf20Sopenharmony_ciMODULE_PARM_DESC(fm_debug, "Set this parameter to enable fastmap debugging by default. Warning, this will make fastmap slow!");
14908c2ecf20Sopenharmony_ci#endif
14918c2ecf20Sopenharmony_ciMODULE_VERSION(__stringify(UBI_VERSION));
14928c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("UBI - Unsorted Block Images");
14938c2ecf20Sopenharmony_ciMODULE_AUTHOR("Artem Bityutskiy");
14948c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL");
1495