|
@@ -9,7 +9,15 @@
|
|
|
|
|
|
|
|
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
|
|
#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 <linux/module.h>
|
|
#include <linux/module.h>
|
|
|
|
|
+#include <linux/delay.h>
|
|
|
#include <linux/fs.h>
|
|
#include <linux/fs.h>
|
|
|
#include <linux/blkdev.h>
|
|
#include <linux/blkdev.h>
|
|
|
#include <linux/bio.h>
|
|
#include <linux/bio.h>
|
|
@@ -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;
|
|
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;
|
|
struct block2mtd_dev *dev;
|
|
|
char *name;
|
|
char *name;
|
|
|
|
|
|
|
@@ -225,15 +237,28 @@ static struct block2mtd_dev *add_device(char *devname, int erase_size)
|
|
|
|
|
|
|
|
/* Get a handle on the device */
|
|
/* Get a handle on the device */
|
|
|
bdev = blkdev_get_by_path(devname, mode, dev);
|
|
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
|
|
#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 */
|
|
/* Device didn't get added, so free the entry */
|
|
|
goto err_destroy_mutex;
|
|
goto err_destroy_mutex;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
list_add(&dev->list, &blkmtd_device_list);
|
|
list_add(&dev->list, &blkmtd_device_list);
|
|
|
pr_info("mtd%d: [%s] erase_size = %dKiB [%d]\n",
|
|
pr_info("mtd%d: [%s] erase_size = %dKiB [%d]\n",
|
|
|
dev->mtd.index,
|
|
dev->mtd.index,
|
|
@@ -348,16 +374,19 @@ static inline void kill_final_newline(char *str)
|
|
|
|
|
|
|
|
#ifndef MODULE
|
|
#ifndef MODULE
|
|
|
static int block2mtd_init_called = 0;
|
|
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
|
|
#endif
|
|
|
|
|
|
|
|
static int block2mtd_setup2(const char *val)
|
|
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 *str = buf;
|
|
|
char *token[2];
|
|
char *token[2];
|
|
|
char *name;
|
|
char *name;
|
|
|
size_t erase_size = PAGE_SIZE;
|
|
size_t erase_size = PAGE_SIZE;
|
|
|
|
|
+ unsigned long timeout = MTD_DEFAULT_TIMEOUT;
|
|
|
int i, ret;
|
|
int i, ret;
|
|
|
|
|
|
|
|
if (strnlen(val, sizeof(buf)) >= sizeof(buf)) {
|
|
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;
|
|
return 0;
|
|
|
}
|
|
}
|
|
@@ -463,8 +492,7 @@ static void block2mtd_exit(void)
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-
|
|
|
|
|
-module_init(block2mtd_init);
|
|
|
|
|
|
|
+late_initcall(block2mtd_init);
|
|
|
module_exit(block2mtd_exit);
|
|
module_exit(block2mtd_exit);
|
|
|
|
|
|
|
|
MODULE_LICENSE("GPL");
|
|
MODULE_LICENSE("GPL");
|