]> git.kernelconcepts.de Git - karo-tx-linux.git/blob - drivers/mtd/devices/block2mtd.c
Merge master.kernel.org:/pub/scm/linux/kernel/git/davem/net-2.6
[karo-tx-linux.git] / drivers / mtd / devices / block2mtd.c
1 /*
2  * $Id: block2mtd.c,v 1.30 2005/11/29 14:48:32 gleixner Exp $
3  *
4  * block2mtd.c - create an mtd from a block device
5  *
6  * Copyright (C) 2001,2002      Simon Evans <spse@secret.org.uk>
7  * Copyright (C) 2004-2006      Jörn Engel <joern@wh.fh-wedel.de>
8  *
9  * Licence: GPL
10  */
11 #include <linux/module.h>
12 #include <linux/fs.h>
13 #include <linux/blkdev.h>
14 #include <linux/bio.h>
15 #include <linux/pagemap.h>
16 #include <linux/list.h>
17 #include <linux/init.h>
18 #include <linux/mtd/mtd.h>
19 #include <linux/buffer_head.h>
20 #include <linux/mutex.h>
21 #include <linux/mount.h>
22
23 #define VERSION "$Revision: 1.30 $"
24
25
26 #define ERROR(fmt, args...) printk(KERN_ERR "block2mtd: " fmt "\n" , ## args)
27 #define INFO(fmt, args...) printk(KERN_INFO "block2mtd: " fmt "\n" , ## args)
28
29
30 /* Info for the block device */
31 struct block2mtd_dev {
32         struct list_head list;
33         struct block_device *blkdev;
34         struct mtd_info mtd;
35         struct mutex write_mutex;
36 };
37
38
39 /* Static info about the MTD, used in cleanup_module */
40 static LIST_HEAD(blkmtd_device_list);
41
42
43 static struct page* page_read(struct address_space *mapping, int index)
44 {
45         filler_t *filler = (filler_t*)mapping->a_ops->readpage;
46         return read_cache_page(mapping, index, filler, NULL);
47 }
48
49
50 /* erase a specified part of the device */
51 static int _block2mtd_erase(struct block2mtd_dev *dev, loff_t to, size_t len)
52 {
53         struct address_space *mapping = dev->blkdev->bd_inode->i_mapping;
54         struct page *page;
55         int index = to >> PAGE_SHIFT;   // page index
56         int pages = len >> PAGE_SHIFT;
57         u_long *p;
58         u_long *max;
59
60         while (pages) {
61                 page = page_read(mapping, index);
62                 if (!page)
63                         return -ENOMEM;
64                 if (IS_ERR(page))
65                         return PTR_ERR(page);
66
67                 max = page_address(page) + PAGE_SIZE;
68                 for (p=page_address(page); p<max; p++)
69                         if (*p != -1UL) {
70                                 lock_page(page);
71                                 memset(page_address(page), 0xff, PAGE_SIZE);
72                                 set_page_dirty(page);
73                                 unlock_page(page);
74                                 break;
75                         }
76
77                 page_cache_release(page);
78                 pages--;
79                 index++;
80         }
81         return 0;
82 }
83 static int block2mtd_erase(struct mtd_info *mtd, struct erase_info *instr)
84 {
85         struct block2mtd_dev *dev = mtd->priv;
86         size_t from = instr->addr;
87         size_t len = instr->len;
88         int err;
89
90         instr->state = MTD_ERASING;
91         mutex_lock(&dev->write_mutex);
92         err = _block2mtd_erase(dev, from, len);
93         mutex_unlock(&dev->write_mutex);
94         if (err) {
95                 ERROR("erase failed err = %d", err);
96                 instr->state = MTD_ERASE_FAILED;
97         } else
98                 instr->state = MTD_ERASE_DONE;
99
100         instr->state = MTD_ERASE_DONE;
101         mtd_erase_callback(instr);
102         return err;
103 }
104
105
106 static int block2mtd_read(struct mtd_info *mtd, loff_t from, size_t len,
107                 size_t *retlen, u_char *buf)
108 {
109         struct block2mtd_dev *dev = mtd->priv;
110         struct page *page;
111         int index = from >> PAGE_SHIFT;
112         int offset = from & (PAGE_SIZE-1);
113         int cpylen;
114
115         if (from > mtd->size)
116                 return -EINVAL;
117         if (from + len > mtd->size)
118                 len = mtd->size - from;
119
120         if (retlen)
121                 *retlen = 0;
122
123         while (len) {
124                 if ((offset + len) > PAGE_SIZE)
125                         cpylen = PAGE_SIZE - offset;    // multiple pages
126                 else
127                         cpylen = len;   // this page
128                 len = len - cpylen;
129
130                 page = page_read(dev->blkdev->bd_inode->i_mapping, index);
131                 if (!page)
132                         return -ENOMEM;
133                 if (IS_ERR(page))
134                         return PTR_ERR(page);
135
136                 memcpy(buf, page_address(page) + offset, cpylen);
137                 page_cache_release(page);
138
139                 if (retlen)
140                         *retlen += cpylen;
141                 buf += cpylen;
142                 offset = 0;
143                 index++;
144         }
145         return 0;
146 }
147
148
149 /* write data to the underlying device */
150 static int _block2mtd_write(struct block2mtd_dev *dev, const u_char *buf,
151                 loff_t to, size_t len, size_t *retlen)
152 {
153         struct page *page;
154         struct address_space *mapping = dev->blkdev->bd_inode->i_mapping;
155         int index = to >> PAGE_SHIFT;   // page index
156         int offset = to & ~PAGE_MASK;   // page offset
157         int cpylen;
158
159         if (retlen)
160                 *retlen = 0;
161         while (len) {
162                 if ((offset+len) > PAGE_SIZE)
163                         cpylen = PAGE_SIZE - offset;    // multiple pages
164                 else
165                         cpylen = len;                   // this page
166                 len = len - cpylen;
167
168                 page = page_read(mapping, index);
169                 if (!page)
170                         return -ENOMEM;
171                 if (IS_ERR(page))
172                         return PTR_ERR(page);
173
174                 if (memcmp(page_address(page)+offset, buf, cpylen)) {
175                         lock_page(page);
176                         memcpy(page_address(page) + offset, buf, cpylen);
177                         set_page_dirty(page);
178                         unlock_page(page);
179                 }
180                 page_cache_release(page);
181
182                 if (retlen)
183                         *retlen += cpylen;
184
185                 buf += cpylen;
186                 offset = 0;
187                 index++;
188         }
189         return 0;
190 }
191
192
193 static int block2mtd_write(struct mtd_info *mtd, loff_t to, size_t len,
194                 size_t *retlen, const u_char *buf)
195 {
196         struct block2mtd_dev *dev = mtd->priv;
197         int err;
198
199         if (!len)
200                 return 0;
201         if (to >= mtd->size)
202                 return -ENOSPC;
203         if (to + len > mtd->size)
204                 len = mtd->size - to;
205
206         mutex_lock(&dev->write_mutex);
207         err = _block2mtd_write(dev, buf, to, len, retlen);
208         mutex_unlock(&dev->write_mutex);
209         if (err > 0)
210                 err = 0;
211         return err;
212 }
213
214
215 /* sync the device - wait until the write queue is empty */
216 static void block2mtd_sync(struct mtd_info *mtd)
217 {
218         struct block2mtd_dev *dev = mtd->priv;
219         sync_blockdev(dev->blkdev);
220         return;
221 }
222
223
224 static void block2mtd_free_device(struct block2mtd_dev *dev)
225 {
226         if (!dev)
227                 return;
228
229         kfree(dev->mtd.name);
230
231         if (dev->blkdev) {
232                 invalidate_mapping_pages(dev->blkdev->bd_inode->i_mapping,
233                                         0, -1);
234                 close_bdev_excl(dev->blkdev);
235         }
236
237         kfree(dev);
238 }
239
240
241 /* FIXME: ensure that mtd->size % erase_size == 0 */
242 static struct block2mtd_dev *add_device(char *devname, int erase_size)
243 {
244         struct block_device *bdev;
245         struct block2mtd_dev *dev;
246
247         if (!devname)
248                 return NULL;
249
250         dev = kzalloc(sizeof(struct block2mtd_dev), GFP_KERNEL);
251         if (!dev)
252                 return NULL;
253
254         /* Get a handle on the device */
255         bdev = open_bdev_excl(devname, O_RDWR, NULL);
256 #ifndef MODULE
257         if (IS_ERR(bdev)) {
258
259                 /* We might not have rootfs mounted at this point. Try
260                    to resolve the device name by other means. */
261
262                 dev_t devt = name_to_dev_t(devname);
263                 if (devt) {
264                         bdev = open_by_devnum(devt, FMODE_WRITE | FMODE_READ);
265                 }
266         }
267 #endif
268
269         if (IS_ERR(bdev)) {
270                 ERROR("error: cannot open device %s", devname);
271                 goto devinit_err;
272         }
273         dev->blkdev = bdev;
274
275         if (MAJOR(bdev->bd_dev) == MTD_BLOCK_MAJOR) {
276                 ERROR("attempting to use an MTD device as a block device");
277                 goto devinit_err;
278         }
279
280         mutex_init(&dev->write_mutex);
281
282         /* Setup the MTD structure */
283         /* make the name contain the block device in */
284         dev->mtd.name = kmalloc(sizeof("block2mtd: ") + strlen(devname),
285                         GFP_KERNEL);
286         if (!dev->mtd.name)
287                 goto devinit_err;
288
289         sprintf(dev->mtd.name, "block2mtd: %s", devname);
290
291         dev->mtd.size = dev->blkdev->bd_inode->i_size & PAGE_MASK;
292         dev->mtd.erasesize = erase_size;
293         dev->mtd.writesize = 1;
294         dev->mtd.type = MTD_RAM;
295         dev->mtd.flags = MTD_CAP_RAM;
296         dev->mtd.erase = block2mtd_erase;
297         dev->mtd.write = block2mtd_write;
298         dev->mtd.writev = default_mtd_writev;
299         dev->mtd.sync = block2mtd_sync;
300         dev->mtd.read = block2mtd_read;
301         dev->mtd.priv = dev;
302         dev->mtd.owner = THIS_MODULE;
303
304         if (add_mtd_device(&dev->mtd)) {
305                 /* Device didnt get added, so free the entry */
306                 goto devinit_err;
307         }
308         list_add(&dev->list, &blkmtd_device_list);
309         INFO("mtd%d: [%s] erase_size = %dKiB [%d]", dev->mtd.index,
310                         dev->mtd.name + strlen("blkmtd: "),
311                         dev->mtd.erasesize >> 10, dev->mtd.erasesize);
312         return dev;
313
314 devinit_err:
315         block2mtd_free_device(dev);
316         return NULL;
317 }
318
319
320 /* This function works similar to reguler strtoul.  In addition, it
321  * allows some suffixes for a more human-readable number format:
322  * ki, Ki, kiB, KiB     - multiply result with 1024
323  * Mi, MiB              - multiply result with 1024^2
324  * Gi, GiB              - multiply result with 1024^3
325  */
326 static int ustrtoul(const char *cp, char **endp, unsigned int base)
327 {
328         unsigned long result = simple_strtoul(cp, endp, base);
329         switch (**endp) {
330         case 'G' :
331                 result *= 1024;
332         case 'M':
333                 result *= 1024;
334         case 'K':
335         case 'k':
336                 result *= 1024;
337         /* By dwmw2 editorial decree, "ki", "Mi" or "Gi" are to be used. */
338                 if ((*endp)[1] == 'i') {
339                         if ((*endp)[2] == 'B')
340                                 (*endp) += 3;
341                         else
342                                 (*endp) += 2;
343                 }
344         }
345         return result;
346 }
347
348
349 static int parse_num(size_t *num, const char *token)
350 {
351         char *endp;
352         size_t n;
353
354         n = (size_t) ustrtoul(token, &endp, 0);
355         if (*endp)
356                 return -EINVAL;
357
358         *num = n;
359         return 0;
360 }
361
362
363 static inline void kill_final_newline(char *str)
364 {
365         char *newline = strrchr(str, '\n');
366         if (newline && !newline[1])
367                 *newline = 0;
368 }
369
370
371 #define parse_err(fmt, args...) do {            \
372         ERROR("block2mtd: " fmt "\n", ## args); \
373         return 0;                               \
374 } while (0)
375
376 #ifndef MODULE
377 static int block2mtd_init_called = 0;
378 static __initdata char block2mtd_paramline[80 + 12]; /* 80 for device, 12 for erase size */
379 #endif
380
381
382 static int block2mtd_setup2(const char *val)
383 {
384         char buf[80 + 12]; /* 80 for device, 12 for erase size */
385         char *str = buf;
386         char *token[2];
387         char *name;
388         size_t erase_size = PAGE_SIZE;
389         int i, ret;
390
391         if (strnlen(val, sizeof(buf)) >= sizeof(buf))
392                 parse_err("parameter too long");
393
394         strcpy(str, val);
395         kill_final_newline(str);
396
397         for (i = 0; i < 2; i++)
398                 token[i] = strsep(&str, ",");
399
400         if (str)
401                 parse_err("too many arguments");
402
403         if (!token[0])
404                 parse_err("no argument");
405
406         name = token[0];
407         if (strlen(name) + 1 > 80)
408                 parse_err("device name too long");
409
410         if (token[1]) {
411                 ret = parse_num(&erase_size, token[1]);
412                 if (ret) {
413                         kfree(name);
414                         parse_err("illegal erase size");
415                 }
416         }
417
418         add_device(name, erase_size);
419
420         return 0;
421 }
422
423
424 static int block2mtd_setup(const char *val, struct kernel_param *kp)
425 {
426 #ifdef MODULE
427         return block2mtd_setup2(val);
428 #else
429         /* If more parameters are later passed in via
430            /sys/module/block2mtd/parameters/block2mtd
431            and block2mtd_init() has already been called,
432            we can parse the argument now. */
433
434         if (block2mtd_init_called)
435                 return block2mtd_setup2(val);
436
437         /* During early boot stage, we only save the parameters
438            here. We must parse them later: if the param passed
439            from kernel boot command line, block2mtd_setup() is
440            called so early that it is not possible to resolve
441            the device (even kmalloc() fails). Deter that work to
442            block2mtd_setup2(). */
443
444         strlcpy(block2mtd_paramline, val, sizeof(block2mtd_paramline));
445
446         return 0;
447 #endif
448 }
449
450
451 module_param_call(block2mtd, block2mtd_setup, NULL, NULL, 0200);
452 MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=<dev>[,<erasesize>]\"");
453
454 static int __init block2mtd_init(void)
455 {
456         int ret = 0;
457         INFO("version " VERSION);
458
459 #ifndef MODULE
460         if (strlen(block2mtd_paramline))
461                 ret = block2mtd_setup2(block2mtd_paramline);
462         block2mtd_init_called = 1;
463 #endif
464
465         return ret;
466 }
467
468
469 static void __devexit block2mtd_exit(void)
470 {
471         struct list_head *pos, *next;
472
473         /* Remove the MTD devices */
474         list_for_each_safe(pos, next, &blkmtd_device_list) {
475                 struct block2mtd_dev *dev = list_entry(pos, typeof(*dev), list);
476                 block2mtd_sync(&dev->mtd);
477                 del_mtd_device(&dev->mtd);
478                 INFO("mtd%d: [%s] removed", dev->mtd.index,
479                                 dev->mtd.name + strlen("blkmtd: "));
480                 list_del(&dev->list);
481                 block2mtd_free_device(dev);
482         }
483 }
484
485
486 module_init(block2mtd_init);
487 module_exit(block2mtd_exit);
488
489 MODULE_LICENSE("GPL");
490 MODULE_AUTHOR("Simon Evans <spse@secret.org.uk> and others");
491 MODULE_DESCRIPTION("Emulate an MTD using a block device");