diff options
-rw-r--r-- | drivers/mtd/devices/block2mtd.c | 58 |
1 files changed, 43 insertions, 15 deletions
diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c index 66f0405f7e53..b16f3cda97ff 100644 --- a/drivers/mtd/devices/block2mtd.c +++ b/drivers/mtd/devices/block2mtd.c | |||
@@ -9,7 +9,15 @@ | |||
9 | 9 | ||
10 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt | 10 | #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt |
11 | 11 | ||
12 | /* | ||
13 | * When the first attempt at device initialization fails, we may need to | ||
14 | * wait a little bit and retry. This timeout, by default 3 seconds, gives | ||
15 | * device time to start up. Required on BCM2708 and a few other chipsets. | ||
16 | */ | ||
17 | #define MTD_DEFAULT_TIMEOUT 3 | ||
18 | |||
12 | #include <linux/module.h> | 19 | #include <linux/module.h> |
20 | #include <linux/delay.h> | ||
13 | #include <linux/fs.h> | 21 | #include <linux/fs.h> |
14 | #include <linux/blkdev.h> | 22 | #include <linux/blkdev.h> |
15 | #include <linux/bio.h> | 23 | #include <linux/bio.h> |
@@ -209,10 +217,14 @@ static void block2mtd_free_device(struct block2mtd_dev *dev) | |||
209 | } | 217 | } |
210 | 218 | ||
211 | 219 | ||
212 | static struct block2mtd_dev *add_device(char *devname, int erase_size) | 220 | static struct block2mtd_dev *add_device(char *devname, int erase_size, |
221 | int timeout) | ||
213 | { | 222 | { |
223 | #ifndef MODULE | ||
224 | int i; | ||
225 | #endif | ||
214 | const fmode_t mode = FMODE_READ | FMODE_WRITE | FMODE_EXCL; | 226 | const fmode_t mode = FMODE_READ | FMODE_WRITE | FMODE_EXCL; |
215 | struct block_device *bdev; | 227 | struct block_device *bdev = ERR_PTR(-ENODEV); |
216 | struct block2mtd_dev *dev; | 228 | struct block2mtd_dev *dev; |
217 | char *name; | 229 | char *name; |
218 | 230 | ||
@@ -225,15 +237,28 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size) | |||
225 | 237 | ||
226 | /* Get a handle on the device */ | 238 | /* Get a handle on the device */ |
227 | bdev = blkdev_get_by_path(devname, mode, dev); | 239 | bdev = blkdev_get_by_path(devname, mode, dev); |
228 | #ifndef MODULE | ||
229 | if (IS_ERR(bdev)) { | ||
230 | |||
231 | /* We might not have rootfs mounted at this point. Try | ||
232 | to resolve the device name by other means. */ | ||
233 | 240 | ||
234 | dev_t devt = name_to_dev_t(devname); | 241 | #ifndef MODULE |
235 | if (devt) | 242 | /* |
236 | bdev = blkdev_get_by_dev(devt, mode, dev); | 243 | * We might not have the root device mounted at this point. |
244 | * Try to resolve the device name by other means. | ||
245 | */ | ||
246 | for (i = 0; IS_ERR(bdev) && i <= timeout; i++) { | ||
247 | dev_t devt; | ||
248 | |||
249 | if (i) | ||
250 | /* | ||
251 | * Calling wait_for_device_probe in the first loop | ||
252 | * was not enough, sleep for a bit in subsequent | ||
253 | * go-arounds. | ||
254 | */ | ||
255 | msleep(1000); | ||
256 | wait_for_device_probe(); | ||
257 | |||
258 | devt = name_to_dev_t(devname); | ||
259 | if (!devt) | ||
260 | continue; | ||
261 | bdev = blkdev_get_by_dev(devt, mode, dev); | ||
237 | } | 262 | } |
238 | #endif | 263 | #endif |
239 | 264 | ||
@@ -280,6 +305,7 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size) | |||
280 | /* Device didn't get added, so free the entry */ | 305 | /* Device didn't get added, so free the entry */ |
281 | goto err_destroy_mutex; | 306 | goto err_destroy_mutex; |
282 | } | 307 | } |
308 | |||
283 | list_add(&dev->list, &blkmtd_device_list); | 309 | list_add(&dev->list, &blkmtd_device_list); |
284 | pr_info("mtd%d: [%s] erase_size = %dKiB [%d]\n", | 310 | pr_info("mtd%d: [%s] erase_size = %dKiB [%d]\n", |
285 | dev->mtd.index, | 311 | dev->mtd.index, |
@@ -348,16 +374,19 @@ static inline void kill_final_newline(char *str) | |||
348 | 374 | ||
349 | #ifndef MODULE | 375 | #ifndef MODULE |
350 | static int block2mtd_init_called = 0; | 376 | static int block2mtd_init_called = 0; |
351 | static char block2mtd_paramline[80 + 12]; /* 80 for device, 12 for erase size */ | 377 | /* 80 for device, 12 for erase size */ |
378 | static char block2mtd_paramline[80 + 12]; | ||
352 | #endif | 379 | #endif |
353 | 380 | ||
354 | static int block2mtd_setup2(const char *val) | 381 | static int block2mtd_setup2(const char *val) |
355 | { | 382 | { |
356 | char buf[80 + 12]; /* 80 for device, 12 for erase size */ | 383 | /* 80 for device, 12 for erase size, 80 for name, 8 for timeout */ |
384 | char buf[80 + 12 + 80 + 8]; | ||
357 | char *str = buf; | 385 | char *str = buf; |
358 | char *token[2]; | 386 | char *token[2]; |
359 | char *name; | 387 | char *name; |
360 | size_t erase_size = PAGE_SIZE; | 388 | size_t erase_size = PAGE_SIZE; |
389 | unsigned long timeout = MTD_DEFAULT_TIMEOUT; | ||
361 | int i, ret; | 390 | int i, ret; |
362 | 391 | ||
363 | if (strnlen(val, sizeof(buf)) >= sizeof(buf)) { | 392 | if (strnlen(val, sizeof(buf)) >= sizeof(buf)) { |
@@ -395,7 +424,7 @@ static int block2mtd_setup2(const char *val) | |||
395 | } | 424 | } |
396 | } | 425 | } |
397 | 426 | ||
398 | add_device(name, erase_size); | 427 | add_device(name, erase_size, timeout); |
399 | 428 | ||
400 | return 0; | 429 | return 0; |
401 | } | 430 | } |
@@ -463,8 +492,7 @@ static void block2mtd_exit(void) | |||
463 | } | 492 | } |
464 | } | 493 | } |
465 | 494 | ||
466 | 495 | late_initcall(block2mtd_init); | |
467 | module_init(block2mtd_init); | ||
468 | module_exit(block2mtd_exit); | 496 | module_exit(block2mtd_exit); |
469 | 497 | ||
470 | MODULE_LICENSE("GPL"); | 498 | MODULE_LICENSE("GPL"); |