aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/mtd/mtd_blkdevs.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/mtd/mtd_blkdevs.c')
-rw-r--r--drivers/mtd/mtd_blkdevs.c74
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
35static 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
37static int do_blktrans_request(struct mtd_blktrans_ops *tr, 43static 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
126static int blktrans_open(struct inode *i, struct file *f) 136static 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
157static int blktrans_release(struct inode *i, struct file *f) 164static 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
187static int blktrans_ioctl(struct inode *inode, struct file *file, 191static 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
212int add_mtd_blktrans_dev(struct mtd_blktrans_dev *new) 216int 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
310static void blktrans_notify_remove(struct mtd_info *mtd) 313static 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
326static void blktrans_notify_add(struct mtd_info *mtd) 324static 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
341static struct mtd_notifier blktrans_notifier = { 335static 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
407int deregister_mtd_blktrans(struct mtd_blktrans_ops *tr) 405int 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);