diff options
Diffstat (limited to 'drivers/mtd/mtd_blkdevs.c')
-rw-r--r-- | drivers/mtd/mtd_blkdevs.c | 74 |
1 files changed, 35 insertions, 39 deletions
diff --git a/drivers/mtd/mtd_blkdevs.c b/drivers/mtd/mtd_blkdevs.c index 839eed8430a2..1409f01406f6 100644 --- a/drivers/mtd/mtd_blkdevs.c +++ b/drivers/mtd/mtd_blkdevs.c | |||
@@ -1,6 +1,4 @@ | |||
1 | /* | 1 | /* |
2 | * $Id: mtd_blkdevs.c,v 1.27 2005/11/07 11:14:20 gleixner Exp $ | ||
3 | * | ||
4 | * (C) 2003 David Woodhouse <dwmw2@infradead.org> | 2 | * (C) 2003 David Woodhouse <dwmw2@infradead.org> |
5 | * | 3 | * |
6 | * Interface to Linux 2.5 block layer for MTD 'translation layers'. | 4 | * Interface to Linux 2.5 block layer for MTD 'translation layers'. |
@@ -34,6 +32,14 @@ struct mtd_blkcore_priv { | |||
34 | spinlock_t queue_lock; | 32 | spinlock_t queue_lock; |
35 | }; | 33 | }; |
36 | 34 | ||
35 | static int blktrans_discard_request(struct request_queue *q, | ||
36 | struct request *req) | ||
37 | { | ||
38 | req->cmd_type = REQ_TYPE_LINUX_BLOCK; | ||
39 | req->cmd[0] = REQ_LB_OP_DISCARD; | ||
40 | return 0; | ||
41 | } | ||
42 | |||
37 | static int do_blktrans_request(struct mtd_blktrans_ops *tr, | 43 | static int do_blktrans_request(struct mtd_blktrans_ops *tr, |
38 | struct mtd_blktrans_dev *dev, | 44 | struct mtd_blktrans_dev *dev, |
39 | struct request *req) | 45 | struct request *req) |
@@ -46,6 +52,10 @@ static int do_blktrans_request(struct mtd_blktrans_ops *tr, | |||
46 | 52 | ||
47 | buf = req->buffer; | 53 | buf = req->buffer; |
48 | 54 | ||
55 | if (req->cmd_type == REQ_TYPE_LINUX_BLOCK && | ||
56 | req->cmd[0] == REQ_LB_OP_DISCARD) | ||
57 | return !tr->discard(dev, block, nsect); | ||
58 | |||
49 | if (!blk_fs_request(req)) | 59 | if (!blk_fs_request(req)) |
50 | return 0; | 60 | return 0; |
51 | 61 | ||
@@ -123,15 +133,12 @@ static void mtd_blktrans_request(struct request_queue *rq) | |||
123 | } | 133 | } |
124 | 134 | ||
125 | 135 | ||
126 | static int blktrans_open(struct inode *i, struct file *f) | 136 | static int blktrans_open(struct block_device *bdev, fmode_t mode) |
127 | { | 137 | { |
128 | struct mtd_blktrans_dev *dev; | 138 | struct mtd_blktrans_dev *dev = bdev->bd_disk->private_data; |
129 | struct mtd_blktrans_ops *tr; | 139 | struct mtd_blktrans_ops *tr = dev->tr; |
130 | int ret = -ENODEV; | 140 | int ret = -ENODEV; |
131 | 141 | ||
132 | dev = i->i_bdev->bd_disk->private_data; | ||
133 | tr = dev->tr; | ||
134 | |||
135 | if (!try_module_get(dev->mtd->owner)) | 142 | if (!try_module_get(dev->mtd->owner)) |
136 | goto out; | 143 | goto out; |
137 | 144 | ||
@@ -154,15 +161,12 @@ static int blktrans_open(struct inode *i, struct file *f) | |||
154 | return ret; | 161 | return ret; |
155 | } | 162 | } |
156 | 163 | ||
157 | static int blktrans_release(struct inode *i, struct file *f) | 164 | static int blktrans_release(struct gendisk *disk, fmode_t mode) |
158 | { | 165 | { |
159 | struct mtd_blktrans_dev *dev; | 166 | struct mtd_blktrans_dev *dev = disk->private_data; |
160 | struct mtd_blktrans_ops *tr; | 167 | struct mtd_blktrans_ops *tr = dev->tr; |
161 | int ret = 0; | 168 | int ret = 0; |
162 | 169 | ||
163 | dev = i->i_bdev->bd_disk->private_data; | ||
164 | tr = dev->tr; | ||
165 | |||
166 | if (tr->release) | 170 | if (tr->release) |
167 | ret = tr->release(dev); | 171 | ret = tr->release(dev); |
168 | 172 | ||
@@ -184,10 +188,10 @@ static int blktrans_getgeo(struct block_device *bdev, struct hd_geometry *geo) | |||
184 | return -ENOTTY; | 188 | return -ENOTTY; |
185 | } | 189 | } |
186 | 190 | ||
187 | static int blktrans_ioctl(struct inode *inode, struct file *file, | 191 | static int blktrans_ioctl(struct block_device *bdev, fmode_t mode, |
188 | unsigned int cmd, unsigned long arg) | 192 | unsigned int cmd, unsigned long arg) |
189 | { | 193 | { |
190 | struct mtd_blktrans_dev *dev = inode->i_bdev->bd_disk->private_data; | 194 | struct mtd_blktrans_dev *dev = bdev->bd_disk->private_data; |
191 | struct mtd_blktrans_ops *tr = dev->tr; | 195 | struct mtd_blktrans_ops *tr = dev->tr; |
192 | 196 | ||
193 | switch (cmd) { | 197 | switch (cmd) { |
@@ -205,14 +209,14 @@ static struct block_device_operations mtd_blktrans_ops = { | |||
205 | .owner = THIS_MODULE, | 209 | .owner = THIS_MODULE, |
206 | .open = blktrans_open, | 210 | .open = blktrans_open, |
207 | .release = blktrans_release, | 211 | .release = blktrans_release, |
208 | .ioctl = blktrans_ioctl, | 212 | .locked_ioctl = blktrans_ioctl, |
209 | .getgeo = blktrans_getgeo, | 213 | .getgeo = blktrans_getgeo, |
210 | }; | 214 | }; |
211 | 215 | ||
212 | int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) | 216 | int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) |
213 | { | 217 | { |
214 | struct mtd_blktrans_ops *tr = new->tr; | 218 | struct mtd_blktrans_ops *tr = new->tr; |
215 | struct list_head *this; | 219 | struct mtd_blktrans_dev *d; |
216 | int last_devnum = -1; | 220 | int last_devnum = -1; |
217 | struct gendisk *gd; | 221 | struct gendisk *gd; |
218 | 222 | ||
@@ -221,8 +225,7 @@ int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) | |||
221 | BUG(); | 225 | BUG(); |
222 | } | 226 | } |
223 | 227 | ||
224 | list_for_each(this, &tr->devs) { | 228 | list_for_each_entry(d, &tr->devs, list) { |
225 | struct mtd_blktrans_dev *d = list_entry(this, struct mtd_blktrans_dev, list); | ||
226 | if (new->devnum == -1) { | 229 | if (new->devnum == -1) { |
227 | /* Use first free number */ | 230 | /* Use first free number */ |
228 | if (d->devnum != last_devnum+1) { | 231 | if (d->devnum != last_devnum+1) { |
@@ -309,33 +312,24 @@ int del_mtd_blktrans_dev(struct mtd_blktrans_dev *old) | |||
309 | 312 | ||
310 | static void blktrans_notify_remove(struct mtd_info *mtd) | 313 | static void blktrans_notify_remove(struct mtd_info *mtd) |
311 | { | 314 | { |
312 | struct list_head *this, *this2, *next; | 315 | struct mtd_blktrans_ops *tr; |
313 | 316 | struct mtd_blktrans_dev *dev, *next; | |
314 | list_for_each(this, &blktrans_majors) { | ||
315 | struct mtd_blktrans_ops *tr = list_entry(this, struct mtd_blktrans_ops, list); | ||
316 | |||
317 | list_for_each_safe(this2, next, &tr->devs) { | ||
318 | struct mtd_blktrans_dev *dev = list_entry(this2, struct mtd_blktrans_dev, list); | ||
319 | 317 | ||
318 | list_for_each_entry(tr, &blktrans_majors, list) | ||
319 | list_for_each_entry_safe(dev, next, &tr->devs, list) | ||
320 | if (dev->mtd == mtd) | 320 | if (dev->mtd == mtd) |
321 | tr->remove_dev(dev); | 321 | tr->remove_dev(dev); |
322 | } | ||
323 | } | ||
324 | } | 322 | } |
325 | 323 | ||
326 | static void blktrans_notify_add(struct mtd_info *mtd) | 324 | static void blktrans_notify_add(struct mtd_info *mtd) |
327 | { | 325 | { |
328 | struct list_head *this; | 326 | struct mtd_blktrans_ops *tr; |
329 | 327 | ||
330 | if (mtd->type == MTD_ABSENT) | 328 | if (mtd->type == MTD_ABSENT) |
331 | return; | 329 | return; |
332 | 330 | ||
333 | list_for_each(this, &blktrans_majors) { | 331 | list_for_each_entry(tr, &blktrans_majors, list) |
334 | struct mtd_blktrans_ops *tr = list_entry(this, struct mtd_blktrans_ops, list); | ||
335 | |||
336 | tr->add_mtd(tr, mtd); | 332 | tr->add_mtd(tr, mtd); |
337 | } | ||
338 | |||
339 | } | 333 | } |
340 | 334 | ||
341 | static struct mtd_notifier blktrans_notifier = { | 335 | static struct mtd_notifier blktrans_notifier = { |
@@ -379,6 +373,10 @@ int register_mtd_blktrans(struct mtd_blktrans_ops *tr) | |||
379 | 373 | ||
380 | tr->blkcore_priv->rq->queuedata = tr; | 374 | tr->blkcore_priv->rq->queuedata = tr; |
381 | blk_queue_hardsect_size(tr->blkcore_priv->rq, tr->blksize); | 375 | blk_queue_hardsect_size(tr->blkcore_priv->rq, tr->blksize); |
376 | if (tr->discard) | ||
377 | blk_queue_set_discard(tr->blkcore_priv->rq, | ||
378 | blktrans_discard_request); | ||
379 | |||
382 | tr->blkshift = ffs(tr->blksize) - 1; | 380 | tr->blkshift = ffs(tr->blksize) - 1; |
383 | 381 | ||
384 | tr->blkcore_priv->thread = kthread_run(mtd_blktrans_thread, tr, | 382 | tr->blkcore_priv->thread = kthread_run(mtd_blktrans_thread, tr, |
@@ -406,7 +404,7 @@ int register_mtd_blktrans(struct mtd_blktrans_ops *tr) | |||
406 | 404 | ||
407 | int deregister_mtd_blktrans(struct mtd_blktrans_ops *tr) | 405 | int deregister_mtd_blktrans(struct mtd_blktrans_ops *tr) |
408 | { | 406 | { |
409 | struct list_head *this, *next; | 407 | struct mtd_blktrans_dev *dev, *next; |
410 | 408 | ||
411 | mutex_lock(&mtd_table_mutex); | 409 | mutex_lock(&mtd_table_mutex); |
412 | 410 | ||
@@ -416,10 +414,8 @@ int deregister_mtd_blktrans(struct mtd_blktrans_ops *tr) | |||
416 | /* Remove it from the list of active majors */ | 414 | /* Remove it from the list of active majors */ |
417 | list_del(&tr->list); | 415 | list_del(&tr->list); |
418 | 416 | ||
419 | list_for_each_safe(this, next, &tr->devs) { | 417 | list_for_each_entry_safe(dev, next, &tr->devs, list) |
420 | struct mtd_blktrans_dev *dev = list_entry(this, struct mtd_blktrans_dev, list); | ||
421 | tr->remove_dev(dev); | 418 | tr->remove_dev(dev); |
422 | } | ||
423 | 419 | ||
424 | blk_cleanup_queue(tr->blkcore_priv->rq); | 420 | blk_cleanup_queue(tr->blkcore_priv->rq); |
425 | unregister_blkdev(tr->major, tr->name); | 421 | unregister_blkdev(tr->major, tr->name); |