From f309d4443130bf814e991f836e919dca22df37ae Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Fri, 1 May 2015 20:10:57 -0400 Subject: [PATCH 1/8] platform_device: better support builtin boilerplate avoidance We have macros that help reduce the boilerplate for modules that register with no extra init/exit complexity other than the most standard use case. However we see an increasing number of non-modular drivers using these modular_driver() type register functions. There are several downsides to this: 1) The code can appear modular to a reader of the code, and they won't know if the code really is modular without checking the Makefile and Kconfig to see if compilation is governed by a bool or tristate. 2) Coders of drivers may be tempted to code up an __exit function that is never used, just in order to satisfy the required three args of the modular registration function. 3) Non-modular code ends up including the which increases CPP overhead that they don't need. 4) It hinders us from performing better separation of the module init code and the generic init code. Here we introduce similar macros, with the mapping from module_driver to builtin_driver and similar, so that simple changes of: module_platform_driver() ---> builtin_platform_driver() module_platform_driver_probe() ---> builtin_platform_driver_probe(). can help us avoid #3 above, without having to code up the same __init functions and device_initcall() boilerplate. For non modular code, module_init becomes __initcall. But direct use of __initcall is discouraged, vs. one of the priority categorized subgroups. As __initcall gets mapped onto device_initcall, our use of device_initcall directly in this change means that the runtime impact is zero -- drivers will remain at level 6 in the initcall ordering. Cc: Greg Kroah-Hartman Signed-off-by: Paul Gortmaker --- include/linux/device.h | 22 ++++++++++++++++++++++ include/linux/platform_device.h | 23 +++++++++++++++++++++++ 2 files changed, 45 insertions(+) diff --git a/include/linux/device.h b/include/linux/device.h index 6558af90c8fe..c2d6167cb4a3 100644 --- a/include/linux/device.h +++ b/include/linux/device.h @@ -1269,4 +1269,26 @@ static void __exit __driver##_exit(void) \ } \ module_exit(__driver##_exit); +/** + * builtin_driver() - Helper macro for drivers that don't do anything + * special in init and have no exit. This eliminates some boilerplate. + * Each driver may only use this macro once, and calling it replaces + * device_initcall (or in some cases, the legacy __initcall). This is + * meant to be a direct parallel of module_driver() above but without + * the __exit stuff that is not used for builtin cases. + * + * @__driver: driver name + * @__register: register function for this driver type + * @...: Additional arguments to be passed to __register + * + * Use this macro to construct bus specific macros for registering + * drivers, and do not use it on its own. + */ +#define builtin_driver(__driver, __register, ...) \ +static int __init __driver##_init(void) \ +{ \ + return __register(&(__driver) , ##__VA_ARGS__); \ +} \ +device_initcall(__driver##_init); + #endif /* _DEVICE_H_ */ diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h index 58f1e75ba105..bba08f44cc97 100644 --- a/include/linux/platform_device.h +++ b/include/linux/platform_device.h @@ -222,6 +222,15 @@ static inline void platform_set_drvdata(struct platform_device *pdev, module_driver(__platform_driver, platform_driver_register, \ platform_driver_unregister) +/* builtin_platform_driver() - Helper macro for builtin drivers that + * don't do anything special in driver init. This eliminates some + * boilerplate. Each driver may only use this macro once, and + * calling it replaces device_initcall(). Note this is meant to be + * a parallel of module_platform_driver() above, but w/o _exit stuff. + */ +#define builtin_platform_driver(__platform_driver) \ + builtin_driver(__platform_driver, platform_driver_register) + /* module_platform_driver_probe() - Helper macro for drivers that don't do * anything special in module init/exit. This eliminates a lot of * boilerplate. Each module may only use this macro once, and @@ -240,6 +249,20 @@ static void __exit __platform_driver##_exit(void) \ } \ module_exit(__platform_driver##_exit); +/* builtin_platform_driver_probe() - Helper macro for drivers that don't do + * anything special in device init. This eliminates some boilerplate. Each + * driver may only use this macro once, and using it replaces device_initcall. + * This is meant to be a parallel of module_platform_driver_probe above, but + * without the __exit parts. + */ +#define builtin_platform_driver_probe(__platform_driver, __platform_probe) \ +static int __init __platform_driver##_init(void) \ +{ \ + return platform_driver_probe(&(__platform_driver), \ + __platform_probe); \ +} \ +device_initcall(__platform_driver##_init); \ + #define platform_create_bundle(driver, probe, res, n_res, data, size) \ __platform_create_bundle(driver, probe, res, n_res, data, size, THIS_MODULE) extern struct platform_device *__platform_create_bundle( From 1dda2b42db1bbc788bf6de0a8141a305484f963b Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Fri, 1 May 2015 20:10:57 -0400 Subject: [PATCH 2/8] drivers/platform: Convert non-modular pdev_bus to use builtin_platform_driver This driver is configured with a Kconfig option that is declared as a bool. Hence it is not possible for the code to be built as modular. However the code is currently using the module_platform_driver() macro for driver registration. While this currently works, we really don't want to be including the module.h header in non-modular code, which we'll be forced to do, pending some upcoming code relocation from init.h into module.h. So we fix it now by using the non-modular equivalent. And since we've already established that the code is non-modular, we can completely drop any code relating to module_exit. Signed-off-by: Paul Gortmaker --- drivers/platform/goldfish/pdev_bus.c | 12 +----------- 1 file changed, 1 insertion(+), 11 deletions(-) diff --git a/drivers/platform/goldfish/pdev_bus.c b/drivers/platform/goldfish/pdev_bus.c index 8c43589c3edb..1f52462f4cdd 100644 --- a/drivers/platform/goldfish/pdev_bus.c +++ b/drivers/platform/goldfish/pdev_bus.c @@ -220,20 +220,10 @@ static int goldfish_pdev_bus_probe(struct platform_device *pdev) return ret; } -static int goldfish_pdev_bus_remove(struct platform_device *pdev) -{ - iounmap(pdev_bus_base); - free_irq(pdev_bus_irq, pdev); - release_mem_region(pdev_bus_addr, pdev_bus_len); - return 0; -} - static struct platform_driver goldfish_pdev_bus_driver = { .probe = goldfish_pdev_bus_probe, - .remove = goldfish_pdev_bus_remove, .driver = { .name = "goldfish_pdev_bus" } }; - -module_platform_driver(goldfish_pdev_bus_driver); +builtin_platform_driver(goldfish_pdev_bus_driver); From 090d1cf103725f583b3f41fc3185698ae5a7aa64 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Fri, 1 May 2015 20:10:57 -0400 Subject: [PATCH 3/8] drivers/cpuidle: Convert non-modular drivers to use builtin_platform_driver All these drivers are configured with Kconfig options that are declared as bool. Hence it is not possible for the code to be built as modular. However the code is currently using the module_platform_driver() macro for driver registration. While this currently works, we really don't want to be including the module.h header in non-modular code, which we'll be forced to do, pending some upcoming code relocation from init.h into module.h. So we fix it now by using the non-modular equivalent. Cc: "Rafael J. Wysocki" Cc: Daniel Lezcano Cc: Michal Simek Cc: linux-pm@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org Signed-off-by: Paul Gortmaker --- drivers/cpuidle/cpuidle-at91.c | 3 +-- drivers/cpuidle/cpuidle-calxeda.c | 3 +-- drivers/cpuidle/cpuidle-zynq.c | 3 +-- 3 files changed, 3 insertions(+), 6 deletions(-) diff --git a/drivers/cpuidle/cpuidle-at91.c b/drivers/cpuidle/cpuidle-at91.c index f2446c78d87c..9c5853b6ca4a 100644 --- a/drivers/cpuidle/cpuidle-at91.c +++ b/drivers/cpuidle/cpuidle-at91.c @@ -62,5 +62,4 @@ static struct platform_driver at91_cpuidle_driver = { }, .probe = at91_cpuidle_probe, }; - -module_platform_driver(at91_cpuidle_driver); +builtin_platform_driver(at91_cpuidle_driver); diff --git a/drivers/cpuidle/cpuidle-calxeda.c b/drivers/cpuidle/cpuidle-calxeda.c index 9445e6cc02be..c13feec89ea1 100644 --- a/drivers/cpuidle/cpuidle-calxeda.c +++ b/drivers/cpuidle/cpuidle-calxeda.c @@ -75,5 +75,4 @@ static struct platform_driver calxeda_cpuidle_plat_driver = { }, .probe = calxeda_cpuidle_probe, }; - -module_platform_driver(calxeda_cpuidle_plat_driver); +builtin_platform_driver(calxeda_cpuidle_plat_driver); diff --git a/drivers/cpuidle/cpuidle-zynq.c b/drivers/cpuidle/cpuidle-zynq.c index 543292b1d38e..6f4257fc56e5 100644 --- a/drivers/cpuidle/cpuidle-zynq.c +++ b/drivers/cpuidle/cpuidle-zynq.c @@ -73,5 +73,4 @@ static struct platform_driver zynq_cpuidle_driver = { }, .probe = zynq_cpuidle_probe, }; - -module_platform_driver(zynq_cpuidle_driver); +builtin_platform_driver(zynq_cpuidle_driver); From 5b64127e0529387d4538ecc3dfd49248baf619c5 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Fri, 1 May 2015 20:10:57 -0400 Subject: [PATCH 4/8] drivers/cpufreq: Convert non-modular s5pv210-cpufreq.c to use builtin_platform_driver This file depends on a Kconfig option which is a bool, so we use the appropriate registration function, which avoids us relying on an implicit inclusion of which we are doing currently. While this currently works, we really don't want to be including the module.h header in non-modular code, which we'd be forced to do, pending some upcoming code relocation from init.h into module.h. So we fix it now by using the non-modular equivalent. Cc: "Rafael J. Wysocki" Cc: Viresh Kumar Acked-by: Viresh Kumar Cc: Kukjin Kim Cc: linux-pm@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org Signed-off-by: Paul Gortmaker --- drivers/cpufreq/s5pv210-cpufreq.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/cpufreq/s5pv210-cpufreq.c b/drivers/cpufreq/s5pv210-cpufreq.c index b0dac7d6ba31..9e231f52150c 100644 --- a/drivers/cpufreq/s5pv210-cpufreq.c +++ b/drivers/cpufreq/s5pv210-cpufreq.c @@ -659,4 +659,4 @@ static struct platform_driver s5pv210_cpufreq_platdrv = { }, .probe = s5pv210_cpufreq_probe, }; -module_platform_driver(s5pv210_cpufreq_platdrv); +builtin_platform_driver(s5pv210_cpufreq_platdrv); From 7d4d9ed6ef5219857865dd57d425f9729d0a39ff Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Fri, 1 May 2015 20:10:57 -0400 Subject: [PATCH 5/8] drivers/soc: Convert non-modular tegra/pmc to use builtin_platform_driver This file depends on Kconfig ARCH_TEGRA which is a bool, so we use the appropriate registration function, which avoids us relying on an implicit inclusion of which we are doing currently. While this currently works, we really don't want to be including the module.h header in non-modular code, which we'd be forced to do, pending some upcoming code relocation from init.h into module.h. So we fix it now by using the non-modular equivalent. Cc: Stephen Warren Cc: Thierry Reding Cc: Alexandre Courbot Cc: linux-tegra@vger.kernel.org Signed-off-by: Paul Gortmaker --- drivers/soc/tegra/pmc.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/tegra/pmc.c b/drivers/soc/tegra/pmc.c index c956395cf46f..e3bca1368058 100644 --- a/drivers/soc/tegra/pmc.c +++ b/drivers/soc/tegra/pmc.c @@ -1010,7 +1010,7 @@ static struct platform_driver tegra_pmc_driver = { }, .probe = tegra_pmc_probe, }; -module_platform_driver(tegra_pmc_driver); +builtin_platform_driver(tegra_pmc_driver); /* * Early initialization to allow access to registers in the very early boot From 0159ae95e6a923f565937f10518aa3c919527733 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Fri, 1 May 2015 20:10:57 -0400 Subject: [PATCH 6/8] drivers/soc: Convert non-modular soc-realview to use builtin_platform_driver This file depends on Kconfig SOC_REALVIEW which is a bool, so we use the appropriate registration function, which avoids us relying on an implicit inclusion of which we are doing currently. While this currently works, we really don't want to be including the module.h header in non-modular code, which we'd be forced to do, pending some upcoming code relocation from init.h into module.h. So we fix it now by using the non-modular equivalent. Cc: Arnd Bergmann Cc: Linus Walleij Acked-by: Linus Walleij Cc: Axel Lin Signed-off-by: Paul Gortmaker --- drivers/soc/versatile/soc-realview.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/soc/versatile/soc-realview.c b/drivers/soc/versatile/soc-realview.c index 1a07bf540fec..e642c4540dda 100644 --- a/drivers/soc/versatile/soc-realview.c +++ b/drivers/soc/versatile/soc-realview.c @@ -142,4 +142,4 @@ static struct platform_driver realview_soc_driver = { .of_match_table = realview_soc_of_match, }, }; -module_platform_driver(realview_soc_driver); +builtin_platform_driver(realview_soc_driver); From e35415e59f86d6b546a3681e2cda4f22b5b142c0 Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Fri, 1 May 2015 20:10:58 -0400 Subject: [PATCH 7/8] drivers/power: Convert non-modular syscon-reboot to use builtin_platform_driver This file depends on Kconfig options all of which are a bool, so we use the appropriate registration function, which avoids us relying on an implicit inclusion of which we are doing currently. While this currently works, we really don't want to be including the module.h header in non-modular code, which we'd be forced to do, pending some upcoming code relocation from init.h into module.h. So we fix it now by using the non-modular equivalent. Cc: Sebastian Reichel Acked-By: Sebastian Reichel Cc: Dmitry Eremin-Solenikov Cc: David Woodhouse Cc: linux-pm@vger.kernel.org Signed-off-by: Paul Gortmaker --- drivers/power/reset/syscon-reboot.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/power/reset/syscon-reboot.c b/drivers/power/reset/syscon-reboot.c index d3c7d245ae63..7d0d269a0837 100644 --- a/drivers/power/reset/syscon-reboot.c +++ b/drivers/power/reset/syscon-reboot.c @@ -88,4 +88,4 @@ static struct platform_driver syscon_reboot_driver = { .of_match_table = syscon_reboot_of_match, }, }; -module_platform_driver(syscon_reboot_driver); +builtin_platform_driver(syscon_reboot_driver); From 77459a0feca4ae8757a905fd1791f039479e8e1e Mon Sep 17 00:00:00 2001 From: Paul Gortmaker Date: Wed, 3 Jun 2015 11:20:05 -0400 Subject: [PATCH 8/8] drivers/clk: convert sunxi/clk-mod0.c to use builtin_platform_driver MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit This driver builds based on obj-y and hence will not ever be modular. Change it to use the non-modular registration so that it won't suffer a compile fail once a header move places the modular registration within the module.h file. Cc: "Emilio López" Cc: Mike Turquette Cc: Stephen Boyd Acked-by: Stephen Boyd Cc: Maxime Ripard Acked-by: Maxime Ripard Cc: linux-clk@vger.kernel.org Cc: linux-arm-kernel@lists.infradead.org Signed-off-by: Paul Gortmaker --- drivers/clk/sunxi/clk-mod0.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/clk/sunxi/clk-mod0.c b/drivers/clk/sunxi/clk-mod0.c index ec8f5a1fca09..9d028aec58e5 100644 --- a/drivers/clk/sunxi/clk-mod0.c +++ b/drivers/clk/sunxi/clk-mod0.c @@ -128,7 +128,7 @@ static struct platform_driver sun4i_a10_mod0_clk_driver = { }, .probe = sun4i_a10_mod0_clk_probe, }; -module_platform_driver(sun4i_a10_mod0_clk_driver); +builtin_platform_driver(sun4i_a10_mod0_clk_driver); static const struct factors_data sun9i_a80_mod0_data __initconst = { .enable = 31,