xref: /linux/drivers/mtd/ubi/block.c (revision aebf526b53aea164508730427597d45f3e06b376)
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, &param->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, &param->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