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