162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-or-later 262306a36Sopenharmony_ci/* 362306a36Sopenharmony_ci * Copyright (c) International Business Machines Corp., 2006 462306a36Sopenharmony_ci * Copyright (c) Nokia Corporation, 2007 562306a36Sopenharmony_ci * 662306a36Sopenharmony_ci * Author: Artem Bityutskiy (Битюцкий Артём), 762306a36Sopenharmony_ci * Frank Haverkamp 862306a36Sopenharmony_ci */ 962306a36Sopenharmony_ci 1062306a36Sopenharmony_ci/* 1162306a36Sopenharmony_ci * This file includes UBI initialization and building of UBI devices. 1262306a36Sopenharmony_ci * 1362306a36Sopenharmony_ci * When UBI is initialized, it attaches all the MTD devices specified as the 1462306a36Sopenharmony_ci * module load parameters or the kernel boot parameters. If MTD devices were 1562306a36Sopenharmony_ci * specified, UBI does not attach any MTD device, but it is possible to do 1662306a36Sopenharmony_ci * later using the "UBI control device". 1762306a36Sopenharmony_ci */ 1862306a36Sopenharmony_ci 1962306a36Sopenharmony_ci#include <linux/err.h> 2062306a36Sopenharmony_ci#include <linux/module.h> 2162306a36Sopenharmony_ci#include <linux/moduleparam.h> 2262306a36Sopenharmony_ci#include <linux/stringify.h> 2362306a36Sopenharmony_ci#include <linux/namei.h> 2462306a36Sopenharmony_ci#include <linux/stat.h> 2562306a36Sopenharmony_ci#include <linux/miscdevice.h> 2662306a36Sopenharmony_ci#include <linux/mtd/partitions.h> 2762306a36Sopenharmony_ci#include <linux/log2.h> 2862306a36Sopenharmony_ci#include <linux/kthread.h> 2962306a36Sopenharmony_ci#include <linux/kernel.h> 3062306a36Sopenharmony_ci#include <linux/slab.h> 3162306a36Sopenharmony_ci#include <linux/major.h> 3262306a36Sopenharmony_ci#include "ubi.h" 3362306a36Sopenharmony_ci 3462306a36Sopenharmony_ci/* Maximum length of the 'mtd=' parameter */ 3562306a36Sopenharmony_ci#define MTD_PARAM_LEN_MAX 64 3662306a36Sopenharmony_ci 3762306a36Sopenharmony_ci/* Maximum number of comma-separated items in the 'mtd=' parameter */ 3862306a36Sopenharmony_ci#define MTD_PARAM_MAX_COUNT 5 3962306a36Sopenharmony_ci 4062306a36Sopenharmony_ci/* Maximum value for the number of bad PEBs per 1024 PEBs */ 4162306a36Sopenharmony_ci#define MAX_MTD_UBI_BEB_LIMIT 768 4262306a36Sopenharmony_ci 4362306a36Sopenharmony_ci#ifdef CONFIG_MTD_UBI_MODULE 4462306a36Sopenharmony_ci#define ubi_is_module() 1 4562306a36Sopenharmony_ci#else 4662306a36Sopenharmony_ci#define ubi_is_module() 0 4762306a36Sopenharmony_ci#endif 4862306a36Sopenharmony_ci 4962306a36Sopenharmony_ci/** 5062306a36Sopenharmony_ci * struct mtd_dev_param - MTD device parameter description data structure. 5162306a36Sopenharmony_ci * @name: MTD character device node path, MTD device name, or MTD device number 5262306a36Sopenharmony_ci * string 5362306a36Sopenharmony_ci * @ubi_num: UBI number 5462306a36Sopenharmony_ci * @vid_hdr_offs: VID header offset 5562306a36Sopenharmony_ci * @max_beb_per1024: maximum expected number of bad PEBs per 1024 PEBs 5662306a36Sopenharmony_ci * @enable_fm: enable fastmap when value is non-zero 5762306a36Sopenharmony_ci */ 5862306a36Sopenharmony_cistruct mtd_dev_param { 5962306a36Sopenharmony_ci char name[MTD_PARAM_LEN_MAX]; 6062306a36Sopenharmony_ci int ubi_num; 6162306a36Sopenharmony_ci int vid_hdr_offs; 6262306a36Sopenharmony_ci int max_beb_per1024; 6362306a36Sopenharmony_ci int enable_fm; 6462306a36Sopenharmony_ci}; 6562306a36Sopenharmony_ci 6662306a36Sopenharmony_ci/* Numbers of elements set in the @mtd_dev_param array */ 6762306a36Sopenharmony_cistatic int mtd_devs; 6862306a36Sopenharmony_ci 6962306a36Sopenharmony_ci/* MTD devices specification parameters */ 7062306a36Sopenharmony_cistatic struct mtd_dev_param mtd_dev_param[UBI_MAX_DEVICES]; 7162306a36Sopenharmony_ci#ifdef CONFIG_MTD_UBI_FASTMAP 7262306a36Sopenharmony_ci/* UBI module parameter to enable fastmap automatically on non-fastmap images */ 7362306a36Sopenharmony_cistatic bool fm_autoconvert; 7462306a36Sopenharmony_cistatic bool fm_debug; 7562306a36Sopenharmony_ci#endif 7662306a36Sopenharmony_ci 7762306a36Sopenharmony_ci/* Slab cache for wear-leveling entries */ 7862306a36Sopenharmony_cistruct kmem_cache *ubi_wl_entry_slab; 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci/* UBI control character device */ 8162306a36Sopenharmony_cistatic struct miscdevice ubi_ctrl_cdev = { 8262306a36Sopenharmony_ci .minor = MISC_DYNAMIC_MINOR, 8362306a36Sopenharmony_ci .name = "ubi_ctrl", 8462306a36Sopenharmony_ci .fops = &ubi_ctrl_cdev_operations, 8562306a36Sopenharmony_ci}; 8662306a36Sopenharmony_ci 8762306a36Sopenharmony_ci/* All UBI devices in system */ 8862306a36Sopenharmony_cistatic struct ubi_device *ubi_devices[UBI_MAX_DEVICES]; 8962306a36Sopenharmony_ci 9062306a36Sopenharmony_ci/* Serializes UBI devices creations and removals */ 9162306a36Sopenharmony_ciDEFINE_MUTEX(ubi_devices_mutex); 9262306a36Sopenharmony_ci 9362306a36Sopenharmony_ci/* Protects @ubi_devices and @ubi->ref_count */ 9462306a36Sopenharmony_cistatic DEFINE_SPINLOCK(ubi_devices_lock); 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci/* "Show" method for files in '/<sysfs>/class/ubi/' */ 9762306a36Sopenharmony_ci/* UBI version attribute ('/<sysfs>/class/ubi/version') */ 9862306a36Sopenharmony_cistatic ssize_t version_show(const struct class *class, const struct class_attribute *attr, 9962306a36Sopenharmony_ci char *buf) 10062306a36Sopenharmony_ci{ 10162306a36Sopenharmony_ci return sprintf(buf, "%d\n", UBI_VERSION); 10262306a36Sopenharmony_ci} 10362306a36Sopenharmony_cistatic CLASS_ATTR_RO(version); 10462306a36Sopenharmony_ci 10562306a36Sopenharmony_cistatic struct attribute *ubi_class_attrs[] = { 10662306a36Sopenharmony_ci &class_attr_version.attr, 10762306a36Sopenharmony_ci NULL, 10862306a36Sopenharmony_ci}; 10962306a36Sopenharmony_ciATTRIBUTE_GROUPS(ubi_class); 11062306a36Sopenharmony_ci 11162306a36Sopenharmony_ci/* Root UBI "class" object (corresponds to '/<sysfs>/class/ubi/') */ 11262306a36Sopenharmony_cistruct class ubi_class = { 11362306a36Sopenharmony_ci .name = UBI_NAME_STR, 11462306a36Sopenharmony_ci .class_groups = ubi_class_groups, 11562306a36Sopenharmony_ci}; 11662306a36Sopenharmony_ci 11762306a36Sopenharmony_cistatic ssize_t dev_attribute_show(struct device *dev, 11862306a36Sopenharmony_ci struct device_attribute *attr, char *buf); 11962306a36Sopenharmony_ci 12062306a36Sopenharmony_ci/* UBI device attributes (correspond to files in '/<sysfs>/class/ubi/ubiX') */ 12162306a36Sopenharmony_cistatic struct device_attribute dev_eraseblock_size = 12262306a36Sopenharmony_ci __ATTR(eraseblock_size, S_IRUGO, dev_attribute_show, NULL); 12362306a36Sopenharmony_cistatic struct device_attribute dev_avail_eraseblocks = 12462306a36Sopenharmony_ci __ATTR(avail_eraseblocks, S_IRUGO, dev_attribute_show, NULL); 12562306a36Sopenharmony_cistatic struct device_attribute dev_total_eraseblocks = 12662306a36Sopenharmony_ci __ATTR(total_eraseblocks, S_IRUGO, dev_attribute_show, NULL); 12762306a36Sopenharmony_cistatic struct device_attribute dev_volumes_count = 12862306a36Sopenharmony_ci __ATTR(volumes_count, S_IRUGO, dev_attribute_show, NULL); 12962306a36Sopenharmony_cistatic struct device_attribute dev_max_ec = 13062306a36Sopenharmony_ci __ATTR(max_ec, S_IRUGO, dev_attribute_show, NULL); 13162306a36Sopenharmony_cistatic struct device_attribute dev_reserved_for_bad = 13262306a36Sopenharmony_ci __ATTR(reserved_for_bad, S_IRUGO, dev_attribute_show, NULL); 13362306a36Sopenharmony_cistatic struct device_attribute dev_bad_peb_count = 13462306a36Sopenharmony_ci __ATTR(bad_peb_count, S_IRUGO, dev_attribute_show, NULL); 13562306a36Sopenharmony_cistatic struct device_attribute dev_max_vol_count = 13662306a36Sopenharmony_ci __ATTR(max_vol_count, S_IRUGO, dev_attribute_show, NULL); 13762306a36Sopenharmony_cistatic struct device_attribute dev_min_io_size = 13862306a36Sopenharmony_ci __ATTR(min_io_size, S_IRUGO, dev_attribute_show, NULL); 13962306a36Sopenharmony_cistatic struct device_attribute dev_bgt_enabled = 14062306a36Sopenharmony_ci __ATTR(bgt_enabled, S_IRUGO, dev_attribute_show, NULL); 14162306a36Sopenharmony_cistatic struct device_attribute dev_mtd_num = 14262306a36Sopenharmony_ci __ATTR(mtd_num, S_IRUGO, dev_attribute_show, NULL); 14362306a36Sopenharmony_cistatic struct device_attribute dev_ro_mode = 14462306a36Sopenharmony_ci __ATTR(ro_mode, S_IRUGO, dev_attribute_show, NULL); 14562306a36Sopenharmony_ci 14662306a36Sopenharmony_ci/** 14762306a36Sopenharmony_ci * ubi_volume_notify - send a volume change notification. 14862306a36Sopenharmony_ci * @ubi: UBI device description object 14962306a36Sopenharmony_ci * @vol: volume description object of the changed volume 15062306a36Sopenharmony_ci * @ntype: notification type to send (%UBI_VOLUME_ADDED, etc) 15162306a36Sopenharmony_ci * 15262306a36Sopenharmony_ci * This is a helper function which notifies all subscribers about a volume 15362306a36Sopenharmony_ci * change event (creation, removal, re-sizing, re-naming, updating). Returns 15462306a36Sopenharmony_ci * zero in case of success and a negative error code in case of failure. 15562306a36Sopenharmony_ci */ 15662306a36Sopenharmony_ciint ubi_volume_notify(struct ubi_device *ubi, struct ubi_volume *vol, int ntype) 15762306a36Sopenharmony_ci{ 15862306a36Sopenharmony_ci int ret; 15962306a36Sopenharmony_ci struct ubi_notification nt; 16062306a36Sopenharmony_ci 16162306a36Sopenharmony_ci ubi_do_get_device_info(ubi, &nt.di); 16262306a36Sopenharmony_ci ubi_do_get_volume_info(ubi, vol, &nt.vi); 16362306a36Sopenharmony_ci 16462306a36Sopenharmony_ci switch (ntype) { 16562306a36Sopenharmony_ci case UBI_VOLUME_ADDED: 16662306a36Sopenharmony_ci case UBI_VOLUME_REMOVED: 16762306a36Sopenharmony_ci case UBI_VOLUME_RESIZED: 16862306a36Sopenharmony_ci case UBI_VOLUME_RENAMED: 16962306a36Sopenharmony_ci ret = ubi_update_fastmap(ubi); 17062306a36Sopenharmony_ci if (ret) 17162306a36Sopenharmony_ci ubi_msg(ubi, "Unable to write a new fastmap: %i", ret); 17262306a36Sopenharmony_ci } 17362306a36Sopenharmony_ci 17462306a36Sopenharmony_ci return blocking_notifier_call_chain(&ubi_notifiers, ntype, &nt); 17562306a36Sopenharmony_ci} 17662306a36Sopenharmony_ci 17762306a36Sopenharmony_ci/** 17862306a36Sopenharmony_ci * ubi_notify_all - send a notification to all volumes. 17962306a36Sopenharmony_ci * @ubi: UBI device description object 18062306a36Sopenharmony_ci * @ntype: notification type to send (%UBI_VOLUME_ADDED, etc) 18162306a36Sopenharmony_ci * @nb: the notifier to call 18262306a36Sopenharmony_ci * 18362306a36Sopenharmony_ci * This function walks all volumes of UBI device @ubi and sends the @ntype 18462306a36Sopenharmony_ci * notification for each volume. If @nb is %NULL, then all registered notifiers 18562306a36Sopenharmony_ci * are called, otherwise only the @nb notifier is called. Returns the number of 18662306a36Sopenharmony_ci * sent notifications. 18762306a36Sopenharmony_ci */ 18862306a36Sopenharmony_ciint ubi_notify_all(struct ubi_device *ubi, int ntype, struct notifier_block *nb) 18962306a36Sopenharmony_ci{ 19062306a36Sopenharmony_ci struct ubi_notification nt; 19162306a36Sopenharmony_ci int i, count = 0; 19262306a36Sopenharmony_ci 19362306a36Sopenharmony_ci ubi_do_get_device_info(ubi, &nt.di); 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci mutex_lock(&ubi->device_mutex); 19662306a36Sopenharmony_ci for (i = 0; i < ubi->vtbl_slots; i++) { 19762306a36Sopenharmony_ci /* 19862306a36Sopenharmony_ci * Since the @ubi->device is locked, and we are not going to 19962306a36Sopenharmony_ci * change @ubi->volumes, we do not have to lock 20062306a36Sopenharmony_ci * @ubi->volumes_lock. 20162306a36Sopenharmony_ci */ 20262306a36Sopenharmony_ci if (!ubi->volumes[i]) 20362306a36Sopenharmony_ci continue; 20462306a36Sopenharmony_ci 20562306a36Sopenharmony_ci ubi_do_get_volume_info(ubi, ubi->volumes[i], &nt.vi); 20662306a36Sopenharmony_ci if (nb) 20762306a36Sopenharmony_ci nb->notifier_call(nb, ntype, &nt); 20862306a36Sopenharmony_ci else 20962306a36Sopenharmony_ci blocking_notifier_call_chain(&ubi_notifiers, ntype, 21062306a36Sopenharmony_ci &nt); 21162306a36Sopenharmony_ci count += 1; 21262306a36Sopenharmony_ci } 21362306a36Sopenharmony_ci mutex_unlock(&ubi->device_mutex); 21462306a36Sopenharmony_ci 21562306a36Sopenharmony_ci return count; 21662306a36Sopenharmony_ci} 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci/** 21962306a36Sopenharmony_ci * ubi_enumerate_volumes - send "add" notification for all existing volumes. 22062306a36Sopenharmony_ci * @nb: the notifier to call 22162306a36Sopenharmony_ci * 22262306a36Sopenharmony_ci * This function walks all UBI devices and volumes and sends the 22362306a36Sopenharmony_ci * %UBI_VOLUME_ADDED notification for each volume. If @nb is %NULL, then all 22462306a36Sopenharmony_ci * registered notifiers are called, otherwise only the @nb notifier is called. 22562306a36Sopenharmony_ci * Returns the number of sent notifications. 22662306a36Sopenharmony_ci */ 22762306a36Sopenharmony_ciint ubi_enumerate_volumes(struct notifier_block *nb) 22862306a36Sopenharmony_ci{ 22962306a36Sopenharmony_ci int i, count = 0; 23062306a36Sopenharmony_ci 23162306a36Sopenharmony_ci /* 23262306a36Sopenharmony_ci * Since the @ubi_devices_mutex is locked, and we are not going to 23362306a36Sopenharmony_ci * change @ubi_devices, we do not have to lock @ubi_devices_lock. 23462306a36Sopenharmony_ci */ 23562306a36Sopenharmony_ci for (i = 0; i < UBI_MAX_DEVICES; i++) { 23662306a36Sopenharmony_ci struct ubi_device *ubi = ubi_devices[i]; 23762306a36Sopenharmony_ci 23862306a36Sopenharmony_ci if (!ubi) 23962306a36Sopenharmony_ci continue; 24062306a36Sopenharmony_ci count += ubi_notify_all(ubi, UBI_VOLUME_ADDED, nb); 24162306a36Sopenharmony_ci } 24262306a36Sopenharmony_ci 24362306a36Sopenharmony_ci return count; 24462306a36Sopenharmony_ci} 24562306a36Sopenharmony_ci 24662306a36Sopenharmony_ci/** 24762306a36Sopenharmony_ci * ubi_get_device - get UBI device. 24862306a36Sopenharmony_ci * @ubi_num: UBI device number 24962306a36Sopenharmony_ci * 25062306a36Sopenharmony_ci * This function returns UBI device description object for UBI device number 25162306a36Sopenharmony_ci * @ubi_num, or %NULL if the device does not exist. This function increases the 25262306a36Sopenharmony_ci * device reference count to prevent removal of the device. In other words, the 25362306a36Sopenharmony_ci * device cannot be removed if its reference count is not zero. 25462306a36Sopenharmony_ci */ 25562306a36Sopenharmony_cistruct ubi_device *ubi_get_device(int ubi_num) 25662306a36Sopenharmony_ci{ 25762306a36Sopenharmony_ci struct ubi_device *ubi; 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_ci spin_lock(&ubi_devices_lock); 26062306a36Sopenharmony_ci ubi = ubi_devices[ubi_num]; 26162306a36Sopenharmony_ci if (ubi) { 26262306a36Sopenharmony_ci ubi_assert(ubi->ref_count >= 0); 26362306a36Sopenharmony_ci ubi->ref_count += 1; 26462306a36Sopenharmony_ci get_device(&ubi->dev); 26562306a36Sopenharmony_ci } 26662306a36Sopenharmony_ci spin_unlock(&ubi_devices_lock); 26762306a36Sopenharmony_ci 26862306a36Sopenharmony_ci return ubi; 26962306a36Sopenharmony_ci} 27062306a36Sopenharmony_ci 27162306a36Sopenharmony_ci/** 27262306a36Sopenharmony_ci * ubi_put_device - drop an UBI device reference. 27362306a36Sopenharmony_ci * @ubi: UBI device description object 27462306a36Sopenharmony_ci */ 27562306a36Sopenharmony_civoid ubi_put_device(struct ubi_device *ubi) 27662306a36Sopenharmony_ci{ 27762306a36Sopenharmony_ci spin_lock(&ubi_devices_lock); 27862306a36Sopenharmony_ci ubi->ref_count -= 1; 27962306a36Sopenharmony_ci put_device(&ubi->dev); 28062306a36Sopenharmony_ci spin_unlock(&ubi_devices_lock); 28162306a36Sopenharmony_ci} 28262306a36Sopenharmony_ci 28362306a36Sopenharmony_ci/** 28462306a36Sopenharmony_ci * ubi_get_by_major - get UBI device by character device major number. 28562306a36Sopenharmony_ci * @major: major number 28662306a36Sopenharmony_ci * 28762306a36Sopenharmony_ci * This function is similar to 'ubi_get_device()', but it searches the device 28862306a36Sopenharmony_ci * by its major number. 28962306a36Sopenharmony_ci */ 29062306a36Sopenharmony_cistruct ubi_device *ubi_get_by_major(int major) 29162306a36Sopenharmony_ci{ 29262306a36Sopenharmony_ci int i; 29362306a36Sopenharmony_ci struct ubi_device *ubi; 29462306a36Sopenharmony_ci 29562306a36Sopenharmony_ci spin_lock(&ubi_devices_lock); 29662306a36Sopenharmony_ci for (i = 0; i < UBI_MAX_DEVICES; i++) { 29762306a36Sopenharmony_ci ubi = ubi_devices[i]; 29862306a36Sopenharmony_ci if (ubi && MAJOR(ubi->cdev.dev) == major) { 29962306a36Sopenharmony_ci ubi_assert(ubi->ref_count >= 0); 30062306a36Sopenharmony_ci ubi->ref_count += 1; 30162306a36Sopenharmony_ci get_device(&ubi->dev); 30262306a36Sopenharmony_ci spin_unlock(&ubi_devices_lock); 30362306a36Sopenharmony_ci return ubi; 30462306a36Sopenharmony_ci } 30562306a36Sopenharmony_ci } 30662306a36Sopenharmony_ci spin_unlock(&ubi_devices_lock); 30762306a36Sopenharmony_ci 30862306a36Sopenharmony_ci return NULL; 30962306a36Sopenharmony_ci} 31062306a36Sopenharmony_ci 31162306a36Sopenharmony_ci/** 31262306a36Sopenharmony_ci * ubi_major2num - get UBI device number by character device major number. 31362306a36Sopenharmony_ci * @major: major number 31462306a36Sopenharmony_ci * 31562306a36Sopenharmony_ci * This function searches UBI device number object by its major number. If UBI 31662306a36Sopenharmony_ci * device was not found, this function returns -ENODEV, otherwise the UBI device 31762306a36Sopenharmony_ci * number is returned. 31862306a36Sopenharmony_ci */ 31962306a36Sopenharmony_ciint ubi_major2num(int major) 32062306a36Sopenharmony_ci{ 32162306a36Sopenharmony_ci int i, ubi_num = -ENODEV; 32262306a36Sopenharmony_ci 32362306a36Sopenharmony_ci spin_lock(&ubi_devices_lock); 32462306a36Sopenharmony_ci for (i = 0; i < UBI_MAX_DEVICES; i++) { 32562306a36Sopenharmony_ci struct ubi_device *ubi = ubi_devices[i]; 32662306a36Sopenharmony_ci 32762306a36Sopenharmony_ci if (ubi && MAJOR(ubi->cdev.dev) == major) { 32862306a36Sopenharmony_ci ubi_num = ubi->ubi_num; 32962306a36Sopenharmony_ci break; 33062306a36Sopenharmony_ci } 33162306a36Sopenharmony_ci } 33262306a36Sopenharmony_ci spin_unlock(&ubi_devices_lock); 33362306a36Sopenharmony_ci 33462306a36Sopenharmony_ci return ubi_num; 33562306a36Sopenharmony_ci} 33662306a36Sopenharmony_ci 33762306a36Sopenharmony_ci/* "Show" method for files in '/<sysfs>/class/ubi/ubiX/' */ 33862306a36Sopenharmony_cistatic ssize_t dev_attribute_show(struct device *dev, 33962306a36Sopenharmony_ci struct device_attribute *attr, char *buf) 34062306a36Sopenharmony_ci{ 34162306a36Sopenharmony_ci ssize_t ret; 34262306a36Sopenharmony_ci struct ubi_device *ubi; 34362306a36Sopenharmony_ci 34462306a36Sopenharmony_ci /* 34562306a36Sopenharmony_ci * The below code looks weird, but it actually makes sense. We get the 34662306a36Sopenharmony_ci * UBI device reference from the contained 'struct ubi_device'. But it 34762306a36Sopenharmony_ci * is unclear if the device was removed or not yet. Indeed, if the 34862306a36Sopenharmony_ci * device was removed before we increased its reference count, 34962306a36Sopenharmony_ci * 'ubi_get_device()' will return -ENODEV and we fail. 35062306a36Sopenharmony_ci * 35162306a36Sopenharmony_ci * Remember, 'struct ubi_device' is freed in the release function, so 35262306a36Sopenharmony_ci * we still can use 'ubi->ubi_num'. 35362306a36Sopenharmony_ci */ 35462306a36Sopenharmony_ci ubi = container_of(dev, struct ubi_device, dev); 35562306a36Sopenharmony_ci 35662306a36Sopenharmony_ci if (attr == &dev_eraseblock_size) 35762306a36Sopenharmony_ci ret = sprintf(buf, "%d\n", ubi->leb_size); 35862306a36Sopenharmony_ci else if (attr == &dev_avail_eraseblocks) 35962306a36Sopenharmony_ci ret = sprintf(buf, "%d\n", ubi->avail_pebs); 36062306a36Sopenharmony_ci else if (attr == &dev_total_eraseblocks) 36162306a36Sopenharmony_ci ret = sprintf(buf, "%d\n", ubi->good_peb_count); 36262306a36Sopenharmony_ci else if (attr == &dev_volumes_count) 36362306a36Sopenharmony_ci ret = sprintf(buf, "%d\n", ubi->vol_count - UBI_INT_VOL_COUNT); 36462306a36Sopenharmony_ci else if (attr == &dev_max_ec) 36562306a36Sopenharmony_ci ret = sprintf(buf, "%d\n", ubi->max_ec); 36662306a36Sopenharmony_ci else if (attr == &dev_reserved_for_bad) 36762306a36Sopenharmony_ci ret = sprintf(buf, "%d\n", ubi->beb_rsvd_pebs); 36862306a36Sopenharmony_ci else if (attr == &dev_bad_peb_count) 36962306a36Sopenharmony_ci ret = sprintf(buf, "%d\n", ubi->bad_peb_count); 37062306a36Sopenharmony_ci else if (attr == &dev_max_vol_count) 37162306a36Sopenharmony_ci ret = sprintf(buf, "%d\n", ubi->vtbl_slots); 37262306a36Sopenharmony_ci else if (attr == &dev_min_io_size) 37362306a36Sopenharmony_ci ret = sprintf(buf, "%d\n", ubi->min_io_size); 37462306a36Sopenharmony_ci else if (attr == &dev_bgt_enabled) 37562306a36Sopenharmony_ci ret = sprintf(buf, "%d\n", ubi->thread_enabled); 37662306a36Sopenharmony_ci else if (attr == &dev_mtd_num) 37762306a36Sopenharmony_ci ret = sprintf(buf, "%d\n", ubi->mtd->index); 37862306a36Sopenharmony_ci else if (attr == &dev_ro_mode) 37962306a36Sopenharmony_ci ret = sprintf(buf, "%d\n", ubi->ro_mode); 38062306a36Sopenharmony_ci else 38162306a36Sopenharmony_ci ret = -EINVAL; 38262306a36Sopenharmony_ci 38362306a36Sopenharmony_ci return ret; 38462306a36Sopenharmony_ci} 38562306a36Sopenharmony_ci 38662306a36Sopenharmony_cistatic struct attribute *ubi_dev_attrs[] = { 38762306a36Sopenharmony_ci &dev_eraseblock_size.attr, 38862306a36Sopenharmony_ci &dev_avail_eraseblocks.attr, 38962306a36Sopenharmony_ci &dev_total_eraseblocks.attr, 39062306a36Sopenharmony_ci &dev_volumes_count.attr, 39162306a36Sopenharmony_ci &dev_max_ec.attr, 39262306a36Sopenharmony_ci &dev_reserved_for_bad.attr, 39362306a36Sopenharmony_ci &dev_bad_peb_count.attr, 39462306a36Sopenharmony_ci &dev_max_vol_count.attr, 39562306a36Sopenharmony_ci &dev_min_io_size.attr, 39662306a36Sopenharmony_ci &dev_bgt_enabled.attr, 39762306a36Sopenharmony_ci &dev_mtd_num.attr, 39862306a36Sopenharmony_ci &dev_ro_mode.attr, 39962306a36Sopenharmony_ci NULL 40062306a36Sopenharmony_ci}; 40162306a36Sopenharmony_ciATTRIBUTE_GROUPS(ubi_dev); 40262306a36Sopenharmony_ci 40362306a36Sopenharmony_cistatic void dev_release(struct device *dev) 40462306a36Sopenharmony_ci{ 40562306a36Sopenharmony_ci struct ubi_device *ubi = container_of(dev, struct ubi_device, dev); 40662306a36Sopenharmony_ci 40762306a36Sopenharmony_ci kfree(ubi); 40862306a36Sopenharmony_ci} 40962306a36Sopenharmony_ci 41062306a36Sopenharmony_ci/** 41162306a36Sopenharmony_ci * kill_volumes - destroy all user volumes. 41262306a36Sopenharmony_ci * @ubi: UBI device description object 41362306a36Sopenharmony_ci */ 41462306a36Sopenharmony_cistatic void kill_volumes(struct ubi_device *ubi) 41562306a36Sopenharmony_ci{ 41662306a36Sopenharmony_ci int i; 41762306a36Sopenharmony_ci 41862306a36Sopenharmony_ci for (i = 0; i < ubi->vtbl_slots; i++) 41962306a36Sopenharmony_ci if (ubi->volumes[i]) 42062306a36Sopenharmony_ci ubi_free_volume(ubi, ubi->volumes[i]); 42162306a36Sopenharmony_ci} 42262306a36Sopenharmony_ci 42362306a36Sopenharmony_ci/** 42462306a36Sopenharmony_ci * uif_init - initialize user interfaces for an UBI device. 42562306a36Sopenharmony_ci * @ubi: UBI device description object 42662306a36Sopenharmony_ci * 42762306a36Sopenharmony_ci * This function initializes various user interfaces for an UBI device. If the 42862306a36Sopenharmony_ci * initialization fails at an early stage, this function frees all the 42962306a36Sopenharmony_ci * resources it allocated, returns an error. 43062306a36Sopenharmony_ci * 43162306a36Sopenharmony_ci * This function returns zero in case of success and a negative error code in 43262306a36Sopenharmony_ci * case of failure. 43362306a36Sopenharmony_ci */ 43462306a36Sopenharmony_cistatic int uif_init(struct ubi_device *ubi) 43562306a36Sopenharmony_ci{ 43662306a36Sopenharmony_ci int i, err; 43762306a36Sopenharmony_ci dev_t dev; 43862306a36Sopenharmony_ci 43962306a36Sopenharmony_ci sprintf(ubi->ubi_name, UBI_NAME_STR "%d", ubi->ubi_num); 44062306a36Sopenharmony_ci 44162306a36Sopenharmony_ci /* 44262306a36Sopenharmony_ci * Major numbers for the UBI character devices are allocated 44362306a36Sopenharmony_ci * dynamically. Major numbers of volume character devices are 44462306a36Sopenharmony_ci * equivalent to ones of the corresponding UBI character device. Minor 44562306a36Sopenharmony_ci * numbers of UBI character devices are 0, while minor numbers of 44662306a36Sopenharmony_ci * volume character devices start from 1. Thus, we allocate one major 44762306a36Sopenharmony_ci * number and ubi->vtbl_slots + 1 minor numbers. 44862306a36Sopenharmony_ci */ 44962306a36Sopenharmony_ci err = alloc_chrdev_region(&dev, 0, ubi->vtbl_slots + 1, ubi->ubi_name); 45062306a36Sopenharmony_ci if (err) { 45162306a36Sopenharmony_ci ubi_err(ubi, "cannot register UBI character devices"); 45262306a36Sopenharmony_ci return err; 45362306a36Sopenharmony_ci } 45462306a36Sopenharmony_ci 45562306a36Sopenharmony_ci ubi->dev.devt = dev; 45662306a36Sopenharmony_ci 45762306a36Sopenharmony_ci ubi_assert(MINOR(dev) == 0); 45862306a36Sopenharmony_ci cdev_init(&ubi->cdev, &ubi_cdev_operations); 45962306a36Sopenharmony_ci dbg_gen("%s major is %u", ubi->ubi_name, MAJOR(dev)); 46062306a36Sopenharmony_ci ubi->cdev.owner = THIS_MODULE; 46162306a36Sopenharmony_ci 46262306a36Sopenharmony_ci dev_set_name(&ubi->dev, UBI_NAME_STR "%d", ubi->ubi_num); 46362306a36Sopenharmony_ci err = cdev_device_add(&ubi->cdev, &ubi->dev); 46462306a36Sopenharmony_ci if (err) 46562306a36Sopenharmony_ci goto out_unreg; 46662306a36Sopenharmony_ci 46762306a36Sopenharmony_ci for (i = 0; i < ubi->vtbl_slots; i++) 46862306a36Sopenharmony_ci if (ubi->volumes[i]) { 46962306a36Sopenharmony_ci err = ubi_add_volume(ubi, ubi->volumes[i]); 47062306a36Sopenharmony_ci if (err) { 47162306a36Sopenharmony_ci ubi_err(ubi, "cannot add volume %d", i); 47262306a36Sopenharmony_ci ubi->volumes[i] = NULL; 47362306a36Sopenharmony_ci goto out_volumes; 47462306a36Sopenharmony_ci } 47562306a36Sopenharmony_ci } 47662306a36Sopenharmony_ci 47762306a36Sopenharmony_ci return 0; 47862306a36Sopenharmony_ci 47962306a36Sopenharmony_ciout_volumes: 48062306a36Sopenharmony_ci kill_volumes(ubi); 48162306a36Sopenharmony_ci cdev_device_del(&ubi->cdev, &ubi->dev); 48262306a36Sopenharmony_ciout_unreg: 48362306a36Sopenharmony_ci unregister_chrdev_region(ubi->cdev.dev, ubi->vtbl_slots + 1); 48462306a36Sopenharmony_ci ubi_err(ubi, "cannot initialize UBI %s, error %d", 48562306a36Sopenharmony_ci ubi->ubi_name, err); 48662306a36Sopenharmony_ci return err; 48762306a36Sopenharmony_ci} 48862306a36Sopenharmony_ci 48962306a36Sopenharmony_ci/** 49062306a36Sopenharmony_ci * uif_close - close user interfaces for an UBI device. 49162306a36Sopenharmony_ci * @ubi: UBI device description object 49262306a36Sopenharmony_ci * 49362306a36Sopenharmony_ci * Note, since this function un-registers UBI volume device objects (@vol->dev), 49462306a36Sopenharmony_ci * the memory allocated voe the volumes is freed as well (in the release 49562306a36Sopenharmony_ci * function). 49662306a36Sopenharmony_ci */ 49762306a36Sopenharmony_cistatic void uif_close(struct ubi_device *ubi) 49862306a36Sopenharmony_ci{ 49962306a36Sopenharmony_ci kill_volumes(ubi); 50062306a36Sopenharmony_ci cdev_device_del(&ubi->cdev, &ubi->dev); 50162306a36Sopenharmony_ci unregister_chrdev_region(ubi->cdev.dev, ubi->vtbl_slots + 1); 50262306a36Sopenharmony_ci} 50362306a36Sopenharmony_ci 50462306a36Sopenharmony_ci/** 50562306a36Sopenharmony_ci * ubi_free_volumes_from - free volumes from specific index. 50662306a36Sopenharmony_ci * @ubi: UBI device description object 50762306a36Sopenharmony_ci * @from: the start index used for volume free. 50862306a36Sopenharmony_ci */ 50962306a36Sopenharmony_cistatic void ubi_free_volumes_from(struct ubi_device *ubi, int from) 51062306a36Sopenharmony_ci{ 51162306a36Sopenharmony_ci int i; 51262306a36Sopenharmony_ci 51362306a36Sopenharmony_ci for (i = from; i < ubi->vtbl_slots + UBI_INT_VOL_COUNT; i++) { 51462306a36Sopenharmony_ci if (!ubi->volumes[i]) 51562306a36Sopenharmony_ci continue; 51662306a36Sopenharmony_ci ubi_eba_replace_table(ubi->volumes[i], NULL); 51762306a36Sopenharmony_ci ubi_fastmap_destroy_checkmap(ubi->volumes[i]); 51862306a36Sopenharmony_ci kfree(ubi->volumes[i]); 51962306a36Sopenharmony_ci ubi->volumes[i] = NULL; 52062306a36Sopenharmony_ci } 52162306a36Sopenharmony_ci} 52262306a36Sopenharmony_ci 52362306a36Sopenharmony_ci/** 52462306a36Sopenharmony_ci * ubi_free_all_volumes - free all volumes. 52562306a36Sopenharmony_ci * @ubi: UBI device description object 52662306a36Sopenharmony_ci */ 52762306a36Sopenharmony_civoid ubi_free_all_volumes(struct ubi_device *ubi) 52862306a36Sopenharmony_ci{ 52962306a36Sopenharmony_ci ubi_free_volumes_from(ubi, 0); 53062306a36Sopenharmony_ci} 53162306a36Sopenharmony_ci 53262306a36Sopenharmony_ci/** 53362306a36Sopenharmony_ci * ubi_free_internal_volumes - free internal volumes. 53462306a36Sopenharmony_ci * @ubi: UBI device description object 53562306a36Sopenharmony_ci */ 53662306a36Sopenharmony_civoid ubi_free_internal_volumes(struct ubi_device *ubi) 53762306a36Sopenharmony_ci{ 53862306a36Sopenharmony_ci ubi_free_volumes_from(ubi, ubi->vtbl_slots); 53962306a36Sopenharmony_ci} 54062306a36Sopenharmony_ci 54162306a36Sopenharmony_cistatic int get_bad_peb_limit(const struct ubi_device *ubi, int max_beb_per1024) 54262306a36Sopenharmony_ci{ 54362306a36Sopenharmony_ci int limit, device_pebs; 54462306a36Sopenharmony_ci uint64_t device_size; 54562306a36Sopenharmony_ci 54662306a36Sopenharmony_ci if (!max_beb_per1024) { 54762306a36Sopenharmony_ci /* 54862306a36Sopenharmony_ci * Since max_beb_per1024 has not been set by the user in either 54962306a36Sopenharmony_ci * the cmdline or Kconfig, use mtd_max_bad_blocks to set the 55062306a36Sopenharmony_ci * limit if it is supported by the device. 55162306a36Sopenharmony_ci */ 55262306a36Sopenharmony_ci limit = mtd_max_bad_blocks(ubi->mtd, 0, ubi->mtd->size); 55362306a36Sopenharmony_ci if (limit < 0) 55462306a36Sopenharmony_ci return 0; 55562306a36Sopenharmony_ci return limit; 55662306a36Sopenharmony_ci } 55762306a36Sopenharmony_ci 55862306a36Sopenharmony_ci /* 55962306a36Sopenharmony_ci * Here we are using size of the entire flash chip and 56062306a36Sopenharmony_ci * not just the MTD partition size because the maximum 56162306a36Sopenharmony_ci * number of bad eraseblocks is a percentage of the 56262306a36Sopenharmony_ci * whole device and bad eraseblocks are not fairly 56362306a36Sopenharmony_ci * distributed over the flash chip. So the worst case 56462306a36Sopenharmony_ci * is that all the bad eraseblocks of the chip are in 56562306a36Sopenharmony_ci * the MTD partition we are attaching (ubi->mtd). 56662306a36Sopenharmony_ci */ 56762306a36Sopenharmony_ci device_size = mtd_get_device_size(ubi->mtd); 56862306a36Sopenharmony_ci device_pebs = mtd_div_by_eb(device_size, ubi->mtd); 56962306a36Sopenharmony_ci limit = mult_frac(device_pebs, max_beb_per1024, 1024); 57062306a36Sopenharmony_ci 57162306a36Sopenharmony_ci /* Round it up */ 57262306a36Sopenharmony_ci if (mult_frac(limit, 1024, max_beb_per1024) < device_pebs) 57362306a36Sopenharmony_ci limit += 1; 57462306a36Sopenharmony_ci 57562306a36Sopenharmony_ci return limit; 57662306a36Sopenharmony_ci} 57762306a36Sopenharmony_ci 57862306a36Sopenharmony_ci/** 57962306a36Sopenharmony_ci * io_init - initialize I/O sub-system for a given UBI device. 58062306a36Sopenharmony_ci * @ubi: UBI device description object 58162306a36Sopenharmony_ci * @max_beb_per1024: maximum expected number of bad PEB per 1024 PEBs 58262306a36Sopenharmony_ci * 58362306a36Sopenharmony_ci * If @ubi->vid_hdr_offset or @ubi->leb_start is zero, default offsets are 58462306a36Sopenharmony_ci * assumed: 58562306a36Sopenharmony_ci * o EC header is always at offset zero - this cannot be changed; 58662306a36Sopenharmony_ci * o VID header starts just after the EC header at the closest address 58762306a36Sopenharmony_ci * aligned to @io->hdrs_min_io_size; 58862306a36Sopenharmony_ci * o data starts just after the VID header at the closest address aligned to 58962306a36Sopenharmony_ci * @io->min_io_size 59062306a36Sopenharmony_ci * 59162306a36Sopenharmony_ci * This function returns zero in case of success and a negative error code in 59262306a36Sopenharmony_ci * case of failure. 59362306a36Sopenharmony_ci */ 59462306a36Sopenharmony_cistatic int io_init(struct ubi_device *ubi, int max_beb_per1024) 59562306a36Sopenharmony_ci{ 59662306a36Sopenharmony_ci dbg_gen("sizeof(struct ubi_ainf_peb) %zu", sizeof(struct ubi_ainf_peb)); 59762306a36Sopenharmony_ci dbg_gen("sizeof(struct ubi_wl_entry) %zu", sizeof(struct ubi_wl_entry)); 59862306a36Sopenharmony_ci 59962306a36Sopenharmony_ci if (ubi->mtd->numeraseregions != 0) { 60062306a36Sopenharmony_ci /* 60162306a36Sopenharmony_ci * Some flashes have several erase regions. Different regions 60262306a36Sopenharmony_ci * may have different eraseblock size and other 60362306a36Sopenharmony_ci * characteristics. It looks like mostly multi-region flashes 60462306a36Sopenharmony_ci * have one "main" region and one or more small regions to 60562306a36Sopenharmony_ci * store boot loader code or boot parameters or whatever. I 60662306a36Sopenharmony_ci * guess we should just pick the largest region. But this is 60762306a36Sopenharmony_ci * not implemented. 60862306a36Sopenharmony_ci */ 60962306a36Sopenharmony_ci ubi_err(ubi, "multiple regions, not implemented"); 61062306a36Sopenharmony_ci return -EINVAL; 61162306a36Sopenharmony_ci } 61262306a36Sopenharmony_ci 61362306a36Sopenharmony_ci if (ubi->vid_hdr_offset < 0) 61462306a36Sopenharmony_ci return -EINVAL; 61562306a36Sopenharmony_ci 61662306a36Sopenharmony_ci /* 61762306a36Sopenharmony_ci * Note, in this implementation we support MTD devices with 0x7FFFFFFF 61862306a36Sopenharmony_ci * physical eraseblocks maximum. 61962306a36Sopenharmony_ci */ 62062306a36Sopenharmony_ci 62162306a36Sopenharmony_ci ubi->peb_size = ubi->mtd->erasesize; 62262306a36Sopenharmony_ci ubi->peb_count = mtd_div_by_eb(ubi->mtd->size, ubi->mtd); 62362306a36Sopenharmony_ci ubi->flash_size = ubi->mtd->size; 62462306a36Sopenharmony_ci 62562306a36Sopenharmony_ci if (mtd_can_have_bb(ubi->mtd)) { 62662306a36Sopenharmony_ci ubi->bad_allowed = 1; 62762306a36Sopenharmony_ci ubi->bad_peb_limit = get_bad_peb_limit(ubi, max_beb_per1024); 62862306a36Sopenharmony_ci } 62962306a36Sopenharmony_ci 63062306a36Sopenharmony_ci if (ubi->mtd->type == MTD_NORFLASH) 63162306a36Sopenharmony_ci ubi->nor_flash = 1; 63262306a36Sopenharmony_ci 63362306a36Sopenharmony_ci ubi->min_io_size = ubi->mtd->writesize; 63462306a36Sopenharmony_ci ubi->hdrs_min_io_size = ubi->mtd->writesize >> ubi->mtd->subpage_sft; 63562306a36Sopenharmony_ci 63662306a36Sopenharmony_ci /* 63762306a36Sopenharmony_ci * Make sure minimal I/O unit is power of 2. Note, there is no 63862306a36Sopenharmony_ci * fundamental reason for this assumption. It is just an optimization 63962306a36Sopenharmony_ci * which allows us to avoid costly division operations. 64062306a36Sopenharmony_ci */ 64162306a36Sopenharmony_ci if (!is_power_of_2(ubi->min_io_size)) { 64262306a36Sopenharmony_ci ubi_err(ubi, "min. I/O unit (%d) is not power of 2", 64362306a36Sopenharmony_ci ubi->min_io_size); 64462306a36Sopenharmony_ci return -EINVAL; 64562306a36Sopenharmony_ci } 64662306a36Sopenharmony_ci 64762306a36Sopenharmony_ci ubi_assert(ubi->hdrs_min_io_size > 0); 64862306a36Sopenharmony_ci ubi_assert(ubi->hdrs_min_io_size <= ubi->min_io_size); 64962306a36Sopenharmony_ci ubi_assert(ubi->min_io_size % ubi->hdrs_min_io_size == 0); 65062306a36Sopenharmony_ci 65162306a36Sopenharmony_ci ubi->max_write_size = ubi->mtd->writebufsize; 65262306a36Sopenharmony_ci /* 65362306a36Sopenharmony_ci * Maximum write size has to be greater or equivalent to min. I/O 65462306a36Sopenharmony_ci * size, and be multiple of min. I/O size. 65562306a36Sopenharmony_ci */ 65662306a36Sopenharmony_ci if (ubi->max_write_size < ubi->min_io_size || 65762306a36Sopenharmony_ci ubi->max_write_size % ubi->min_io_size || 65862306a36Sopenharmony_ci !is_power_of_2(ubi->max_write_size)) { 65962306a36Sopenharmony_ci ubi_err(ubi, "bad write buffer size %d for %d min. I/O unit", 66062306a36Sopenharmony_ci ubi->max_write_size, ubi->min_io_size); 66162306a36Sopenharmony_ci return -EINVAL; 66262306a36Sopenharmony_ci } 66362306a36Sopenharmony_ci 66462306a36Sopenharmony_ci /* Calculate default aligned sizes of EC and VID headers */ 66562306a36Sopenharmony_ci ubi->ec_hdr_alsize = ALIGN(UBI_EC_HDR_SIZE, ubi->hdrs_min_io_size); 66662306a36Sopenharmony_ci ubi->vid_hdr_alsize = ALIGN(UBI_VID_HDR_SIZE, ubi->hdrs_min_io_size); 66762306a36Sopenharmony_ci 66862306a36Sopenharmony_ci dbg_gen("min_io_size %d", ubi->min_io_size); 66962306a36Sopenharmony_ci dbg_gen("max_write_size %d", ubi->max_write_size); 67062306a36Sopenharmony_ci dbg_gen("hdrs_min_io_size %d", ubi->hdrs_min_io_size); 67162306a36Sopenharmony_ci dbg_gen("ec_hdr_alsize %d", ubi->ec_hdr_alsize); 67262306a36Sopenharmony_ci dbg_gen("vid_hdr_alsize %d", ubi->vid_hdr_alsize); 67362306a36Sopenharmony_ci 67462306a36Sopenharmony_ci if (ubi->vid_hdr_offset == 0) 67562306a36Sopenharmony_ci /* Default offset */ 67662306a36Sopenharmony_ci ubi->vid_hdr_offset = ubi->vid_hdr_aloffset = 67762306a36Sopenharmony_ci ubi->ec_hdr_alsize; 67862306a36Sopenharmony_ci else { 67962306a36Sopenharmony_ci ubi->vid_hdr_aloffset = ubi->vid_hdr_offset & 68062306a36Sopenharmony_ci ~(ubi->hdrs_min_io_size - 1); 68162306a36Sopenharmony_ci ubi->vid_hdr_shift = ubi->vid_hdr_offset - 68262306a36Sopenharmony_ci ubi->vid_hdr_aloffset; 68362306a36Sopenharmony_ci } 68462306a36Sopenharmony_ci 68562306a36Sopenharmony_ci /* 68662306a36Sopenharmony_ci * Memory allocation for VID header is ubi->vid_hdr_alsize 68762306a36Sopenharmony_ci * which is described in comments in io.c. 68862306a36Sopenharmony_ci * Make sure VID header shift + UBI_VID_HDR_SIZE not exceeds 68962306a36Sopenharmony_ci * ubi->vid_hdr_alsize, so that all vid header operations 69062306a36Sopenharmony_ci * won't access memory out of bounds. 69162306a36Sopenharmony_ci */ 69262306a36Sopenharmony_ci if ((ubi->vid_hdr_shift + UBI_VID_HDR_SIZE) > ubi->vid_hdr_alsize) { 69362306a36Sopenharmony_ci ubi_err(ubi, "Invalid VID header offset %d, VID header shift(%d)" 69462306a36Sopenharmony_ci " + VID header size(%zu) > VID header aligned size(%d).", 69562306a36Sopenharmony_ci ubi->vid_hdr_offset, ubi->vid_hdr_shift, 69662306a36Sopenharmony_ci UBI_VID_HDR_SIZE, ubi->vid_hdr_alsize); 69762306a36Sopenharmony_ci return -EINVAL; 69862306a36Sopenharmony_ci } 69962306a36Sopenharmony_ci 70062306a36Sopenharmony_ci /* Similar for the data offset */ 70162306a36Sopenharmony_ci ubi->leb_start = ubi->vid_hdr_offset + UBI_VID_HDR_SIZE; 70262306a36Sopenharmony_ci ubi->leb_start = ALIGN(ubi->leb_start, ubi->min_io_size); 70362306a36Sopenharmony_ci 70462306a36Sopenharmony_ci dbg_gen("vid_hdr_offset %d", ubi->vid_hdr_offset); 70562306a36Sopenharmony_ci dbg_gen("vid_hdr_aloffset %d", ubi->vid_hdr_aloffset); 70662306a36Sopenharmony_ci dbg_gen("vid_hdr_shift %d", ubi->vid_hdr_shift); 70762306a36Sopenharmony_ci dbg_gen("leb_start %d", ubi->leb_start); 70862306a36Sopenharmony_ci 70962306a36Sopenharmony_ci /* The shift must be aligned to 32-bit boundary */ 71062306a36Sopenharmony_ci if (ubi->vid_hdr_shift % 4) { 71162306a36Sopenharmony_ci ubi_err(ubi, "unaligned VID header shift %d", 71262306a36Sopenharmony_ci ubi->vid_hdr_shift); 71362306a36Sopenharmony_ci return -EINVAL; 71462306a36Sopenharmony_ci } 71562306a36Sopenharmony_ci 71662306a36Sopenharmony_ci /* Check sanity */ 71762306a36Sopenharmony_ci if (ubi->vid_hdr_offset < UBI_EC_HDR_SIZE || 71862306a36Sopenharmony_ci ubi->leb_start < ubi->vid_hdr_offset + UBI_VID_HDR_SIZE || 71962306a36Sopenharmony_ci ubi->leb_start > ubi->peb_size - UBI_VID_HDR_SIZE || 72062306a36Sopenharmony_ci ubi->leb_start & (ubi->min_io_size - 1)) { 72162306a36Sopenharmony_ci ubi_err(ubi, "bad VID header (%d) or data offsets (%d)", 72262306a36Sopenharmony_ci ubi->vid_hdr_offset, ubi->leb_start); 72362306a36Sopenharmony_ci return -EINVAL; 72462306a36Sopenharmony_ci } 72562306a36Sopenharmony_ci 72662306a36Sopenharmony_ci /* 72762306a36Sopenharmony_ci * Set maximum amount of physical erroneous eraseblocks to be 10%. 72862306a36Sopenharmony_ci * Erroneous PEB are those which have read errors. 72962306a36Sopenharmony_ci */ 73062306a36Sopenharmony_ci ubi->max_erroneous = ubi->peb_count / 10; 73162306a36Sopenharmony_ci if (ubi->max_erroneous < 16) 73262306a36Sopenharmony_ci ubi->max_erroneous = 16; 73362306a36Sopenharmony_ci dbg_gen("max_erroneous %d", ubi->max_erroneous); 73462306a36Sopenharmony_ci 73562306a36Sopenharmony_ci /* 73662306a36Sopenharmony_ci * It may happen that EC and VID headers are situated in one minimal 73762306a36Sopenharmony_ci * I/O unit. In this case we can only accept this UBI image in 73862306a36Sopenharmony_ci * read-only mode. 73962306a36Sopenharmony_ci */ 74062306a36Sopenharmony_ci if (ubi->vid_hdr_offset + UBI_VID_HDR_SIZE <= ubi->hdrs_min_io_size) { 74162306a36Sopenharmony_ci ubi_warn(ubi, "EC and VID headers are in the same minimal I/O unit, switch to read-only mode"); 74262306a36Sopenharmony_ci ubi->ro_mode = 1; 74362306a36Sopenharmony_ci } 74462306a36Sopenharmony_ci 74562306a36Sopenharmony_ci ubi->leb_size = ubi->peb_size - ubi->leb_start; 74662306a36Sopenharmony_ci 74762306a36Sopenharmony_ci if (!(ubi->mtd->flags & MTD_WRITEABLE)) { 74862306a36Sopenharmony_ci ubi_msg(ubi, "MTD device %d is write-protected, attach in read-only mode", 74962306a36Sopenharmony_ci ubi->mtd->index); 75062306a36Sopenharmony_ci ubi->ro_mode = 1; 75162306a36Sopenharmony_ci } 75262306a36Sopenharmony_ci 75362306a36Sopenharmony_ci /* 75462306a36Sopenharmony_ci * Note, ideally, we have to initialize @ubi->bad_peb_count here. But 75562306a36Sopenharmony_ci * unfortunately, MTD does not provide this information. We should loop 75662306a36Sopenharmony_ci * over all physical eraseblocks and invoke mtd->block_is_bad() for 75762306a36Sopenharmony_ci * each physical eraseblock. So, we leave @ubi->bad_peb_count 75862306a36Sopenharmony_ci * uninitialized so far. 75962306a36Sopenharmony_ci */ 76062306a36Sopenharmony_ci 76162306a36Sopenharmony_ci return 0; 76262306a36Sopenharmony_ci} 76362306a36Sopenharmony_ci 76462306a36Sopenharmony_ci/** 76562306a36Sopenharmony_ci * autoresize - re-size the volume which has the "auto-resize" flag set. 76662306a36Sopenharmony_ci * @ubi: UBI device description object 76762306a36Sopenharmony_ci * @vol_id: ID of the volume to re-size 76862306a36Sopenharmony_ci * 76962306a36Sopenharmony_ci * This function re-sizes the volume marked by the %UBI_VTBL_AUTORESIZE_FLG in 77062306a36Sopenharmony_ci * the volume table to the largest possible size. See comments in ubi-header.h 77162306a36Sopenharmony_ci * for more description of the flag. Returns zero in case of success and a 77262306a36Sopenharmony_ci * negative error code in case of failure. 77362306a36Sopenharmony_ci */ 77462306a36Sopenharmony_cistatic int autoresize(struct ubi_device *ubi, int vol_id) 77562306a36Sopenharmony_ci{ 77662306a36Sopenharmony_ci struct ubi_volume_desc desc; 77762306a36Sopenharmony_ci struct ubi_volume *vol = ubi->volumes[vol_id]; 77862306a36Sopenharmony_ci int err, old_reserved_pebs = vol->reserved_pebs; 77962306a36Sopenharmony_ci 78062306a36Sopenharmony_ci if (ubi->ro_mode) { 78162306a36Sopenharmony_ci ubi_warn(ubi, "skip auto-resize because of R/O mode"); 78262306a36Sopenharmony_ci return 0; 78362306a36Sopenharmony_ci } 78462306a36Sopenharmony_ci 78562306a36Sopenharmony_ci /* 78662306a36Sopenharmony_ci * Clear the auto-resize flag in the volume in-memory copy of the 78762306a36Sopenharmony_ci * volume table, and 'ubi_resize_volume()' will propagate this change 78862306a36Sopenharmony_ci * to the flash. 78962306a36Sopenharmony_ci */ 79062306a36Sopenharmony_ci ubi->vtbl[vol_id].flags &= ~UBI_VTBL_AUTORESIZE_FLG; 79162306a36Sopenharmony_ci 79262306a36Sopenharmony_ci if (ubi->avail_pebs == 0) { 79362306a36Sopenharmony_ci struct ubi_vtbl_record vtbl_rec; 79462306a36Sopenharmony_ci 79562306a36Sopenharmony_ci /* 79662306a36Sopenharmony_ci * No available PEBs to re-size the volume, clear the flag on 79762306a36Sopenharmony_ci * flash and exit. 79862306a36Sopenharmony_ci */ 79962306a36Sopenharmony_ci vtbl_rec = ubi->vtbl[vol_id]; 80062306a36Sopenharmony_ci err = ubi_change_vtbl_record(ubi, vol_id, &vtbl_rec); 80162306a36Sopenharmony_ci if (err) 80262306a36Sopenharmony_ci ubi_err(ubi, "cannot clean auto-resize flag for volume %d", 80362306a36Sopenharmony_ci vol_id); 80462306a36Sopenharmony_ci } else { 80562306a36Sopenharmony_ci desc.vol = vol; 80662306a36Sopenharmony_ci err = ubi_resize_volume(&desc, 80762306a36Sopenharmony_ci old_reserved_pebs + ubi->avail_pebs); 80862306a36Sopenharmony_ci if (err) 80962306a36Sopenharmony_ci ubi_err(ubi, "cannot auto-resize volume %d", 81062306a36Sopenharmony_ci vol_id); 81162306a36Sopenharmony_ci } 81262306a36Sopenharmony_ci 81362306a36Sopenharmony_ci if (err) 81462306a36Sopenharmony_ci return err; 81562306a36Sopenharmony_ci 81662306a36Sopenharmony_ci ubi_msg(ubi, "volume %d (\"%s\") re-sized from %d to %d LEBs", 81762306a36Sopenharmony_ci vol_id, vol->name, old_reserved_pebs, vol->reserved_pebs); 81862306a36Sopenharmony_ci return 0; 81962306a36Sopenharmony_ci} 82062306a36Sopenharmony_ci 82162306a36Sopenharmony_ci/** 82262306a36Sopenharmony_ci * ubi_attach_mtd_dev - attach an MTD device. 82362306a36Sopenharmony_ci * @mtd: MTD device description object 82462306a36Sopenharmony_ci * @ubi_num: number to assign to the new UBI device 82562306a36Sopenharmony_ci * @vid_hdr_offset: VID header offset 82662306a36Sopenharmony_ci * @max_beb_per1024: maximum expected number of bad PEB per 1024 PEBs 82762306a36Sopenharmony_ci * @disable_fm: whether disable fastmap 82862306a36Sopenharmony_ci * 82962306a36Sopenharmony_ci * This function attaches MTD device @mtd_dev to UBI and assign @ubi_num number 83062306a36Sopenharmony_ci * to the newly created UBI device, unless @ubi_num is %UBI_DEV_NUM_AUTO, in 83162306a36Sopenharmony_ci * which case this function finds a vacant device number and assigns it 83262306a36Sopenharmony_ci * automatically. Returns the new UBI device number in case of success and a 83362306a36Sopenharmony_ci * negative error code in case of failure. 83462306a36Sopenharmony_ci * 83562306a36Sopenharmony_ci * If @disable_fm is true, ubi doesn't create new fastmap even the module param 83662306a36Sopenharmony_ci * 'fm_autoconvert' is set, and existed old fastmap will be destroyed after 83762306a36Sopenharmony_ci * doing full scanning. 83862306a36Sopenharmony_ci * 83962306a36Sopenharmony_ci * Note, the invocations of this function has to be serialized by the 84062306a36Sopenharmony_ci * @ubi_devices_mutex. 84162306a36Sopenharmony_ci */ 84262306a36Sopenharmony_ciint ubi_attach_mtd_dev(struct mtd_info *mtd, int ubi_num, 84362306a36Sopenharmony_ci int vid_hdr_offset, int max_beb_per1024, bool disable_fm) 84462306a36Sopenharmony_ci{ 84562306a36Sopenharmony_ci struct ubi_device *ubi; 84662306a36Sopenharmony_ci int i, err; 84762306a36Sopenharmony_ci 84862306a36Sopenharmony_ci if (max_beb_per1024 < 0 || max_beb_per1024 > MAX_MTD_UBI_BEB_LIMIT) 84962306a36Sopenharmony_ci return -EINVAL; 85062306a36Sopenharmony_ci 85162306a36Sopenharmony_ci if (!max_beb_per1024) 85262306a36Sopenharmony_ci max_beb_per1024 = CONFIG_MTD_UBI_BEB_LIMIT; 85362306a36Sopenharmony_ci 85462306a36Sopenharmony_ci /* 85562306a36Sopenharmony_ci * Check if we already have the same MTD device attached. 85662306a36Sopenharmony_ci * 85762306a36Sopenharmony_ci * Note, this function assumes that UBI devices creations and deletions 85862306a36Sopenharmony_ci * are serialized, so it does not take the &ubi_devices_lock. 85962306a36Sopenharmony_ci */ 86062306a36Sopenharmony_ci for (i = 0; i < UBI_MAX_DEVICES; i++) { 86162306a36Sopenharmony_ci ubi = ubi_devices[i]; 86262306a36Sopenharmony_ci if (ubi && mtd->index == ubi->mtd->index) { 86362306a36Sopenharmony_ci pr_err("ubi: mtd%d is already attached to ubi%d\n", 86462306a36Sopenharmony_ci mtd->index, i); 86562306a36Sopenharmony_ci return -EEXIST; 86662306a36Sopenharmony_ci } 86762306a36Sopenharmony_ci } 86862306a36Sopenharmony_ci 86962306a36Sopenharmony_ci /* 87062306a36Sopenharmony_ci * Make sure this MTD device is not emulated on top of an UBI volume 87162306a36Sopenharmony_ci * already. Well, generally this recursion works fine, but there are 87262306a36Sopenharmony_ci * different problems like the UBI module takes a reference to itself 87362306a36Sopenharmony_ci * by attaching (and thus, opening) the emulated MTD device. This 87462306a36Sopenharmony_ci * results in inability to unload the module. And in general it makes 87562306a36Sopenharmony_ci * no sense to attach emulated MTD devices, so we prohibit this. 87662306a36Sopenharmony_ci */ 87762306a36Sopenharmony_ci if (mtd->type == MTD_UBIVOLUME) { 87862306a36Sopenharmony_ci pr_err("ubi: refuse attaching mtd%d - it is already emulated on top of UBI\n", 87962306a36Sopenharmony_ci mtd->index); 88062306a36Sopenharmony_ci return -EINVAL; 88162306a36Sopenharmony_ci } 88262306a36Sopenharmony_ci 88362306a36Sopenharmony_ci /* 88462306a36Sopenharmony_ci * Both UBI and UBIFS have been designed for SLC NAND and NOR flashes. 88562306a36Sopenharmony_ci * MLC NAND is different and needs special care, otherwise UBI or UBIFS 88662306a36Sopenharmony_ci * will die soon and you will lose all your data. 88762306a36Sopenharmony_ci * Relax this rule if the partition we're attaching to operates in SLC 88862306a36Sopenharmony_ci * mode. 88962306a36Sopenharmony_ci */ 89062306a36Sopenharmony_ci if (mtd->type == MTD_MLCNANDFLASH && 89162306a36Sopenharmony_ci !(mtd->flags & MTD_SLC_ON_MLC_EMULATION)) { 89262306a36Sopenharmony_ci pr_err("ubi: refuse attaching mtd%d - MLC NAND is not supported\n", 89362306a36Sopenharmony_ci mtd->index); 89462306a36Sopenharmony_ci return -EINVAL; 89562306a36Sopenharmony_ci } 89662306a36Sopenharmony_ci 89762306a36Sopenharmony_ci /* UBI cannot work on flashes with zero erasesize. */ 89862306a36Sopenharmony_ci if (!mtd->erasesize) { 89962306a36Sopenharmony_ci pr_err("ubi: refuse attaching mtd%d - zero erasesize flash is not supported\n", 90062306a36Sopenharmony_ci mtd->index); 90162306a36Sopenharmony_ci return -EINVAL; 90262306a36Sopenharmony_ci } 90362306a36Sopenharmony_ci 90462306a36Sopenharmony_ci if (ubi_num == UBI_DEV_NUM_AUTO) { 90562306a36Sopenharmony_ci /* Search for an empty slot in the @ubi_devices array */ 90662306a36Sopenharmony_ci for (ubi_num = 0; ubi_num < UBI_MAX_DEVICES; ubi_num++) 90762306a36Sopenharmony_ci if (!ubi_devices[ubi_num]) 90862306a36Sopenharmony_ci break; 90962306a36Sopenharmony_ci if (ubi_num == UBI_MAX_DEVICES) { 91062306a36Sopenharmony_ci pr_err("ubi: only %d UBI devices may be created\n", 91162306a36Sopenharmony_ci UBI_MAX_DEVICES); 91262306a36Sopenharmony_ci return -ENFILE; 91362306a36Sopenharmony_ci } 91462306a36Sopenharmony_ci } else { 91562306a36Sopenharmony_ci if (ubi_num >= UBI_MAX_DEVICES) 91662306a36Sopenharmony_ci return -EINVAL; 91762306a36Sopenharmony_ci 91862306a36Sopenharmony_ci /* Make sure ubi_num is not busy */ 91962306a36Sopenharmony_ci if (ubi_devices[ubi_num]) { 92062306a36Sopenharmony_ci pr_err("ubi: ubi%i already exists\n", ubi_num); 92162306a36Sopenharmony_ci return -EEXIST; 92262306a36Sopenharmony_ci } 92362306a36Sopenharmony_ci } 92462306a36Sopenharmony_ci 92562306a36Sopenharmony_ci ubi = kzalloc(sizeof(struct ubi_device), GFP_KERNEL); 92662306a36Sopenharmony_ci if (!ubi) 92762306a36Sopenharmony_ci return -ENOMEM; 92862306a36Sopenharmony_ci 92962306a36Sopenharmony_ci device_initialize(&ubi->dev); 93062306a36Sopenharmony_ci ubi->dev.release = dev_release; 93162306a36Sopenharmony_ci ubi->dev.class = &ubi_class; 93262306a36Sopenharmony_ci ubi->dev.groups = ubi_dev_groups; 93362306a36Sopenharmony_ci ubi->dev.parent = &mtd->dev; 93462306a36Sopenharmony_ci 93562306a36Sopenharmony_ci ubi->mtd = mtd; 93662306a36Sopenharmony_ci ubi->ubi_num = ubi_num; 93762306a36Sopenharmony_ci ubi->vid_hdr_offset = vid_hdr_offset; 93862306a36Sopenharmony_ci ubi->autoresize_vol_id = -1; 93962306a36Sopenharmony_ci 94062306a36Sopenharmony_ci#ifdef CONFIG_MTD_UBI_FASTMAP 94162306a36Sopenharmony_ci ubi->fm_pool.used = ubi->fm_pool.size = 0; 94262306a36Sopenharmony_ci ubi->fm_wl_pool.used = ubi->fm_wl_pool.size = 0; 94362306a36Sopenharmony_ci 94462306a36Sopenharmony_ci /* 94562306a36Sopenharmony_ci * fm_pool.max_size is 5% of the total number of PEBs but it's also 94662306a36Sopenharmony_ci * between UBI_FM_MAX_POOL_SIZE and UBI_FM_MIN_POOL_SIZE. 94762306a36Sopenharmony_ci */ 94862306a36Sopenharmony_ci ubi->fm_pool.max_size = min(((int)mtd_div_by_eb(ubi->mtd->size, 94962306a36Sopenharmony_ci ubi->mtd) / 100) * 5, UBI_FM_MAX_POOL_SIZE); 95062306a36Sopenharmony_ci ubi->fm_pool.max_size = max(ubi->fm_pool.max_size, 95162306a36Sopenharmony_ci UBI_FM_MIN_POOL_SIZE); 95262306a36Sopenharmony_ci 95362306a36Sopenharmony_ci ubi->fm_wl_pool.max_size = ubi->fm_pool.max_size / 2; 95462306a36Sopenharmony_ci ubi->fm_disabled = (!fm_autoconvert || disable_fm) ? 1 : 0; 95562306a36Sopenharmony_ci if (fm_debug) 95662306a36Sopenharmony_ci ubi_enable_dbg_chk_fastmap(ubi); 95762306a36Sopenharmony_ci 95862306a36Sopenharmony_ci if (!ubi->fm_disabled && (int)mtd_div_by_eb(ubi->mtd->size, ubi->mtd) 95962306a36Sopenharmony_ci <= UBI_FM_MAX_START) { 96062306a36Sopenharmony_ci ubi_err(ubi, "More than %i PEBs are needed for fastmap, sorry.", 96162306a36Sopenharmony_ci UBI_FM_MAX_START); 96262306a36Sopenharmony_ci ubi->fm_disabled = 1; 96362306a36Sopenharmony_ci } 96462306a36Sopenharmony_ci 96562306a36Sopenharmony_ci ubi_msg(ubi, "default fastmap pool size: %d", ubi->fm_pool.max_size); 96662306a36Sopenharmony_ci ubi_msg(ubi, "default fastmap WL pool size: %d", 96762306a36Sopenharmony_ci ubi->fm_wl_pool.max_size); 96862306a36Sopenharmony_ci#else 96962306a36Sopenharmony_ci ubi->fm_disabled = 1; 97062306a36Sopenharmony_ci#endif 97162306a36Sopenharmony_ci mutex_init(&ubi->buf_mutex); 97262306a36Sopenharmony_ci mutex_init(&ubi->ckvol_mutex); 97362306a36Sopenharmony_ci mutex_init(&ubi->device_mutex); 97462306a36Sopenharmony_ci spin_lock_init(&ubi->volumes_lock); 97562306a36Sopenharmony_ci init_rwsem(&ubi->fm_protect); 97662306a36Sopenharmony_ci init_rwsem(&ubi->fm_eba_sem); 97762306a36Sopenharmony_ci 97862306a36Sopenharmony_ci ubi_msg(ubi, "attaching mtd%d", mtd->index); 97962306a36Sopenharmony_ci 98062306a36Sopenharmony_ci err = io_init(ubi, max_beb_per1024); 98162306a36Sopenharmony_ci if (err) 98262306a36Sopenharmony_ci goto out_free; 98362306a36Sopenharmony_ci 98462306a36Sopenharmony_ci err = -ENOMEM; 98562306a36Sopenharmony_ci ubi->peb_buf = vmalloc(ubi->peb_size); 98662306a36Sopenharmony_ci if (!ubi->peb_buf) 98762306a36Sopenharmony_ci goto out_free; 98862306a36Sopenharmony_ci 98962306a36Sopenharmony_ci#ifdef CONFIG_MTD_UBI_FASTMAP 99062306a36Sopenharmony_ci ubi->fm_size = ubi_calc_fm_size(ubi); 99162306a36Sopenharmony_ci ubi->fm_buf = vzalloc(ubi->fm_size); 99262306a36Sopenharmony_ci if (!ubi->fm_buf) 99362306a36Sopenharmony_ci goto out_free; 99462306a36Sopenharmony_ci#endif 99562306a36Sopenharmony_ci err = ubi_attach(ubi, disable_fm ? 1 : 0); 99662306a36Sopenharmony_ci if (err) { 99762306a36Sopenharmony_ci ubi_err(ubi, "failed to attach mtd%d, error %d", 99862306a36Sopenharmony_ci mtd->index, err); 99962306a36Sopenharmony_ci goto out_free; 100062306a36Sopenharmony_ci } 100162306a36Sopenharmony_ci 100262306a36Sopenharmony_ci if (ubi->autoresize_vol_id != -1) { 100362306a36Sopenharmony_ci err = autoresize(ubi, ubi->autoresize_vol_id); 100462306a36Sopenharmony_ci if (err) 100562306a36Sopenharmony_ci goto out_detach; 100662306a36Sopenharmony_ci } 100762306a36Sopenharmony_ci 100862306a36Sopenharmony_ci err = uif_init(ubi); 100962306a36Sopenharmony_ci if (err) 101062306a36Sopenharmony_ci goto out_detach; 101162306a36Sopenharmony_ci 101262306a36Sopenharmony_ci err = ubi_debugfs_init_dev(ubi); 101362306a36Sopenharmony_ci if (err) 101462306a36Sopenharmony_ci goto out_uif; 101562306a36Sopenharmony_ci 101662306a36Sopenharmony_ci ubi->bgt_thread = kthread_create(ubi_thread, ubi, "%s", ubi->bgt_name); 101762306a36Sopenharmony_ci if (IS_ERR(ubi->bgt_thread)) { 101862306a36Sopenharmony_ci err = PTR_ERR(ubi->bgt_thread); 101962306a36Sopenharmony_ci ubi_err(ubi, "cannot spawn \"%s\", error %d", 102062306a36Sopenharmony_ci ubi->bgt_name, err); 102162306a36Sopenharmony_ci goto out_debugfs; 102262306a36Sopenharmony_ci } 102362306a36Sopenharmony_ci 102462306a36Sopenharmony_ci ubi_msg(ubi, "attached mtd%d (name \"%s\", size %llu MiB)", 102562306a36Sopenharmony_ci mtd->index, mtd->name, ubi->flash_size >> 20); 102662306a36Sopenharmony_ci ubi_msg(ubi, "PEB size: %d bytes (%d KiB), LEB size: %d bytes", 102762306a36Sopenharmony_ci ubi->peb_size, ubi->peb_size >> 10, ubi->leb_size); 102862306a36Sopenharmony_ci ubi_msg(ubi, "min./max. I/O unit sizes: %d/%d, sub-page size %d", 102962306a36Sopenharmony_ci ubi->min_io_size, ubi->max_write_size, ubi->hdrs_min_io_size); 103062306a36Sopenharmony_ci ubi_msg(ubi, "VID header offset: %d (aligned %d), data offset: %d", 103162306a36Sopenharmony_ci ubi->vid_hdr_offset, ubi->vid_hdr_aloffset, ubi->leb_start); 103262306a36Sopenharmony_ci ubi_msg(ubi, "good PEBs: %d, bad PEBs: %d, corrupted PEBs: %d", 103362306a36Sopenharmony_ci ubi->good_peb_count, ubi->bad_peb_count, ubi->corr_peb_count); 103462306a36Sopenharmony_ci ubi_msg(ubi, "user volume: %d, internal volumes: %d, max. volumes count: %d", 103562306a36Sopenharmony_ci ubi->vol_count - UBI_INT_VOL_COUNT, UBI_INT_VOL_COUNT, 103662306a36Sopenharmony_ci ubi->vtbl_slots); 103762306a36Sopenharmony_ci ubi_msg(ubi, "max/mean erase counter: %d/%d, WL threshold: %d, image sequence number: %u", 103862306a36Sopenharmony_ci ubi->max_ec, ubi->mean_ec, CONFIG_MTD_UBI_WL_THRESHOLD, 103962306a36Sopenharmony_ci ubi->image_seq); 104062306a36Sopenharmony_ci ubi_msg(ubi, "available PEBs: %d, total reserved PEBs: %d, PEBs reserved for bad PEB handling: %d", 104162306a36Sopenharmony_ci ubi->avail_pebs, ubi->rsvd_pebs, ubi->beb_rsvd_pebs); 104262306a36Sopenharmony_ci 104362306a36Sopenharmony_ci /* 104462306a36Sopenharmony_ci * The below lock makes sure we do not race with 'ubi_thread()' which 104562306a36Sopenharmony_ci * checks @ubi->thread_enabled. Otherwise we may fail to wake it up. 104662306a36Sopenharmony_ci */ 104762306a36Sopenharmony_ci spin_lock(&ubi->wl_lock); 104862306a36Sopenharmony_ci ubi->thread_enabled = 1; 104962306a36Sopenharmony_ci wake_up_process(ubi->bgt_thread); 105062306a36Sopenharmony_ci spin_unlock(&ubi->wl_lock); 105162306a36Sopenharmony_ci 105262306a36Sopenharmony_ci ubi_devices[ubi_num] = ubi; 105362306a36Sopenharmony_ci ubi_notify_all(ubi, UBI_VOLUME_ADDED, NULL); 105462306a36Sopenharmony_ci return ubi_num; 105562306a36Sopenharmony_ci 105662306a36Sopenharmony_ciout_debugfs: 105762306a36Sopenharmony_ci ubi_debugfs_exit_dev(ubi); 105862306a36Sopenharmony_ciout_uif: 105962306a36Sopenharmony_ci uif_close(ubi); 106062306a36Sopenharmony_ciout_detach: 106162306a36Sopenharmony_ci ubi_wl_close(ubi); 106262306a36Sopenharmony_ci ubi_free_all_volumes(ubi); 106362306a36Sopenharmony_ci vfree(ubi->vtbl); 106462306a36Sopenharmony_ciout_free: 106562306a36Sopenharmony_ci vfree(ubi->peb_buf); 106662306a36Sopenharmony_ci vfree(ubi->fm_buf); 106762306a36Sopenharmony_ci put_device(&ubi->dev); 106862306a36Sopenharmony_ci return err; 106962306a36Sopenharmony_ci} 107062306a36Sopenharmony_ci 107162306a36Sopenharmony_ci/** 107262306a36Sopenharmony_ci * ubi_detach_mtd_dev - detach an MTD device. 107362306a36Sopenharmony_ci * @ubi_num: UBI device number to detach from 107462306a36Sopenharmony_ci * @anyway: detach MTD even if device reference count is not zero 107562306a36Sopenharmony_ci * 107662306a36Sopenharmony_ci * This function destroys an UBI device number @ubi_num and detaches the 107762306a36Sopenharmony_ci * underlying MTD device. Returns zero in case of success and %-EBUSY if the 107862306a36Sopenharmony_ci * UBI device is busy and cannot be destroyed, and %-EINVAL if it does not 107962306a36Sopenharmony_ci * exist. 108062306a36Sopenharmony_ci * 108162306a36Sopenharmony_ci * Note, the invocations of this function has to be serialized by the 108262306a36Sopenharmony_ci * @ubi_devices_mutex. 108362306a36Sopenharmony_ci */ 108462306a36Sopenharmony_ciint ubi_detach_mtd_dev(int ubi_num, int anyway) 108562306a36Sopenharmony_ci{ 108662306a36Sopenharmony_ci struct ubi_device *ubi; 108762306a36Sopenharmony_ci 108862306a36Sopenharmony_ci if (ubi_num < 0 || ubi_num >= UBI_MAX_DEVICES) 108962306a36Sopenharmony_ci return -EINVAL; 109062306a36Sopenharmony_ci 109162306a36Sopenharmony_ci ubi = ubi_get_device(ubi_num); 109262306a36Sopenharmony_ci if (!ubi) 109362306a36Sopenharmony_ci return -EINVAL; 109462306a36Sopenharmony_ci 109562306a36Sopenharmony_ci spin_lock(&ubi_devices_lock); 109662306a36Sopenharmony_ci put_device(&ubi->dev); 109762306a36Sopenharmony_ci ubi->ref_count -= 1; 109862306a36Sopenharmony_ci if (ubi->ref_count) { 109962306a36Sopenharmony_ci if (!anyway) { 110062306a36Sopenharmony_ci spin_unlock(&ubi_devices_lock); 110162306a36Sopenharmony_ci return -EBUSY; 110262306a36Sopenharmony_ci } 110362306a36Sopenharmony_ci /* This may only happen if there is a bug */ 110462306a36Sopenharmony_ci ubi_err(ubi, "%s reference count %d, destroy anyway", 110562306a36Sopenharmony_ci ubi->ubi_name, ubi->ref_count); 110662306a36Sopenharmony_ci } 110762306a36Sopenharmony_ci ubi_devices[ubi_num] = NULL; 110862306a36Sopenharmony_ci spin_unlock(&ubi_devices_lock); 110962306a36Sopenharmony_ci 111062306a36Sopenharmony_ci ubi_assert(ubi_num == ubi->ubi_num); 111162306a36Sopenharmony_ci ubi_notify_all(ubi, UBI_VOLUME_REMOVED, NULL); 111262306a36Sopenharmony_ci ubi_msg(ubi, "detaching mtd%d", ubi->mtd->index); 111362306a36Sopenharmony_ci#ifdef CONFIG_MTD_UBI_FASTMAP 111462306a36Sopenharmony_ci /* If we don't write a new fastmap at detach time we lose all 111562306a36Sopenharmony_ci * EC updates that have been made since the last written fastmap. 111662306a36Sopenharmony_ci * In case of fastmap debugging we omit the update to simulate an 111762306a36Sopenharmony_ci * unclean shutdown. */ 111862306a36Sopenharmony_ci if (!ubi_dbg_chk_fastmap(ubi)) 111962306a36Sopenharmony_ci ubi_update_fastmap(ubi); 112062306a36Sopenharmony_ci#endif 112162306a36Sopenharmony_ci /* 112262306a36Sopenharmony_ci * Before freeing anything, we have to stop the background thread to 112362306a36Sopenharmony_ci * prevent it from doing anything on this device while we are freeing. 112462306a36Sopenharmony_ci */ 112562306a36Sopenharmony_ci if (ubi->bgt_thread) 112662306a36Sopenharmony_ci kthread_stop(ubi->bgt_thread); 112762306a36Sopenharmony_ci 112862306a36Sopenharmony_ci#ifdef CONFIG_MTD_UBI_FASTMAP 112962306a36Sopenharmony_ci cancel_work_sync(&ubi->fm_work); 113062306a36Sopenharmony_ci#endif 113162306a36Sopenharmony_ci ubi_debugfs_exit_dev(ubi); 113262306a36Sopenharmony_ci uif_close(ubi); 113362306a36Sopenharmony_ci 113462306a36Sopenharmony_ci ubi_wl_close(ubi); 113562306a36Sopenharmony_ci ubi_free_internal_volumes(ubi); 113662306a36Sopenharmony_ci vfree(ubi->vtbl); 113762306a36Sopenharmony_ci vfree(ubi->peb_buf); 113862306a36Sopenharmony_ci vfree(ubi->fm_buf); 113962306a36Sopenharmony_ci ubi_msg(ubi, "mtd%d is detached", ubi->mtd->index); 114062306a36Sopenharmony_ci put_mtd_device(ubi->mtd); 114162306a36Sopenharmony_ci put_device(&ubi->dev); 114262306a36Sopenharmony_ci return 0; 114362306a36Sopenharmony_ci} 114462306a36Sopenharmony_ci 114562306a36Sopenharmony_ci/** 114662306a36Sopenharmony_ci * open_mtd_by_chdev - open an MTD device by its character device node path. 114762306a36Sopenharmony_ci * @mtd_dev: MTD character device node path 114862306a36Sopenharmony_ci * 114962306a36Sopenharmony_ci * This helper function opens an MTD device by its character node device path. 115062306a36Sopenharmony_ci * Returns MTD device description object in case of success and a negative 115162306a36Sopenharmony_ci * error code in case of failure. 115262306a36Sopenharmony_ci */ 115362306a36Sopenharmony_cistatic struct mtd_info * __init open_mtd_by_chdev(const char *mtd_dev) 115462306a36Sopenharmony_ci{ 115562306a36Sopenharmony_ci int err, minor; 115662306a36Sopenharmony_ci struct path path; 115762306a36Sopenharmony_ci struct kstat stat; 115862306a36Sopenharmony_ci 115962306a36Sopenharmony_ci /* Probably this is an MTD character device node path */ 116062306a36Sopenharmony_ci err = kern_path(mtd_dev, LOOKUP_FOLLOW, &path); 116162306a36Sopenharmony_ci if (err) 116262306a36Sopenharmony_ci return ERR_PTR(err); 116362306a36Sopenharmony_ci 116462306a36Sopenharmony_ci err = vfs_getattr(&path, &stat, STATX_TYPE, AT_STATX_SYNC_AS_STAT); 116562306a36Sopenharmony_ci path_put(&path); 116662306a36Sopenharmony_ci if (err) 116762306a36Sopenharmony_ci return ERR_PTR(err); 116862306a36Sopenharmony_ci 116962306a36Sopenharmony_ci /* MTD device number is defined by the major / minor numbers */ 117062306a36Sopenharmony_ci if (MAJOR(stat.rdev) != MTD_CHAR_MAJOR || !S_ISCHR(stat.mode)) 117162306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 117262306a36Sopenharmony_ci 117362306a36Sopenharmony_ci minor = MINOR(stat.rdev); 117462306a36Sopenharmony_ci 117562306a36Sopenharmony_ci if (minor & 1) 117662306a36Sopenharmony_ci /* 117762306a36Sopenharmony_ci * Just do not think the "/dev/mtdrX" devices support is need, 117862306a36Sopenharmony_ci * so do not support them to avoid doing extra work. 117962306a36Sopenharmony_ci */ 118062306a36Sopenharmony_ci return ERR_PTR(-EINVAL); 118162306a36Sopenharmony_ci 118262306a36Sopenharmony_ci return get_mtd_device(NULL, minor / 2); 118362306a36Sopenharmony_ci} 118462306a36Sopenharmony_ci 118562306a36Sopenharmony_ci/** 118662306a36Sopenharmony_ci * open_mtd_device - open MTD device by name, character device path, or number. 118762306a36Sopenharmony_ci * @mtd_dev: name, character device node path, or MTD device device number 118862306a36Sopenharmony_ci * 118962306a36Sopenharmony_ci * This function tries to open and MTD device described by @mtd_dev string, 119062306a36Sopenharmony_ci * which is first treated as ASCII MTD device number, and if it is not true, it 119162306a36Sopenharmony_ci * is treated as MTD device name, and if that is also not true, it is treated 119262306a36Sopenharmony_ci * as MTD character device node path. Returns MTD device description object in 119362306a36Sopenharmony_ci * case of success and a negative error code in case of failure. 119462306a36Sopenharmony_ci */ 119562306a36Sopenharmony_cistatic struct mtd_info * __init open_mtd_device(const char *mtd_dev) 119662306a36Sopenharmony_ci{ 119762306a36Sopenharmony_ci struct mtd_info *mtd; 119862306a36Sopenharmony_ci int mtd_num; 119962306a36Sopenharmony_ci char *endp; 120062306a36Sopenharmony_ci 120162306a36Sopenharmony_ci mtd_num = simple_strtoul(mtd_dev, &endp, 0); 120262306a36Sopenharmony_ci if (*endp != '\0' || mtd_dev == endp) { 120362306a36Sopenharmony_ci /* 120462306a36Sopenharmony_ci * This does not look like an ASCII integer, probably this is 120562306a36Sopenharmony_ci * MTD device name. 120662306a36Sopenharmony_ci */ 120762306a36Sopenharmony_ci mtd = get_mtd_device_nm(mtd_dev); 120862306a36Sopenharmony_ci if (PTR_ERR(mtd) == -ENODEV) 120962306a36Sopenharmony_ci /* Probably this is an MTD character device node path */ 121062306a36Sopenharmony_ci mtd = open_mtd_by_chdev(mtd_dev); 121162306a36Sopenharmony_ci } else 121262306a36Sopenharmony_ci mtd = get_mtd_device(NULL, mtd_num); 121362306a36Sopenharmony_ci 121462306a36Sopenharmony_ci return mtd; 121562306a36Sopenharmony_ci} 121662306a36Sopenharmony_ci 121762306a36Sopenharmony_cistatic int __init ubi_init(void) 121862306a36Sopenharmony_ci{ 121962306a36Sopenharmony_ci int err, i, k; 122062306a36Sopenharmony_ci 122162306a36Sopenharmony_ci /* Ensure that EC and VID headers have correct size */ 122262306a36Sopenharmony_ci BUILD_BUG_ON(sizeof(struct ubi_ec_hdr) != 64); 122362306a36Sopenharmony_ci BUILD_BUG_ON(sizeof(struct ubi_vid_hdr) != 64); 122462306a36Sopenharmony_ci 122562306a36Sopenharmony_ci if (mtd_devs > UBI_MAX_DEVICES) { 122662306a36Sopenharmony_ci pr_err("UBI error: too many MTD devices, maximum is %d\n", 122762306a36Sopenharmony_ci UBI_MAX_DEVICES); 122862306a36Sopenharmony_ci return -EINVAL; 122962306a36Sopenharmony_ci } 123062306a36Sopenharmony_ci 123162306a36Sopenharmony_ci /* Create base sysfs directory and sysfs files */ 123262306a36Sopenharmony_ci err = class_register(&ubi_class); 123362306a36Sopenharmony_ci if (err < 0) 123462306a36Sopenharmony_ci return err; 123562306a36Sopenharmony_ci 123662306a36Sopenharmony_ci err = misc_register(&ubi_ctrl_cdev); 123762306a36Sopenharmony_ci if (err) { 123862306a36Sopenharmony_ci pr_err("UBI error: cannot register device\n"); 123962306a36Sopenharmony_ci goto out; 124062306a36Sopenharmony_ci } 124162306a36Sopenharmony_ci 124262306a36Sopenharmony_ci ubi_wl_entry_slab = kmem_cache_create("ubi_wl_entry_slab", 124362306a36Sopenharmony_ci sizeof(struct ubi_wl_entry), 124462306a36Sopenharmony_ci 0, 0, NULL); 124562306a36Sopenharmony_ci if (!ubi_wl_entry_slab) { 124662306a36Sopenharmony_ci err = -ENOMEM; 124762306a36Sopenharmony_ci goto out_dev_unreg; 124862306a36Sopenharmony_ci } 124962306a36Sopenharmony_ci 125062306a36Sopenharmony_ci err = ubi_debugfs_init(); 125162306a36Sopenharmony_ci if (err) 125262306a36Sopenharmony_ci goto out_slab; 125362306a36Sopenharmony_ci 125462306a36Sopenharmony_ci 125562306a36Sopenharmony_ci /* Attach MTD devices */ 125662306a36Sopenharmony_ci for (i = 0; i < mtd_devs; i++) { 125762306a36Sopenharmony_ci struct mtd_dev_param *p = &mtd_dev_param[i]; 125862306a36Sopenharmony_ci struct mtd_info *mtd; 125962306a36Sopenharmony_ci 126062306a36Sopenharmony_ci cond_resched(); 126162306a36Sopenharmony_ci 126262306a36Sopenharmony_ci mtd = open_mtd_device(p->name); 126362306a36Sopenharmony_ci if (IS_ERR(mtd)) { 126462306a36Sopenharmony_ci err = PTR_ERR(mtd); 126562306a36Sopenharmony_ci pr_err("UBI error: cannot open mtd %s, error %d\n", 126662306a36Sopenharmony_ci p->name, err); 126762306a36Sopenharmony_ci /* See comment below re-ubi_is_module(). */ 126862306a36Sopenharmony_ci if (ubi_is_module()) 126962306a36Sopenharmony_ci goto out_detach; 127062306a36Sopenharmony_ci continue; 127162306a36Sopenharmony_ci } 127262306a36Sopenharmony_ci 127362306a36Sopenharmony_ci mutex_lock(&ubi_devices_mutex); 127462306a36Sopenharmony_ci err = ubi_attach_mtd_dev(mtd, p->ubi_num, 127562306a36Sopenharmony_ci p->vid_hdr_offs, p->max_beb_per1024, 127662306a36Sopenharmony_ci p->enable_fm == 0); 127762306a36Sopenharmony_ci mutex_unlock(&ubi_devices_mutex); 127862306a36Sopenharmony_ci if (err < 0) { 127962306a36Sopenharmony_ci pr_err("UBI error: cannot attach mtd%d\n", 128062306a36Sopenharmony_ci mtd->index); 128162306a36Sopenharmony_ci put_mtd_device(mtd); 128262306a36Sopenharmony_ci 128362306a36Sopenharmony_ci /* 128462306a36Sopenharmony_ci * Originally UBI stopped initializing on any error. 128562306a36Sopenharmony_ci * However, later on it was found out that this 128662306a36Sopenharmony_ci * behavior is not very good when UBI is compiled into 128762306a36Sopenharmony_ci * the kernel and the MTD devices to attach are passed 128862306a36Sopenharmony_ci * through the command line. Indeed, UBI failure 128962306a36Sopenharmony_ci * stopped whole boot sequence. 129062306a36Sopenharmony_ci * 129162306a36Sopenharmony_ci * To fix this, we changed the behavior for the 129262306a36Sopenharmony_ci * non-module case, but preserved the old behavior for 129362306a36Sopenharmony_ci * the module case, just for compatibility. This is a 129462306a36Sopenharmony_ci * little inconsistent, though. 129562306a36Sopenharmony_ci */ 129662306a36Sopenharmony_ci if (ubi_is_module()) 129762306a36Sopenharmony_ci goto out_detach; 129862306a36Sopenharmony_ci } 129962306a36Sopenharmony_ci } 130062306a36Sopenharmony_ci 130162306a36Sopenharmony_ci err = ubiblock_init(); 130262306a36Sopenharmony_ci if (err) { 130362306a36Sopenharmony_ci pr_err("UBI error: block: cannot initialize, error %d\n", err); 130462306a36Sopenharmony_ci 130562306a36Sopenharmony_ci /* See comment above re-ubi_is_module(). */ 130662306a36Sopenharmony_ci if (ubi_is_module()) 130762306a36Sopenharmony_ci goto out_detach; 130862306a36Sopenharmony_ci } 130962306a36Sopenharmony_ci 131062306a36Sopenharmony_ci return 0; 131162306a36Sopenharmony_ci 131262306a36Sopenharmony_ciout_detach: 131362306a36Sopenharmony_ci for (k = 0; k < i; k++) 131462306a36Sopenharmony_ci if (ubi_devices[k]) { 131562306a36Sopenharmony_ci mutex_lock(&ubi_devices_mutex); 131662306a36Sopenharmony_ci ubi_detach_mtd_dev(ubi_devices[k]->ubi_num, 1); 131762306a36Sopenharmony_ci mutex_unlock(&ubi_devices_mutex); 131862306a36Sopenharmony_ci } 131962306a36Sopenharmony_ci ubi_debugfs_exit(); 132062306a36Sopenharmony_ciout_slab: 132162306a36Sopenharmony_ci kmem_cache_destroy(ubi_wl_entry_slab); 132262306a36Sopenharmony_ciout_dev_unreg: 132362306a36Sopenharmony_ci misc_deregister(&ubi_ctrl_cdev); 132462306a36Sopenharmony_ciout: 132562306a36Sopenharmony_ci class_unregister(&ubi_class); 132662306a36Sopenharmony_ci pr_err("UBI error: cannot initialize UBI, error %d\n", err); 132762306a36Sopenharmony_ci return err; 132862306a36Sopenharmony_ci} 132962306a36Sopenharmony_cilate_initcall(ubi_init); 133062306a36Sopenharmony_ci 133162306a36Sopenharmony_cistatic void __exit ubi_exit(void) 133262306a36Sopenharmony_ci{ 133362306a36Sopenharmony_ci int i; 133462306a36Sopenharmony_ci 133562306a36Sopenharmony_ci ubiblock_exit(); 133662306a36Sopenharmony_ci 133762306a36Sopenharmony_ci for (i = 0; i < UBI_MAX_DEVICES; i++) 133862306a36Sopenharmony_ci if (ubi_devices[i]) { 133962306a36Sopenharmony_ci mutex_lock(&ubi_devices_mutex); 134062306a36Sopenharmony_ci ubi_detach_mtd_dev(ubi_devices[i]->ubi_num, 1); 134162306a36Sopenharmony_ci mutex_unlock(&ubi_devices_mutex); 134262306a36Sopenharmony_ci } 134362306a36Sopenharmony_ci ubi_debugfs_exit(); 134462306a36Sopenharmony_ci kmem_cache_destroy(ubi_wl_entry_slab); 134562306a36Sopenharmony_ci misc_deregister(&ubi_ctrl_cdev); 134662306a36Sopenharmony_ci class_unregister(&ubi_class); 134762306a36Sopenharmony_ci} 134862306a36Sopenharmony_cimodule_exit(ubi_exit); 134962306a36Sopenharmony_ci 135062306a36Sopenharmony_ci/** 135162306a36Sopenharmony_ci * bytes_str_to_int - convert a number of bytes string into an integer. 135262306a36Sopenharmony_ci * @str: the string to convert 135362306a36Sopenharmony_ci * 135462306a36Sopenharmony_ci * This function returns positive resulting integer in case of success and a 135562306a36Sopenharmony_ci * negative error code in case of failure. 135662306a36Sopenharmony_ci */ 135762306a36Sopenharmony_cistatic int bytes_str_to_int(const char *str) 135862306a36Sopenharmony_ci{ 135962306a36Sopenharmony_ci char *endp; 136062306a36Sopenharmony_ci unsigned long result; 136162306a36Sopenharmony_ci 136262306a36Sopenharmony_ci result = simple_strtoul(str, &endp, 0); 136362306a36Sopenharmony_ci if (str == endp || result >= INT_MAX) { 136462306a36Sopenharmony_ci pr_err("UBI error: incorrect bytes count: \"%s\"\n", str); 136562306a36Sopenharmony_ci return -EINVAL; 136662306a36Sopenharmony_ci } 136762306a36Sopenharmony_ci 136862306a36Sopenharmony_ci switch (*endp) { 136962306a36Sopenharmony_ci case 'G': 137062306a36Sopenharmony_ci result *= 1024; 137162306a36Sopenharmony_ci fallthrough; 137262306a36Sopenharmony_ci case 'M': 137362306a36Sopenharmony_ci result *= 1024; 137462306a36Sopenharmony_ci fallthrough; 137562306a36Sopenharmony_ci case 'K': 137662306a36Sopenharmony_ci result *= 1024; 137762306a36Sopenharmony_ci break; 137862306a36Sopenharmony_ci case '\0': 137962306a36Sopenharmony_ci break; 138062306a36Sopenharmony_ci default: 138162306a36Sopenharmony_ci pr_err("UBI error: incorrect bytes count: \"%s\"\n", str); 138262306a36Sopenharmony_ci return -EINVAL; 138362306a36Sopenharmony_ci } 138462306a36Sopenharmony_ci 138562306a36Sopenharmony_ci return result; 138662306a36Sopenharmony_ci} 138762306a36Sopenharmony_ci 138862306a36Sopenharmony_ci/** 138962306a36Sopenharmony_ci * ubi_mtd_param_parse - parse the 'mtd=' UBI parameter. 139062306a36Sopenharmony_ci * @val: the parameter value to parse 139162306a36Sopenharmony_ci * @kp: not used 139262306a36Sopenharmony_ci * 139362306a36Sopenharmony_ci * This function returns zero in case of success and a negative error code in 139462306a36Sopenharmony_ci * case of error. 139562306a36Sopenharmony_ci */ 139662306a36Sopenharmony_cistatic int ubi_mtd_param_parse(const char *val, const struct kernel_param *kp) 139762306a36Sopenharmony_ci{ 139862306a36Sopenharmony_ci int i, len; 139962306a36Sopenharmony_ci struct mtd_dev_param *p; 140062306a36Sopenharmony_ci char buf[MTD_PARAM_LEN_MAX]; 140162306a36Sopenharmony_ci char *pbuf = &buf[0]; 140262306a36Sopenharmony_ci char *tokens[MTD_PARAM_MAX_COUNT], *token; 140362306a36Sopenharmony_ci 140462306a36Sopenharmony_ci if (!val) 140562306a36Sopenharmony_ci return -EINVAL; 140662306a36Sopenharmony_ci 140762306a36Sopenharmony_ci if (mtd_devs == UBI_MAX_DEVICES) { 140862306a36Sopenharmony_ci pr_err("UBI error: too many parameters, max. is %d\n", 140962306a36Sopenharmony_ci UBI_MAX_DEVICES); 141062306a36Sopenharmony_ci return -EINVAL; 141162306a36Sopenharmony_ci } 141262306a36Sopenharmony_ci 141362306a36Sopenharmony_ci len = strnlen(val, MTD_PARAM_LEN_MAX); 141462306a36Sopenharmony_ci if (len == MTD_PARAM_LEN_MAX) { 141562306a36Sopenharmony_ci pr_err("UBI error: parameter \"%s\" is too long, max. is %d\n", 141662306a36Sopenharmony_ci val, MTD_PARAM_LEN_MAX); 141762306a36Sopenharmony_ci return -EINVAL; 141862306a36Sopenharmony_ci } 141962306a36Sopenharmony_ci 142062306a36Sopenharmony_ci if (len == 0) { 142162306a36Sopenharmony_ci pr_warn("UBI warning: empty 'mtd=' parameter - ignored\n"); 142262306a36Sopenharmony_ci return 0; 142362306a36Sopenharmony_ci } 142462306a36Sopenharmony_ci 142562306a36Sopenharmony_ci strcpy(buf, val); 142662306a36Sopenharmony_ci 142762306a36Sopenharmony_ci /* Get rid of the final newline */ 142862306a36Sopenharmony_ci if (buf[len - 1] == '\n') 142962306a36Sopenharmony_ci buf[len - 1] = '\0'; 143062306a36Sopenharmony_ci 143162306a36Sopenharmony_ci for (i = 0; i < MTD_PARAM_MAX_COUNT; i++) 143262306a36Sopenharmony_ci tokens[i] = strsep(&pbuf, ","); 143362306a36Sopenharmony_ci 143462306a36Sopenharmony_ci if (pbuf) { 143562306a36Sopenharmony_ci pr_err("UBI error: too many arguments at \"%s\"\n", val); 143662306a36Sopenharmony_ci return -EINVAL; 143762306a36Sopenharmony_ci } 143862306a36Sopenharmony_ci 143962306a36Sopenharmony_ci p = &mtd_dev_param[mtd_devs]; 144062306a36Sopenharmony_ci strcpy(&p->name[0], tokens[0]); 144162306a36Sopenharmony_ci 144262306a36Sopenharmony_ci token = tokens[1]; 144362306a36Sopenharmony_ci if (token) { 144462306a36Sopenharmony_ci p->vid_hdr_offs = bytes_str_to_int(token); 144562306a36Sopenharmony_ci 144662306a36Sopenharmony_ci if (p->vid_hdr_offs < 0) 144762306a36Sopenharmony_ci return p->vid_hdr_offs; 144862306a36Sopenharmony_ci } 144962306a36Sopenharmony_ci 145062306a36Sopenharmony_ci token = tokens[2]; 145162306a36Sopenharmony_ci if (token) { 145262306a36Sopenharmony_ci int err = kstrtoint(token, 10, &p->max_beb_per1024); 145362306a36Sopenharmony_ci 145462306a36Sopenharmony_ci if (err) { 145562306a36Sopenharmony_ci pr_err("UBI error: bad value for max_beb_per1024 parameter: %s\n", 145662306a36Sopenharmony_ci token); 145762306a36Sopenharmony_ci return -EINVAL; 145862306a36Sopenharmony_ci } 145962306a36Sopenharmony_ci } 146062306a36Sopenharmony_ci 146162306a36Sopenharmony_ci token = tokens[3]; 146262306a36Sopenharmony_ci if (token) { 146362306a36Sopenharmony_ci int err = kstrtoint(token, 10, &p->ubi_num); 146462306a36Sopenharmony_ci 146562306a36Sopenharmony_ci if (err) { 146662306a36Sopenharmony_ci pr_err("UBI error: bad value for ubi_num parameter: %s\n", 146762306a36Sopenharmony_ci token); 146862306a36Sopenharmony_ci return -EINVAL; 146962306a36Sopenharmony_ci } 147062306a36Sopenharmony_ci } else 147162306a36Sopenharmony_ci p->ubi_num = UBI_DEV_NUM_AUTO; 147262306a36Sopenharmony_ci 147362306a36Sopenharmony_ci token = tokens[4]; 147462306a36Sopenharmony_ci if (token) { 147562306a36Sopenharmony_ci int err = kstrtoint(token, 10, &p->enable_fm); 147662306a36Sopenharmony_ci 147762306a36Sopenharmony_ci if (err) { 147862306a36Sopenharmony_ci pr_err("UBI error: bad value for enable_fm parameter: %s\n", 147962306a36Sopenharmony_ci token); 148062306a36Sopenharmony_ci return -EINVAL; 148162306a36Sopenharmony_ci } 148262306a36Sopenharmony_ci } else 148362306a36Sopenharmony_ci p->enable_fm = 0; 148462306a36Sopenharmony_ci 148562306a36Sopenharmony_ci mtd_devs += 1; 148662306a36Sopenharmony_ci return 0; 148762306a36Sopenharmony_ci} 148862306a36Sopenharmony_ci 148962306a36Sopenharmony_cimodule_param_call(mtd, ubi_mtd_param_parse, NULL, NULL, 0400); 149062306a36Sopenharmony_ciMODULE_PARM_DESC(mtd, "MTD devices to attach. Parameter format: mtd=<name|num|path>[,<vid_hdr_offs>[,max_beb_per1024[,ubi_num]]].\n" 149162306a36Sopenharmony_ci "Multiple \"mtd\" parameters may be specified.\n" 149262306a36Sopenharmony_ci "MTD devices may be specified by their number, name, or path to the MTD character device node.\n" 149362306a36Sopenharmony_ci "Optional \"vid_hdr_offs\" parameter specifies UBI VID header position to be used by UBI. (default value if 0)\n" 149462306a36Sopenharmony_ci "Optional \"max_beb_per1024\" parameter specifies the maximum expected bad eraseblock per 1024 eraseblocks. (default value (" 149562306a36Sopenharmony_ci __stringify(CONFIG_MTD_UBI_BEB_LIMIT) ") if 0)\n" 149662306a36Sopenharmony_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" 149762306a36Sopenharmony_ci "Optional \"enable_fm\" parameter determines whether to enable fastmap during attach. If the value is non-zero, fastmap is enabled. Default value is 0.\n" 149862306a36Sopenharmony_ci "\n" 149962306a36Sopenharmony_ci "Example 1: mtd=/dev/mtd0 - attach MTD device /dev/mtd0.\n" 150062306a36Sopenharmony_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" 150162306a36Sopenharmony_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" 150262306a36Sopenharmony_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" 150362306a36Sopenharmony_ci "example 5: mtd=1,0,0,5 mtd=2,0,0,6,1 - attach MTD device /dev/mtd1 to UBI 5 and disable fastmap; attach MTD device /dev/mtd2 to UBI 6 and enable fastmap.(only works when fastmap is enabled and fm_autoconvert=Y).\n" 150462306a36Sopenharmony_ci "\t(e.g. if the NAND *chipset* has 4096 PEB, 100 will be reserved for this UBI device)."); 150562306a36Sopenharmony_ci#ifdef CONFIG_MTD_UBI_FASTMAP 150662306a36Sopenharmony_cimodule_param(fm_autoconvert, bool, 0644); 150762306a36Sopenharmony_ciMODULE_PARM_DESC(fm_autoconvert, "Set this parameter to enable fastmap automatically on images without a fastmap."); 150862306a36Sopenharmony_cimodule_param(fm_debug, bool, 0); 150962306a36Sopenharmony_ciMODULE_PARM_DESC(fm_debug, "Set this parameter to enable fastmap debugging by default. Warning, this will make fastmap slow!"); 151062306a36Sopenharmony_ci#endif 151162306a36Sopenharmony_ciMODULE_VERSION(__stringify(UBI_VERSION)); 151262306a36Sopenharmony_ciMODULE_DESCRIPTION("UBI - Unsorted Block Images"); 151362306a36Sopenharmony_ciMODULE_AUTHOR("Artem Bityutskiy"); 151462306a36Sopenharmony_ciMODULE_LICENSE("GPL"); 1515