diff --git a/drivers/mtd/devices/block2mtd.c b/drivers/mtd/devices/block2mtd.c index 66f0405f7e535b33f02f71586ffe4bc13b5f1ee0..b16f3cda97ff0a6c12fb9ef3d8830603f5e5dc39 100644 --- a/drivers/mtd/devices/block2mtd.c +++ b/drivers/mtd/devices/block2mtd.c @@ -9,7 +9,15 @@ #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt +/* + * When the first attempt at device initialization fails, we may need to + * wait a little bit and retry. This timeout, by default 3 seconds, gives + * device time to start up. Required on BCM2708 and a few other chipsets. + */ +#define MTD_DEFAULT_TIMEOUT 3 + #include +#include #include #include #include @@ -209,10 +217,14 @@ static void block2mtd_free_device(struct block2mtd_dev *dev) } -static struct block2mtd_dev *add_device(char *devname, int erase_size) +static struct block2mtd_dev *add_device(char *devname, int erase_size, + int timeout) { +#ifndef MODULE + int i; +#endif const fmode_t mode = FMODE_READ | FMODE_WRITE | FMODE_EXCL; - struct block_device *bdev; + struct block_device *bdev = ERR_PTR(-ENODEV); struct block2mtd_dev *dev; char *name; @@ -225,15 +237,28 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size) /* Get a handle on the device */ bdev = blkdev_get_by_path(devname, mode, dev); -#ifndef MODULE - if (IS_ERR(bdev)) { - - /* We might not have rootfs mounted at this point. Try - to resolve the device name by other means. */ - dev_t devt = name_to_dev_t(devname); - if (devt) - bdev = blkdev_get_by_dev(devt, mode, dev); +#ifndef MODULE + /* + * We might not have the root device mounted at this point. + * Try to resolve the device name by other means. + */ + for (i = 0; IS_ERR(bdev) && i <= timeout; i++) { + dev_t devt; + + if (i) + /* + * Calling wait_for_device_probe in the first loop + * was not enough, sleep for a bit in subsequent + * go-arounds. + */ + msleep(1000); + wait_for_device_probe(); + + devt = name_to_dev_t(devname); + if (!devt) + continue; + bdev = blkdev_get_by_dev(devt, mode, dev); } #endif @@ -280,6 +305,7 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size) /* Device didn't get added, so free the entry */ goto err_destroy_mutex; } + list_add(&dev->list, &blkmtd_device_list); pr_info("mtd%d: [%s] erase_size = %dKiB [%d]\n", dev->mtd.index, @@ -348,16 +374,19 @@ static inline void kill_final_newline(char *str) #ifndef MODULE static int block2mtd_init_called = 0; -static char block2mtd_paramline[80 + 12]; /* 80 for device, 12 for erase size */ +/* 80 for device, 12 for erase size */ +static char block2mtd_paramline[80 + 12]; #endif static int block2mtd_setup2(const char *val) { - char buf[80 + 12]; /* 80 for device, 12 for erase size */ + /* 80 for device, 12 for erase size, 80 for name, 8 for timeout */ + char buf[80 + 12 + 80 + 8]; char *str = buf; char *token[2]; char *name; size_t erase_size = PAGE_SIZE; + unsigned long timeout = MTD_DEFAULT_TIMEOUT; int i, ret; if (strnlen(val, sizeof(buf)) >= sizeof(buf)) { @@ -395,7 +424,7 @@ static int block2mtd_setup2(const char *val) } } - add_device(name, erase_size); + add_device(name, erase_size, timeout); return 0; } @@ -463,8 +492,7 @@ static void block2mtd_exit(void) } } - -module_init(block2mtd_init); +late_initcall(block2mtd_init); module_exit(block2mtd_exit); MODULE_LICENSE("GPL");