> OK, let’s do that as a workaround and hope that deferred probes won’t overlap 
> past late_initcall()
What about using register_mtd_user function: routerboot can call
rb_hardconfig_init and rb_softconfig_init when mtd subsystem notifies
it about a new mtd device? It works.

---
 .../drivers/platform/mikrotik/rb_hardconfig.c | 12 ++++------
 .../drivers/platform/mikrotik/rb_softconfig.c | 12 ++++------
 .../drivers/platform/mikrotik/routerboot.c    | 24 +++++++++++++------
 .../drivers/platform/mikrotik/routerboot.h    |  5 ++--
 4 files changed, 30 insertions(+), 23 deletions(-)

diff --git 
a/target/linux/generic/files/drivers/platform/mikrotik/rb_hardconfig.c
b/target/linux/generic/files/drivers/platform/mikrotik/rb_hardconfig.c
index e6a6928896..724851474e 100644
--- a/target/linux/generic/files/drivers/platform/mikrotik/rb_hardconfig.c
+++ b/target/linux/generic/files/drivers/platform/mikrotik/rb_hardconfig.c
@@ -676,10 +676,9 @@ static ssize_t hc_wlan_data_bin_read(struct file
*filp, struct kobject *kobj,
     return count;
 }

-int __init rb_hardconfig_init(struct kobject *rb_kobj)
+int __init rb_hardconfig_init(struct kobject *rb_kobj, struct mtd_info *mtd)
 {
     struct kobject *hc_wlan_kobj;
-    struct mtd_info *mtd;
     size_t bytes_read, buflen, outlen;
     const u8 *buf;
     void *outbuf;
@@ -690,20 +689,19 @@ int __init rb_hardconfig_init(struct kobject *rb_kobj)
     hc_kobj = NULL;
     hc_wlan_kobj = NULL;

-    // TODO allow override
-    mtd = get_mtd_device_nm(RB_MTD_HARD_CONFIG);
-    if (IS_ERR(mtd))
+    ret = __get_mtd_device(mtd);
+    if (IS_ERR(ret))
         return -ENODEV;

     hc_buflen = mtd->size;
     hc_buf = kmalloc(hc_buflen, GFP_KERNEL);
     if (!hc_buf) {
-        put_mtd_device(mtd);
+        __put_mtd_device(mtd);
         return -ENOMEM;
     }

     ret = mtd_read(mtd, 0, hc_buflen, &bytes_read, hc_buf);
-    put_mtd_device(mtd);
+    __put_mtd_device(mtd);

     if (ret)
         goto fail;
diff --git 
a/target/linux/generic/files/drivers/platform/mikrotik/rb_softconfig.c
b/target/linux/generic/files/drivers/platform/mikrotik/rb_softconfig.c
index 070bd32d5a..59c42e4cf4 100644
--- a/target/linux/generic/files/drivers/platform/mikrotik/rb_softconfig.c
+++ b/target/linux/generic/files/drivers/platform/mikrotik/rb_softconfig.c
@@ -705,9 +705,8 @@ mtdfail:

 static struct kobj_attribute sc_kattrcommit = __ATTR(commit,
RB_SC_RMODE|RB_SC_WMODE, sc_commit_show, sc_commit_store);

-int __init rb_softconfig_init(struct kobject *rb_kobj)
+int __init rb_softconfig_init(struct kobject *rb_kobj, struct mtd_info *mtd)
 {
-    struct mtd_info *mtd;
     size_t bytes_read, buflen;
     const u8 *buf;
     int i, ret;
@@ -716,20 +715,19 @@ int __init rb_softconfig_init(struct kobject *rb_kobj)
     sc_buf = NULL;
     sc_kobj = NULL;

-    // TODO allow override
-    mtd = get_mtd_device_nm(RB_MTD_SOFT_CONFIG);
-    if (IS_ERR(mtd))
+    ret = __get_mtd_device(mtd);
+    if (IS_ERR(ret))
         return -ENODEV;

     sc_buflen = mtd->size;
     sc_buf = kmalloc(sc_buflen, GFP_KERNEL);
     if (!sc_buf) {
-        put_mtd_device(mtd);
+        __put_mtd_device(mtd);
         return -ENOMEM;
     }

     ret = mtd_read(mtd, 0, sc_buflen, &bytes_read, sc_buf);
-    put_mtd_device(mtd);
+    __put_mtd_device(mtd);

     if (ret)
         goto fail;
diff --git a/target/linux/generic/files/drivers/platform/mikrotik/routerboot.c
b/target/linux/generic/files/drivers/platform/mikrotik/routerboot.c
index 4c8c0bfac5..77f39709ce 100644
--- a/target/linux/generic/files/drivers/platform/mikrotik/routerboot.c
+++ b/target/linux/generic/files/drivers/platform/mikrotik/routerboot.c
@@ -160,25 +160,35 @@ fail:
     return ret;
 }

+static void routerboot_mtd_notifier_add(struct mtd_info *mtd)
+{
+    if (mtd->type != MTD_NORFLASH)
+        return;
+    if (!strcmp(mtd->name, RB_MTD_HARD_CONFIG)) {
+        rb_hardconfig_init(rb_kobj, mtd);
+    } else if (!strcmp(mtd->name, RB_MTD_SOFT_CONFIG)) {
+        rb_softconfig_init(rb_kobj, mtd);
+    }
+}
+
+static struct mtd_notifier routerboot_mtd_notifier = {
+        .add = routerboot_mtd_notifier_add,
+};
+
 static int __init routerboot_init(void)
 {
     rb_kobj = kobject_create_and_add("mikrotik", firmware_kobj);
     if (!rb_kobj)
         return -ENOMEM;

-    /*
-     * We ignore the following return values and always register.
-     * These init() routines are designed so that their failed state is
-     * always manageable by the corresponding exit() calls.
-     */
-    rb_hardconfig_init(rb_kobj);
-    rb_softconfig_init(rb_kobj);
+    register_mtd_user(&routerboot_mtd_notifier);

     return 0;
 }

 static void __exit routerboot_exit(void)
 {
+    unregister_mtd_user(&routerboot_mtd_notifier);
     rb_softconfig_exit();
     rb_hardconfig_exit();
     kobject_put(rb_kobj);    // recursive afaict
diff --git a/target/linux/generic/files/drivers/platform/mikrotik/routerboot.h
b/target/linux/generic/files/drivers/platform/mikrotik/routerboot.h
index 67d89808d5..5277a3cd94 100644
--- a/target/linux/generic/files/drivers/platform/mikrotik/routerboot.h
+++ b/target/linux/generic/files/drivers/platform/mikrotik/routerboot.h
@@ -10,6 +10,7 @@
 #define _ROUTERBOOT_H_

 #include <linux/types.h>
+#include <linux/mtd/mtd.h>

 // these magic values are stored in cpu-endianness on flash
 #define RB_MAGIC_HARD    (('H') | ('a' << 8) | ('r' << 16) | ('d' << 24))
@@ -25,10 +26,10 @@
 int routerboot_tag_find(const u8 *bufhead, const size_t buflen, const
u16 tag_id, u16 *pld_ofs, u16 *pld_len);
 int routerboot_rle_decode(const u8 *in, size_t inlen, u8 *out, size_t *outlen);

-int __init rb_hardconfig_init(struct kobject *rb_kobj);
+int __init rb_hardconfig_init(struct kobject *rb_kobj, struct mtd_info *mtd);
 void __exit rb_hardconfig_exit(void);

-int __init rb_softconfig_init(struct kobject *rb_kobj);
+int __init rb_softconfig_init(struct kobject *rb_kobj, struct mtd_info *mtd);
 void __exit rb_softconfig_exit(void);

 ssize_t routerboot_tag_show_string(const u8 *pld, u16 pld_len, char *buf);
--

Regards, Denis
From b82bebe35d2e26d0dc2fbf4ac2cef6592aff7722 Mon Sep 17 00:00:00 2001
From: Denis Kalashnikov <denis281...@gmail.com>
Date: Fri, 12 Nov 2021 15:25:21 +0300
Subject: [PATCH] routerboot: fix mtd nodev error

We get this error when SPI NOR probe is called _after_
routerboot init.

Signed-off-by: Denis Kalashnikov <denis281...@gmail.com>
---
 .../drivers/platform/mikrotik/rb_hardconfig.c | 12 ++++------
 .../drivers/platform/mikrotik/rb_softconfig.c | 12 ++++------
 .../drivers/platform/mikrotik/routerboot.c    | 24 +++++++++++++------
 .../drivers/platform/mikrotik/routerboot.h    |  5 ++--
 4 files changed, 30 insertions(+), 23 deletions(-)

diff --git a/target/linux/generic/files/drivers/platform/mikrotik/rb_hardconfig.c b/target/linux/generic/files/drivers/platform/mikrotik/rb_hardconfig.c
index e6a6928896..724851474e 100644
--- a/target/linux/generic/files/drivers/platform/mikrotik/rb_hardconfig.c
+++ b/target/linux/generic/files/drivers/platform/mikrotik/rb_hardconfig.c
@@ -676,10 +676,9 @@ static ssize_t hc_wlan_data_bin_read(struct file *filp, struct kobject *kobj,
 	return count;
 }
 
-int __init rb_hardconfig_init(struct kobject *rb_kobj)
+int __init rb_hardconfig_init(struct kobject *rb_kobj, struct mtd_info *mtd)
 {
 	struct kobject *hc_wlan_kobj;
-	struct mtd_info *mtd;
 	size_t bytes_read, buflen, outlen;
 	const u8 *buf;
 	void *outbuf;
@@ -690,20 +689,19 @@ int __init rb_hardconfig_init(struct kobject *rb_kobj)
 	hc_kobj = NULL;
 	hc_wlan_kobj = NULL;
 
-	// TODO allow override
-	mtd = get_mtd_device_nm(RB_MTD_HARD_CONFIG);
-	if (IS_ERR(mtd))
+	ret = __get_mtd_device(mtd);
+	if (IS_ERR(ret))
 		return -ENODEV;
 
 	hc_buflen = mtd->size;
 	hc_buf = kmalloc(hc_buflen, GFP_KERNEL);
 	if (!hc_buf) {
-		put_mtd_device(mtd);
+		__put_mtd_device(mtd);
 		return -ENOMEM;
 	}
 
 	ret = mtd_read(mtd, 0, hc_buflen, &bytes_read, hc_buf);
-	put_mtd_device(mtd);
+	__put_mtd_device(mtd);
 
 	if (ret)
 		goto fail;
diff --git a/target/linux/generic/files/drivers/platform/mikrotik/rb_softconfig.c b/target/linux/generic/files/drivers/platform/mikrotik/rb_softconfig.c
index 070bd32d5a..59c42e4cf4 100644
--- a/target/linux/generic/files/drivers/platform/mikrotik/rb_softconfig.c
+++ b/target/linux/generic/files/drivers/platform/mikrotik/rb_softconfig.c
@@ -705,9 +705,8 @@ mtdfail:
 
 static struct kobj_attribute sc_kattrcommit = __ATTR(commit, RB_SC_RMODE|RB_SC_WMODE, sc_commit_show, sc_commit_store);
 
-int __init rb_softconfig_init(struct kobject *rb_kobj)
+int __init rb_softconfig_init(struct kobject *rb_kobj, struct mtd_info *mtd)
 {
-	struct mtd_info *mtd;
 	size_t bytes_read, buflen;
 	const u8 *buf;
 	int i, ret;
@@ -716,20 +715,19 @@ int __init rb_softconfig_init(struct kobject *rb_kobj)
 	sc_buf = NULL;
 	sc_kobj = NULL;
 
-	// TODO allow override
-	mtd = get_mtd_device_nm(RB_MTD_SOFT_CONFIG);
-	if (IS_ERR(mtd))
+	ret = __get_mtd_device(mtd);
+	if (IS_ERR(ret))
 		return -ENODEV;
 
 	sc_buflen = mtd->size;
 	sc_buf = kmalloc(sc_buflen, GFP_KERNEL);
 	if (!sc_buf) {
-		put_mtd_device(mtd);
+		__put_mtd_device(mtd);
 		return -ENOMEM;
 	}
 
 	ret = mtd_read(mtd, 0, sc_buflen, &bytes_read, sc_buf);
-	put_mtd_device(mtd);
+	__put_mtd_device(mtd);
 
 	if (ret)
 		goto fail;
diff --git a/target/linux/generic/files/drivers/platform/mikrotik/routerboot.c b/target/linux/generic/files/drivers/platform/mikrotik/routerboot.c
index 4c8c0bfac5..77f39709ce 100644
--- a/target/linux/generic/files/drivers/platform/mikrotik/routerboot.c
+++ b/target/linux/generic/files/drivers/platform/mikrotik/routerboot.c
@@ -160,25 +160,35 @@ fail:
 	return ret;
 }
 
+static void routerboot_mtd_notifier_add(struct mtd_info *mtd)
+{
+	if (mtd->type != MTD_NORFLASH)
+		return;
+	if (!strcmp(mtd->name, RB_MTD_HARD_CONFIG)) {
+		rb_hardconfig_init(rb_kobj, mtd);
+	} else if (!strcmp(mtd->name, RB_MTD_SOFT_CONFIG)) {
+		rb_softconfig_init(rb_kobj, mtd);
+	}
+}
+
+static struct mtd_notifier routerboot_mtd_notifier = {
+        .add = routerboot_mtd_notifier_add,
+};
+
 static int __init routerboot_init(void)
 {
 	rb_kobj = kobject_create_and_add("mikrotik", firmware_kobj);
 	if (!rb_kobj)
 		return -ENOMEM;
 
-	/*
-	 * We ignore the following return values and always register.
-	 * These init() routines are designed so that their failed state is
-	 * always manageable by the corresponding exit() calls.
-	 */
-	rb_hardconfig_init(rb_kobj);
-	rb_softconfig_init(rb_kobj);
+	register_mtd_user(&routerboot_mtd_notifier);
 
 	return 0;
 }
 
 static void __exit routerboot_exit(void)
 {
+	unregister_mtd_user(&routerboot_mtd_notifier);
 	rb_softconfig_exit();
 	rb_hardconfig_exit();
 	kobject_put(rb_kobj);	// recursive afaict
diff --git a/target/linux/generic/files/drivers/platform/mikrotik/routerboot.h b/target/linux/generic/files/drivers/platform/mikrotik/routerboot.h
index 67d89808d5..5277a3cd94 100644
--- a/target/linux/generic/files/drivers/platform/mikrotik/routerboot.h
+++ b/target/linux/generic/files/drivers/platform/mikrotik/routerboot.h
@@ -10,6 +10,7 @@
 #define _ROUTERBOOT_H_
 
 #include <linux/types.h>
+#include <linux/mtd/mtd.h>
 
 // these magic values are stored in cpu-endianness on flash
 #define RB_MAGIC_HARD	(('H') | ('a' << 8) | ('r' << 16) | ('d' << 24))
@@ -25,10 +26,10 @@
 int routerboot_tag_find(const u8 *bufhead, const size_t buflen, const u16 tag_id, u16 *pld_ofs, u16 *pld_len);
 int routerboot_rle_decode(const u8 *in, size_t inlen, u8 *out, size_t *outlen);
 
-int __init rb_hardconfig_init(struct kobject *rb_kobj);
+int __init rb_hardconfig_init(struct kobject *rb_kobj, struct mtd_info *mtd);
 void __exit rb_hardconfig_exit(void);
 
-int __init rb_softconfig_init(struct kobject *rb_kobj);
+int __init rb_softconfig_init(struct kobject *rb_kobj, struct mtd_info *mtd);
 void __exit rb_softconfig_exit(void);
 
 ssize_t routerboot_tag_show_string(const u8 *pld, u16 pld_len, char *buf);
-- 
2.31.1

_______________________________________________
openwrt-devel mailing list
openwrt-devel@lists.openwrt.org
https://lists.openwrt.org/mailman/listinfo/openwrt-devel

Reply via email to