base: soc: Early register bus when needed
authorGeert Uytterhoeven <geert+renesas@glider.be>
Tue, 27 Sep 2016 15:10:29 +0000 (17:10 +0200)
committerGeert Uytterhoeven <geert+renesas@glider.be>
Thu, 10 Nov 2016 09:10:25 +0000 (10:10 +0100)
If soc_device_register() is called before soc_bus_register(), it crashes
with a NULL pointer dereference.

soc_bus_register() is already a core_initcall(), but drivers/base/ is
entered later than e.g. drivers/pinctrl/ and drivers/soc/. Hence there
are several subsystems that may need to know SoC revision information,
while it's not so easy to initialize the SoC bus even earlier using an
initcall.

To fix this, let soc_device_register() register the bus early if that
hasn't happened yet.

Signed-off-by: Geert Uytterhoeven <geert+renesas@glider.be>
Acked-by: Arnd Bergmann <arnd@arndb.de>
drivers/base/soc.c

index b63f23e6ad61b647ff26eecaeb4685e55fd67ad0..028cef377fd49959aec641716531a5d14668d141 100644 (file)
@@ -113,6 +113,12 @@ struct soc_device *soc_device_register(struct soc_device_attribute *soc_dev_attr
        struct soc_device *soc_dev;
        int ret;
 
+       if (!soc_bus_type.p) {
+               ret = bus_register(&soc_bus_type);
+               if (ret)
+                       goto out1;
+       }
+
        soc_dev = kzalloc(sizeof(*soc_dev), GFP_KERNEL);
        if (!soc_dev) {
                ret = -ENOMEM;
@@ -156,6 +162,9 @@ void soc_device_unregister(struct soc_device *soc_dev)
 
 static int __init soc_bus_register(void)
 {
+       if (soc_bus_type.p)
+               return 0;
+
        return bus_register(&soc_bus_type);
 }
 core_initcall(soc_bus_register);