> 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