19d54c8a3SEzequiel Garcia /* 29d54c8a3SEzequiel Garcia * Copyright (c) 2014 Ezequiel Garcia 39d54c8a3SEzequiel Garcia * Copyright (c) 2011 Free Electrons 49d54c8a3SEzequiel Garcia * 59d54c8a3SEzequiel Garcia * Driver parameter handling strongly based on drivers/mtd/ubi/build.c 69d54c8a3SEzequiel Garcia * Copyright (c) International Business Machines Corp., 2006 79d54c8a3SEzequiel Garcia * Copyright (c) Nokia Corporation, 2007 89d54c8a3SEzequiel Garcia * Authors: Artem Bityutskiy, Frank Haverkamp 99d54c8a3SEzequiel Garcia * 109d54c8a3SEzequiel Garcia * This program is free software; you can redistribute it and/or modify 119d54c8a3SEzequiel Garcia * it under the terms of the GNU General Public License as published by 129d54c8a3SEzequiel Garcia * the Free Software Foundation, version 2. 139d54c8a3SEzequiel Garcia * 149d54c8a3SEzequiel Garcia * This program is distributed in the hope that it will be useful, 159d54c8a3SEzequiel Garcia * but WITHOUT ANY WARRANTY; without even the implied warranty of 169d54c8a3SEzequiel Garcia * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See 179d54c8a3SEzequiel Garcia * the GNU General Public License for more details. 189d54c8a3SEzequiel Garcia */ 199d54c8a3SEzequiel Garcia 209d54c8a3SEzequiel Garcia /* 219d54c8a3SEzequiel Garcia * Read-only block devices on top of UBI volumes 229d54c8a3SEzequiel Garcia * 239d54c8a3SEzequiel Garcia * A simple implementation to allow a block device to be layered on top of a 249d54c8a3SEzequiel Garcia * UBI volume. The implementation is provided by creating a static 1-to-1 259d54c8a3SEzequiel Garcia * mapping between the block device and the UBI volume. 269d54c8a3SEzequiel Garcia * 279d54c8a3SEzequiel Garcia * The addressed byte is obtained from the addressed block sector, which is 289d54c8a3SEzequiel Garcia * mapped linearly into the corresponding LEB: 299d54c8a3SEzequiel Garcia * 309d54c8a3SEzequiel Garcia * LEB number = addressed byte / LEB size 319d54c8a3SEzequiel Garcia * 324d283ee2SArtem Bityutskiy * This feature is compiled in the UBI core, and adds a 'block' parameter 334d283ee2SArtem Bityutskiy * to allow early creation of block devices on top of UBI volumes. Runtime 344d283ee2SArtem Bityutskiy * block creation/removal for UBI volumes is provided through two UBI ioctls: 358af87188SArtem Bityutskiy * UBI_IOCVOLCRBLK and UBI_IOCVOLRMBLK. 369d54c8a3SEzequiel Garcia */ 379d54c8a3SEzequiel Garcia 389d54c8a3SEzequiel Garcia #include <linux/module.h> 399d54c8a3SEzequiel Garcia #include <linux/init.h> 409d54c8a3SEzequiel Garcia #include <linux/err.h> 419d54c8a3SEzequiel Garcia #include <linux/kernel.h> 429d54c8a3SEzequiel Garcia #include <linux/list.h> 439d54c8a3SEzequiel Garcia #include <linux/mutex.h> 449d54c8a3SEzequiel Garcia #include <linux/slab.h> 459d54c8a3SEzequiel Garcia #include <linux/mtd/ubi.h> 469d54c8a3SEzequiel Garcia #include <linux/workqueue.h> 479d54c8a3SEzequiel Garcia #include <linux/blkdev.h> 48ff1f48eeSRichard Weinberger #include <linux/blk-mq.h> 499d54c8a3SEzequiel Garcia #include <linux/hdreg.h> 50ff1f48eeSRichard Weinberger #include <linux/scatterlist.h> 512bf50d42SDan Ehrenberg #include <linux/idr.h> 529d54c8a3SEzequiel Garcia #include <asm/div64.h> 539d54c8a3SEzequiel Garcia 549d54c8a3SEzequiel Garcia #include "ubi-media.h" 559d54c8a3SEzequiel Garcia #include "ubi.h" 569d54c8a3SEzequiel Garcia 579d54c8a3SEzequiel Garcia /* Maximum number of supported devices */ 589d54c8a3SEzequiel Garcia #define UBIBLOCK_MAX_DEVICES 32 599d54c8a3SEzequiel Garcia 609d54c8a3SEzequiel Garcia /* Maximum length of the 'block=' parameter */ 619d54c8a3SEzequiel Garcia #define UBIBLOCK_PARAM_LEN 63 629d54c8a3SEzequiel Garcia 639d54c8a3SEzequiel Garcia /* Maximum number of comma-separated items in the 'block=' parameter */ 649d54c8a3SEzequiel Garcia #define UBIBLOCK_PARAM_COUNT 2 659d54c8a3SEzequiel Garcia 669d54c8a3SEzequiel Garcia struct ubiblock_param { 679d54c8a3SEzequiel Garcia int ubi_num; 689d54c8a3SEzequiel Garcia int vol_id; 699d54c8a3SEzequiel Garcia char name[UBIBLOCK_PARAM_LEN+1]; 709d54c8a3SEzequiel Garcia }; 719d54c8a3SEzequiel Garcia 72ff1f48eeSRichard Weinberger struct ubiblock_pdu { 73ff1f48eeSRichard Weinberger struct work_struct work; 74ff1f48eeSRichard Weinberger struct ubi_sgl usgl; 75ff1f48eeSRichard Weinberger }; 76ff1f48eeSRichard Weinberger 779d54c8a3SEzequiel Garcia /* Numbers of elements set in the @ubiblock_param array */ 789d54c8a3SEzequiel Garcia static int ubiblock_devs __initdata; 799d54c8a3SEzequiel Garcia 809d54c8a3SEzequiel Garcia /* MTD devices specification parameters */ 819d54c8a3SEzequiel Garcia static struct ubiblock_param ubiblock_param[UBIBLOCK_MAX_DEVICES] __initdata; 829d54c8a3SEzequiel Garcia 839d54c8a3SEzequiel Garcia struct ubiblock { 849d54c8a3SEzequiel Garcia struct ubi_volume_desc *desc; 859d54c8a3SEzequiel Garcia int ubi_num; 869d54c8a3SEzequiel Garcia int vol_id; 879d54c8a3SEzequiel Garcia int refcnt; 889d54c8a3SEzequiel Garcia int leb_size; 899d54c8a3SEzequiel Garcia 909d54c8a3SEzequiel Garcia struct gendisk *gd; 919d54c8a3SEzequiel Garcia struct request_queue *rq; 929d54c8a3SEzequiel Garcia 939d54c8a3SEzequiel Garcia struct workqueue_struct *wq; 949d54c8a3SEzequiel Garcia 959d54c8a3SEzequiel Garcia struct mutex dev_mutex; 969d54c8a3SEzequiel Garcia struct list_head list; 97ff1f48eeSRichard Weinberger struct blk_mq_tag_set tag_set; 989d54c8a3SEzequiel Garcia }; 999d54c8a3SEzequiel Garcia 1009d54c8a3SEzequiel Garcia /* Linked list of all ubiblock instances */ 1019d54c8a3SEzequiel Garcia static LIST_HEAD(ubiblock_devices); 1029d54c8a3SEzequiel Garcia static DEFINE_MUTEX(devices_mutex); 1039d54c8a3SEzequiel Garcia static int ubiblock_major; 1049d54c8a3SEzequiel Garcia 1059d54c8a3SEzequiel Garcia static int __init ubiblock_set_param(const char *val, 1069d54c8a3SEzequiel Garcia const struct kernel_param *kp) 1079d54c8a3SEzequiel Garcia { 1089d54c8a3SEzequiel Garcia int i, ret; 1099d54c8a3SEzequiel Garcia size_t len; 1109d54c8a3SEzequiel Garcia struct ubiblock_param *param; 1119d54c8a3SEzequiel Garcia char buf[UBIBLOCK_PARAM_LEN]; 1129d54c8a3SEzequiel Garcia char *pbuf = &buf[0]; 1139d54c8a3SEzequiel Garcia char *tokens[UBIBLOCK_PARAM_COUNT]; 1149d54c8a3SEzequiel Garcia 1159d54c8a3SEzequiel Garcia if (!val) 1169d54c8a3SEzequiel Garcia return -EINVAL; 1179d54c8a3SEzequiel Garcia 1189d54c8a3SEzequiel Garcia len = strnlen(val, UBIBLOCK_PARAM_LEN); 1199d54c8a3SEzequiel Garcia if (len == 0) { 12032608703STanya Brokhman pr_warn("UBI: block: empty 'block=' parameter - ignored\n"); 1219d54c8a3SEzequiel Garcia return 0; 1229d54c8a3SEzequiel Garcia } 1239d54c8a3SEzequiel Garcia 1249d54c8a3SEzequiel Garcia if (len == UBIBLOCK_PARAM_LEN) { 12532608703STanya Brokhman pr_err("UBI: block: parameter \"%s\" is too long, max. is %d\n", 1269d54c8a3SEzequiel Garcia val, UBIBLOCK_PARAM_LEN); 1279d54c8a3SEzequiel Garcia return -EINVAL; 1289d54c8a3SEzequiel Garcia } 1299d54c8a3SEzequiel Garcia 1309d54c8a3SEzequiel Garcia strcpy(buf, val); 1319d54c8a3SEzequiel Garcia 1329d54c8a3SEzequiel Garcia /* Get rid of the final newline */ 1339d54c8a3SEzequiel Garcia if (buf[len - 1] == '\n') 1349d54c8a3SEzequiel Garcia buf[len - 1] = '\0'; 1359d54c8a3SEzequiel Garcia 1369d54c8a3SEzequiel Garcia for (i = 0; i < UBIBLOCK_PARAM_COUNT; i++) 1379d54c8a3SEzequiel Garcia tokens[i] = strsep(&pbuf, ","); 1389d54c8a3SEzequiel Garcia 1399d54c8a3SEzequiel Garcia param = &ubiblock_param[ubiblock_devs]; 1409d54c8a3SEzequiel Garcia if (tokens[1]) { 1419d54c8a3SEzequiel Garcia /* Two parameters: can be 'ubi, vol_id' or 'ubi, vol_name' */ 1429d54c8a3SEzequiel Garcia ret = kstrtoint(tokens[0], 10, ¶m->ubi_num); 1439d54c8a3SEzequiel Garcia if (ret < 0) 1449d54c8a3SEzequiel Garcia return -EINVAL; 1459d54c8a3SEzequiel Garcia 1469d54c8a3SEzequiel Garcia /* Second param can be a number or a name */ 1479d54c8a3SEzequiel Garcia ret = kstrtoint(tokens[1], 10, ¶m->vol_id); 1489d54c8a3SEzequiel Garcia if (ret < 0) { 1499d54c8a3SEzequiel Garcia param->vol_id = -1; 1509d54c8a3SEzequiel Garcia strcpy(param->name, tokens[1]); 1519d54c8a3SEzequiel Garcia } 1529d54c8a3SEzequiel Garcia 1539d54c8a3SEzequiel Garcia } else { 1549d54c8a3SEzequiel Garcia /* One parameter: must be device path */ 1559d54c8a3SEzequiel Garcia strcpy(param->name, tokens[0]); 1569d54c8a3SEzequiel Garcia param->ubi_num = -1; 1579d54c8a3SEzequiel Garcia param->vol_id = -1; 1589d54c8a3SEzequiel Garcia } 1599d54c8a3SEzequiel Garcia 1609d54c8a3SEzequiel Garcia ubiblock_devs++; 1619d54c8a3SEzequiel Garcia 1629d54c8a3SEzequiel Garcia return 0; 1639d54c8a3SEzequiel Garcia } 1649d54c8a3SEzequiel Garcia 1659c27847dSLuis R. Rodriguez static const struct kernel_param_ops ubiblock_param_ops = { 1669d54c8a3SEzequiel Garcia .set = ubiblock_set_param, 1679d54c8a3SEzequiel Garcia }; 1689d54c8a3SEzequiel Garcia module_param_cb(block, &ubiblock_param_ops, NULL, 0); 1699d54c8a3SEzequiel Garcia MODULE_PARM_DESC(block, "Attach block devices to UBI volumes. Parameter format: block=<path|dev,num|dev,name>.\n" 1709d54c8a3SEzequiel Garcia "Multiple \"block\" parameters may be specified.\n" 1719d54c8a3SEzequiel Garcia "UBI volumes may be specified by their number, name, or path to the device node.\n" 1729d54c8a3SEzequiel Garcia "Examples\n" 1739d54c8a3SEzequiel Garcia "Using the UBI volume path:\n" 1749d54c8a3SEzequiel Garcia "ubi.block=/dev/ubi0_0\n" 1759d54c8a3SEzequiel Garcia "Using the UBI device, and the volume name:\n" 1769d54c8a3SEzequiel Garcia "ubi.block=0,rootfs\n" 1779d54c8a3SEzequiel Garcia "Using both UBI device number and UBI volume number:\n" 1789d54c8a3SEzequiel Garcia "ubi.block=0,0\n"); 1799d54c8a3SEzequiel Garcia 1809d54c8a3SEzequiel Garcia static struct ubiblock *find_dev_nolock(int ubi_num, int vol_id) 1819d54c8a3SEzequiel Garcia { 1829d54c8a3SEzequiel Garcia struct ubiblock *dev; 1839d54c8a3SEzequiel Garcia 1849d54c8a3SEzequiel Garcia list_for_each_entry(dev, &ubiblock_devices, list) 1859d54c8a3SEzequiel Garcia if (dev->ubi_num == ubi_num && dev->vol_id == vol_id) 1869d54c8a3SEzequiel Garcia return dev; 1879d54c8a3SEzequiel Garcia return NULL; 1889d54c8a3SEzequiel Garcia } 1899d54c8a3SEzequiel Garcia 190ff1f48eeSRichard Weinberger static int ubiblock_read(struct ubiblock_pdu *pdu) 1919d54c8a3SEzequiel Garcia { 192ff1f48eeSRichard Weinberger int ret, leb, offset, bytes_left, to_read; 193ff1f48eeSRichard Weinberger u64 pos; 194ff1f48eeSRichard Weinberger struct request *req = blk_mq_rq_from_pdu(pdu); 195ff1f48eeSRichard Weinberger struct ubiblock *dev = req->q->queuedata; 1969d54c8a3SEzequiel Garcia 197ff1f48eeSRichard Weinberger to_read = blk_rq_bytes(req); 198ff1f48eeSRichard Weinberger pos = blk_rq_pos(req) << 9; 1999d54c8a3SEzequiel Garcia 2009d54c8a3SEzequiel Garcia /* Get LEB:offset address to read from */ 2019d54c8a3SEzequiel Garcia offset = do_div(pos, dev->leb_size); 2029d54c8a3SEzequiel Garcia leb = pos; 203ff1f48eeSRichard Weinberger bytes_left = to_read; 2049d54c8a3SEzequiel Garcia 2059d54c8a3SEzequiel Garcia while (bytes_left) { 2069d54c8a3SEzequiel Garcia /* 2079d54c8a3SEzequiel Garcia * We can only read one LEB at a time. Therefore if the read 2089d54c8a3SEzequiel Garcia * length is larger than one LEB size, we split the operation. 2099d54c8a3SEzequiel Garcia */ 2109d54c8a3SEzequiel Garcia if (offset + to_read > dev->leb_size) 2119d54c8a3SEzequiel Garcia to_read = dev->leb_size - offset; 2129d54c8a3SEzequiel Garcia 213ff1f48eeSRichard Weinberger ret = ubi_read_sg(dev->desc, leb, &pdu->usgl, offset, to_read); 214ff1f48eeSRichard Weinberger if (ret < 0) 2159d54c8a3SEzequiel Garcia return ret; 2169d54c8a3SEzequiel Garcia 2179d54c8a3SEzequiel Garcia bytes_left -= to_read; 2189d54c8a3SEzequiel Garcia to_read = bytes_left; 2199d54c8a3SEzequiel Garcia leb += 1; 2209d54c8a3SEzequiel Garcia offset = 0; 2219d54c8a3SEzequiel Garcia } 2229d54c8a3SEzequiel Garcia return 0; 2239d54c8a3SEzequiel Garcia } 2249d54c8a3SEzequiel Garcia 2259d54c8a3SEzequiel Garcia static int ubiblock_open(struct block_device *bdev, fmode_t mode) 2269d54c8a3SEzequiel Garcia { 2279d54c8a3SEzequiel Garcia struct ubiblock *dev = bdev->bd_disk->private_data; 2289d54c8a3SEzequiel Garcia int ret; 2299d54c8a3SEzequiel Garcia 2309d54c8a3SEzequiel Garcia mutex_lock(&dev->dev_mutex); 2319d54c8a3SEzequiel Garcia if (dev->refcnt > 0) { 2329d54c8a3SEzequiel Garcia /* 2339d54c8a3SEzequiel Garcia * The volume is already open, just increase the reference 2349d54c8a3SEzequiel Garcia * counter. 2359d54c8a3SEzequiel Garcia */ 2369d54c8a3SEzequiel Garcia goto out_done; 2379d54c8a3SEzequiel Garcia } 2389d54c8a3SEzequiel Garcia 2399d54c8a3SEzequiel Garcia /* 2409d54c8a3SEzequiel Garcia * We want users to be aware they should only mount us as read-only. 2419d54c8a3SEzequiel Garcia * It's just a paranoid check, as write requests will get rejected 2429d54c8a3SEzequiel Garcia * in any case. 2439d54c8a3SEzequiel Garcia */ 2449d54c8a3SEzequiel Garcia if (mode & FMODE_WRITE) { 2459d54c8a3SEzequiel Garcia ret = -EPERM; 2469d54c8a3SEzequiel Garcia goto out_unlock; 2479d54c8a3SEzequiel Garcia } 2489d54c8a3SEzequiel Garcia 2499d54c8a3SEzequiel Garcia dev->desc = ubi_open_volume(dev->ubi_num, dev->vol_id, UBI_READONLY); 2509d54c8a3SEzequiel Garcia if (IS_ERR(dev->desc)) { 25132608703STanya Brokhman dev_err(disk_to_dev(dev->gd), "failed to open ubi volume %d_%d", 25232608703STanya Brokhman dev->ubi_num, dev->vol_id); 2539d54c8a3SEzequiel Garcia ret = PTR_ERR(dev->desc); 2549d54c8a3SEzequiel Garcia dev->desc = NULL; 2559d54c8a3SEzequiel Garcia goto out_unlock; 2569d54c8a3SEzequiel Garcia } 2579d54c8a3SEzequiel Garcia 2589d54c8a3SEzequiel Garcia out_done: 2599d54c8a3SEzequiel Garcia dev->refcnt++; 2609d54c8a3SEzequiel Garcia mutex_unlock(&dev->dev_mutex); 2619d54c8a3SEzequiel Garcia return 0; 2629d54c8a3SEzequiel Garcia 2639d54c8a3SEzequiel Garcia out_unlock: 2649d54c8a3SEzequiel Garcia mutex_unlock(&dev->dev_mutex); 2659d54c8a3SEzequiel Garcia return ret; 2669d54c8a3SEzequiel Garcia } 2679d54c8a3SEzequiel Garcia 2689d54c8a3SEzequiel Garcia static void ubiblock_release(struct gendisk *gd, fmode_t mode) 2699d54c8a3SEzequiel Garcia { 2709d54c8a3SEzequiel Garcia struct ubiblock *dev = gd->private_data; 2719d54c8a3SEzequiel Garcia 2729d54c8a3SEzequiel Garcia mutex_lock(&dev->dev_mutex); 2739d54c8a3SEzequiel Garcia dev->refcnt--; 2749d54c8a3SEzequiel Garcia if (dev->refcnt == 0) { 2759d54c8a3SEzequiel Garcia ubi_close_volume(dev->desc); 2769d54c8a3SEzequiel Garcia dev->desc = NULL; 2779d54c8a3SEzequiel Garcia } 2789d54c8a3SEzequiel Garcia mutex_unlock(&dev->dev_mutex); 2799d54c8a3SEzequiel Garcia } 2809d54c8a3SEzequiel Garcia 2819d54c8a3SEzequiel Garcia static int ubiblock_getgeo(struct block_device *bdev, struct hd_geometry *geo) 2829d54c8a3SEzequiel Garcia { 2839d54c8a3SEzequiel Garcia /* Some tools might require this information */ 2849d54c8a3SEzequiel Garcia geo->heads = 1; 2859d54c8a3SEzequiel Garcia geo->cylinders = 1; 2869d54c8a3SEzequiel Garcia geo->sectors = get_capacity(bdev->bd_disk); 2879d54c8a3SEzequiel Garcia geo->start = 0; 2889d54c8a3SEzequiel Garcia return 0; 2899d54c8a3SEzequiel Garcia } 2909d54c8a3SEzequiel Garcia 2919d54c8a3SEzequiel Garcia static const struct block_device_operations ubiblock_ops = { 2929d54c8a3SEzequiel Garcia .owner = THIS_MODULE, 2939d54c8a3SEzequiel Garcia .open = ubiblock_open, 2949d54c8a3SEzequiel Garcia .release = ubiblock_release, 2959d54c8a3SEzequiel Garcia .getgeo = ubiblock_getgeo, 2969d54c8a3SEzequiel Garcia }; 2979d54c8a3SEzequiel Garcia 298ff1f48eeSRichard Weinberger static void ubiblock_do_work(struct work_struct *work) 299ff1f48eeSRichard Weinberger { 300ff1f48eeSRichard Weinberger int ret; 301ff1f48eeSRichard Weinberger struct ubiblock_pdu *pdu = container_of(work, struct ubiblock_pdu, work); 302ff1f48eeSRichard Weinberger struct request *req = blk_mq_rq_from_pdu(pdu); 303ff1f48eeSRichard Weinberger 304ff1f48eeSRichard Weinberger blk_mq_start_request(req); 305832b52a1SRichard Weinberger 306832b52a1SRichard Weinberger /* 307832b52a1SRichard Weinberger * It is safe to ignore the return value of blk_rq_map_sg() because 308832b52a1SRichard Weinberger * the number of sg entries is limited to UBI_MAX_SG_COUNT 309832b52a1SRichard Weinberger * and ubi_read_sg() will check that limit. 310832b52a1SRichard Weinberger */ 311ff1f48eeSRichard Weinberger blk_rq_map_sg(req->q, req, pdu->usgl.sg); 312ff1f48eeSRichard Weinberger 313ff1f48eeSRichard Weinberger ret = ubiblock_read(pdu); 31498fb1ffdSKevin Cernekee rq_flush_dcache_pages(req); 31598fb1ffdSKevin Cernekee 316ff1f48eeSRichard Weinberger blk_mq_end_request(req, ret); 317ff1f48eeSRichard Weinberger } 318ff1f48eeSRichard Weinberger 319ff1f48eeSRichard Weinberger static int ubiblock_queue_rq(struct blk_mq_hw_ctx *hctx, 320ff1f48eeSRichard Weinberger const struct blk_mq_queue_data *bd) 321ff1f48eeSRichard Weinberger { 322ff1f48eeSRichard Weinberger struct request *req = bd->rq; 323ff1f48eeSRichard Weinberger struct ubiblock *dev = hctx->queue->queuedata; 324ff1f48eeSRichard Weinberger struct ubiblock_pdu *pdu = blk_mq_rq_to_pdu(req); 325ff1f48eeSRichard Weinberger 326*aebf526bSChristoph Hellwig switch (req_op(req)) { 327*aebf526bSChristoph Hellwig case REQ_OP_READ: 328ff1f48eeSRichard Weinberger ubi_sgl_init(&pdu->usgl); 329ff1f48eeSRichard Weinberger queue_work(dev->wq, &pdu->work); 330ff1f48eeSRichard Weinberger return BLK_MQ_RQ_QUEUE_OK; 331*aebf526bSChristoph Hellwig default: 332*aebf526bSChristoph Hellwig return BLK_MQ_RQ_QUEUE_ERROR; 333*aebf526bSChristoph Hellwig } 334*aebf526bSChristoph Hellwig 335ff1f48eeSRichard Weinberger } 336ff1f48eeSRichard Weinberger 337ff1f48eeSRichard Weinberger static int ubiblock_init_request(void *data, struct request *req, 338ff1f48eeSRichard Weinberger unsigned int hctx_idx, 339ff1f48eeSRichard Weinberger unsigned int request_idx, 340ff1f48eeSRichard Weinberger unsigned int numa_node) 341ff1f48eeSRichard Weinberger { 342ff1f48eeSRichard Weinberger struct ubiblock_pdu *pdu = blk_mq_rq_to_pdu(req); 343ff1f48eeSRichard Weinberger 344ff1f48eeSRichard Weinberger sg_init_table(pdu->usgl.sg, UBI_MAX_SG_COUNT); 345ff1f48eeSRichard Weinberger INIT_WORK(&pdu->work, ubiblock_do_work); 346ff1f48eeSRichard Weinberger 347ff1f48eeSRichard Weinberger return 0; 348ff1f48eeSRichard Weinberger } 349ff1f48eeSRichard Weinberger 350ff1f48eeSRichard Weinberger static struct blk_mq_ops ubiblock_mq_ops = { 351ff1f48eeSRichard Weinberger .queue_rq = ubiblock_queue_rq, 352ff1f48eeSRichard Weinberger .init_request = ubiblock_init_request, 353ff1f48eeSRichard Weinberger }; 354ff1f48eeSRichard Weinberger 3552bf50d42SDan Ehrenberg static DEFINE_IDR(ubiblock_minor_idr); 3562bf50d42SDan Ehrenberg 3574d283ee2SArtem Bityutskiy int ubiblock_create(struct ubi_volume_info *vi) 3589d54c8a3SEzequiel Garcia { 3599d54c8a3SEzequiel Garcia struct ubiblock *dev; 3609d54c8a3SEzequiel Garcia struct gendisk *gd; 361978d6496SEzequiel Garcia u64 disk_capacity = vi->used_bytes >> 9; 3629d54c8a3SEzequiel Garcia int ret; 3639d54c8a3SEzequiel Garcia 3644df38926SRichard Weinberger if ((sector_t)disk_capacity != disk_capacity) 3654df38926SRichard Weinberger return -EFBIG; 3669d54c8a3SEzequiel Garcia /* Check that the volume isn't already handled */ 3679d54c8a3SEzequiel Garcia mutex_lock(&devices_mutex); 3689d54c8a3SEzequiel Garcia if (find_dev_nolock(vi->ubi_num, vi->vol_id)) { 3699d54c8a3SEzequiel Garcia mutex_unlock(&devices_mutex); 3709d54c8a3SEzequiel Garcia return -EEXIST; 3719d54c8a3SEzequiel Garcia } 3729d54c8a3SEzequiel Garcia mutex_unlock(&devices_mutex); 3739d54c8a3SEzequiel Garcia 3749d54c8a3SEzequiel Garcia dev = kzalloc(sizeof(struct ubiblock), GFP_KERNEL); 3759d54c8a3SEzequiel Garcia if (!dev) 3769d54c8a3SEzequiel Garcia return -ENOMEM; 3779d54c8a3SEzequiel Garcia 3789d54c8a3SEzequiel Garcia mutex_init(&dev->dev_mutex); 3799d54c8a3SEzequiel Garcia 3809d54c8a3SEzequiel Garcia dev->ubi_num = vi->ubi_num; 3819d54c8a3SEzequiel Garcia dev->vol_id = vi->vol_id; 3829d54c8a3SEzequiel Garcia dev->leb_size = vi->usable_leb_size; 3839d54c8a3SEzequiel Garcia 3849d54c8a3SEzequiel Garcia /* Initialize the gendisk of this ubiblock device */ 3859d54c8a3SEzequiel Garcia gd = alloc_disk(1); 3869d54c8a3SEzequiel Garcia if (!gd) { 38732608703STanya Brokhman pr_err("UBI: block: alloc_disk failed"); 3889d54c8a3SEzequiel Garcia ret = -ENODEV; 3899d54c8a3SEzequiel Garcia goto out_free_dev; 3909d54c8a3SEzequiel Garcia } 3919d54c8a3SEzequiel Garcia 3929d54c8a3SEzequiel Garcia gd->fops = &ubiblock_ops; 3939d54c8a3SEzequiel Garcia gd->major = ubiblock_major; 3942bf50d42SDan Ehrenberg gd->first_minor = idr_alloc(&ubiblock_minor_idr, dev, 0, 0, GFP_KERNEL); 3952bf50d42SDan Ehrenberg if (gd->first_minor < 0) { 3962bf50d42SDan Ehrenberg dev_err(disk_to_dev(gd), 3972bf50d42SDan Ehrenberg "block: dynamic minor allocation failed"); 3982bf50d42SDan Ehrenberg ret = -ENODEV; 3992bf50d42SDan Ehrenberg goto out_put_disk; 4002bf50d42SDan Ehrenberg } 4019d54c8a3SEzequiel Garcia gd->private_data = dev; 4029d54c8a3SEzequiel Garcia sprintf(gd->disk_name, "ubiblock%d_%d", dev->ubi_num, dev->vol_id); 4039d54c8a3SEzequiel Garcia set_capacity(gd, disk_capacity); 4049d54c8a3SEzequiel Garcia dev->gd = gd; 4059d54c8a3SEzequiel Garcia 406ff1f48eeSRichard Weinberger dev->tag_set.ops = &ubiblock_mq_ops; 407ff1f48eeSRichard Weinberger dev->tag_set.queue_depth = 64; 408ff1f48eeSRichard Weinberger dev->tag_set.numa_node = NUMA_NO_NODE; 409ff1f48eeSRichard Weinberger dev->tag_set.flags = BLK_MQ_F_SHOULD_MERGE; 410ff1f48eeSRichard Weinberger dev->tag_set.cmd_size = sizeof(struct ubiblock_pdu); 411ff1f48eeSRichard Weinberger dev->tag_set.driver_data = dev; 412ff1f48eeSRichard Weinberger dev->tag_set.nr_hw_queues = 1; 413ff1f48eeSRichard Weinberger 414ff1f48eeSRichard Weinberger ret = blk_mq_alloc_tag_set(&dev->tag_set); 415ff1f48eeSRichard Weinberger if (ret) { 416ff1f48eeSRichard Weinberger dev_err(disk_to_dev(dev->gd), "blk_mq_alloc_tag_set failed"); 4172bf50d42SDan Ehrenberg goto out_remove_minor; 4189d54c8a3SEzequiel Garcia } 4199d54c8a3SEzequiel Garcia 420ff1f48eeSRichard Weinberger dev->rq = blk_mq_init_queue(&dev->tag_set); 4218168b9bbSDan Carpenter if (IS_ERR(dev->rq)) { 422ff1f48eeSRichard Weinberger dev_err(disk_to_dev(gd), "blk_mq_init_queue failed"); 4238168b9bbSDan Carpenter ret = PTR_ERR(dev->rq); 424ff1f48eeSRichard Weinberger goto out_free_tags; 425ff1f48eeSRichard Weinberger } 426ff1f48eeSRichard Weinberger blk_queue_max_segments(dev->rq, UBI_MAX_SG_COUNT); 427ff1f48eeSRichard Weinberger 4289d54c8a3SEzequiel Garcia dev->rq->queuedata = dev; 4299d54c8a3SEzequiel Garcia dev->gd->queue = dev->rq; 4309d54c8a3SEzequiel Garcia 4319d54c8a3SEzequiel Garcia /* 4329d54c8a3SEzequiel Garcia * Create one workqueue per volume (per registered block device). 4339d54c8a3SEzequiel Garcia * Rembember workqueues are cheap, they're not threads. 4349d54c8a3SEzequiel Garcia */ 435bebfef15SKees Cook dev->wq = alloc_workqueue("%s", 0, 0, gd->disk_name); 436151d6b21SHelmut Schaa if (!dev->wq) { 437151d6b21SHelmut Schaa ret = -ENOMEM; 4389d54c8a3SEzequiel Garcia goto out_free_queue; 439151d6b21SHelmut Schaa } 4409d54c8a3SEzequiel Garcia 4419d54c8a3SEzequiel Garcia mutex_lock(&devices_mutex); 4429d54c8a3SEzequiel Garcia list_add_tail(&dev->list, &ubiblock_devices); 4439d54c8a3SEzequiel Garcia mutex_unlock(&devices_mutex); 4449d54c8a3SEzequiel Garcia 4459d54c8a3SEzequiel Garcia /* Must be the last step: anyone can call file ops from now on */ 4469d54c8a3SEzequiel Garcia add_disk(dev->gd); 44732608703STanya Brokhman dev_info(disk_to_dev(dev->gd), "created from ubi%d:%d(%s)", 44832608703STanya Brokhman dev->ubi_num, dev->vol_id, vi->name); 4499d54c8a3SEzequiel Garcia return 0; 4509d54c8a3SEzequiel Garcia 4519d54c8a3SEzequiel Garcia out_free_queue: 4529d54c8a3SEzequiel Garcia blk_cleanup_queue(dev->rq); 453ff1f48eeSRichard Weinberger out_free_tags: 454ff1f48eeSRichard Weinberger blk_mq_free_tag_set(&dev->tag_set); 4552bf50d42SDan Ehrenberg out_remove_minor: 4562bf50d42SDan Ehrenberg idr_remove(&ubiblock_minor_idr, gd->first_minor); 4579d54c8a3SEzequiel Garcia out_put_disk: 4589d54c8a3SEzequiel Garcia put_disk(dev->gd); 4599d54c8a3SEzequiel Garcia out_free_dev: 4609d54c8a3SEzequiel Garcia kfree(dev); 4619d54c8a3SEzequiel Garcia 4629d54c8a3SEzequiel Garcia return ret; 4639d54c8a3SEzequiel Garcia } 4649d54c8a3SEzequiel Garcia 4659d54c8a3SEzequiel Garcia static void ubiblock_cleanup(struct ubiblock *dev) 4669d54c8a3SEzequiel Garcia { 467ff1f48eeSRichard Weinberger /* Stop new requests to arrive */ 4689d54c8a3SEzequiel Garcia del_gendisk(dev->gd); 469ff1f48eeSRichard Weinberger /* Flush pending work */ 470ff1f48eeSRichard Weinberger destroy_workqueue(dev->wq); 471ff1f48eeSRichard Weinberger /* Finally destroy the blk queue */ 4729d54c8a3SEzequiel Garcia blk_cleanup_queue(dev->rq); 473ff1f48eeSRichard Weinberger blk_mq_free_tag_set(&dev->tag_set); 47432608703STanya Brokhman dev_info(disk_to_dev(dev->gd), "released"); 4752bf50d42SDan Ehrenberg idr_remove(&ubiblock_minor_idr, dev->gd->first_minor); 4769d54c8a3SEzequiel Garcia put_disk(dev->gd); 4779d54c8a3SEzequiel Garcia } 4789d54c8a3SEzequiel Garcia 4794d283ee2SArtem Bityutskiy int ubiblock_remove(struct ubi_volume_info *vi) 4809d54c8a3SEzequiel Garcia { 4819d54c8a3SEzequiel Garcia struct ubiblock *dev; 4829d54c8a3SEzequiel Garcia 4839d54c8a3SEzequiel Garcia mutex_lock(&devices_mutex); 4849d54c8a3SEzequiel Garcia dev = find_dev_nolock(vi->ubi_num, vi->vol_id); 4859d54c8a3SEzequiel Garcia if (!dev) { 4869d54c8a3SEzequiel Garcia mutex_unlock(&devices_mutex); 4879d54c8a3SEzequiel Garcia return -ENODEV; 4889d54c8a3SEzequiel Garcia } 4899d54c8a3SEzequiel Garcia 4909d54c8a3SEzequiel Garcia /* Found a device, let's lock it so we can check if it's busy */ 4919d54c8a3SEzequiel Garcia mutex_lock(&dev->dev_mutex); 4929d54c8a3SEzequiel Garcia if (dev->refcnt > 0) { 4939d54c8a3SEzequiel Garcia mutex_unlock(&dev->dev_mutex); 4949d54c8a3SEzequiel Garcia mutex_unlock(&devices_mutex); 4959d54c8a3SEzequiel Garcia return -EBUSY; 4969d54c8a3SEzequiel Garcia } 4979d54c8a3SEzequiel Garcia 4989d54c8a3SEzequiel Garcia /* Remove from device list */ 4999d54c8a3SEzequiel Garcia list_del(&dev->list); 5009d54c8a3SEzequiel Garcia mutex_unlock(&devices_mutex); 5019d54c8a3SEzequiel Garcia 5029d54c8a3SEzequiel Garcia ubiblock_cleanup(dev); 5039d54c8a3SEzequiel Garcia mutex_unlock(&dev->dev_mutex); 5049d54c8a3SEzequiel Garcia kfree(dev); 5059d54c8a3SEzequiel Garcia return 0; 5069d54c8a3SEzequiel Garcia } 5079d54c8a3SEzequiel Garcia 508495f2bf6SEzequiel Garcia static int ubiblock_resize(struct ubi_volume_info *vi) 5099d54c8a3SEzequiel Garcia { 5109d54c8a3SEzequiel Garcia struct ubiblock *dev; 511978d6496SEzequiel Garcia u64 disk_capacity = vi->used_bytes >> 9; 5129d54c8a3SEzequiel Garcia 5139d54c8a3SEzequiel Garcia /* 5149d54c8a3SEzequiel Garcia * Need to lock the device list until we stop using the device, 5154d283ee2SArtem Bityutskiy * otherwise the device struct might get released in 5164d283ee2SArtem Bityutskiy * 'ubiblock_remove()'. 5179d54c8a3SEzequiel Garcia */ 5189d54c8a3SEzequiel Garcia mutex_lock(&devices_mutex); 5199d54c8a3SEzequiel Garcia dev = find_dev_nolock(vi->ubi_num, vi->vol_id); 5209d54c8a3SEzequiel Garcia if (!dev) { 5219d54c8a3SEzequiel Garcia mutex_unlock(&devices_mutex); 522495f2bf6SEzequiel Garcia return -ENODEV; 5239d54c8a3SEzequiel Garcia } 5243df77072SColin Ian King if ((sector_t)disk_capacity != disk_capacity) { 5253df77072SColin Ian King mutex_unlock(&devices_mutex); 52632608703STanya Brokhman dev_warn(disk_to_dev(dev->gd), "the volume is too big (%d LEBs), cannot resize", 52732608703STanya Brokhman vi->size); 5283df77072SColin Ian King return -EFBIG; 5293df77072SColin Ian King } 5309d54c8a3SEzequiel Garcia 5319d54c8a3SEzequiel Garcia mutex_lock(&dev->dev_mutex); 53206d9c290SEzequiel Garcia 53306d9c290SEzequiel Garcia if (get_capacity(dev->gd) != disk_capacity) { 5349d54c8a3SEzequiel Garcia set_capacity(dev->gd, disk_capacity); 53532608703STanya Brokhman dev_info(disk_to_dev(dev->gd), "resized to %lld bytes", 53606d9c290SEzequiel Garcia vi->used_bytes); 53706d9c290SEzequiel Garcia } 5389d54c8a3SEzequiel Garcia mutex_unlock(&dev->dev_mutex); 5399d54c8a3SEzequiel Garcia mutex_unlock(&devices_mutex); 540495f2bf6SEzequiel Garcia return 0; 5419d54c8a3SEzequiel Garcia } 5429d54c8a3SEzequiel Garcia 5439d54c8a3SEzequiel Garcia static int ubiblock_notify(struct notifier_block *nb, 5449d54c8a3SEzequiel Garcia unsigned long notification_type, void *ns_ptr) 5459d54c8a3SEzequiel Garcia { 5469d54c8a3SEzequiel Garcia struct ubi_notification *nt = ns_ptr; 5479d54c8a3SEzequiel Garcia 5489d54c8a3SEzequiel Garcia switch (notification_type) { 5499d54c8a3SEzequiel Garcia case UBI_VOLUME_ADDED: 5509d54c8a3SEzequiel Garcia /* 5514d283ee2SArtem Bityutskiy * We want to enforce explicit block device creation for 5529d54c8a3SEzequiel Garcia * volumes, so when a volume is added we do nothing. 5539d54c8a3SEzequiel Garcia */ 5549d54c8a3SEzequiel Garcia break; 5559d54c8a3SEzequiel Garcia case UBI_VOLUME_REMOVED: 5564d283ee2SArtem Bityutskiy ubiblock_remove(&nt->vi); 5579d54c8a3SEzequiel Garcia break; 5589d54c8a3SEzequiel Garcia case UBI_VOLUME_RESIZED: 5599d54c8a3SEzequiel Garcia ubiblock_resize(&nt->vi); 5609d54c8a3SEzequiel Garcia break; 56106d9c290SEzequiel Garcia case UBI_VOLUME_UPDATED: 56206d9c290SEzequiel Garcia /* 56306d9c290SEzequiel Garcia * If the volume is static, a content update might mean the 56406d9c290SEzequiel Garcia * size (i.e. used_bytes) was also changed. 56506d9c290SEzequiel Garcia */ 56606d9c290SEzequiel Garcia if (nt->vi.vol_type == UBI_STATIC_VOLUME) 56706d9c290SEzequiel Garcia ubiblock_resize(&nt->vi); 56806d9c290SEzequiel Garcia break; 5699d54c8a3SEzequiel Garcia default: 5709d54c8a3SEzequiel Garcia break; 5719d54c8a3SEzequiel Garcia } 5729d54c8a3SEzequiel Garcia return NOTIFY_OK; 5739d54c8a3SEzequiel Garcia } 5749d54c8a3SEzequiel Garcia 5759d54c8a3SEzequiel Garcia static struct notifier_block ubiblock_notifier = { 5769d54c8a3SEzequiel Garcia .notifier_call = ubiblock_notify, 5779d54c8a3SEzequiel Garcia }; 5789d54c8a3SEzequiel Garcia 5799d54c8a3SEzequiel Garcia static struct ubi_volume_desc * __init 5809d54c8a3SEzequiel Garcia open_volume_desc(const char *name, int ubi_num, int vol_id) 5819d54c8a3SEzequiel Garcia { 5829d54c8a3SEzequiel Garcia if (ubi_num == -1) 5839d54c8a3SEzequiel Garcia /* No ubi num, name must be a vol device path */ 5849d54c8a3SEzequiel Garcia return ubi_open_volume_path(name, UBI_READONLY); 5859d54c8a3SEzequiel Garcia else if (vol_id == -1) 5869d54c8a3SEzequiel Garcia /* No vol_id, must be vol_name */ 5879d54c8a3SEzequiel Garcia return ubi_open_volume_nm(ubi_num, name, UBI_READONLY); 5889d54c8a3SEzequiel Garcia else 5899d54c8a3SEzequiel Garcia return ubi_open_volume(ubi_num, vol_id, UBI_READONLY); 5909d54c8a3SEzequiel Garcia } 5919d54c8a3SEzequiel Garcia 5921440061bSDan Ehrenberg static void __init ubiblock_create_from_param(void) 5939d54c8a3SEzequiel Garcia { 5941440061bSDan Ehrenberg int i, ret = 0; 5959d54c8a3SEzequiel Garcia struct ubiblock_param *p; 5969d54c8a3SEzequiel Garcia struct ubi_volume_desc *desc; 5979d54c8a3SEzequiel Garcia struct ubi_volume_info vi; 5989d54c8a3SEzequiel Garcia 5991440061bSDan Ehrenberg /* 6001440061bSDan Ehrenberg * If there is an error creating one of the ubiblocks, continue on to 6011440061bSDan Ehrenberg * create the following ubiblocks. This helps in a circumstance where 6021440061bSDan Ehrenberg * the kernel command-line specifies multiple block devices and some 6031440061bSDan Ehrenberg * may be broken, but we still want the working ones to come up. 6041440061bSDan Ehrenberg */ 6059d54c8a3SEzequiel Garcia for (i = 0; i < ubiblock_devs; i++) { 6069d54c8a3SEzequiel Garcia p = &ubiblock_param[i]; 6079d54c8a3SEzequiel Garcia 6089d54c8a3SEzequiel Garcia desc = open_volume_desc(p->name, p->ubi_num, p->vol_id); 6099d54c8a3SEzequiel Garcia if (IS_ERR(desc)) { 6101440061bSDan Ehrenberg pr_err( 6111440061bSDan Ehrenberg "UBI: block: can't open volume on ubi%d_%d, err=%ld", 6121440061bSDan Ehrenberg p->ubi_num, p->vol_id, PTR_ERR(desc)); 6131440061bSDan Ehrenberg continue; 6149d54c8a3SEzequiel Garcia } 6159d54c8a3SEzequiel Garcia 6169d54c8a3SEzequiel Garcia ubi_get_volume_info(desc, &vi); 6179d54c8a3SEzequiel Garcia ubi_close_volume(desc); 6189d54c8a3SEzequiel Garcia 6194d283ee2SArtem Bityutskiy ret = ubiblock_create(&vi); 6209d54c8a3SEzequiel Garcia if (ret) { 6211440061bSDan Ehrenberg pr_err( 6221440061bSDan Ehrenberg "UBI: block: can't add '%s' volume on ubi%d_%d, err=%d", 6231440061bSDan Ehrenberg vi.name, p->ubi_num, p->vol_id, ret); 6241440061bSDan Ehrenberg continue; 6259d54c8a3SEzequiel Garcia } 6269d54c8a3SEzequiel Garcia } 6279d54c8a3SEzequiel Garcia } 6289d54c8a3SEzequiel Garcia 6294d283ee2SArtem Bityutskiy static void ubiblock_remove_all(void) 6309d54c8a3SEzequiel Garcia { 6319d54c8a3SEzequiel Garcia struct ubiblock *next; 6329d54c8a3SEzequiel Garcia struct ubiblock *dev; 6339d54c8a3SEzequiel Garcia 6349d54c8a3SEzequiel Garcia list_for_each_entry_safe(dev, next, &ubiblock_devices, list) { 6359d54c8a3SEzequiel Garcia /* The module is being forcefully removed */ 6369d54c8a3SEzequiel Garcia WARN_ON(dev->desc); 6379d54c8a3SEzequiel Garcia /* Remove from device list */ 6389d54c8a3SEzequiel Garcia list_del(&dev->list); 6399d54c8a3SEzequiel Garcia ubiblock_cleanup(dev); 6409d54c8a3SEzequiel Garcia kfree(dev); 6419d54c8a3SEzequiel Garcia } 6429d54c8a3SEzequiel Garcia } 6439d54c8a3SEzequiel Garcia 6449d54c8a3SEzequiel Garcia int __init ubiblock_init(void) 6459d54c8a3SEzequiel Garcia { 6469d54c8a3SEzequiel Garcia int ret; 6479d54c8a3SEzequiel Garcia 6489d54c8a3SEzequiel Garcia ubiblock_major = register_blkdev(0, "ubiblock"); 6499d54c8a3SEzequiel Garcia if (ubiblock_major < 0) 6509d54c8a3SEzequiel Garcia return ubiblock_major; 6519d54c8a3SEzequiel Garcia 6521440061bSDan Ehrenberg /* 6531440061bSDan Ehrenberg * Attach block devices from 'block=' module param. 6541440061bSDan Ehrenberg * Even if one block device in the param list fails to come up, 6551440061bSDan Ehrenberg * still allow the module to load and leave any others up. 6561440061bSDan Ehrenberg */ 6571440061bSDan Ehrenberg ubiblock_create_from_param(); 6589d54c8a3SEzequiel Garcia 6599d54c8a3SEzequiel Garcia /* 6604d283ee2SArtem Bityutskiy * Block devices are only created upon user requests, so we ignore 6614d283ee2SArtem Bityutskiy * existing volumes. 6629d54c8a3SEzequiel Garcia */ 6639d54c8a3SEzequiel Garcia ret = ubi_register_volume_notifier(&ubiblock_notifier, 1); 6649d54c8a3SEzequiel Garcia if (ret) 6659d54c8a3SEzequiel Garcia goto err_unreg; 6669d54c8a3SEzequiel Garcia return 0; 6679d54c8a3SEzequiel Garcia 6689d54c8a3SEzequiel Garcia err_unreg: 6699d54c8a3SEzequiel Garcia unregister_blkdev(ubiblock_major, "ubiblock"); 6704d283ee2SArtem Bityutskiy ubiblock_remove_all(); 6719d54c8a3SEzequiel Garcia return ret; 6729d54c8a3SEzequiel Garcia } 6739d54c8a3SEzequiel Garcia 6749d54c8a3SEzequiel Garcia void __exit ubiblock_exit(void) 6759d54c8a3SEzequiel Garcia { 6769d54c8a3SEzequiel Garcia ubi_unregister_volume_notifier(&ubiblock_notifier); 6774d283ee2SArtem Bityutskiy ubiblock_remove_all(); 6789d54c8a3SEzequiel Garcia unregister_blkdev(ubiblock_major, "ubiblock"); 6799d54c8a3SEzequiel Garcia } 680