Blame view
drivers/mtd/mtd_blkdevs.c
13.5 KB
fd534e9b5 treewide: Replace... |
1 |
// SPDX-License-Identifier: GPL-2.0-or-later |
1da177e4c Linux-2.6.12-rc2 |
2 |
/* |
a1452a377 mtd: Update copyr... |
3 |
* Interface to Linux block layer for MTD 'translation layers'. |
1da177e4c Linux-2.6.12-rc2 |
4 |
* |
a1452a377 mtd: Update copyr... |
5 |
* Copyright © 2003-2010 David Woodhouse <dwmw2@infradead.org> |
1da177e4c Linux-2.6.12-rc2 |
6 7 8 9 10 11 12 13 14 15 |
*/ #include <linux/kernel.h> #include <linux/slab.h> #include <linux/module.h> #include <linux/list.h> #include <linux/fs.h> #include <linux/mtd/blktrans.h> #include <linux/mtd/mtd.h> #include <linux/blkdev.h> |
891b7c5fb mtd_blkdevs: conv... |
16 |
#include <linux/blk-mq.h> |
1da177e4c Linux-2.6.12-rc2 |
17 18 19 |
#include <linux/blkpg.h> #include <linux/spinlock.h> #include <linux/hdreg.h> |
48b192686 [PATCH] sem2mutex... |
20 |
#include <linux/mutex.h> |
7c0f6ba68 Replace <asm/uacc... |
21 |
#include <linux/uaccess.h> |
1da177e4c Linux-2.6.12-rc2 |
22 |
|
356d70f19 [MTD] mtdcore.c: ... |
23 |
#include "mtdcore.h" |
1da177e4c Linux-2.6.12-rc2 |
24 |
|
356d70f19 [MTD] mtdcore.c: ... |
25 |
static LIST_HEAD(blktrans_majors); |
048d87199 mtd: blktrans: Ho... |
26 |
static DEFINE_MUTEX(blktrans_ref_mutex); |
7f53f12f0 mtd: mtd_blkdevs:... |
27 |
static void blktrans_dev_release(struct kref *kref) |
048d87199 mtd: blktrans: Ho... |
28 29 30 31 32 |
{ struct mtd_blktrans_dev *dev = container_of(kref, struct mtd_blktrans_dev, ref); dev->disk->private_data = NULL; |
e4d64cab9 mtd: blktrans: do... |
33 |
blk_cleanup_queue(dev->rq); |
891b7c5fb mtd_blkdevs: conv... |
34 35 |
blk_mq_free_tag_set(dev->tag_set); kfree(dev->tag_set); |
048d87199 mtd: blktrans: Ho... |
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 |
put_disk(dev->disk); list_del(&dev->list); kfree(dev); } static struct mtd_blktrans_dev *blktrans_dev_get(struct gendisk *disk) { struct mtd_blktrans_dev *dev; mutex_lock(&blktrans_ref_mutex); dev = disk->private_data; if (!dev) goto unlock; kref_get(&dev->ref); unlock: mutex_unlock(&blktrans_ref_mutex); return dev; } |
7f53f12f0 mtd: mtd_blkdevs:... |
55 |
static void blktrans_dev_put(struct mtd_blktrans_dev *dev) |
048d87199 mtd: blktrans: Ho... |
56 57 58 59 60 |
{ mutex_lock(&blktrans_ref_mutex); kref_put(&dev->ref, blktrans_dev_release); mutex_unlock(&blktrans_ref_mutex); } |
1da177e4c Linux-2.6.12-rc2 |
61 |
|
1da177e4c Linux-2.6.12-rc2 |
62 |
|
2a842acab block: introduce ... |
63 |
static blk_status_t do_blktrans_request(struct mtd_blktrans_ops *tr, |
1da177e4c Linux-2.6.12-rc2 |
64 65 66 67 68 |
struct mtd_blktrans_dev *dev, struct request *req) { unsigned long block, nsect; char *buf; |
83096ebf1 block: convert to... |
69 |
block = blk_rq_pos(req) << 9 >> tr->blkshift; |
1011c1b9f block: blk_rq_[cu... |
70 |
nsect = blk_rq_cur_bytes(req) >> tr->blkshift; |
1da177e4c Linux-2.6.12-rc2 |
71 |
|
2a842acab block: introduce ... |
72 73 74 75 76 |
if (req_op(req) == REQ_OP_FLUSH) { if (tr->flush(dev)) return BLK_STS_IOERR; return BLK_STS_OK; } |
566c0d6a7 mtd: mtd_blkdevs:... |
77 |
|
83096ebf1 block: convert to... |
78 79 |
if (blk_rq_pos(req) + blk_rq_cur_sectors(req) > get_capacity(req->rq_disk)) |
2a842acab block: introduce ... |
80 |
return BLK_STS_IOERR; |
1da177e4c Linux-2.6.12-rc2 |
81 |
|
aebf526b5 block: fold cmd_t... |
82 83 |
switch (req_op(req)) { case REQ_OP_DISCARD: |
2a842acab block: introduce ... |
84 85 86 |
if (tr->discard(dev, block, nsect)) return BLK_STS_IOERR; return BLK_STS_OK; |
aebf526b5 block: fold cmd_t... |
87 |
case REQ_OP_READ: |
34ab96e6c mtd_blkdevs: hand... |
88 89 90 91 |
buf = kmap(bio_page(req->bio)) + bio_offset(req->bio); for (; nsect > 0; nsect--, block++, buf += tr->blksize) { if (tr->readsect(dev, block, buf)) { kunmap(bio_page(req->bio)); |
2a842acab block: introduce ... |
92 |
return BLK_STS_IOERR; |
34ab96e6c mtd_blkdevs: hand... |
93 94 95 |
} } kunmap(bio_page(req->bio)); |
2d4dc890b block: add helper... |
96 |
rq_flush_dcache_pages(req); |
2a842acab block: introduce ... |
97 |
return BLK_STS_OK; |
aebf526b5 block: fold cmd_t... |
98 |
case REQ_OP_WRITE: |
1da177e4c Linux-2.6.12-rc2 |
99 |
if (!tr->writesect) |
2a842acab block: introduce ... |
100 |
return BLK_STS_IOERR; |
1da177e4c Linux-2.6.12-rc2 |
101 |
|
2d4dc890b block: add helper... |
102 |
rq_flush_dcache_pages(req); |
34ab96e6c mtd_blkdevs: hand... |
103 104 105 106 |
buf = kmap(bio_page(req->bio)) + bio_offset(req->bio); for (; nsect > 0; nsect--, block++, buf += tr->blksize) { if (tr->writesect(dev, block, buf)) { kunmap(bio_page(req->bio)); |
2a842acab block: introduce ... |
107 |
return BLK_STS_IOERR; |
34ab96e6c mtd_blkdevs: hand... |
108 109 110 |
} } kunmap(bio_page(req->bio)); |
9a5154477 mtd: blkdevs: Fix... |
111 |
return BLK_STS_OK; |
aebf526b5 block: fold cmd_t... |
112 |
default: |
2a842acab block: introduce ... |
113 |
return BLK_STS_IOERR; |
1da177e4c Linux-2.6.12-rc2 |
114 115 |
} } |
c7519dbf6 mtd_blkdevs: Add ... |
116 117 |
int mtd_blktrans_cease_background(struct mtd_blktrans_dev *dev) { |
7bf7e370d Merge branch 'mas... |
118 |
return dev->bg_stop; |
c7519dbf6 mtd_blkdevs: Add ... |
119 120 |
} EXPORT_SYMBOL_GPL(mtd_blktrans_cease_background); |
891b7c5fb mtd_blkdevs: conv... |
121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 |
static struct request *mtd_next_request(struct mtd_blktrans_dev *dev) { struct request *rq; rq = list_first_entry_or_null(&dev->rq_list, struct request, queuelist); if (rq) { list_del_init(&rq->queuelist); blk_mq_start_request(rq); return rq; } return NULL; } static void mtd_blktrans_work(struct mtd_blktrans_dev *dev) __releases(&dev->queue_lock) __acquires(&dev->queue_lock) |
1da177e4c Linux-2.6.12-rc2 |
138 |
{ |
c7519dbf6 mtd_blkdevs: Add ... |
139 |
struct mtd_blktrans_ops *tr = dev->tr; |
1498ada7a mtd_blkdevs: dequ... |
140 |
struct request *req = NULL; |
c7519dbf6 mtd_blkdevs: Add ... |
141 |
int background_done = 0; |
1da177e4c Linux-2.6.12-rc2 |
142 |
|
22a8578fc mtd: mtd_blkdevs:... |
143 |
while (1) { |
2a842acab block: introduce ... |
144 |
blk_status_t res; |
1da177e4c Linux-2.6.12-rc2 |
145 |
|
7bf7e370d Merge branch 'mas... |
146 |
dev->bg_stop = false; |
891b7c5fb mtd_blkdevs: conv... |
147 |
if (!req && !(req = mtd_next_request(dev))) { |
c7519dbf6 mtd_blkdevs: Add ... |
148 |
if (tr->background && !background_done) { |
891b7c5fb mtd_blkdevs: conv... |
149 |
spin_unlock_irq(&dev->queue_lock); |
c7519dbf6 mtd_blkdevs: Add ... |
150 151 152 |
mutex_lock(&dev->lock); tr->background(dev); mutex_unlock(&dev->lock); |
891b7c5fb mtd_blkdevs: conv... |
153 |
spin_lock_irq(&dev->queue_lock); |
c7519dbf6 mtd_blkdevs: Add ... |
154 155 156 157 |
/* * Do background processing just once per idle * period. */ |
7bf7e370d Merge branch 'mas... |
158 |
background_done = !dev->bg_stop; |
c7519dbf6 mtd_blkdevs: Add ... |
159 160 |
continue; } |
22a8578fc mtd: mtd_blkdevs:... |
161 |
break; |
1da177e4c Linux-2.6.12-rc2 |
162 |
} |
891b7c5fb mtd_blkdevs: conv... |
163 |
spin_unlock_irq(&dev->queue_lock); |
1da177e4c Linux-2.6.12-rc2 |
164 |
|
48b192686 [PATCH] sem2mutex... |
165 |
mutex_lock(&dev->lock); |
a86386225 mtd: blktrans: re... |
166 |
res = do_blktrans_request(dev->tr, dev, req); |
48b192686 [PATCH] sem2mutex... |
167 |
mutex_unlock(&dev->lock); |
1da177e4c Linux-2.6.12-rc2 |
168 |
|
891b7c5fb mtd_blkdevs: conv... |
169 170 |
if (!blk_update_request(req, res, blk_rq_cur_bytes(req))) { __blk_mq_end_request(req, res); |
1498ada7a mtd_blkdevs: dequ... |
171 |
req = NULL; |
891b7c5fb mtd_blkdevs: conv... |
172 |
} |
c7519dbf6 mtd_blkdevs: Add ... |
173 174 |
background_done = 0; |
891b7c5fb mtd_blkdevs: conv... |
175 |
spin_lock_irq(&dev->queue_lock); |
1da177e4c Linux-2.6.12-rc2 |
176 |
} |
1da177e4c Linux-2.6.12-rc2 |
177 |
} |
891b7c5fb mtd_blkdevs: conv... |
178 179 |
static blk_status_t mtd_queue_rq(struct blk_mq_hw_ctx *hctx, const struct blk_mq_queue_data *bd) |
1da177e4c Linux-2.6.12-rc2 |
180 |
{ |
048d87199 mtd: blktrans: Ho... |
181 |
struct mtd_blktrans_dev *dev; |
048d87199 mtd: blktrans: Ho... |
182 |
|
891b7c5fb mtd_blkdevs: conv... |
183 184 185 186 187 188 189 190 191 192 |
dev = hctx->queue->queuedata; if (!dev) { blk_mq_start_request(bd->rq); return BLK_STS_IOERR; } spin_lock_irq(&dev->queue_lock); list_add_tail(&bd->rq->queuelist, &dev->rq_list); mtd_blktrans_work(dev); spin_unlock_irq(&dev->queue_lock); |
1da177e4c Linux-2.6.12-rc2 |
193 |
|
891b7c5fb mtd_blkdevs: conv... |
194 |
return BLK_STS_OK; |
048d87199 mtd: blktrans: Ho... |
195 |
} |
1da177e4c Linux-2.6.12-rc2 |
196 |
|
af0e2a0a8 [PATCH] switch mt... |
197 |
static int blktrans_open(struct block_device *bdev, fmode_t mode) |
1da177e4c Linux-2.6.12-rc2 |
198 |
{ |
048d87199 mtd: blktrans: Ho... |
199 |
struct mtd_blktrans_dev *dev = blktrans_dev_get(bdev->bd_disk); |
008c751ec mtd: allow to unl... |
200 |
int ret = 0; |
048d87199 mtd: blktrans: Ho... |
201 202 |
if (!dev) |
6e9624b8c block: push down ... |
203 |
return -ERESTARTSYS; /* FIXME: busy loop! -arnd*/ |
048d87199 mtd: blktrans: Ho... |
204 |
|
073db4a51 mtd: fix: avoid r... |
205 |
mutex_lock(&mtd_table_mutex); |
f3c63795e mtd: blkdevs: fix... |
206 |
mutex_lock(&dev->lock); |
048d87199 mtd: blktrans: Ho... |
207 |
|
342ff28f5 mtd: mtd_blkdevs:... |
208 |
if (dev->open) |
048d87199 mtd: blktrans: Ho... |
209 |
goto unlock; |
048d87199 mtd: blktrans: Ho... |
210 |
|
008c751ec mtd: allow to unl... |
211 212 |
kref_get(&dev->ref); __module_get(dev->tr->owner); |
94735ec40 mtd: mtd_blkdevs:... |
213 214 215 216 217 218 219 |
if (!dev->mtd) goto unlock; if (dev->tr->open) { ret = dev->tr->open(dev); if (ret) goto error_put; |
008c751ec mtd: allow to unl... |
220 |
} |
048d87199 mtd: blktrans: Ho... |
221 |
|
94735ec40 mtd: mtd_blkdevs:... |
222 223 224 |
ret = __get_mtd_device(dev->mtd); if (ret) goto error_release; |
70d5098a4 mtd: mtdblock: ca... |
225 |
dev->file_mode = mode; |
94735ec40 mtd: mtd_blkdevs:... |
226 |
|
048d87199 mtd: blktrans: Ho... |
227 |
unlock: |
342ff28f5 mtd: mtd_blkdevs:... |
228 |
dev->open++; |
048d87199 mtd: blktrans: Ho... |
229 |
mutex_unlock(&dev->lock); |
f3c63795e mtd: blkdevs: fix... |
230 |
mutex_unlock(&mtd_table_mutex); |
048d87199 mtd: blktrans: Ho... |
231 |
blktrans_dev_put(dev); |
1da177e4c Linux-2.6.12-rc2 |
232 |
return ret; |
94735ec40 mtd: mtd_blkdevs:... |
233 234 235 236 237 238 239 240 |
error_release: if (dev->tr->release) dev->tr->release(dev); error_put: module_put(dev->tr->owner); kref_put(&dev->ref, blktrans_dev_release); mutex_unlock(&dev->lock); |
f3c63795e mtd: blkdevs: fix... |
241 |
mutex_unlock(&mtd_table_mutex); |
94735ec40 mtd: mtd_blkdevs:... |
242 243 |
blktrans_dev_put(dev); return ret; |
1da177e4c Linux-2.6.12-rc2 |
244 |
} |
db2a144be block_device_oper... |
245 |
static void blktrans_release(struct gendisk *disk, fmode_t mode) |
1da177e4c Linux-2.6.12-rc2 |
246 |
{ |
048d87199 mtd: blktrans: Ho... |
247 |
struct mtd_blktrans_dev *dev = blktrans_dev_get(disk); |
1da177e4c Linux-2.6.12-rc2 |
248 |
|
048d87199 mtd: blktrans: Ho... |
249 |
if (!dev) |
db2a144be block_device_oper... |
250 |
return; |
1da177e4c Linux-2.6.12-rc2 |
251 |
|
073db4a51 mtd: fix: avoid r... |
252 |
mutex_lock(&mtd_table_mutex); |
f3c63795e mtd: blkdevs: fix... |
253 |
mutex_lock(&dev->lock); |
048d87199 mtd: blktrans: Ho... |
254 |
|
008c751ec mtd: allow to unl... |
255 |
if (--dev->open) |
048d87199 mtd: blktrans: Ho... |
256 |
goto unlock; |
008c751ec mtd: allow to unl... |
257 258 259 260 |
kref_put(&dev->ref, blktrans_dev_release); module_put(dev->tr->owner); if (dev->mtd) { |
a8ca889ed mtd_blktrans_ops-... |
261 262 |
if (dev->tr->release) dev->tr->release(dev); |
008c751ec mtd: allow to unl... |
263 264 |
__put_mtd_device(dev->mtd); } |
048d87199 mtd: blktrans: Ho... |
265 266 |
unlock: mutex_unlock(&dev->lock); |
f3c63795e mtd: blkdevs: fix... |
267 |
mutex_unlock(&mtd_table_mutex); |
048d87199 mtd: blktrans: Ho... |
268 |
blktrans_dev_put(dev); |
1da177e4c Linux-2.6.12-rc2 |
269 |
} |
a885c8c43 [PATCH] Add block... |
270 271 |
static int blktrans_getgeo(struct block_device *bdev, struct hd_geometry *geo) { |
048d87199 mtd: blktrans: Ho... |
272 273 274 275 276 277 278 |
struct mtd_blktrans_dev *dev = blktrans_dev_get(bdev->bd_disk); int ret = -ENXIO; if (!dev) return ret; mutex_lock(&dev->lock); |
a885c8c43 [PATCH] Add block... |
279 |
|
048d87199 mtd: blktrans: Ho... |
280 281 |
if (!dev->mtd) goto unlock; |
c4a3f13c2 mtd: blktrans: us... |
282 |
ret = dev->tr->getgeo ? dev->tr->getgeo(dev, geo) : -ENOTTY; |
048d87199 mtd: blktrans: Ho... |
283 284 285 286 |
unlock: mutex_unlock(&dev->lock); blktrans_dev_put(dev); return ret; |
a885c8c43 [PATCH] Add block... |
287 |
} |
1da177e4c Linux-2.6.12-rc2 |
288 |
|
af0e2a0a8 [PATCH] switch mt... |
289 |
static int blktrans_ioctl(struct block_device *bdev, fmode_t mode, |
1da177e4c Linux-2.6.12-rc2 |
290 291 |
unsigned int cmd, unsigned long arg) { |
048d87199 mtd: blktrans: Ho... |
292 293 294 295 296 297 298 299 300 301 |
struct mtd_blktrans_dev *dev = blktrans_dev_get(bdev->bd_disk); int ret = -ENXIO; if (!dev) return ret; mutex_lock(&dev->lock); if (!dev->mtd) goto unlock; |
1da177e4c Linux-2.6.12-rc2 |
302 303 304 |
switch (cmd) { case BLKFLSBUF: |
048d87199 mtd: blktrans: Ho... |
305 |
ret = dev->tr->flush ? dev->tr->flush(dev) : 0; |
007c2d876 mtd: return succe... |
306 |
break; |
1da177e4c Linux-2.6.12-rc2 |
307 |
default: |
048d87199 mtd: blktrans: Ho... |
308 |
ret = -ENOTTY; |
1da177e4c Linux-2.6.12-rc2 |
309 |
} |
048d87199 mtd: blktrans: Ho... |
310 311 312 313 |
unlock: mutex_unlock(&dev->lock); blktrans_dev_put(dev); return ret; |
1da177e4c Linux-2.6.12-rc2 |
314 |
} |
9329c5eb5 mtd: mtd_blkdev: ... |
315 |
static const struct block_device_operations mtd_block_ops = { |
1da177e4c Linux-2.6.12-rc2 |
316 |
.owner = THIS_MODULE, |
af0e2a0a8 [PATCH] switch mt... |
317 318 |
.open = blktrans_open, .release = blktrans_release, |
8a6cfeb6d block: push down ... |
319 |
.ioctl = blktrans_ioctl, |
a885c8c43 [PATCH] Add block... |
320 |
.getgeo = blktrans_getgeo, |
1da177e4c Linux-2.6.12-rc2 |
321 |
}; |
891b7c5fb mtd_blkdevs: conv... |
322 323 324 |
static const struct blk_mq_ops mtd_mq_ops = { .queue_rq = mtd_queue_rq, }; |
1da177e4c Linux-2.6.12-rc2 |
325 326 327 |
int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) { struct mtd_blktrans_ops *tr = new->tr; |
71a928c0e [MTD] Use list_fo... |
328 |
struct mtd_blktrans_dev *d; |
1da177e4c Linux-2.6.12-rc2 |
329 330 |
int last_devnum = -1; struct gendisk *gd; |
a86386225 mtd: blktrans: re... |
331 |
int ret; |
1da177e4c Linux-2.6.12-rc2 |
332 |
|
b3561ea94 Clean up mutex_tr... |
333 |
if (mutex_trylock(&mtd_table_mutex)) { |
48b192686 [PATCH] sem2mutex... |
334 |
mutex_unlock(&mtd_table_mutex); |
1da177e4c Linux-2.6.12-rc2 |
335 336 |
BUG(); } |
048d87199 mtd: blktrans: Ho... |
337 |
mutex_lock(&blktrans_ref_mutex); |
71a928c0e [MTD] Use list_fo... |
338 |
list_for_each_entry(d, &tr->devs, list) { |
1da177e4c Linux-2.6.12-rc2 |
339 340 341 342 343 344 345 346 347 348 |
if (new->devnum == -1) { /* Use first free number */ if (d->devnum != last_devnum+1) { /* Found a free devnum. Plug it in here */ new->devnum = last_devnum+1; list_add_tail(&new->list, &d->list); goto added; } } else if (d->devnum == new->devnum) { /* Required number taken */ |
048d87199 mtd: blktrans: Ho... |
349 |
mutex_unlock(&blktrans_ref_mutex); |
1da177e4c Linux-2.6.12-rc2 |
350 351 352 353 354 |
return -EBUSY; } else if (d->devnum > new->devnum) { /* Required number was free */ list_add_tail(&new->list, &d->list); goto added; |
97894cda5 [MTD] core: Clean... |
355 |
} |
1da177e4c Linux-2.6.12-rc2 |
356 357 |
last_devnum = d->devnum; } |
a86386225 mtd: blktrans: re... |
358 359 |
ret = -EBUSY; |
1da177e4c Linux-2.6.12-rc2 |
360 361 |
if (new->devnum == -1) new->devnum = last_devnum+1; |
4d3a8534b mtd: Raise limit ... |
362 363 364 365 |
/* Check that the device and any partitions will get valid * minor numbers and that the disk naming code below can cope * with this number. */ if (new->devnum > (MINORMASK >> tr->part_bits) || |
048d87199 mtd: blktrans: Ho... |
366 367 |
(tr->part_bits && new->devnum >= 27 * 26)) { mutex_unlock(&blktrans_ref_mutex); |
a86386225 mtd: blktrans: re... |
368 |
goto error1; |
048d87199 mtd: blktrans: Ho... |
369 |
} |
1da177e4c Linux-2.6.12-rc2 |
370 |
|
1da177e4c Linux-2.6.12-rc2 |
371 372 |
list_add_tail(&new->list, &tr->devs); added: |
048d87199 mtd: blktrans: Ho... |
373 |
mutex_unlock(&blktrans_ref_mutex); |
ce37ab42a [MTD] Always init... |
374 |
mutex_init(&new->lock); |
048d87199 mtd: blktrans: Ho... |
375 |
kref_init(&new->ref); |
1da177e4c Linux-2.6.12-rc2 |
376 377 |
if (!tr->writesect) new->readonly = 1; |
a86386225 mtd: blktrans: re... |
378 379 |
/* Create gendisk */ ret = -ENOMEM; |
1da177e4c Linux-2.6.12-rc2 |
380 |
gd = alloc_disk(1 << tr->part_bits); |
a86386225 mtd: blktrans: re... |
381 382 383 384 385 386 |
if (!gd) goto error2; new->disk = gd; gd->private_data = new; |
1da177e4c Linux-2.6.12-rc2 |
387 388 |
gd->major = tr->major; gd->first_minor = (new->devnum) << tr->part_bits; |
9329c5eb5 mtd: mtd_blkdev: ... |
389 |
gd->fops = &mtd_block_ops; |
97894cda5 [MTD] core: Clean... |
390 |
|
65a8de36b [MTD] mtd_blkdevs... |
391 392 393 394 395 396 397 398 399 400 401 402 |
if (tr->part_bits) if (new->devnum < 26) snprintf(gd->disk_name, sizeof(gd->disk_name), "%s%c", tr->name, 'a' + new->devnum); else snprintf(gd->disk_name, sizeof(gd->disk_name), "%s%c%c", tr->name, 'a' - 1 + new->devnum / 26, 'a' + new->devnum % 26); else snprintf(gd->disk_name, sizeof(gd->disk_name), "%s%d", tr->name, new->devnum); |
1da177e4c Linux-2.6.12-rc2 |
403 |
|
2ce401d56 mtd: blktrans: fi... |
404 |
set_capacity(gd, ((u64)new->size * tr->blksize) >> 9); |
1da177e4c Linux-2.6.12-rc2 |
405 |
|
a86386225 mtd: blktrans: re... |
406 407 |
/* Create the request queue */ spin_lock_init(&new->queue_lock); |
891b7c5fb mtd_blkdevs: conv... |
408 |
INIT_LIST_HEAD(&new->rq_list); |
a86386225 mtd: blktrans: re... |
409 |
|
891b7c5fb mtd_blkdevs: conv... |
410 411 |
new->tag_set = kzalloc(sizeof(*new->tag_set), GFP_KERNEL); if (!new->tag_set) |
a86386225 mtd: blktrans: re... |
412 |
goto error3; |
891b7c5fb mtd_blkdevs: conv... |
413 414 415 416 417 418 419 |
new->rq = blk_mq_init_sq_queue(new->tag_set, &mtd_mq_ops, 2, BLK_MQ_F_SHOULD_MERGE | BLK_MQ_F_BLOCKING); if (IS_ERR(new->rq)) { ret = PTR_ERR(new->rq); new->rq = NULL; goto error4; } |
566c0d6a7 mtd: mtd_blkdevs:... |
420 |
if (tr->flush) |
fec3ff5d1 mtd: switch to us... |
421 |
blk_queue_write_cache(new->rq, true, false); |
566c0d6a7 mtd: mtd_blkdevs:... |
422 |
|
a86386225 mtd: blktrans: re... |
423 424 |
new->rq->queuedata = new; blk_queue_logical_block_size(new->rq, tr->blksize); |
8b904b5b6 block: Use blk_qu... |
425 426 |
blk_queue_flag_set(QUEUE_FLAG_NONROT, new->rq); blk_queue_flag_clear(QUEUE_FLAG_ADD_RANDOM, new->rq); |
16f7eca58 mtd: mark block d... |
427 |
|
115ee88c1 mtd_blkdevs: Set ... |
428 |
if (tr->discard) { |
8b904b5b6 block: Use blk_qu... |
429 |
blk_queue_flag_set(QUEUE_FLAG_DISCARD, new->rq); |
2bb4cd5cc block: have drive... |
430 |
blk_queue_max_discard_sectors(new->rq, UINT_MAX); |
115ee88c1 mtd_blkdevs: Set ... |
431 |
} |
a86386225 mtd: blktrans: re... |
432 433 |
gd->queue = new->rq; |
1da177e4c Linux-2.6.12-rc2 |
434 435 |
if (new->readonly) set_disk_ro(gd, 1); |
fef912bf8 block: genhd: add... |
436 |
device_add_disk(&new->mtd->dev, gd, NULL); |
026ec5788 mtd: blktrans: al... |
437 |
|
133fa8c7d mtd: Few follow u... |
438 439 |
if (new->disk_attributes) { ret = sysfs_create_group(&disk_to_dev(gd)->kobj, |
026ec5788 mtd: blktrans: al... |
440 |
new->disk_attributes); |
133fa8c7d mtd: Few follow u... |
441 442 |
WARN_ON(ret); } |
1da177e4c Linux-2.6.12-rc2 |
443 |
return 0; |
a86386225 mtd: blktrans: re... |
444 |
error4: |
891b7c5fb mtd_blkdevs: conv... |
445 |
kfree(new->tag_set); |
a86386225 mtd: blktrans: re... |
446 447 448 449 450 |
error3: put_disk(new->disk); error2: list_del(&new->list); error1: |
a86386225 mtd: blktrans: re... |
451 |
return ret; |
1da177e4c Linux-2.6.12-rc2 |
452 453 454 455 |
} int del_mtd_blktrans_dev(struct mtd_blktrans_dev *old) { |
048d87199 mtd: blktrans: Ho... |
456 |
unsigned long flags; |
b3561ea94 Clean up mutex_tr... |
457 |
if (mutex_trylock(&mtd_table_mutex)) { |
48b192686 [PATCH] sem2mutex... |
458 |
mutex_unlock(&mtd_table_mutex); |
1da177e4c Linux-2.6.12-rc2 |
459 460 |
BUG(); } |
026ec5788 mtd: blktrans: al... |
461 462 463 |
if (old->disk_attributes) sysfs_remove_group(&disk_to_dev(old->disk)->kobj, old->disk_attributes); |
dba76c033 mtd: blkdevs: fix... |
464 465 |
/* Stop new requests to arrive */ del_gendisk(old->disk); |
048d87199 mtd: blktrans: Ho... |
466 467 468 |
/* Kill current requests */ spin_lock_irqsave(&old->queue_lock, flags); old->rq->queuedata = NULL; |
048d87199 mtd: blktrans: Ho... |
469 |
spin_unlock_irqrestore(&old->queue_lock, flags); |
048d87199 mtd: blktrans: Ho... |
470 |
|
891b7c5fb mtd_blkdevs: conv... |
471 472 473 474 475 |
/* freeze+quiesce queue to ensure all requests are flushed */ blk_mq_freeze_queue(old->rq); blk_mq_quiesce_queue(old->rq); blk_mq_unquiesce_queue(old->rq); blk_mq_unfreeze_queue(old->rq); |
008c751ec mtd: allow to unl... |
476 477 |
/* If the device is currently open, tell trans driver to close it, then put mtd device, and don't touch it again */ |
048d87199 mtd: blktrans: Ho... |
478 |
mutex_lock(&old->lock); |
008c751ec mtd: allow to unl... |
479 480 481 482 |
if (old->open) { if (old->tr->release) old->tr->release(old); __put_mtd_device(old->mtd); |
048d87199 mtd: blktrans: Ho... |
483 |
} |
048d87199 mtd: blktrans: Ho... |
484 485 486 487 |
old->mtd = NULL; mutex_unlock(&old->lock); blktrans_dev_put(old); |
1da177e4c Linux-2.6.12-rc2 |
488 489 490 491 492 |
return 0; } static void blktrans_notify_remove(struct mtd_info *mtd) { |
71a928c0e [MTD] Use list_fo... |
493 494 |
struct mtd_blktrans_ops *tr; struct mtd_blktrans_dev *dev, *next; |
1da177e4c Linux-2.6.12-rc2 |
495 |
|
71a928c0e [MTD] Use list_fo... |
496 497 |
list_for_each_entry(tr, &blktrans_majors, list) list_for_each_entry_safe(dev, next, &tr->devs, list) |
1da177e4c Linux-2.6.12-rc2 |
498 499 |
if (dev->mtd == mtd) tr->remove_dev(dev); |
1da177e4c Linux-2.6.12-rc2 |
500 501 502 503 |
} static void blktrans_notify_add(struct mtd_info *mtd) { |
71a928c0e [MTD] Use list_fo... |
504 |
struct mtd_blktrans_ops *tr; |
1da177e4c Linux-2.6.12-rc2 |
505 506 507 |
if (mtd->type == MTD_ABSENT) return; |
71a928c0e [MTD] Use list_fo... |
508 |
list_for_each_entry(tr, &blktrans_majors, list) |
1da177e4c Linux-2.6.12-rc2 |
509 |
tr->add_mtd(tr, mtd); |
1da177e4c Linux-2.6.12-rc2 |
510 511 512 513 514 515 |
} static struct mtd_notifier blktrans_notifier = { .add = blktrans_notify_add, .remove = blktrans_notify_remove, }; |
97894cda5 [MTD] core: Clean... |
516 |
|
1da177e4c Linux-2.6.12-rc2 |
517 518 |
int register_mtd_blktrans(struct mtd_blktrans_ops *tr) { |
f1332ba2f mtd: Introduce an... |
519 520 |
struct mtd_info *mtd; int ret; |
1da177e4c Linux-2.6.12-rc2 |
521 |
|
97894cda5 [MTD] core: Clean... |
522 |
/* Register the notifier if/when the first device type is |
1da177e4c Linux-2.6.12-rc2 |
523 524 525 526 |
registered, to prevent the link/init ordering from fucking us over. */ if (!blktrans_notifier.list.next) register_mtd_user(&blktrans_notifier); |
1da177e4c Linux-2.6.12-rc2 |
527 |
|
48b192686 [PATCH] sem2mutex... |
528 |
mutex_lock(&mtd_table_mutex); |
1da177e4c Linux-2.6.12-rc2 |
529 530 |
ret = register_blkdev(tr->major, tr->name); |
6fe4c5903 MTD: Fix wrong ch... |
531 |
if (ret < 0) { |
1da177e4c Linux-2.6.12-rc2 |
532 533 534 |
printk(KERN_WARNING "Unable to register %s block device on major %d: %d ", tr->name, tr->major, ret); |
48b192686 [PATCH] sem2mutex... |
535 |
mutex_unlock(&mtd_table_mutex); |
1da177e4c Linux-2.6.12-rc2 |
536 537 |
return ret; } |
eae9acd13 Support 'discard ... |
538 |
|
6fe4c5903 MTD: Fix wrong ch... |
539 540 |
if (ret) tr->major = ret; |
191876729 [MTD] Allow varia... |
541 |
tr->blkshift = ffs(tr->blksize) - 1; |
1da177e4c Linux-2.6.12-rc2 |
542 |
|
1da177e4c Linux-2.6.12-rc2 |
543 544 |
INIT_LIST_HEAD(&tr->devs); list_add(&tr->list, &blktrans_majors); |
f1332ba2f mtd: Introduce an... |
545 546 547 |
mtd_for_each_device(mtd) if (mtd->type != MTD_ABSENT) tr->add_mtd(tr, mtd); |
1da177e4c Linux-2.6.12-rc2 |
548 |
|
48b192686 [PATCH] sem2mutex... |
549 |
mutex_unlock(&mtd_table_mutex); |
1da177e4c Linux-2.6.12-rc2 |
550 551 552 553 554 |
return 0; } int deregister_mtd_blktrans(struct mtd_blktrans_ops *tr) { |
71a928c0e [MTD] Use list_fo... |
555 |
struct mtd_blktrans_dev *dev, *next; |
1da177e4c Linux-2.6.12-rc2 |
556 |
|
48b192686 [PATCH] sem2mutex... |
557 |
mutex_lock(&mtd_table_mutex); |
1da177e4c Linux-2.6.12-rc2 |
558 |
|
1da177e4c Linux-2.6.12-rc2 |
559 560 |
/* Remove it from the list of active majors */ list_del(&tr->list); |
71a928c0e [MTD] Use list_fo... |
561 |
list_for_each_entry_safe(dev, next, &tr->devs, list) |
1da177e4c Linux-2.6.12-rc2 |
562 |
tr->remove_dev(dev); |
1da177e4c Linux-2.6.12-rc2 |
563 |
|
1da177e4c Linux-2.6.12-rc2 |
564 |
unregister_blkdev(tr->major, tr->name); |
48b192686 [PATCH] sem2mutex... |
565 |
mutex_unlock(&mtd_table_mutex); |
1da177e4c Linux-2.6.12-rc2 |
566 |
|
373ebfbf1 BUG_ON() Conversi... |
567 |
BUG_ON(!list_empty(&tr->devs)); |
1da177e4c Linux-2.6.12-rc2 |
568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 |
return 0; } static void __exit mtd_blktrans_exit(void) { /* No race here -- if someone's currently in register_mtd_blktrans we're screwed anyway. */ if (blktrans_notifier.list.next) unregister_mtd_user(&blktrans_notifier); } module_exit(mtd_blktrans_exit); EXPORT_SYMBOL_GPL(register_mtd_blktrans); EXPORT_SYMBOL_GPL(deregister_mtd_blktrans); EXPORT_SYMBOL_GPL(add_mtd_blktrans_dev); EXPORT_SYMBOL_GPL(del_mtd_blktrans_dev); MODULE_AUTHOR("David Woodhouse <dwmw2@infradead.org>"); MODULE_LICENSE("GPL"); MODULE_DESCRIPTION("Common interface to block layer for MTD 'translation layers'"); |