diff options
| -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 | ||
