aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFelix Fietkau <nbd@openwrt.org>2014-11-09 07:21:13 -0500
committerBrian Norris <computersforpeace@gmail.com>2015-02-24 02:44:12 -0500
commitd6a3f0176fe03c33f2853dfef33e15547e357dd0 (patch)
treecdd2733467a2f092db3f06d6e35fc4ba74f21a35
parentc517d838eb7d07bbe9507871fab3931deccff539 (diff)
mtd: block2mtd: wait until block devices are presented
Ensures that block2mtd is triggered after the block devices are enumerated at boot time. This issue is seen on BCM2835 (Raspberry Pi) systems when mounting JFFS2 block2mtd filesystems, probably because of the delay on enumerating a USB MMC card reader. Signed-off-by: Felix Fietkau <nbd@openwrt.org> Signed-off-by: Rodrigo Freire <rfreire@redhat.com> Signed-off-by: Herton Krzesinski <herton@redhat.com> Signed-off-by: Brian Norris <computersforpeace@gmail.com>
-rw-r--r--drivers/mtd/devices/block2mtd.c58
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
212static struct block2mtd_dev *add_device(char *devname, int erase_size) 220static 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
350static int block2mtd_init_called = 0; 376static int block2mtd_init_called = 0;
351static char block2mtd_paramline[80 + 12]; /* 80 for device, 12 for erase size */ 377/* 80 for device, 12 for erase size */
378static char block2mtd_paramline[80 + 12];
352#endif 379#endif
353 380
354static int block2mtd_setup2(const char *val) 381static 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 495late_initcall(block2mtd_init);
467module_init(block2mtd_init);
468module_exit(block2mtd_exit); 496module_exit(block2mtd_exit);
469 497
470MODULE_LICENSE("GPL"); 498MODULE_LICENSE("GPL");