diff options
Diffstat (limited to 'drivers/mtd/devices/block2mtd.c')
-rw-r--r-- | drivers/mtd/devices/block2mtd.c | 93 |
1 files changed, 63 insertions, 30 deletions
diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c index ede3561be870..401c6a294baa 100644 --- a/drivers/mtd/devices/block2mtd.c +++ b/drivers/mtd/devices/block2mtd.c | |||
@@ -18,6 +18,7 @@ | |||
18 | #include <linux/mtd/mtd.h> | 18 | #include <linux/mtd/mtd.h> |
19 | #include <linux/buffer_head.h> | 19 | #include <linux/buffer_head.h> |
20 | #include <linux/mutex.h> | 20 | #include <linux/mutex.h> |
21 | #include <linux/mount.h> | ||
21 | 22 | ||
22 | #define VERSION "$Revision: 1.30 $" | 23 | #define VERSION "$Revision: 1.30 $" |
23 | 24 | ||
@@ -236,6 +237,8 @@ static int _block2mtd_write(struct block2mtd_dev *dev, const u_char *buf, | |||
236 | } | 237 | } |
237 | return 0; | 238 | return 0; |
238 | } | 239 | } |
240 | |||
241 | |||
239 | static int block2mtd_write(struct mtd_info *mtd, loff_t to, size_t len, | 242 | static int block2mtd_write(struct mtd_info *mtd, loff_t to, size_t len, |
240 | size_t *retlen, const u_char *buf) | 243 | size_t *retlen, const u_char *buf) |
241 | { | 244 | { |
@@ -299,6 +302,19 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size) | |||
299 | 302 | ||
300 | /* Get a handle on the device */ | 303 | /* Get a handle on the device */ |
301 | bdev = open_bdev_excl(devname, O_RDWR, NULL); | 304 | bdev = open_bdev_excl(devname, O_RDWR, NULL); |
305 | #ifndef MODULE | ||
306 | if (IS_ERR(bdev)) { | ||
307 | |||
308 | /* We might not have rootfs mounted at this point. Try | ||
309 | to resolve the device name by other means. */ | ||
310 | |||
311 | dev_t dev = name_to_dev_t(devname); | ||
312 | if (dev != 0) { | ||
313 | bdev = open_by_devnum(dev, FMODE_WRITE | FMODE_READ); | ||
314 | } | ||
315 | } | ||
316 | #endif | ||
317 | |||
302 | if (IS_ERR(bdev)) { | 318 | if (IS_ERR(bdev)) { |
303 | ERROR("error: cannot open device %s", devname); | 319 | ERROR("error: cannot open device %s", devname); |
304 | goto devinit_err; | 320 | goto devinit_err; |
@@ -393,26 +409,6 @@ static int parse_num(size_t *num, const char *token) | |||
393 | } | 409 | } |
394 | 410 | ||
395 | 411 | ||
396 | static int parse_name(char **pname, const char *token, size_t limit) | ||
397 | { | ||
398 | size_t len; | ||
399 | char *name; | ||
400 | |||
401 | len = strlen(token) + 1; | ||
402 | if (len > limit) | ||
403 | return -ENOSPC; | ||
404 | |||
405 | name = kmalloc(len, GFP_KERNEL); | ||
406 | if (!name) | ||
407 | return -ENOMEM; | ||
408 | |||
409 | strcpy(name, token); | ||
410 | |||
411 | *pname = name; | ||
412 | return 0; | ||
413 | } | ||
414 | |||
415 | |||
416 | static inline void kill_final_newline(char *str) | 412 | static inline void kill_final_newline(char *str) |
417 | { | 413 | { |
418 | char *newline = strrchr(str, '\n'); | 414 | char *newline = strrchr(str, '\n'); |
@@ -426,9 +422,15 @@ static inline void kill_final_newline(char *str) | |||
426 | return 0; \ | 422 | return 0; \ |
427 | } while (0) | 423 | } while (0) |
428 | 424 | ||
429 | static int block2mtd_setup(const char *val, struct kernel_param *kp) | 425 | #ifndef MODULE |
426 | static int block2mtd_init_called = 0; | ||
427 | static __initdata char block2mtd_paramline[80 + 12]; /* 80 for device, 12 for erase size */ | ||
428 | #endif | ||
429 | |||
430 | |||
431 | static int block2mtd_setup2(const char *val) | ||
430 | { | 432 | { |
431 | char buf[80+12]; /* 80 for device, 12 for erase size */ | 433 | char buf[80 + 12]; /* 80 for device, 12 for erase size */ |
432 | char *str = buf; | 434 | char *str = buf; |
433 | char *token[2]; | 435 | char *token[2]; |
434 | char *name; | 436 | char *name; |
@@ -450,13 +452,9 @@ static int block2mtd_setup(const char *val, struct kernel_param *kp) | |||
450 | if (!token[0]) | 452 | if (!token[0]) |
451 | parse_err("no argument"); | 453 | parse_err("no argument"); |
452 | 454 | ||
453 | ret = parse_name(&name, token[0], 80); | 455 | name = token[0]; |
454 | if (ret == -ENOMEM) | 456 | if (strlen(name) + 1 > 80) |
455 | parse_err("out of memory"); | 457 | parse_err("device name too long"); |
456 | if (ret == -ENOSPC) | ||
457 | parse_err("name too long"); | ||
458 | if (ret) | ||
459 | return 0; | ||
460 | 458 | ||
461 | if (token[1]) { | 459 | if (token[1]) { |
462 | ret = parse_num(&erase_size, token[1]); | 460 | ret = parse_num(&erase_size, token[1]); |
@@ -472,13 +470,48 @@ static int block2mtd_setup(const char *val, struct kernel_param *kp) | |||
472 | } | 470 | } |
473 | 471 | ||
474 | 472 | ||
473 | static int block2mtd_setup(const char *val, struct kernel_param *kp) | ||
474 | { | ||
475 | #ifdef MODULE | ||
476 | return block2mtd_setup2(val); | ||
477 | #else | ||
478 | /* If more parameters are later passed in via | ||
479 | /sys/module/block2mtd/parameters/block2mtd | ||
480 | and block2mtd_init() has already been called, | ||
481 | we can parse the argument now. */ | ||
482 | |||
483 | if (block2mtd_init_called) | ||
484 | return block2mtd_setup2(val); | ||
485 | |||
486 | /* During early boot stage, we only save the parameters | ||
487 | here. We must parse them later: if the param passed | ||
488 | from kernel boot command line, block2mtd_setup() is | ||
489 | called so early that it is not possible to resolve | ||
490 | the device (even kmalloc() fails). Deter that work to | ||
491 | block2mtd_setup2(). */ | ||
492 | |||
493 | strlcpy(block2mtd_paramline, val, sizeof(block2mtd_paramline)); | ||
494 | |||
495 | return 0; | ||
496 | #endif | ||
497 | } | ||
498 | |||
499 | |||
475 | module_param_call(block2mtd, block2mtd_setup, NULL, NULL, 0200); | 500 | module_param_call(block2mtd, block2mtd_setup, NULL, NULL, 0200); |
476 | MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=<dev>[,<erasesize>]\""); | 501 | MODULE_PARM_DESC(block2mtd, "Device to use. \"block2mtd=<dev>[,<erasesize>]\""); |
477 | 502 | ||
478 | static int __init block2mtd_init(void) | 503 | static int __init block2mtd_init(void) |
479 | { | 504 | { |
505 | int ret = 0; | ||
480 | INFO("version " VERSION); | 506 | INFO("version " VERSION); |
481 | return 0; | 507 | |
508 | #ifndef MODULE | ||
509 | if (strlen(block2mtd_paramline)) | ||
510 | ret = block2mtd_setup2(block2mtd_paramline); | ||
511 | block2mtd_init_called = 1; | ||
512 | #endif | ||
513 | |||
514 | return ret; | ||
482 | } | 515 | } |
483 | 516 | ||
484 | 517 | ||