linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/14] init: deps: dependency based (parallelized) init
@ 2015-10-17 17:14 Alexander Holler
  2015-10-17 17:14 ` [PATCH 01/14] init: deps: introduce annotated initcalls Alexander Holler
                   ` (15 more replies)
  0 siblings, 16 replies; 59+ messages in thread
From: Alexander Holler @ 2015-10-17 17:14 UTC (permalink / raw)
  To: linux-kernel
  Cc: Linus Torvalds, Andrew Morton, Greg Kroah-Hartman, Russell King,
	Grant Likely

Hello,

here is the newest version of my patches to use a dependency based
initialization order. It now works without DT too.

Background:

Currently initcalls are ordered by some levels and the link order. This
means whenever a file is renamed, changes directory or a Makefile is
modified the order with which initcalls are called might change. This
might result in problems. Furthermore, the required dependencies are
often not documented, sometimes there are comments in the source or in a
commit message, but most often the knowledge why a specific initcall
belongs to a specific initcall level isn't obvious without carefully
examing he source. And initcalls are used by drivers and subsystems, and
the count of both have grown quiet a lot in the last years. So it's
rather difficult to maintain a proper link order.
Another problem is that the link order can't be modified dynamically at
boot time to include dependencies dictated by the hardware. To circumvent
this, a brute-force trial-and-error mechanism called deferred probes has
been introduced, but this approach, while beeing KISS, has its own
problems.

To solve these problems I've written patches to use a topological sort at
boot time which uses dependencies to calculate the order with which
initcalls are called.

Why? What are the benefits (assuming correct dependencies are available)?

- It offers a clear in-source documentation for dependencies between
  initcalls.
- It is robust in regard to file or directory name changes and changes in
  a Makefile.
- If enabled, the order with which drivers for interfaces are called
  (e.g. network interfaces, hard disks), can be defined independent of
  the link order. These might result in more stable interface names or
  numbers.
- If enabled, it makes the the deferred probes obsolete, which might
  result in faster boot times.
- If enabled, it is possible to call initcalls in parallel. E.g. the
  shipped kernel for Fedora 21 (4.1.7-100.fc21.x86_64) contains around
  560 initcalls. These are all called in series. Also some of them use
  asynchronous stuff by themself, most don't do.

Drawbacks:

- It requires a small amount of time to calculate the order a boot time.
  But this time is most often smaller than the time saved by using
  multiple cores to call initcalls or by not needing deferred probes.
- Dependencies are required. For everything which can be build as a
  module, looking at modules.dep might give some pointers. Looking at
  the help from menuconfig also might give some pointers. But in the
  end, the most preferable way would be if maintainers or other people
  which have a deeper knowledge about the source and functionality
  would add the dependencies.

And last but not least, these feature is totally optional. If disabled,
nothing changes.


Some words about the patches:

Patch 1 introduces annotated initcalls, patch 2 uses them and patch 3
adds hardware specific dependencies from the device tree to the existent
set of dependencies.

Patch 4 and 5 are examples about how to achieve a stable initialization
order for various type of drivers. The two patches are doing this for
network interfaces (based on the existing link order) and I2C busses
(based on the new driver IDs). I leave it for discussion which one should
be used. My suggestion would be to order the IDs like the link order and
then use the order based on IDs. That would get rid of the link order while
also beeing downwards compatible.

Patches 6-9 do contain changes for dtc to enhance the binary blob (dtb)
with type information for phandles (the dependencies used by patch 3).
I've already posted these patches a year ago.

Patch 10 contains the list of driver IDs I've annotated and is NOT meant
for merging. Patch 11 contains all the changes on drivers I've annotated
and is NOT meant for merge too. I've no idea how such patches might end
up in the kernel (in fact I've no idea what's necessary for any patch),
therefor these two patches are there to offer a quick start to evaluate
this feature.

The final 3 patches contain a few changes for the DTs of 3 ARM boards.

Because I don't want to fiddle with problems in the unstable mainline tree,
these patches are based on the latest stable kernel (4.2.3). But besides
the big patch (11) with all the driver changes, they apply without problems
to the current mainline too. And the necessary changes to use the big patch
on mainline should be trivial, as all the changes in this patch are trivial
too.

I've tested this patch series with several ARM(32) systems, x86 and x86_64
and the boot time was faster on allmost all systems. Either through
avoiding deferred probes (on single core machines) or by using the
parallel initialization. And keep in mind that, also I've already
annotated quiet a lot of initcalls, a big bunch of them still are left
and therefor are still called in series using just one core and not in
parallel.

Keep in mind that these patches are an offer, I wasn't paid for them and
I don't need them in the mainline kernel.
As long as you are able to use a polite language, you can send me any
comment, regardless if it's good or bad. But, please, keep away with
Baby-Speak or contumelious comments.

And, just in case, I'm aware that adding the necessary dependencies means
some effort and a lot of (trivial) commits and therefor having all
possible initcalls annotated would be a long term goal. But, besides that
this could be done smoothly without any need to hurry, I think it makes
sense. Otherwise, in my humble opinion, the problems to keep an overview
and ordering initcalls will just become worse.


Alexander Holler

^ permalink raw reply	[flat|nested] 59+ messages in thread

* [PATCH 01/14] init: deps: introduce annotated initcalls
  2015-10-17 17:14 [PATCH 0/14] init: deps: dependency based (parallelized) init Alexander Holler
@ 2015-10-17 17:14 ` Alexander Holler
  2015-10-17 17:14 ` [PATCH 02/14] init: deps: use annotated initcalls for a dependency based (optionally parallelized) init Alexander Holler
                   ` (14 subsequent siblings)
  15 siblings, 0 replies; 59+ messages in thread
From: Alexander Holler @ 2015-10-17 17:14 UTC (permalink / raw)
  To: linux-kernel
  Cc: Linus Torvalds, Andrew Morton, Greg Kroah-Hartman, Russell King,
	Grant Likely, Alexander Holler

Make it possible to identify initcalls before calling them by adding an
ID, an optional pointer to a list of IDs the initcalls depends on and
an optional pointer to a struct device_driver.

This is e.g. necessary in order to sort initcalls by whatever means
before calling them.

To annotate an initcall, the following changes are necessary on
drivers which want to offer that feature:

now		annotated
------------------------------------------------------------------------
pure_initcall(fn)
		annotated_initcall(pure, fn, id, dependencies) or
		annotated_initcall_drv(pure, fn, id, dependencies, drv)
core_initcall(fn)
		annotated_initcall(core, fn, id, dependencies) or
		annotated_initcall_drv(core, fn, id, dependencies, drv)
core_initcall_sync(fn)
		annotated_initcall_sync(core, fn, id, dependencies) or
		annotated_initcall_sync_drv(core, fn, id, dependencies,
								drv)
(...)
late_initcall(fn)
		annotated_initcall(late, fn, id, dependencies)
module_init(fn)
		annotated_module_init(fn, id, dependencies)

module_platform_driver(drv)
		annotated_module_platform_driver(drv, id, dependencies)
module_platform_driver_probe(drv, probe)
		annotated:module_platform_driver_probe(drv, probe, id,
							 dependencies)
module_i2c_driver(i2c_drv)
		annotated_module_i2c_driver(i2c_drv, id, dependencies)
module_usb_driver(usb_drv)
		annotated_module_usb_driver(usb_drv, id, dependencies)
module_phy_driver(__phy_drivers)
		annotated_module_phy_driver(__phy_drivers, id,
						dependencies)
module_pci_driver(pci_driver)
		annotated_module_pci_driver(pci_driver, id,
						dependencies)
module_serio_driver(serio_driver)
		annotated_module_serio_driver(serio_driver, id,
						dependencies)
module_acpi_driver(acpi_driver)
		annotated_module_acpi_driver(acpi_driver, id,
						dependencies)

E.g. to make the driver sram offering an annotated initcall the
following patch is necessary:

----
-postcore_initcall(sram_init);
+annotated_initcall_drv(postcore, sram_init, drvid_sram, NULL,
+			sram_driver.driver);
----

The change for a module with dependencies might look like:

----
-module_platform_driver(gpio_led_driver);
+static const unsigned dependencies[] __initdata __maybe_unused = {
+	drvid_leds,
+	0
+};
+
+annotated_module_platform_driver(gpio_led_driver, drvid_gpio_led,
+					dependencies);
----

These changes can be done without any fear. If the feature is disabled,
which is the default, the new macros will just map to the old ones and
nothing is changed at all.

Signed-off-by: Alexander Holler <holler@ahsoftware.de>
---
 arch/arm/kernel/vmlinux.lds.S     |  1 +
 arch/arm/mach-omap2/soc.h         | 10 ++++++-
 drivers/usb/storage/usb.h         | 14 ++++++++++
 include/acpi/acpi_bus.h           | 13 +++++++++
 include/asm-generic/vmlinux.lds.h |  7 +++++
 include/linux/device.h            | 14 ++++++++++
 include/linux/driver_ids.h        | 21 ++++++++++++++
 include/linux/i2c.h               |  4 +++
 include/linux/init.h              | 58 +++++++++++++++++++++++++++++++++++++++
 include/linux/module.h            |  7 +++++
 include/linux/pci.h               |  4 +++
 include/linux/phy.h               | 16 +++++++++++
 include/linux/platform_device.h   | 41 +++++++++++++++++++++++++--
 include/linux/serio.h             |  5 ++++
 include/linux/usb.h               | 12 ++++++++
 init/Kconfig                      |  3 ++
 16 files changed, 226 insertions(+), 4 deletions(-)
 create mode 100644 include/linux/driver_ids.h

diff --git a/arch/arm/kernel/vmlinux.lds.S b/arch/arm/kernel/vmlinux.lds.S
index 8b60fde..c22784e 100644
--- a/arch/arm/kernel/vmlinux.lds.S
+++ b/arch/arm/kernel/vmlinux.lds.S
@@ -213,6 +213,7 @@ SECTIONS
 #endif
 		INIT_SETUP(16)
 		INIT_CALLS
+		ANNOTATED_INITCALLS
 		CON_INITCALL
 		SECURITY_INITCALL
 		INIT_RAM_FS
diff --git a/arch/arm/mach-omap2/soc.h b/arch/arm/mach-omap2/soc.h
index f97654d..75f7012 100644
--- a/arch/arm/mach-omap2/soc.h
+++ b/arch/arm/mach-omap2/soc.h
@@ -554,5 +554,13 @@ level(__##fn);
 #define omap_late_initcall(fn)		omap_initcall(late_initcall, fn)
 #define omap_late_initcall_sync(fn)	omap_initcall(late_initcall_sync, fn)
 
-#endif	/* __ASSEMBLY__ */
+#define annotated_omap_initcall(level, fn, id, deps)	\
+static int __init __used __##fn(void)		\
+{						\
+	if (!soc_is_omap())			\
+		return 0;			\
+	return fn();				\
+}						\
+annotated_initcall(level, __##fn, id, deps)
 
+#endif	/* __ASSEMBLY__ */
diff --git a/drivers/usb/storage/usb.h b/drivers/usb/storage/usb.h
index da0ad32..f2ed368 100644
--- a/drivers/usb/storage/usb.h
+++ b/drivers/usb/storage/usb.h
@@ -218,4 +218,18 @@ static void __exit __driver##_exit(void) \
 } \
 module_exit(__driver##_exit)
 
+#define annotated_module_usb_stor_driver(__driver, __sht, __name, \
+					 __id, __deps) \
+static int __init __driver##_init(void) \
+{ \
+	usb_stor_host_template_init(&(__sht), __name, THIS_MODULE); \
+	return usb_register(&(__driver)); \
+} \
+annotated_module_init(__driver##_init, __id, __deps); \
+static void __exit __driver##_exit(void) \
+{ \
+	usb_deregister(&(__driver)); \
+} \
+module_exit(__driver##_exit)
+
 #endif
diff --git a/include/acpi/acpi_bus.h b/include/acpi/acpi_bus.h
index 83061ca..42d0612 100644
--- a/include/acpi/acpi_bus.h
+++ b/include/acpi/acpi_bus.h
@@ -541,6 +541,19 @@ static inline bool acpi_device_enumerated(struct acpi_device *adev)
 	module_driver(__acpi_driver, acpi_bus_register_driver, \
 		      acpi_bus_unregister_driver)
 
+#define annotated_module_acpi_driver(__acpi_driver, __id, __deps) \
+static int __init __acpi_driver##_init(void) \
+{ \
+	return acpi_bus_register_driver(&(__acpi_driver)); \
+} \
+annotated_module_init_drv(__acpi_driver##_init, __id, __deps, \
+			  __acpi_driver.drv); \
+static void __exit __acpi_driver##_exit(void) \
+{ \
+	acpi_bus_unregister_driver(&(__acpi_driver)); \
+} \
+module_exit(__acpi_driver##_exit)
+
 /*
  * Bind physical devices with ACPI devices
  */
diff --git a/include/asm-generic/vmlinux.lds.h b/include/asm-generic/vmlinux.lds.h
index 8bd374d..ad6cace 100644
--- a/include/asm-generic/vmlinux.lds.h
+++ b/include/asm-generic/vmlinux.lds.h
@@ -660,6 +660,12 @@
 		INIT_CALLS_LEVEL(7)					\
 		VMLINUX_SYMBOL(__initcall_end) = .;
 
+#define ANNOTATED_INITCALLS						\
+		. = ALIGN(32);						\
+		VMLINUX_SYMBOL(__annotated_initcall_start) = .;		\
+		*(.annotated_initcall.init)				\
+		VMLINUX_SYMBOL(__annotated_initcall_end) = .;
+
 #define CON_INITCALL							\
 		VMLINUX_SYMBOL(__con_initcall_start) = .;		\
 		*(.con_initcall.init)					\
@@ -816,6 +822,7 @@
 		INIT_DATA						\
 		INIT_SETUP(initsetup_align)				\
 		INIT_CALLS						\
+		ANNOTATED_INITCALLS					\
 		CON_INITCALL						\
 		SECURITY_INITCALL					\
 		INIT_RAM_FS						\
diff --git a/include/linux/device.h b/include/linux/device.h
index a2b4ea7..7320dc9 100644
--- a/include/linux/device.h
+++ b/include/linux/device.h
@@ -1321,4 +1321,18 @@ static int __init __driver##_init(void) \
 } \
 device_initcall(__driver##_init);
 
+#define annotated_module_driver(__driver, __register, __unregister, \
+				__id, __deps, ...) \
+static int __init __driver##_init(void) \
+{ \
+	return __register(&(__driver), ##__VA_ARGS__); \
+} \
+annotated_module_init_drv(__driver##_init, __id, __deps, __driver.driver); \
+static void __exit __driver##_exit(void) \
+{ \
+	__unregister(&(__driver), ##__VA_ARGS__); \
+} \
+module_exit(__driver##_exit)
+
+
 #endif /* _DEVICE_H_ */
diff --git a/include/linux/driver_ids.h b/include/linux/driver_ids.h
new file mode 100644
index 0000000..60964fe
--- /dev/null
+++ b/include/linux/driver_ids.h
@@ -0,0 +1,21 @@
+#ifndef _LINUX_DRIVER_IDS_H
+#define _LINUX_DRIVER_IDS_H
+
+/*
+ * In fact, the IDs listed here are IDs for initcalls, and not for
+ * drivers. But most of the time, a driver or subsystem has only one
+ * initcall, and talking about IDs for drivers makes more sense than
+ * talking about initcalls, something many people have no clear
+ * understanding about.
+ *
+ * Please use the name of the module as the name for the ID if
+ * something can be build as a module.
+ */
+
+enum {
+	drvid_unused,
+	/* To be filled */
+	drvid_max
+};
+
+#endif /* _LINUX_DRIVER_IDS_H */
diff --git a/include/linux/i2c.h b/include/linux/i2c.h
index e83a738..efe0e7d 100644
--- a/include/linux/i2c.h
+++ b/include/linux/i2c.h
@@ -629,6 +629,10 @@ static inline int i2c_adapter_id(struct i2c_adapter *adap)
 	module_driver(__i2c_driver, i2c_add_driver, \
 			i2c_del_driver)
 
+#define annotated_module_i2c_driver(__i2c_driver, __id, __deps) \
+	annotated_module_driver(__i2c_driver, i2c_add_driver, \
+			i2c_del_driver, __id, __deps)
+
 #endif /* I2C */
 
 #if IS_ENABLED(CONFIG_OF)
diff --git a/include/linux/init.h b/include/linux/init.h
index b449f37..758fd18 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -3,6 +3,9 @@
 
 #include <linux/compiler.h>
 #include <linux/types.h>
+#ifndef __ASSEMBLY__
+#include <linux/driver_ids.h>
+#endif
 
 /* These macros are used to mark some functions or 
  * initialized data (doesn't apply to uninitialized data)
@@ -124,6 +127,17 @@
 typedef int (*initcall_t)(void);
 typedef void (*exitcall_t)(void);
 
+struct device_driver;
+
+struct _annotated_initcall {
+	const initcall_t initcall;
+	const unsigned id; /* from driver_ids.h */
+	const unsigned *dependencies;
+	const struct device_driver *driver;
+};
+extern const struct _annotated_initcall __annotated_initcall_start[],
+				  __annotated_initcall_end[];
+
 extern initcall_t __con_initcall_start[], __con_initcall_end[];
 extern initcall_t __security_initcall_start[], __security_initcall_end[];
 
@@ -184,6 +198,18 @@ extern bool initcall_debug;
 	__attribute__((__section__(".initcall" #id ".init"))) = fn; \
 	LTO_REFERENCE_INITCALL(__initcall_##fn##id)
 
+#define __define_annotated_initcall(fn, __id, deps) \
+	static struct _annotated_initcall __annotated_initcall_##fn __used \
+	__attribute__((__section__(".annotated_initcall.init"))) = \
+		{ .initcall = fn, .id = __id, .dependencies = deps, \
+		  .driver = NULL }
+
+#define __define_annotated_initcall_drv(fn, __id, deps, drv) \
+	static struct _annotated_initcall __annotated_initcall_##fn __used \
+	__attribute__((__section__(".annotated_initcall.init"))) = \
+		{ .initcall = fn, .id = __id, .dependencies = deps, \
+		  .driver = &(drv) }
+
 /*
  * Early initcalls run before initializing SMP.
  *
@@ -216,6 +242,38 @@ extern bool initcall_debug;
 #define late_initcall(fn)		__define_initcall(fn, 7)
 #define late_initcall_sync(fn)		__define_initcall(fn, 7s)
 
+/*
+ * Annotated initcalls are accompanied by a struct device_driver.
+ * This makes initcalls identifiable and is used to order initcalls.
+ *
+ * If disabled, nothing is changed and the classic level based
+ * initialization sequence is in use.
+ */
+#ifdef CONFIG_ANNOTATED_INITCALLS
+#define annotated_module_init(fn, id, deps) \
+	__define_annotated_initcall(fn, id, deps)
+#define annotated_module_init_drv(fn, id, deps, drv) \
+	__define_annotated_initcall_drv(fn, id, deps, drv)
+#define annotated_initcall(level, fn, id, deps) \
+	__define_annotated_initcall(fn, id, deps)
+#define annotated_initcall_sync(level, fn, id, deps) \
+	__define_annotated_initcall(fn, id, deps)
+#define annotated_initcall_drv(level, fn, id, deps, drv) \
+	__define_annotated_initcall_drv(fn, id, deps, drv)
+#define annotated_initcall_drv_sync(level, fn, id, deps, drv) \
+	__define_annotated_initcall_drv(fn, id, deps, drv)
+#else
+#define annotated_module_init(fn, id, deps)	module_init(fn)
+#define annotated_module_init_drv(fn, id, deps, drv)	module_init(fn)
+#define annotated_initcall(level, fn, id, deps)	level ## _initcall(fn)
+#define annotated_initcall_sync(level, fn, id, deps) \
+	level ## _initcall_sync(fn)
+#define annotated_initcall_drv(level, fn, id, deps, drv) \
+	level ## _initcall(fn)
+#define annotated_initcall_drv_sync(level, fn, id, deps, drv) \
+	level ## _initcall_sync(fn)
+#endif
+
 #define __initcall(fn) device_initcall(fn)
 
 #define __exitcall(fn) \
diff --git a/include/linux/module.h b/include/linux/module.h
index 3a19c79..880fdda 100644
--- a/include/linux/module.h
+++ b/include/linux/module.h
@@ -120,6 +120,13 @@ extern void cleanup_module(void);
 #define late_initcall(fn)		module_init(fn)
 #define late_initcall_sync(fn)		module_init(fn)
 
+#define annotated_initcall(level, fn, id, deps)	module_init(fn)
+#define annotated_initcall_sync(level, fn, id, deps)	module_init(fn)
+#define annotated_initcall_drv(level, fn, id, deps, drv)	module_init(fn)
+#define annotated_initcall_drv_sync(level, fn, id, deps, drv)	module_init(fn)
+#define annotated_module_init(fn, id, deps)	module_init(fn)
+#define annotated_module_init_drv(fn, id, deps, drv)	module_init(fn)
+
 #define console_initcall(fn)		module_init(fn)
 #define security_initcall(fn)		module_init(fn)
 
diff --git a/include/linux/pci.h b/include/linux/pci.h
index 1d4eb60..8093898 100644
--- a/include/linux/pci.h
+++ b/include/linux/pci.h
@@ -1162,6 +1162,10 @@ void pci_unregister_driver(struct pci_driver *dev);
 	module_driver(__pci_driver, pci_register_driver, \
 		       pci_unregister_driver)
 
+#define annotated_module_pci_driver(__pci_driver, __id, __dependencies) \
+	annotated_module_driver(__pci_driver, pci_register_driver, \
+		       pci_unregister_driver, __id, __dependencies)
+
 struct pci_driver *pci_dev_driver(const struct pci_dev *dev);
 int pci_add_dynid(struct pci_driver *drv,
 		  unsigned int vendor, unsigned int device,
diff --git a/include/linux/phy.h b/include/linux/phy.h
index a26c3f8..e5377fb 100644
--- a/include/linux/phy.h
+++ b/include/linux/phy.h
@@ -824,4 +824,20 @@ module_exit(phy_module_exit)
 #define module_phy_driver(__phy_drivers)				\
 	phy_module_driver(__phy_drivers, ARRAY_SIZE(__phy_drivers))
 
+#define annotated_phy_module_driver(__phy_drivers, __count, id, deps)	\
+static int __init phy_module_init(void)					\
+{									\
+	return phy_drivers_register(__phy_drivers, __count);		\
+}									\
+annotated_module_init(phy_module_init, id, deps);			\
+static void __exit phy_module_exit(void)				\
+{									\
+	phy_drivers_unregister(__phy_drivers, __count);			\
+}									\
+module_exit(phy_module_exit)
+
+#define annotated_module_phy_driver(__phy_drivers, id, deps)		\
+	annotated_phy_module_driver(__phy_drivers,			\
+				    ARRAY_SIZE(__phy_drivers), id, deps)
+
 #endif /* __PHY_H */
diff --git a/include/linux/platform_device.h b/include/linux/platform_device.h
index bba08f4..10452cb 100644
--- a/include/linux/platform_device.h
+++ b/include/linux/platform_device.h
@@ -218,9 +218,29 @@ static inline void platform_set_drvdata(struct platform_device *pdev,
  * boilerplate.  Each module may only use this macro once, and
  * calling it replaces module_init() and module_exit()
  */
-#define module_platform_driver(__platform_driver) \
-	module_driver(__platform_driver, platform_driver_register, \
-			platform_driver_unregister)
+#define module_platform_driver(__driver) \
+static int __init __driver##_init(void) \
+{ \
+	return platform_driver_register(&(__driver)); \
+} \
+module_init(__driver##_init); \
+static void __exit __driver##_exit(void) \
+{ \
+	platform_driver_unregister(&(__driver)); \
+} \
+module_exit(__driver##_exit)
+
+#define annotated_module_platform_driver(__driver, __id, __deps) \
+static int __init __driver##_init(void) \
+{ \
+	return platform_driver_register(&(__driver)); \
+} \
+annotated_module_init_drv(__driver##_init, __id, __deps, __driver.driver); \
+static void __exit __driver##_exit(void) \
+{ \
+	platform_driver_unregister(&(__driver)); \
+} \
+module_exit(__driver##_exit)
 
 /* builtin_platform_driver() - Helper macro for builtin drivers that
  * don't do anything special in driver init.  This eliminates some
@@ -249,6 +269,21 @@ static void __exit __platform_driver##_exit(void) \
 } \
 module_exit(__platform_driver##_exit);
 
+#define annotated_module_platform_driver_probe(__platform_driver, \
+				__platform_probe, __id, __deps) \
+static int __init __platform_driver##_init(void) \
+{ \
+	return platform_driver_probe(&(__platform_driver), \
+				     __platform_probe);    \
+} \
+annotated_module_init_drv(__platform_driver##_init, __id, __deps, \
+			  __platform_driver.driver); \
+static void __exit __platform_driver##_exit(void) \
+{ \
+	platform_driver_unregister(&(__platform_driver)); \
+} \
+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.
diff --git a/include/linux/serio.h b/include/linux/serio.h
index 9f779c7..e5a9ef6 100644
--- a/include/linux/serio.h
+++ b/include/linux/serio.h
@@ -105,6 +105,11 @@ void serio_unregister_driver(struct serio_driver *drv);
 	module_driver(__serio_driver, serio_register_driver, \
 		       serio_unregister_driver)
 
+#define annotated_module_serio_driver(__serio_driver, id, deps) \
+	annotated_module_driver(__serio_driver, serio_register_driver, \
+		       serio_unregister_driver, id, deps)
+
+
 static inline int serio_write(struct serio *serio, unsigned char data)
 {
 	if (serio->write)
diff --git a/include/linux/usb.h b/include/linux/usb.h
index 447fe29..f8d7a15 100644
--- a/include/linux/usb.h
+++ b/include/linux/usb.h
@@ -1187,6 +1187,18 @@ extern void usb_deregister(struct usb_driver *);
 	module_driver(__usb_driver, usb_register, \
 		       usb_deregister)
 
+#define annotated_module_usb_driver(__usb_driver, __id, __deps) \
+static int __init __usb_driver##_init(void) \
+{ \
+	return usb_register(&(__usb_driver)); \
+} \
+annotated_module_init(__usb_driver##_init, __id, __deps); \
+static void __exit __usb_driver##_exit(void) \
+{ \
+	usb_deregister(&(__usb_driver)); \
+} \
+module_exit(__usb_driver##_exit)
+
 extern int usb_register_device_driver(struct usb_device_driver *,
 			struct module *);
 extern void usb_deregister_device_driver(struct usb_device_driver *);
diff --git a/init/Kconfig b/init/Kconfig
index af09b4f..5cfd7c4 100644
--- a/init/Kconfig
+++ b/init/Kconfig
@@ -26,6 +26,9 @@ config IRQ_WORK
 config BUILDTIME_EXTABLE_SORT
 	bool
 
+config ANNOTATED_INITCALLS
+	bool
+
 menu "General setup"
 
 config BROKEN
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 02/14] init: deps: use annotated initcalls for a dependency based (optionally parallelized) init
  2015-10-17 17:14 [PATCH 0/14] init: deps: dependency based (parallelized) init Alexander Holler
  2015-10-17 17:14 ` [PATCH 01/14] init: deps: introduce annotated initcalls Alexander Holler
@ 2015-10-17 17:14 ` Alexander Holler
  2015-10-17 17:14 ` [PATCH 03/14] init: deps: dt: use (HW-specific) dependencies provided by the DT too Alexander Holler
                   ` (13 subsequent siblings)
  15 siblings, 0 replies; 59+ messages in thread
From: Alexander Holler @ 2015-10-17 17:14 UTC (permalink / raw)
  To: linux-kernel
  Cc: Linus Torvalds, Andrew Morton, Greg Kroah-Hartman, Russell King,
	Grant Likely, Alexander Holler

Based on the dependencies provided by annotated initcalls, this patch
introduces a topological sort to sort initcalls and (optionally) uses
multiple threads to call initcalls.

If the feature is disabled, nothing changes.

Signed-off-by: Alexander Holler <holler@ahsoftware.de>
---
 include/linux/init.h |   6 +
 init/.gitignore      |   1 +
 init/Kconfig.deps    |  38 +++++
 init/Makefile        |  15 ++
 init/dependencies.c  | 394 +++++++++++++++++++++++++++++++++++++++++++++++++++
 init/main.c          |  10 +-
 lib/Kconfig.debug    |   1 +
 7 files changed, 464 insertions(+), 1 deletion(-)
 create mode 100644 init/.gitignore
 create mode 100644 init/Kconfig.deps
 create mode 100644 init/dependencies.c

diff --git a/include/linux/init.h b/include/linux/init.h
index 758fd18..264f83f 100644
--- a/include/linux/init.h
+++ b/include/linux/init.h
@@ -160,6 +160,12 @@ extern void (*late_time_init)(void);
 
 extern bool initcall_debug;
 
+/* Defined in init/dependencies.c */
+void __init do_annotated_initcalls(void);
+
+/* id_dependency will be initialized before id */
+int __init add_initcall_dependency(unsigned id, unsigned id_dependency);
+
 #endif
   
 #ifndef MODULE
diff --git a/init/.gitignore b/init/.gitignore
new file mode 100644
index 0000000..38e6d06
--- /dev/null
+++ b/init/.gitignore
@@ -0,0 +1 @@
+driver_names.c
diff --git a/init/Kconfig.deps b/init/Kconfig.deps
new file mode 100644
index 0000000..9ced0d4
--- /dev/null
+++ b/init/Kconfig.deps
@@ -0,0 +1,38 @@
+config DEPENDENCIES
+	bool "Use dependency based initialization sequence (DO NOT USE)"
+	select ANNOTATED_INITCALLS
+	help
+	  This will likely crash your kernel at startup. You have been warned.
+	  That means you should make sure you have a working backup kernel
+	  you can boot from in case the kernel with this feature turned on
+	  crashes.
+	  In order to benefit from this feature, statically linked drivers
+	  have to provide dependencies.
+
+config DEPENDENCIES_PRINT_INIT_ORDER
+	bool "Print dependency based initialization order"
+	depends on DEPENDENCIES
+	help
+	  Used for debugging purposes.
+
+config DEPENDENCIES_PRINT_CALLS
+	bool "Show when annotated initcalls are actually called"
+	depends on DEPENDENCIES
+	help
+	  Used for debugging purposes.
+
+config DEPENDENCIES_PARALLEL
+	bool "Call annotated initcalls in parallel"
+	depends on DEPENDENCIES
+	help
+	  Calculates which (annotated) initcalls can be called in parallel
+	  and calls them using multiple threads.
+
+config DEPENDENCIES_THREADS
+	int "Number of threads to use for parallel initialization"
+	depends on DEPENDENCIES_PARALLEL
+	default 0
+	help
+	  0 means the number of threads used for parallel initialization
+	  of drivers equals the number of online CPUs.
+	  1 means the threaded initialization is disabled.
diff --git a/init/Makefile b/init/Makefile
index 7bc47ee..6a8c22c 100644
--- a/init/Makefile
+++ b/init/Makefile
@@ -9,6 +9,7 @@ else
 obj-$(CONFIG_BLK_DEV_INITRD)   += initramfs.o
 endif
 obj-$(CONFIG_GENERIC_CALIBRATE_DELAY) += calibrate.o
+obj-$(CONFIG_DEPENDENCIES) += dependencies.o
 
 ifneq ($(CONFIG_ARCH_INIT_TASK),y)
 obj-y                          += init_task.o
@@ -19,6 +20,20 @@ mounts-$(CONFIG_BLK_DEV_RAM)	+= do_mounts_rd.o
 mounts-$(CONFIG_BLK_DEV_INITRD)	+= do_mounts_initrd.o
 mounts-$(CONFIG_BLK_DEV_MD)	+= do_mounts_md.o
 
+quiet_cmd_make-driver_names = GEN     $@
+      cmd_make-driver_names = sed $< > $@ \
+		-e 's/^\tdrvid_\(.*\),/\t"\1",/' \
+		-e 's/^\tdrvid_max$$/\t"max"/' \
+		-e 's/^enum {/static const char *driver_names[] __initdata = {/' \
+		-e '/^\#ifndef _LINUX_DRIVER_IDS_H$$/d' \
+		-e '/^\#define _LINUX_DRIVER_IDS_H$$/d' \
+		-e '/^\#endif \/\* _LINUX_DRIVER_IDS_H \*\/$$/d'
+
+$(obj)/driver_names.c: $(srctree)/include/linux/driver_ids.h
+	$(call cmd,make-driver_names)
+
+$(obj)/dependencies.o: $(obj)/driver_names.c
+
 # dependencies on generated files need to be listed explicitly
 $(obj)/version.o: include/generated/compile.h
 
diff --git a/init/dependencies.c b/init/dependencies.c
new file mode 100644
index 0000000..c47817c
--- /dev/null
+++ b/init/dependencies.c
@@ -0,0 +1,394 @@
+/*
+ * Code for building a deterministic initialization order
+ * based on dependencies.
+ *
+ * Copyright (C) 2014 Alexander Holler <holler@ahsoftware.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+/* #define DEBUG */
+
+#include <linux/kthread.h>
+#include <linux/sort.h>
+#include <linux/device.h>
+#include <linux/mod_devicetable.h>
+#include <linux/init.h>
+
+#if defined(CONFIG_DEPENDENCIES_PRINT_INIT_ORDER) \
+	|| defined(CONFIG_DEPENDENCIES_PRINT_CALLS)
+#include "driver_names.c"
+#endif
+
+#define MAX_VERTICES drvid_max /* maximum number of vertices */
+#define MAX_EDGES (MAX_VERTICES*5) /* maximum number of edges (dependencies) */
+
+struct edgenode {
+	unsigned y; /* initcall ID */
+#ifdef CONFIG_DEPENDENCIES_PARALLEL
+	unsigned x;
+#endif
+	struct edgenode *next; /* next edge in list */
+};
+
+/* Vertex numbers correspond to initcall IDs. */
+static struct edgenode edge_slots[MAX_EDGES] __initdata; /* avoid kmalloc */
+static struct edgenode *edges[MAX_VERTICES] __initdata; /* adjacency info */
+static unsigned nedges __initdata; /* number of edges */
+static unsigned nvertices __initdata; /* number of vertices */
+static bool processed[MAX_VERTICES] __initdata;
+static bool include_node[MAX_VERTICES] __initdata;
+static bool discovered[MAX_VERTICES] __initdata;
+
+static unsigned order[MAX_VERTICES] __initdata;
+static unsigned norder __initdata;
+static const struct _annotated_initcall
+		*annotated_initcall_by_drvid[MAX_VERTICES] __initdata;
+
+int __init add_initcall_dependency(unsigned id, unsigned id_dependency)
+{
+	struct edgenode *p;
+
+	if (!id || !id_dependency)
+		return 0; /* ignore root */
+	if (unlikely(nedges >= MAX_EDGES)) {
+		pr_err("init: maximum number of edges (%u) reached!\n",
+			MAX_EDGES);
+		return -EINVAL;
+	}
+	if (unlikely(id == id_dependency))
+		return 0;
+	if (!include_node[id] || !include_node[id_dependency])
+		return 0; /* ignore edges for initcalls not included */
+	p = &edge_slots[nedges++];
+	p->y = id_dependency;
+#ifdef CONFIG_DEPENDENCIES_PARALLEL
+	p->x = id;
+#endif
+	/* insert at head of list */
+	p->next = edges[id];
+	edges[id] = p;
+
+	return 0;
+}
+
+static int __init depth_first_search(unsigned v)
+{
+	struct edgenode *p;
+	unsigned y; /* successor vertex */
+
+	discovered[v] = 1;
+	p = edges[v];
+	while (p) {
+		y = p->y;
+		if (unlikely(discovered[y] && !processed[y])) {
+			pr_err("init: cycle found %u <-> %u!\n", v, y);
+			return -EINVAL;
+		}
+		if (!discovered[y] && depth_first_search(y))
+			return -EINVAL;
+		p = p->next;
+	}
+	order[norder++] = v;
+	processed[v] = 1;
+	return 0;
+}
+
+static int __init topological_sort(void)
+{
+	unsigned i;
+
+	for (i = 1; i <= nvertices; ++i)
+		if (!discovered[i] && include_node[i])
+			if (depth_first_search(i))
+				return -EINVAL;
+	return 0;
+}
+
+#ifdef CONFIG_DEPENDENCIES_PARALLEL
+/*
+ * The algorithm I've used below to calculate the max. distance for
+ * nodes to the root node likely isn't the fasted. But based on the
+ * already done implementation of the topological sort, this is an
+ * easy way to achieve this. Instead of first doing an topological
+ * sort and then using the stuff below to calculate the distances,
+ * using an algorithm which does spit out distances directly would
+ * be likely faster (also we are talking here about a few ms).
+ * If you want to spend the time, you could have a look e.g. at the
+ * topic 'layered graph drawing'.
+ */
+/* max. distance from a node to root */
+static unsigned distance[MAX_VERTICES] __initdata;
+static struct {
+	unsigned start;
+	unsigned length;
+} tgroup[20] __initdata;
+static unsigned count_groups __initdata;
+static __initdata DECLARE_COMPLETION(initcall_thread_done);
+static atomic_t shared_counter __initdata;
+static atomic_t count_initcall_threads __initdata;
+static atomic_t ostart __initdata;
+static atomic_t ocount __initdata;
+static atomic_t current_group __initdata;
+static unsigned num_threads __initdata;
+static __initdata DECLARE_WAIT_QUEUE_HEAD(group_waitqueue);
+
+static void __init calc_max_distance(uint32_t v)
+{
+	unsigned i;
+	unsigned max_dist = 0;
+
+	for (i = 0; i < nedges; ++i)
+		if (edge_slots[i].x == v)
+			max_dist = max(max_dist,
+				distance[edge_slots[i].y] + 1);
+	distance[v] = max_dist;
+}
+
+static void __init calc_distances(void)
+{
+	unsigned i;
+
+	for (i = 0; i < norder; ++i)
+		calc_max_distance(order[i]);
+}
+
+static int __init compare_by_distance(const void *lhs, const void *rhs)
+{
+	if (distance[*(unsigned *)lhs] < distance[*(unsigned *)rhs])
+		return -1;
+	if (distance[*(unsigned *)lhs] > distance[*(unsigned *)rhs])
+		return 1;
+	return 0;
+}
+
+static void __init build_order_by_distance(void)
+{
+	calc_distances();
+	sort(order, norder, sizeof(unsigned), &compare_by_distance, NULL);
+}
+
+static void __init build_tgroups(void)
+{
+	unsigned i;
+	unsigned dist = 0;
+
+	for (i = 0; i < norder; ++i) {
+		if (distance[order[i]] != dist) {
+			dist = distance[order[i]];
+			count_groups++;
+			tgroup[count_groups].start = i;
+		}
+		tgroup[count_groups].length++;
+	}
+	count_groups++;
+#ifdef DEBUG
+	for (i = 0; i < count_groups; ++i)
+		pr_info("init: group %u length %u (start %u)\n", i,
+				tgroup[i].length, tgroup[i].start);
+#endif
+}
+
+static int __init initcall_thread(void *thread_nr)
+{
+	int i;
+	unsigned group;
+	int start, count;
+	const struct _annotated_initcall *ac;
+	DEFINE_WAIT(wait);
+
+	while ((group = atomic_read(&current_group)) < count_groups) {
+		start = atomic_read(&ostart);
+		count = atomic_read(&ocount);
+		while ((i = atomic_dec_return(&shared_counter)) >= 0) {
+			ac = annotated_initcall_by_drvid[
+					order[start + count - 1 - i]];
+#ifdef CONFIG_DEPENDENCIES_PRINT_CALLS
+			pr_info("init: thread %lu calling initcall for driver %s (ID %u)\n",
+				(unsigned long)thread_nr,
+				driver_names[ac->id], ac->id);
+#endif
+			do_one_initcall(*ac->initcall);
+		}
+		prepare_to_wait(&group_waitqueue, &wait, TASK_UNINTERRUPTIBLE);
+		if (!atomic_dec_and_test(&count_initcall_threads)) {
+			/*
+			 * The current group was processed, sleep until the
+			 * last thread finished work on this group, changes
+			 * the group and wakes up all threads.
+			 */
+			schedule();
+			finish_wait(&group_waitqueue, &wait);
+			continue;
+		}
+		atomic_inc(&current_group);
+		atomic_set(&count_initcall_threads, num_threads);
+		if (++group >= count_groups) {
+			/*
+			 * All groups processed and all threads finished.
+			 * Prepare to process unordered annotated
+			 * initcalls and wake up other threads to call
+			 * them too.
+			 */
+			atomic_set(&shared_counter,
+				__annotated_initcall_end -
+					__annotated_initcall_start);
+			wake_up_all(&group_waitqueue);
+			finish_wait(&group_waitqueue, &wait);
+			break;
+		}
+		/*
+		 * Finalize the switch to the next group and wake up other
+		 * threads to process the new group too.
+		 */
+		pr_debug("init: thread %lu changes group\n",
+			(unsigned long)thread_nr);
+		atomic_set(&ostart, tgroup[group].start);
+		atomic_set(&ocount, tgroup[group].length);
+		atomic_set(&shared_counter, tgroup[group].length);
+		wake_up_all(&group_waitqueue);
+		finish_wait(&group_waitqueue, &wait);
+	}
+	if (atomic_dec_and_test(&count_initcall_threads))
+		complete(&initcall_thread_done);
+	do_exit(0);
+	return 0;
+}
+#else
+#define build_order_by_distance()
+#define build_tgroups()
+#endif /* CONFIG_DEPENDENCIES_PARALLEL */
+
+static void __init init_drivers_non_threaded(void)
+{
+	unsigned i;
+	const struct _annotated_initcall *ac;
+
+	for (i = 0; i < norder; ++i) {
+		ac = annotated_initcall_by_drvid[order[i]];
+#ifdef CONFIG_DEPENDENCIES_PRINT_CALLS
+		pr_info("init: calling initcall for driver %s (ID %u)\n",
+			driver_names[ac->id], ac->id);
+#endif
+		do_one_initcall(*ac->initcall);
+	}
+}
+
+static int __init add_dependencies(void)
+{
+	int rc;
+	const struct _annotated_initcall *ac;
+	const unsigned *dep;
+	unsigned i;
+
+	ac = __annotated_initcall_start;
+	for (; ac < __annotated_initcall_end; ++ac) {
+		dep = ac->dependencies;
+		if (dep)
+			for (i = 0; dep[i]; ++i) {
+				rc = add_initcall_dependency(ac->id, dep[i]);
+				if (unlikely(rc))
+					return rc;
+			}
+	}
+	return 0;
+}
+
+static void __init build_inventory(void)
+{
+	const struct _annotated_initcall *ac;
+
+	ac = __annotated_initcall_start;
+	for (; ac < __annotated_initcall_end; ++ac) {
+		include_node[ac->id] = true;
+		annotated_initcall_by_drvid[ac->id] = ac;
+		nvertices = max(nvertices, ac->id);
+	}
+}
+
+#ifdef CONFIG_DEPENDENCIES_PRINT_INIT_ORDER
+static void __init print_order(void)
+{
+	unsigned i;
+
+	pr_info("init: initialization order:\n");
+	for (i = 0; i < norder; ++i) {
+#ifdef CONFIG_DEPENDENCIES_PARALLEL
+		pr_info("init: %u (group %u) %s (ID %u)\n", i,
+			distance[order[i]], driver_names[order[i]], order[i]);
+#else
+		pr_info("init: %u %s (ID %u)\n", i,
+			driver_names[order[i]], order[i]);
+#endif
+	}
+}
+#else
+#define print_order()
+#endif
+
+static int __init build_order(void)
+{
+	int rc = 0;
+
+	build_inventory();
+	add_dependencies();
+	if (topological_sort())
+		return -EINVAL; /* cycle found */
+	pr_debug("init: vertices: %u edges %u count %u\n",
+					nvertices, nedges, norder);
+	build_order_by_distance();
+	build_tgroups();
+	print_order();
+	return rc;
+}
+
+void __init do_annotated_initcalls(void)
+{
+	unsigned i;
+
+	i = __annotated_initcall_end - __annotated_initcall_start;
+	if (!i)
+		return;
+
+	if (build_order()) {
+		/*
+		 * Building order failed (likely because of a dependency
+		 * circle). Try to boot anyway by calling all annotated
+		 * initcalls unordered.
+		 */
+		const struct _annotated_initcall *ac;
+
+		ac = __annotated_initcall_start;
+		for (; ac < __annotated_initcall_end; ++ac)
+			do_one_initcall(*ac->initcall);
+		return;
+	}
+
+#ifndef CONFIG_DEPENDENCIES_PARALLEL
+	init_drivers_non_threaded();
+#else
+	if (CONFIG_DEPENDENCIES_THREADS == 0)
+		num_threads = num_online_cpus();
+	else
+		num_threads = CONFIG_DEPENDENCIES_THREADS;
+	if (num_threads < 2) {
+		init_drivers_non_threaded();
+		return;
+	}
+	pr_debug("init: using %u threads to call annotated initcalls\n",
+				num_threads);
+	atomic_set(&count_initcall_threads, num_threads);
+	atomic_set(&ostart, tgroup[0].start);
+	atomic_set(&ocount, tgroup[0].length);
+	atomic_set(&shared_counter, tgroup[0].length);
+	atomic_set(&current_group, 0);
+	for (i = 0; i < num_threads; ++i)
+		kthread_run(initcall_thread, (void *)(unsigned long)i,
+			"initcalls");
+	wait_for_completion(&initcall_thread_done);
+	pr_debug("init: all threads done\n");
+#endif
+}
diff --git a/init/main.c b/init/main.c
index 5650655..f873c08 100644
--- a/init/main.c
+++ b/init/main.c
@@ -863,8 +863,16 @@ static void __init do_initcalls(void)
 {
 	int level;
 
-	for (level = 0; level < ARRAY_SIZE(initcall_levels) - 1; level++)
+	for (level = 0; level < ARRAY_SIZE(initcall_levels) - 3; level++)
 		do_initcall_level(level);
+#ifdef CONFIG_DEPENDENCIES
+	/* call annotated drivers (sorted) */
+	do_annotated_initcalls();
+#endif
+	/* call normal and not annoted drivers (not sorted) */
+	do_initcall_level(level++);
+	/* call late drivers */
+	do_initcall_level(level);
 }
 
 /*
diff --git a/lib/Kconfig.debug b/lib/Kconfig.debug
index e2894b2..4815b15 100644
--- a/lib/Kconfig.debug
+++ b/lib/Kconfig.debug
@@ -1844,3 +1844,4 @@ source "samples/Kconfig"
 
 source "lib/Kconfig.kgdb"
 
+source "init/Kconfig.deps"
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 03/14] init: deps: dt: use (HW-specific) dependencies provided by the DT too
  2015-10-17 17:14 [PATCH 0/14] init: deps: dependency based (parallelized) init Alexander Holler
  2015-10-17 17:14 ` [PATCH 01/14] init: deps: introduce annotated initcalls Alexander Holler
  2015-10-17 17:14 ` [PATCH 02/14] init: deps: use annotated initcalls for a dependency based (optionally parallelized) init Alexander Holler
@ 2015-10-17 17:14 ` Alexander Holler
  2015-10-19 12:37   ` Mark Brown
  2015-10-17 17:14 ` [PATCH 04/14] init: deps: order network interfaces by link order Alexander Holler
                   ` (12 subsequent siblings)
  15 siblings, 1 reply; 59+ messages in thread
From: Alexander Holler @ 2015-10-17 17:14 UTC (permalink / raw)
  To: linux-kernel
  Cc: Linus Torvalds, Andrew Morton, Greg Kroah-Hartman, Russell King,
	Grant Likely, Alexander Holler

This patch adds dependencies provided by the hardware description in
the used DT. This avoids the use of the deferred probe mechanism
on most (if not all) DT based kernels.

Drawback is that the binary DT blob has to be enhanced with type
information for phandles (which are used as dependencies) which
needs a modified dtc.

Signed-off-by: Alexander Holler <holler@ahsoftware.de>
---
 drivers/of/base.c   | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/of.h  |   3 ++
 init/dependencies.c |   4 ++
 3 files changed, 121 insertions(+)

diff --git a/drivers/of/base.c b/drivers/of/base.c
index 8b5a187..423ddff 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -12,6 +12,8 @@
  *  Reconsolidated from arch/x/kernel/prom.c by Stephen Rothwell and
  *  Grant Likely.
  *
+ *  The dependency related stuff was done by Alexander Holler.
+ *
  *      This program is free software; you can redistribute it and/or
  *      modify it under the terms of the GNU General Public License
  *      as published by the Free Software Foundation; either version
@@ -2308,3 +2310,115 @@ struct device_node *of_graph_get_remote_port(const struct device_node *node)
 	return of_get_next_parent(np);
 }
 EXPORT_SYMBOL(of_graph_get_remote_port);
+
+#ifdef CONFIG_DEPENDENCIES
+
+static const struct _annotated_initcall * __init find_matching_driver(
+	const struct _annotated_initcall *from, const struct device_node *node)
+{
+	while (++from != __annotated_initcall_end)
+		if (from->driver &&
+				__of_match_node(from->driver->of_match_table,
+					node))
+			return from;
+	return NULL;
+}
+
+static int __init add_dep_list(const struct device_node *node, unsigned drvid)
+{
+	const __be32 *list, *list_end;
+	uint32_t ph;
+	int size = 0;
+	int rc = 0;
+	const struct device_node *dep;
+	const struct _annotated_initcall *ac;
+
+	list = __of_get_property(node, "dependencies", &size);
+	if (!list || !size || size % sizeof(*list))
+		return 0;
+	list_end = list + size / sizeof(*list);
+	while (list < list_end) {
+		ph = be32_to_cpup(list++);
+		if (unlikely(!ph)) {
+			/* Should never happen */
+			if (node->name)
+				pr_warn("phandle == 0 for %s\n", node->name);
+			continue;
+		}
+		dep = of_find_node_by_phandle(ph);
+		if (unlikely(!dep)) {
+			pr_err("No DT node for dependency with phandle 0x%x found\n",
+				ph);
+			continue;
+		}
+		ac = __annotated_initcall_start - 1;
+		while ((ac = find_matching_driver(ac, dep))) {
+			if (!ac->id)
+				continue;
+			rc = add_initcall_dependency(drvid, ac->id);
+			if (rc)
+				return rc;
+		}
+	}
+
+	return rc;
+}
+
+static int __init add_deps(unsigned parent, const struct device_node *node)
+{
+	struct device_node *child;
+	const struct _annotated_initcall *ac;
+	int rc = 0;
+	bool found_one_driver = false;
+
+	if (!__of_device_is_available(node))
+		return 0;
+	if (__of_get_property(node, "compatible", NULL)) {
+		ac = __annotated_initcall_start - 1;
+		while ((ac = find_matching_driver(ac, node))) {
+			if (!ac->id)
+				continue;
+			found_one_driver = true;
+			rc = add_initcall_dependency(ac->id, parent);
+			if (unlikely(rc))
+				return rc;
+			rc = add_dep_list(node, ac->id);
+			if (unlikely(rc))
+				return rc;
+			for_each_child_of_node(node, child) {
+				rc = add_deps(ac->id, child);
+				if (unlikely(rc))
+					return rc;
+			}
+		}
+		if (found_one_driver)
+			return rc;
+	}
+	for_each_child_of_node(node, child) {
+		rc = add_deps(parent, child);
+		if (unlikely(rc))
+			break;
+	}
+
+	return rc;
+}
+
+int __init of_add_dependencies(void)
+{
+	int rc = 0;
+	struct device_node *child;
+	struct device_node *root =  of_find_node_by_path("/");
+
+	if (unlikely(!root))
+		return -EINVAL;
+
+	for_each_child_of_node(root, child) {
+		rc = add_deps(0, child);
+		if (unlikely(rc))
+			break;
+	}
+	of_node_put(root);
+
+	return rc;
+}
+#endif /* CONFIG_DEPENDENCIES */
diff --git a/include/linux/of.h b/include/linux/of.h
index edc068d..e3b65c8 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -1101,4 +1101,7 @@ static inline int of_overlay_destroy_all(void)
 
 #endif
 
+/* Inserts dependencies for drivers referenced in the loaded DT. */
+int __init of_add_dependencies(void);
+
 #endif /* _LINUX_OF_H */
diff --git a/init/dependencies.c b/init/dependencies.c
index c47817c..b484f67 100644
--- a/init/dependencies.c
+++ b/init/dependencies.c
@@ -17,6 +17,7 @@
 #include <linux/device.h>
 #include <linux/mod_devicetable.h>
 #include <linux/init.h>
+#include <linux/of.h>
 
 #if defined(CONFIG_DEPENDENCIES_PRINT_INIT_ORDER) \
 	|| defined(CONFIG_DEPENDENCIES_PRINT_CALLS)
@@ -335,6 +336,9 @@ static int __init build_order(void)
 
 	build_inventory();
 	add_dependencies();
+#ifdef CONFIG_OF
+	of_add_dependencies();
+#endif
 	if (topological_sort())
 		return -EINVAL; /* cycle found */
 	pr_debug("init: vertices: %u edges %u count %u\n",
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 04/14] init: deps: order network interfaces by link order
  2015-10-17 17:14 [PATCH 0/14] init: deps: dependency based (parallelized) init Alexander Holler
                   ` (2 preceding siblings ...)
  2015-10-17 17:14 ` [PATCH 03/14] init: deps: dt: use (HW-specific) dependencies provided by the DT too Alexander Holler
@ 2015-10-17 17:14 ` Alexander Holler
  2015-10-17 18:23   ` Linus Torvalds
  2015-10-17 17:14 ` [PATCH 05/14] init: deps: order I2C bus drivers by their ID Alexander Holler
                   ` (11 subsequent siblings)
  15 siblings, 1 reply; 59+ messages in thread
From: Alexander Holler @ 2015-10-17 17:14 UTC (permalink / raw)
  To: linux-kernel
  Cc: Linus Torvalds, Andrew Morton, Greg Kroah-Hartman, Russell King,
	Grant Likely, Alexander Holler

In order to provide stable interface numbers, network interface drivers
will be ordered by the link order. This is easy to accomplish by adding
dependencies.

Assuming three different ethernet-drivers, without any special code,
the dependency graph would not require any special order inbetween them
and would look like that:

    eth-driver-base
   /      |       \
eth-x   eth-y    eth-z

Now we just add dependencies. With the additional dependencies the graph
looks like:

 eth-driver-base
  |     | |
eth-x   | |
  |     | |
eth-y  -| |
  |       |
eth-z  ---|

Signed-off-by: Alexander Holler <holler@ahsoftware.de>
---
 include/linux/driver_ids.h | 11 +++++++++++
 init/dependencies.c        |  9 +++++++++
 2 files changed, 20 insertions(+)

diff --git a/include/linux/driver_ids.h b/include/linux/driver_ids.h
index 60964fe..1133a68 100644
--- a/include/linux/driver_ids.h
+++ b/include/linux/driver_ids.h
@@ -15,6 +15,17 @@
 enum {
 	drvid_unused,
 	/* To be filled */
+
+	/*
+	 * Network drivers will be ordered according to the link order
+	 * (which means not necessarily according to their appearance
+	 * here).
+	 * This provides stable interface numbers.
+	 * Therefor their IDs have to be in the following block.
+	 */
+	drvid_network_drivers_start,
+	drvid_network_drivers_end,
+
 	drvid_max
 };
 
diff --git a/init/dependencies.c b/init/dependencies.c
index b484f67..027fc4b 100644
--- a/init/dependencies.c
+++ b/init/dependencies.c
@@ -301,12 +301,21 @@ static int __init add_dependencies(void)
 static void __init build_inventory(void)
 {
 	const struct _annotated_initcall *ac;
+	unsigned id_last_network_driver = 0;
 
 	ac = __annotated_initcall_start;
 	for (; ac < __annotated_initcall_end; ++ac) {
 		include_node[ac->id] = true;
 		annotated_initcall_by_drvid[ac->id] = ac;
 		nvertices = max(nvertices, ac->id);
+		/* order network drivers by link order*/
+		if (ac->id > drvid_network_drivers_start &&
+				ac->id < drvid_network_drivers_end) {
+			if (id_last_network_driver)
+				add_initcall_dependency(ac->id,
+					id_last_network_driver);
+			id_last_network_driver = ac->id;
+		}
 	}
 }
 
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 05/14] init: deps: order I2C bus drivers by their ID
  2015-10-17 17:14 [PATCH 0/14] init: deps: dependency based (parallelized) init Alexander Holler
                   ` (3 preceding siblings ...)
  2015-10-17 17:14 ` [PATCH 04/14] init: deps: order network interfaces by link order Alexander Holler
@ 2015-10-17 17:14 ` Alexander Holler
  2015-10-17 17:14 ` [PATCH 06/14] dtc: deps: Automatically add new property 'dependencies' which contains a list of referenced phandles Alexander Holler
                   ` (10 subsequent siblings)
  15 siblings, 0 replies; 59+ messages in thread
From: Alexander Holler @ 2015-10-17 17:14 UTC (permalink / raw)
  To: linux-kernel
  Cc: Linus Torvalds, Andrew Morton, Greg Kroah-Hartman, Russell King,
	Grant Likely, Alexander Holler

In order to provide a stable I2C bus numbering, we order I2C bus drivers
according to their driver ID.

If that is better or worse than ordering by link order might have to be
discussed, but for now, it's good to provide an example about how to order
something based on driver IDs.

Signed-off-by: Alexander Holler <holler@ahsoftware.de>
---
 include/linux/driver_ids.h |  9 +++++++++
 init/dependencies.c        | 25 +++++++++++++++++++++++++
 2 files changed, 34 insertions(+)

diff --git a/include/linux/driver_ids.h b/include/linux/driver_ids.h
index 1133a68..330080e 100644
--- a/include/linux/driver_ids.h
+++ b/include/linux/driver_ids.h
@@ -17,6 +17,15 @@ enum {
 	/* To be filled */
 
 	/*
+	 * I2C bus drivers will be ordered according to their ID (which
+	 * means according to their appearance here).
+	 * This provides stable I2C bus numbers.
+	 * Therefor their IDs have to be in the following block.
+	 */
+	drvid_i2c_busses_start,
+	drvid_i2c_busses_end,
+
+	/*
 	 * Network drivers will be ordered according to the link order
 	 * (which means not necessarily according to their appearance
 	 * here).
diff --git a/init/dependencies.c b/init/dependencies.c
index 027fc4b..d20d6fc 100644
--- a/init/dependencies.c
+++ b/init/dependencies.c
@@ -298,10 +298,22 @@ static int __init add_dependencies(void)
 	return 0;
 }
 
+static int __init compare_unsigned(const void *lhs, const void *rhs)
+{
+	if (*(unsigned *)lhs < *(unsigned *)rhs)
+		return -1;
+	if (*(unsigned *)lhs > *(unsigned *)rhs)
+		return 1;
+	return 0;
+}
+
 static void __init build_inventory(void)
 {
 	const struct _annotated_initcall *ac;
 	unsigned id_last_network_driver = 0;
+	unsigned id_i2c_bus_driver[drvid_i2c_busses_end
+				   - drvid_i2c_busses_start];
+	unsigned count_i2c_bus_drivers = 0;
 
 	ac = __annotated_initcall_start;
 	for (; ac < __annotated_initcall_end; ++ac) {
@@ -316,6 +328,19 @@ static void __init build_inventory(void)
 					id_last_network_driver);
 			id_last_network_driver = ac->id;
 		}
+		/* order I2C bus drivers by their ID */
+		if (ac->id > drvid_i2c_busses_start &&
+				ac->id < drvid_i2c_busses_end)
+			id_i2c_bus_driver[count_i2c_bus_drivers++] = ac->id;
+	}
+	if (count_i2c_bus_drivers > 1) {
+		unsigned i;
+
+		sort(id_i2c_bus_driver, count_i2c_bus_drivers,
+				sizeof(unsigned), &compare_unsigned, NULL);
+		for (i = 1; i < count_i2c_bus_drivers; ++i)
+			add_initcall_dependency(id_i2c_bus_driver[i],
+				id_i2c_bus_driver[i-1]);
 	}
 }
 
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 06/14] dtc: deps: Automatically add new property 'dependencies' which contains a list of referenced phandles
  2015-10-17 17:14 [PATCH 0/14] init: deps: dependency based (parallelized) init Alexander Holler
                   ` (4 preceding siblings ...)
  2015-10-17 17:14 ` [PATCH 05/14] init: deps: order I2C bus drivers by their ID Alexander Holler
@ 2015-10-17 17:14 ` Alexander Holler
  2015-10-17 17:14 ` [PATCH 07/14] dtc: deps: introduce new (virtual) property no-dependencies Alexander Holler
                   ` (9 subsequent siblings)
  15 siblings, 0 replies; 59+ messages in thread
From: Alexander Holler @ 2015-10-17 17:14 UTC (permalink / raw)
  To: linux-kernel
  Cc: Linus Torvalds, Andrew Morton, Greg Kroah-Hartman, Russell King,
	Grant Likely, Alexander Holler

During the step from .dts to .dtb the information about dependcies
contained in the .dts through phandle references is lost. This makes it
impossible to use the binary blob to create a dependency graph without
knowing the semantic of all cell arrays.

Therefor automatically add a new property called 'dependencies' to all
nodes which have phandle references in one of their properties.

This new property will contain an array of phandles with one value for
every phandle referenced by other properties in the node.

If such a property already exists (e.g. to manually add dependencies
through the .dts), the existing list will be expanded.

Added phandles will be the phandle of either the referenced node itself
(if it has a property named 'compatible', or of the next parent of the
referenced node which as property named 'compatible'. This ensures only
dependencies to drivers will be added.

References to phandles of parent or child nodes will not be added to this
property, because this information is already contained in the blob (in
the form of the tree itself).

No dependencies to disabled nodes will be added.

Signed-off-by: Alexander Holler <holler@ahsoftware.de>
---
 scripts/dtc/Makefile       |   3 +-
 scripts/dtc/Makefile.dtc   |   1 +
 scripts/dtc/dependencies.c | 108 +++++++++++++++++++++++++++++++++++++++++++++
 scripts/dtc/dtc.c          |  12 ++++-
 scripts/dtc/dtc.h          |   3 ++
 5 files changed, 125 insertions(+), 2 deletions(-)
 create mode 100644 scripts/dtc/dependencies.c

diff --git a/scripts/dtc/Makefile b/scripts/dtc/Makefile
index 2a48022..1174cf9 100644
--- a/scripts/dtc/Makefile
+++ b/scripts/dtc/Makefile
@@ -4,7 +4,7 @@ hostprogs-y	:= dtc
 always		:= $(hostprogs-y)
 
 dtc-objs	:= dtc.o flattree.o fstree.o data.o livetree.o treesource.o \
-		   srcpos.o checks.o util.o
+		   srcpos.o checks.o util.o dependencies.o
 dtc-objs	+= dtc-lexer.lex.o dtc-parser.tab.o
 
 # Source files need to get at the userspace version of libfdt_env.h to compile
@@ -13,6 +13,7 @@ HOSTCFLAGS_DTC := -I$(src) -I$(src)/libfdt
 
 HOSTCFLAGS_checks.o := $(HOSTCFLAGS_DTC)
 HOSTCFLAGS_data.o := $(HOSTCFLAGS_DTC)
+HOSTCFLAGS_dependencies.o := $(HOSTCFLAGS_DTC)
 HOSTCFLAGS_dtc.o := $(HOSTCFLAGS_DTC)
 HOSTCFLAGS_flattree.o := $(HOSTCFLAGS_DTC)
 HOSTCFLAGS_fstree.o := $(HOSTCFLAGS_DTC)
diff --git a/scripts/dtc/Makefile.dtc b/scripts/dtc/Makefile.dtc
index bece49b..5fb5343 100644
--- a/scripts/dtc/Makefile.dtc
+++ b/scripts/dtc/Makefile.dtc
@@ -6,6 +6,7 @@
 DTC_SRCS = \
 	checks.c \
 	data.c \
+	dependencies.c \
 	dtc.c \
 	flattree.c \
 	fstree.c \
diff --git a/scripts/dtc/dependencies.c b/scripts/dtc/dependencies.c
new file mode 100644
index 0000000..dd4658c
--- /dev/null
+++ b/scripts/dtc/dependencies.c
@@ -0,0 +1,108 @@
+/*
+ * Code to add a property which contains dependencies (used phandle references)
+ * to all (driver) nodes which are having phandle references.
+ *
+ * Copyright (C) 2014 Alexander Holler <holler@ahsoftware.de>
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <dtc.h>
+
+/* Searches upwards for a node with a property 'compatible' */
+static struct node *find_compatible_not_disabled(struct node *node)
+{
+	struct property *prop;
+
+	while (node) {
+		prop = get_property(node, "compatible");
+		if (prop) {
+			prop = get_property(node, "status");
+			if (prop)
+				if (!prop->val.len ||
+					(strcmp(prop->val.val, "okay") &&
+						strcmp(prop->val.val, "ok")))
+					return NULL; /* disabled */
+			return node;
+		}
+		node = node->parent;
+	}
+	return NULL;
+}
+
+static bool is_parent_of(struct node *node1, struct node *node2)
+{
+	while (node2) {
+		if (node2->parent == node1)
+			return true;
+		node2 = node2->parent;
+	}
+	return false;
+
+}
+
+static void add_deps(struct node *dt, struct node *node, struct property *prop)
+{
+	struct marker *m = prop->val.markers;
+	struct node *refnode;
+	cell_t phandle;
+	struct property *prop_deps;
+	unsigned i;
+	cell_t *cell;
+	struct node *source;
+	struct node *target;
+
+	for_each_marker_of_type(m, REF_PHANDLE) {
+		assert(m->offset + sizeof(cell_t) <= prop->val.len);
+
+		refnode = get_node_by_ref(dt, m->ref);
+		if (!refnode) {
+			fprintf(stderr,
+				"ERROR: Reference to non-existent node or label \"%s\"\n",
+				m->ref);
+			continue;
+		}
+
+		source = find_compatible_not_disabled(node);
+		target = find_compatible_not_disabled(refnode);
+		if (!source || !target || source == target ||
+				is_parent_of(source, target) ||
+				is_parent_of(target, source))
+			continue;
+		phandle = get_node_phandle(dt, target);
+		prop_deps = get_property(source, "dependencies");
+		if (!prop_deps) {
+			add_property(source,
+			     build_property("dependencies",
+				data_append_cell(empty_data, phandle)));
+			continue;
+		}
+		cell = (cell_t *)prop_deps->val.val;
+		for (i = 0; i < prop_deps->val.len/4; ++i)
+			if (*cell++ == cpu_to_fdt32(phandle))
+				break;
+		if (i < prop_deps->val.len/4)
+			continue; /* avoid duplicates */
+		prop_deps->val = data_append_cell(prop_deps->val, phandle);
+	}
+}
+
+static void process_nodes_props(struct node *dt, struct node *node)
+{
+	struct node *child;
+	struct property *prop;
+
+	for_each_property(node, prop)
+		add_deps(dt, node, prop);
+
+	for_each_child(node, child)
+		process_nodes_props(dt, child);
+}
+
+void add_dependencies(struct boot_info *bi)
+{
+	process_nodes_props(bi->dt, bi->dt);
+}
diff --git a/scripts/dtc/dtc.c b/scripts/dtc/dtc.c
index 8c4add6..28def27 100644
--- a/scripts/dtc/dtc.c
+++ b/scripts/dtc/dtc.c
@@ -51,7 +51,7 @@ static void fill_fullpaths(struct node *tree, const char *prefix)
 #define FDT_VERSION(version)	_FDT_VERSION(version)
 #define _FDT_VERSION(version)	#version
 static const char usage_synopsis[] = "dtc [options] <input file>";
-static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:fb:i:H:sW:E:hv";
+static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:fb:i:H:sDW:E:hv";
 static struct option const usage_long_opts[] = {
 	{"quiet",            no_argument, NULL, 'q'},
 	{"in-format",         a_argument, NULL, 'I'},
@@ -66,6 +66,7 @@ static struct option const usage_long_opts[] = {
 	{"force",            no_argument, NULL, 'f'},
 	{"include",           a_argument, NULL, 'i'},
 	{"sort",             no_argument, NULL, 's'},
+	{"no-deps",          no_argument, NULL, 'D'},
 	{"phandle",           a_argument, NULL, 'H'},
 	{"warning",           a_argument, NULL, 'W'},
 	{"error",             a_argument, NULL, 'E'},
@@ -93,6 +94,7 @@ static const char * const usage_opts_help[] = {
 	"\n\tTry to produce output even if the input tree has errors",
 	"\n\tAdd a path to search for include files",
 	"\n\tSort nodes and properties before outputting (useful for comparing trees)",
+	"\n\tDo not automatically add dependencies for phandle references",
 	"\n\tValid phandle formats are:\n"
 	 "\t\tlegacy - \"linux,phandle\" properties only\n"
 	 "\t\tepapr  - \"phandle\" properties only\n"
@@ -112,6 +114,7 @@ int main(int argc, char *argv[])
 	const char *outname = "-";
 	const char *depname = NULL;
 	bool force = false, sort = false;
+	bool dependencies = true;
 	const char *arg;
 	int opt;
 	FILE *outf = NULL;
@@ -179,6 +182,10 @@ int main(int argc, char *argv[])
 			sort = true;
 			break;
 
+		case 'D':
+			dependencies = false;
+			break;
+
 		case 'W':
 			parse_checks_option(true, false, optarg);
 			break;
@@ -236,6 +243,9 @@ int main(int argc, char *argv[])
 	if (sort)
 		sort_tree(bi);
 
+	if (dependencies)
+		add_dependencies(bi);
+
 	if (streq(outname, "-")) {
 		outf = stdout;
 	} else {
diff --git a/scripts/dtc/dtc.h b/scripts/dtc/dtc.h
index 56212c8..6facad1 100644
--- a/scripts/dtc/dtc.h
+++ b/scripts/dtc/dtc.h
@@ -266,4 +266,7 @@ struct boot_info *dt_from_source(const char *f);
 
 struct boot_info *dt_from_fs(const char *dirname);
 
+/* Dependencies */
+void add_dependencies(struct boot_info *bi);
+
 #endif /* _DTC_H */
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 07/14] dtc: deps: introduce new (virtual) property no-dependencies
  2015-10-17 17:14 [PATCH 0/14] init: deps: dependency based (parallelized) init Alexander Holler
                   ` (5 preceding siblings ...)
  2015-10-17 17:14 ` [PATCH 06/14] dtc: deps: Automatically add new property 'dependencies' which contains a list of referenced phandles Alexander Holler
@ 2015-10-17 17:14 ` Alexander Holler
  2015-10-17 17:14 ` [PATCH 08/14] dtc: deps: Add option to print initialization order Alexander Holler
                   ` (8 subsequent siblings)
  15 siblings, 0 replies; 59+ messages in thread
From: Alexander Holler @ 2015-10-17 17:14 UTC (permalink / raw)
  To: linux-kernel
  Cc: Linus Torvalds, Andrew Morton, Greg Kroah-Hartman, Russell King,
	Grant Likely, Alexander Holler

In some cases it makes sense to handle some phandles not as dependencies.

This is escpecially true for 'remote-endpoint' properties, because these
otherwise introducing dependency cycles into the graph. To avoid these,
one end of each remote-endpoint pairs has not to be handled as a
dependency.

The syntax is like

	foo {
		remote-endpoint = <&bar>;
	};
	bar {
		remote-endpoint = <&foo>;
		no-dependencies = <&foo>;
	};

Without that 'no-dependencies' property dtc would automatically add a
dependency to foo to the property 'dependencies' of the node bar.
But with that 'no-dependencies' it will not automatically add the
listed dependencies.

The property 'no-dependencies' is virtual property and will not be added
to any output file.

Signed-off-by: Alexander Holler <holler@ahsoftware.de>
---
 scripts/dtc/dependencies.c | 33 +++++++++++++++++++++++++++++++++
 1 file changed, 33 insertions(+)

diff --git a/scripts/dtc/dependencies.c b/scripts/dtc/dependencies.c
index dd4658c..77d5c54 100644
--- a/scripts/dtc/dependencies.c
+++ b/scripts/dtc/dependencies.c
@@ -44,6 +44,23 @@ static bool is_parent_of(struct node *node1, struct node *node2)
 
 }
 
+static bool is_no_dependency(struct node *dt, struct property *prop, cell_t ph)
+{
+	struct node *node;
+	unsigned i;
+	cell_t *cell = (cell_t *)(prop->val.val);
+
+	for (i = 0; i < prop->val.len/4; ++i) {
+		node = get_node_by_phandle(dt, cpu_to_fdt32(*cell++));
+		if (node) {
+			node = find_compatible_not_disabled(node);
+			if (node && get_node_phandle(dt, node) == ph)
+				return true;
+		}
+	}
+	return false;
+}
+
 static void add_deps(struct node *dt, struct node *node, struct property *prop)
 {
 	struct marker *m = prop->val.markers;
@@ -73,6 +90,10 @@ static void add_deps(struct node *dt, struct node *node, struct property *prop)
 				is_parent_of(target, source))
 			continue;
 		phandle = get_node_phandle(dt, target);
+		prop_deps = get_property(node, "no-dependencies");
+		if (prop_deps && is_no_dependency(dt, prop_deps, phandle))
+			/* avoid adding non-dependencies */
+			continue;
 		prop_deps = get_property(source, "dependencies");
 		if (!prop_deps) {
 			add_property(source,
@@ -102,7 +123,19 @@ static void process_nodes_props(struct node *dt, struct node *node)
 		process_nodes_props(dt, child);
 }
 
+static void del_prop_no_dependencies(struct node *node)
+{
+	struct node *child;
+
+	if (!node)
+		return;
+	delete_property_by_name(node, "no-dependencies");
+	for_each_child(node, child)
+		del_prop_no_dependencies(child);
+}
+
 void add_dependencies(struct boot_info *bi)
 {
 	process_nodes_props(bi->dt, bi->dt);
+	del_prop_no_dependencies(bi->dt);
 }
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 08/14] dtc: deps: Add option to print initialization order
  2015-10-17 17:14 [PATCH 0/14] init: deps: dependency based (parallelized) init Alexander Holler
                   ` (6 preceding siblings ...)
  2015-10-17 17:14 ` [PATCH 07/14] dtc: deps: introduce new (virtual) property no-dependencies Alexander Holler
@ 2015-10-17 17:14 ` Alexander Holler
  2015-10-17 17:14 ` [PATCH 09/14] dtc: deps: Add option to print dependency graph as dot (Graphviz) Alexander Holler
                   ` (7 subsequent siblings)
  15 siblings, 0 replies; 59+ messages in thread
From: Alexander Holler @ 2015-10-17 17:14 UTC (permalink / raw)
  To: linux-kernel
  Cc: Linus Torvalds, Andrew Morton, Greg Kroah-Hartman, Russell King,
	Grant Likely, Alexander Holler

Add option -t to print the default initialization order.
No other output will be generated.

To print the order, just use something like this:

	CROSS_COMPILE=gcc-foo ARCH=arm make foo.dtb
	scripts/dtc/dtc -I dtb -t arch/arm/boot/dts/foo.dtb

Since it's now possible to check to for cycles in the dependency graph,
this is now done too.

Signed-off-by: Alexander Holler <holler@ahsoftware.de>
---
 scripts/dtc/dependencies.c | 344 +++++++++++++++++++++++++++++++++++++++++++++
 scripts/dtc/dtc.c          |  24 +++-
 scripts/dtc/dtc.h          |   2 +
 3 files changed, 369 insertions(+), 1 deletion(-)

diff --git a/scripts/dtc/dependencies.c b/scripts/dtc/dependencies.c
index 77d5c54..360d8f5 100644
--- a/scripts/dtc/dependencies.c
+++ b/scripts/dtc/dependencies.c
@@ -139,3 +139,347 @@ void add_dependencies(struct boot_info *bi)
 	process_nodes_props(bi->dt, bi->dt);
 	del_prop_no_dependencies(bi->dt);
 }
+
+/*
+ * The code below is in large parts a copy of drivers/of/of_dependencies.c
+ * in the Linux kernel. So both files do share the same bugs.
+ * The next few ugly defines do exist to keep the differences at a minimum.
+ */
+static struct node *tree;
+#define pr_cont(format, ...) printf(format, ##__VA_ARGS__)
+#define pr_info(format, ...) printf(format, ##__VA_ARGS__)
+#define pr_warn(format, ...) printf(format, ##__VA_ARGS__)
+#define pr_err(format, ...) fprintf(stderr, format, ##__VA_ARGS__)
+typedef cell_t __be32;
+#define device_node node
+#define full_name fullpath
+#define __initdata
+#define __init
+#define unlikely(a) (a)
+#define of_node_put(a)
+#define of_find_node_by_phandle(v) get_node_by_phandle(tree, v)
+#define __of_get_property(a, b, c) get_property(a, b)
+#define for_each_child_of_node(a, b) for_each_child(a, b)
+
+
+#define MAX_DT_NODES 1000 /* maximum number of vertices */
+#define MAX_EDGES (MAX_DT_NODES*2) /* maximum number of edges (dependencies) */
+
+struct edgenode {
+	uint32_t y; /* phandle */
+	struct edgenode *next; /* next edge in list */
+};
+
+/*
+ * Vertex numbers do correspond to phandle numbers. That means the graph
+ * does contain as much vertices as the maximum of all phandles.
+ * Or in other words, we assume that for all phandles in the device tree
+ * 0 < phandle < MAX_DT_NODES+1 is true.
+ */
+struct dep_graph {
+	struct edgenode edge_slots[MAX_EDGES]; /* used to avoid kmalloc */
+	struct edgenode *edges[MAX_DT_NODES+1]; /* adjacency info */
+	unsigned nvertices; /* number of vertices in graph */
+	unsigned nedges; /* number of edges in graph */
+	bool processed[MAX_DT_NODES+1]; /* which vertices have been processed */
+	bool include_node[MAX_DT_NODES+1]; /* which nodes to consider */
+	bool discovered[MAX_DT_NODES+1]; /* which vertices have been found */
+	bool finished; /* if true, cut off search immediately */
+};
+static struct dep_graph graph __initdata;
+
+struct init_order {
+	uint32_t max_phandle; /* the max used phandle */
+	uint32_t old_max_phandle; /* used to keep track of added phandles */
+	struct device_node *order[MAX_DT_NODES+1];
+	unsigned count;
+	/* Used to keep track of parent devices in regard to the DT */
+	uint32_t parent_by_phandle[MAX_DT_NODES+1];
+	struct device *device_by_phandle[MAX_DT_NODES+1];
+};
+static struct init_order order __initdata;
+
+
+/* Copied from drivers/of/base.c (because it's lockless). */
+static int __init __of_device_is_available(struct device_node *device)
+{
+	struct property *status;
+
+	if (!device)
+		return 0;
+
+	status = get_property(device, "status");
+	if (status == NULL)
+		return 1;
+
+	if (status->val.len > 0) {
+		if (!strcmp(status->val.val, "okay") ||
+				!strcmp(status->val.val, "ok"))
+			return 1;
+	}
+
+	return 0;
+}
+
+/*
+ * x is a dependant of y or in other words
+ * y will be initialized before x.
+ */
+static int __init insert_edge(uint32_t x, uint32_t y)
+{
+	struct edgenode *p; /* temporary pointer */
+
+	if (unlikely(x > MAX_DT_NODES || y > MAX_DT_NODES)) {
+		pr_err("Node found with phandle 0x%x > MAX_DT_NODES (%d)!\n",
+			x > MAX_DT_NODES ? x : y, MAX_DT_NODES);
+		return -EINVAL;
+	}
+	if (unlikely(!x || !y))
+		return 0;
+	if (unlikely(graph.nedges >= MAX_EDGES)) {
+		pr_err("Maximum number of edges (%d) reached!\n", MAX_EDGES);
+		return -EINVAL;
+	}
+	p = &graph.edge_slots[graph.nedges++];
+	graph.include_node[x] = 1;
+	graph.include_node[y] = 1;
+	p->y = y;
+	p->next = graph.edges[x];
+	graph.edges[x] = p; /* insert at head of list */
+
+	graph.nvertices = (x > graph.nvertices) ? x : graph.nvertices;
+	graph.nvertices = (y > graph.nvertices) ? y : graph.nvertices;
+	return 0;
+}
+
+static void __init print_node_name(uint32_t v)
+{
+	struct device_node *node;
+
+	node = of_find_node_by_phandle(v);
+	if (!node) {
+		pr_err("Node for phandle 0x%x not found", v);
+		return;
+	}
+	if (node->name)
+		pr_err("%s", node->name);
+	if (node->full_name)
+		pr_err(" (%s)", node->full_name);
+	of_node_put(node);
+}
+
+/*
+ * I would prefer to use the BGL (Boost Graph Library), but as I can't use it
+ * here (for obvious reasons), the next four functions below are based on
+ * code of Steven Skiena's book 'The Algorithm Design Manual'.
+ */
+
+static void __init process_edge(uint32_t x, uint32_t y)
+{
+	if (unlikely(graph.discovered[y] && !graph.processed[y])) {
+		pr_err("Cycle found 0x%x ", x);
+		print_node_name(x);
+		pr_cont(" <-> 0x%x ", y);
+		print_node_name(y);
+		pr_cont("!\n");
+		graph.finished = 1;
+	}
+}
+
+static void __init process_vertex_late(uint32_t v)
+{
+	struct device_node *node;
+
+	node = of_find_node_by_phandle(v);
+	if (!node) {
+		pr_err("No node for phandle 0x%x not found", v);
+		return;
+	}
+	order.order[order.count++] = node;
+}
+
+static void __init depth_first_search(uint32_t v)
+{
+	struct edgenode *p;
+	uint32_t y; /* successor vertex */
+
+	if (graph.finished)
+		return;
+	graph.discovered[v] = 1;
+	p = graph.edges[v];
+	while (p) {
+		y = p->y;
+		if (!graph.discovered[y]) {
+			process_edge(v, y);
+			depth_first_search(y);
+		} else
+			process_edge(v, y);
+		if (graph.finished)
+			return;
+		p = p->next;
+	}
+	process_vertex_late(v);
+	graph.processed[v] = 1;
+}
+
+static void __init topological_sort(void)
+{
+	unsigned i;
+
+	for (i = 1; i <= graph.nvertices; ++i)
+		if (!graph.discovered[i] && graph.include_node[i])
+			depth_first_search(i);
+}
+
+static int __init add_dep_list(struct device_node *node)
+{
+	const __be32 *list, *list_end;
+	uint32_t ph;
+	struct property *prop;
+	int rc = 0;
+	struct device_node *dep;
+
+	prop = get_property(node, "dependencies");
+	if (!prop || !prop->val.len || prop->val.len%sizeof(*list))
+		return 0;
+	list = (const __be32 *)prop->val.val;
+	list_end = list + prop->val.len / sizeof(*list);
+	while (list < list_end) {
+		ph = fdt32_to_cpu(*list++);
+		if (unlikely(!ph)) {
+			/* Should never happen */
+			if (node->name)
+				pr_warn("phandle == 0 for %s\n", node->name);
+			continue;
+		}
+		dep = of_find_node_by_phandle(ph);
+		if (unlikely(!dep)) {
+			pr_err("No DT node for dependency with phandle 0x%x found\n",
+				ph);
+			continue;
+		}
+		rc = insert_edge(node->phandle, ph);
+		if (rc)
+			break;
+	}
+
+	return rc;
+}
+
+/* Copied from drivers/of/base.c */
+static const char *of_prop_next_string(struct property *prop, const char *cur)
+{
+	const char *curv = cur;
+
+	if (!prop)
+		return NULL;
+
+	if (!cur)
+		return prop->val.val;
+
+	curv += strlen(cur) + 1;
+	if (curv >= prop->val.val + prop->val.len)
+		return NULL;
+
+	return curv;
+}
+
+static int __init add_deps_lnx(struct device_node *parent,
+				struct device_node *node)
+{
+	struct device_node *child;
+	int rc = 0;
+
+	if (!__of_device_is_available(node))
+		return 0;
+	if (__of_get_property(node, "compatible", NULL)) {
+		if (!parent->phandle) {
+			if (__of_get_property(parent, "compatible", NULL))
+				parent->phandle = 1 + order.max_phandle++;
+		}
+		if (!node->phandle)
+			node->phandle = 1 + order.max_phandle++;
+		rc = insert_edge(node->phandle, parent->phandle);
+		if (rc)
+			return rc;
+		if (unlikely(order.parent_by_phandle[node->phandle])) {
+			/* sanity check */
+			pr_err("0x%x already has a parent!\n", node->phandle);
+			return -EINVAL;
+		}
+		order.parent_by_phandle[node->phandle] = parent->phandle;
+		rc = add_dep_list(node);
+		if (unlikely(rc))
+			return rc;
+		parent = node; /* change the parent only if node is a driver */
+	}
+	for_each_child_of_node(node, child) {
+		rc = add_deps_lnx(parent, child);
+		if (unlikely(rc))
+			break;
+	}
+
+	return rc;
+}
+
+static void calc_max_phandle(struct node *np)
+{
+	struct node *child;
+
+	if (!np || np->deleted)
+		return;
+	if (np->phandle > order.max_phandle)
+		order.max_phandle = np->phandle;
+
+	for_each_child(np, child)
+		calc_max_phandle(child);
+}
+
+void __init of_init_print_order(const char *name)
+{
+	unsigned i;
+	struct property *prop;
+	const char *cp;
+
+	pr_info("Default initialization order for %s:\n", name);
+	for (i = 0; i < order.count; ++i) {
+		pr_info("init %u 0x%x", i, order.order[i]->phandle);
+		if (order.order[i]->name)
+			pr_cont(" %s", order.order[i]->name);
+		if (order.order[i]->full_name)
+			pr_cont(" (%s)", order.order[i]->full_name);
+		prop = get_property(order.order[i], "compatible");
+		for (cp = of_prop_next_string(prop, NULL); cp;
+		     cp = of_prop_next_string(prop, cp))
+			pr_cont(" %s", cp);
+		pr_cont(" (parent 0x%x)\n",
+			order.parent_by_phandle[order.order[i]->phandle]);
+	}
+}
+
+int __init of_init_build_order(struct device_node *root)
+{
+	struct device_node *child;
+	int rc = 0;
+
+	tree = root;
+	if (unlikely(!root))
+		return -EINVAL;
+
+	calc_max_phandle(root);
+	order.old_max_phandle = order.max_phandle;
+
+	for_each_child_of_node(root, child) {
+		rc = add_deps_lnx(root, child);
+		if (unlikely(rc))
+			break;
+	}
+
+	of_node_put(root);
+	topological_sort();
+
+	if (graph.finished)
+		return -EINVAL; /* cycle found */
+
+	return rc;
+}
diff --git a/scripts/dtc/dtc.c b/scripts/dtc/dtc.c
index 28def27..494c531 100644
--- a/scripts/dtc/dtc.c
+++ b/scripts/dtc/dtc.c
@@ -51,7 +51,7 @@ static void fill_fullpaths(struct node *tree, const char *prefix)
 #define FDT_VERSION(version)	_FDT_VERSION(version)
 #define _FDT_VERSION(version)	#version
 static const char usage_synopsis[] = "dtc [options] <input file>";
-static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:fb:i:H:sDW:E:hv";
+static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:fb:i:H:sDtW:E:hv";
 static struct option const usage_long_opts[] = {
 	{"quiet",            no_argument, NULL, 'q'},
 	{"in-format",         a_argument, NULL, 'I'},
@@ -67,6 +67,7 @@ static struct option const usage_long_opts[] = {
 	{"include",           a_argument, NULL, 'i'},
 	{"sort",             no_argument, NULL, 's'},
 	{"no-deps",          no_argument, NULL, 'D'},
+	{"initialization-order", no_argument, NULL, 't'},
 	{"phandle",           a_argument, NULL, 'H'},
 	{"warning",           a_argument, NULL, 'W'},
 	{"error",             a_argument, NULL, 'E'},
@@ -95,6 +96,7 @@ static const char * const usage_opts_help[] = {
 	"\n\tAdd a path to search for include files",
 	"\n\tSort nodes and properties before outputting (useful for comparing trees)",
 	"\n\tDo not automatically add dependencies for phandle references",
+	"\n\tPrint (default) initialization order",
 	"\n\tValid phandle formats are:\n"
 	 "\t\tlegacy - \"linux,phandle\" properties only\n"
 	 "\t\tepapr  - \"phandle\" properties only\n"
@@ -115,6 +117,7 @@ int main(int argc, char *argv[])
 	const char *depname = NULL;
 	bool force = false, sort = false;
 	bool dependencies = true;
+	bool init_order = false;
 	const char *arg;
 	int opt;
 	FILE *outf = NULL;
@@ -186,6 +189,10 @@ int main(int argc, char *argv[])
 			dependencies = false;
 			break;
 
+		case 't':
+			init_order = true;
+			break;
+
 		case 'W':
 			parse_checks_option(true, false, optarg);
 			break;
@@ -246,6 +253,13 @@ int main(int argc, char *argv[])
 	if (dependencies)
 		add_dependencies(bi);
 
+	if (init_order) {
+		if (of_init_build_order(bi->dt))
+			exit(2);
+		of_init_print_order(arg);
+		exit(0);
+	}
+
 	if (streq(outname, "-")) {
 		outf = stdout;
 	} else {
@@ -267,5 +281,13 @@ int main(int argc, char *argv[])
 		die("Unknown output format \"%s\"\n", outform);
 	}
 
+	/*
+	 * Check for cycles by building the initialzation order.
+	 * This is done after the output was saved because it
+	 * changes the tree slightly.
+	 */
+	if (of_init_build_order(bi->dt))
+		exit(2);
+
 	exit(0);
 }
diff --git a/scripts/dtc/dtc.h b/scripts/dtc/dtc.h
index 6facad1..9ae4bfc 100644
--- a/scripts/dtc/dtc.h
+++ b/scripts/dtc/dtc.h
@@ -268,5 +268,7 @@ struct boot_info *dt_from_fs(const char *dirname);
 
 /* Dependencies */
 void add_dependencies(struct boot_info *bi);
+void of_init_print_order(const char *name);
+int of_init_build_order(struct node *root);
 
 #endif /* _DTC_H */
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 09/14] dtc: deps: Add option to print dependency graph as dot (Graphviz)
  2015-10-17 17:14 [PATCH 0/14] init: deps: dependency based (parallelized) init Alexander Holler
                   ` (7 preceding siblings ...)
  2015-10-17 17:14 ` [PATCH 08/14] dtc: deps: Add option to print initialization order Alexander Holler
@ 2015-10-17 17:14 ` Alexander Holler
  2015-10-17 17:14 ` [PATCH 10/14] init: deps: IDs for annotated initcalls Alexander Holler
                   ` (6 subsequent siblings)
  15 siblings, 0 replies; 59+ messages in thread
From: Alexander Holler @ 2015-10-17 17:14 UTC (permalink / raw)
  To: linux-kernel
  Cc: Linus Torvalds, Andrew Morton, Greg Kroah-Hartman, Russell King,
	Grant Likely, Alexander Holler

Add option -T do print a dependency graph in dot format for
generating a picture with Graphviz.

E.g.

	dtc -T foo.dts | dot -T svg -o foo.svg

would generate the picture foo.png with the dependency graph.

Convential dependencies (those based on the tree structure) are having
black arrows, dependencies based on the property 'dependencies' are
having cyan arrows.

Option -D to not automatically add dependencies does still work, so
you could build a classic dependency graph with

	dtc -D -T foo.dts | dot -T png -o foo_no_auto_deps.png

This works with binary blobs as input too. E.g.

	CROSS_COMPILE=gcc-foo ARCH=arm make foo.dtb
	scripts/dtc/dtc -I dtb -T arch/arm/boot/dts/foo.dtb

would print the dot file.

Signed-off-by: Alexander Holler <holler@ahsoftware.de>
---
 scripts/dtc/dependencies.c | 49 ++++++++++++++++++++++++++++++++++++++++------
 scripts/dtc/dtc.c          | 19 +++++++++++++++---
 scripts/dtc/dtc.h          |  2 +-
 3 files changed, 60 insertions(+), 10 deletions(-)

diff --git a/scripts/dtc/dependencies.c b/scripts/dtc/dependencies.c
index 360d8f5..76e4d91 100644
--- a/scripts/dtc/dependencies.c
+++ b/scripts/dtc/dependencies.c
@@ -331,7 +331,7 @@ static void __init topological_sort(void)
 			depth_first_search(i);
 }
 
-static int __init add_dep_list(struct device_node *node)
+static int __init add_dep_list(struct device_node *node, bool print_dot)
 {
 	const __be32 *list, *list_end;
 	uint32_t ph;
@@ -361,6 +361,9 @@ static int __init add_dep_list(struct device_node *node)
 		rc = insert_edge(node->phandle, ph);
 		if (rc)
 			break;
+		if (print_dot)
+			printf("      node0x%x -> node0x%x [color=cyan]\n",
+				node->phandle, ph);
 	}
 
 	return rc;
@@ -385,9 +388,10 @@ static const char *of_prop_next_string(struct property *prop, const char *cur)
 }
 
 static int __init add_deps_lnx(struct device_node *parent,
-				struct device_node *node)
+				struct device_node *node, bool print_dot)
 {
 	struct device_node *child;
+	const char *cp;
 	int rc = 0;
 
 	if (!__of_device_is_available(node))
@@ -408,13 +412,34 @@ static int __init add_deps_lnx(struct device_node *parent,
 			return -EINVAL;
 		}
 		order.parent_by_phandle[node->phandle] = parent->phandle;
-		rc = add_dep_list(node);
+		if (print_dot) {
+			struct property *prop;
+
+			printf("    node0x%x [label=\"0x%x %s", node->phandle,
+						node->phandle, node->name);
+			if (node->full_name)
+				printf(" (%s)", node->full_name);
+			prop = get_property(node, "compatible");
+			if (prop) {
+				printf("\\n");
+				for (cp = of_prop_next_string(prop, NULL); cp;
+				     cp = of_prop_next_string(prop, cp)) {
+					if (cp != prop->val.val)
+						putchar(' ');
+					printf("%s", cp);
+				}
+			}
+			printf("\"];\n");
+			printf("      node0x%x -> node0x%x\n", node->phandle,
+							parent->phandle);
+		}
+		rc = add_dep_list(node, print_dot);
 		if (unlikely(rc))
 			return rc;
 		parent = node; /* change the parent only if node is a driver */
 	}
 	for_each_child_of_node(node, child) {
-		rc = add_deps_lnx(parent, child);
+		rc = add_deps_lnx(parent, child, print_dot);
 		if (unlikely(rc))
 			break;
 	}
@@ -457,7 +482,7 @@ void __init of_init_print_order(const char *name)
 	}
 }
 
-int __init of_init_build_order(struct device_node *root)
+int __init of_init_build_order(struct device_node *root, const char *print_dot)
 {
 	struct device_node *child;
 	int rc = 0;
@@ -469,12 +494,24 @@ int __init of_init_build_order(struct device_node *root)
 	calc_max_phandle(root);
 	order.old_max_phandle = order.max_phandle;
 
+	if (print_dot) {
+		printf("digraph G {\n");
+		printf("    node0x%x [label=\"0x%x root (/)\"];\n",
+			order.max_phandle+1, order.max_phandle+1);
+	}
+
 	for_each_child_of_node(root, child) {
-		rc = add_deps_lnx(root, child);
+		rc = add_deps_lnx(root, child, print_dot);
 		if (unlikely(rc))
 			break;
 	}
 
+	if (print_dot) {
+		printf("  graph [label=\"Dependency Graph for %s (%u nodes, %u edges)\"];\n",
+			print_dot, graph.nvertices, graph.nedges);
+		printf("}\n");
+	}
+
 	of_node_put(root);
 	topological_sort();
 
diff --git a/scripts/dtc/dtc.c b/scripts/dtc/dtc.c
index 494c531..b1ca363 100644
--- a/scripts/dtc/dtc.c
+++ b/scripts/dtc/dtc.c
@@ -51,7 +51,7 @@ static void fill_fullpaths(struct node *tree, const char *prefix)
 #define FDT_VERSION(version)	_FDT_VERSION(version)
 #define _FDT_VERSION(version)	#version
 static const char usage_synopsis[] = "dtc [options] <input file>";
-static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:fb:i:H:sDtW:E:hv";
+static const char usage_short_opts[] = "qI:O:o:V:d:R:S:p:fb:i:H:sDtTW:E:hv";
 static struct option const usage_long_opts[] = {
 	{"quiet",            no_argument, NULL, 'q'},
 	{"in-format",         a_argument, NULL, 'I'},
@@ -68,6 +68,7 @@ static struct option const usage_long_opts[] = {
 	{"sort",             no_argument, NULL, 's'},
 	{"no-deps",          no_argument, NULL, 'D'},
 	{"initialization-order", no_argument, NULL, 't'},
+	{"dot",              no_argument, NULL, 'T'},
 	{"phandle",           a_argument, NULL, 'H'},
 	{"warning",           a_argument, NULL, 'W'},
 	{"error",             a_argument, NULL, 'E'},
@@ -97,6 +98,7 @@ static const char * const usage_opts_help[] = {
 	"\n\tSort nodes and properties before outputting (useful for comparing trees)",
 	"\n\tDo not automatically add dependencies for phandle references",
 	"\n\tPrint (default) initialization order",
+	"\n\tPrint dot with dependency graph (for use with Graphviz)",
 	"\n\tValid phandle formats are:\n"
 	 "\t\tlegacy - \"linux,phandle\" properties only\n"
 	 "\t\tepapr  - \"phandle\" properties only\n"
@@ -118,6 +120,7 @@ int main(int argc, char *argv[])
 	bool force = false, sort = false;
 	bool dependencies = true;
 	bool init_order = false;
+	bool print_dot = false;
 	const char *arg;
 	int opt;
 	FILE *outf = NULL;
@@ -193,6 +196,10 @@ int main(int argc, char *argv[])
 			init_order = true;
 			break;
 
+		case 'T':
+			print_dot = true;
+			break;
+
 		case 'W':
 			parse_checks_option(true, false, optarg);
 			break;
@@ -254,12 +261,18 @@ int main(int argc, char *argv[])
 		add_dependencies(bi);
 
 	if (init_order) {
-		if (of_init_build_order(bi->dt))
+		if (of_init_build_order(bi->dt, 0))
 			exit(2);
 		of_init_print_order(arg);
 		exit(0);
 	}
 
+	if (print_dot) {
+		if (of_init_build_order(bi->dt, arg))
+			exit(2);
+		exit(0);
+	}
+
 	if (streq(outname, "-")) {
 		outf = stdout;
 	} else {
@@ -286,7 +299,7 @@ int main(int argc, char *argv[])
 	 * This is done after the output was saved because it
 	 * changes the tree slightly.
 	 */
-	if (of_init_build_order(bi->dt))
+	if (of_init_build_order(bi->dt, 0))
 		exit(2);
 
 	exit(0);
diff --git a/scripts/dtc/dtc.h b/scripts/dtc/dtc.h
index 9ae4bfc..8ef8e6f 100644
--- a/scripts/dtc/dtc.h
+++ b/scripts/dtc/dtc.h
@@ -269,6 +269,6 @@ struct boot_info *dt_from_fs(const char *dirname);
 /* Dependencies */
 void add_dependencies(struct boot_info *bi);
 void of_init_print_order(const char *name);
-int of_init_build_order(struct node *root);
+int of_init_build_order(struct node *root, const char *print_dot);
 
 #endif /* _DTC_H */
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 10/14] init: deps: IDs for annotated initcalls
  2015-10-17 17:14 [PATCH 0/14] init: deps: dependency based (parallelized) init Alexander Holler
                   ` (8 preceding siblings ...)
  2015-10-17 17:14 ` [PATCH 09/14] dtc: deps: Add option to print dependency graph as dot (Graphviz) Alexander Holler
@ 2015-10-17 17:14 ` Alexander Holler
  2015-10-17 17:45   ` Greg Kroah-Hartman
  2015-10-17 17:14 ` [PATCH 11/14] init: deps: annotate various initcalls Alexander Holler
                   ` (5 subsequent siblings)
  15 siblings, 1 reply; 59+ messages in thread
From: Alexander Holler @ 2015-10-17 17:14 UTC (permalink / raw)
  To: linux-kernel
  Cc: Linus Torvalds, Andrew Morton, Greg Kroah-Hartman, Russell King,
	Grant Likely, Alexander Holler

These patch contains the IDs for initcalls I've annotated.

This patch is NOT meant for merging into mainline in its current form.

It should be discussed about how to add these IDs and in which form, if
the feature ends up in mainline at all.

E.g. it could make sense to split this file into several files in order
to avoid merge conflicts.

It also might make sense to prefill this file with IDs for many drivers.

E.g. the following script will use a modules.dep file to produce IDs for
modules. It's meant to be used on a very complete modules.dep build through
make allmodconfig && make -jN modules && make modules_install.

----
if [ $# -ne 2 -o ! -f "$1" -o -f "$2" ]; then
  echo "Builds drvids"
  echo "usage: $(basename $0) modules.dep headerfile"
  echo "headerfile must not exist"
  exit 1
fi

echo -e "#ifndef _LINUX_DRIVER_IDS_H\n#define _LINUX_DRIVER_IDS_H\n\nenum {\n\tdrvid_unused," > "$2"
sed -e 's%.*/\(.*\).ko.gz:.*%\tdrvid_\1,%' "$1" | sed -e 's/-/_/g' >> "$2"
echo -e "\tdrvid_max\n};\n\n#endif /* _LINUX_DRIVER_IDS_H */\n" >> "$2"
----

Signed-off-by: Alexander Holler <holler@ahsoftware.de>
---
 include/linux/driver_ids.h | 581 ++++++++++++++++++++++++++++++++++++++++++++-
 1 file changed, 580 insertions(+), 1 deletion(-)

diff --git a/include/linux/driver_ids.h b/include/linux/driver_ids.h
index 330080e..f029eaf 100644
--- a/include/linux/driver_ids.h
+++ b/include/linux/driver_ids.h
@@ -14,7 +14,214 @@
 
 enum {
 	drvid_unused,
-	/* To be filled */
+
+	/* arch/arm/common */
+	drvid_edma,
+	/* arch/arm/crypto */
+	drvid_aes_arm,
+	drvid_aes_ce_arm,
+	drvid_aesbs,
+	drvid_sha1_mod,
+	drvid_sha1_neon,
+	/* arch/arm/kernel */
+	drvid_customize_machine,
+	drvid_proc_cpu,
+	drvid_proc_dma_arm,
+	drvid_swp_emulation,
+	/* arch/arm/mach-imx */
+	drvid_imx_gpc,
+	drvid_imx_mmdc,
+	/* arch/arm/mach-omap2 */
+	drvid_omap_i2c_cmdline,
+	/* arch/arm/mm */
+	drvid_alignment,
+	drvid_atomic_pool,
+	drvid_dma_debug,
+	/* arch/arm/plat-omap */
+	drvid_omap_dm_timer,
+	/* arch/x86/crypto */
+	drvid_aes_x86,
+	/* arch/x86/kernel */
+	drvid_apm,
+	drvid_cpufreq_tsc,
+	drvid_hpet_late,
+	drvid_kernel_offset_dumper,
+	drvid_pci_iommu,
+	drvid_pmc_atom,
+	drvid_reboot,
+	drvid_rtc_cmos_x86,
+	drvid_tsc_clocksource,
+	/* arch/x86/kernel/acpi */
+	drvid_ffh_cstate,
+	drvid_hpet_insert_resource,
+	/* arch/x86/kernel/cpu/mcheck */
+	drvid_mcheck,
+	drvid_mcheck_debugfs,
+	drvid_thermal_throttle,
+	/* arch/x86/kernel/cpu/microcode */
+	drvid_microcode,
+	/* arch/x86/pci */
+	drvid_pci_arch,
+	drvid_pci_subsys,
+	drvid_pcibios_assign_resources,
+	/* block */
+	drvid_bio,
+	drvid_blk_dev_integrity,
+	drvid_blk_ioc,
+	drvid_blk_iopoll,
+	drvid_blk_mq,
+	drvid_blk_scsi_ioctl,
+	drvid_blk_settings,
+	drvid_blk_softirq,
+	drvid_bsg,
+	drvid_cfq_iosched,
+	drvid_deadline_iosched,
+	drvid_genhd,
+	drvid_noop,
+	drvid_proc_genhd,
+	/* crypto */
+	drvid_aes_generic,
+	drvid_authenc,
+	drvid_authencesn,
+	drvid_cbc,
+	drvid_chainiv,
+	drvid_crc32c,
+	drvid_crct10dif,
+	drvid_cryptd,
+	drvid_crypto_algapi,
+	drvid_crypto_wq,
+	drvid_cryptomgr,
+	drvid_deflate,
+	drvid_des_generic,
+	drvid_ecb,
+	drvid_eseqiv,
+	drvid_hmac,
+	drvid_lzo,
+	drvid_mcryptd,
+	drvid_md5,
+	drvid_michael_mic,
+	drvid_sha1_generic,
+	drvid_sha256_generic,
+	drvid_sha512_generic,
+	drvid_xor,
+	/* crypto/asymmetric_keys */
+	drvid_asymmetric_key,
+	drvid_x509,
+	/* drivers/acpi */
+	drvid_acpi,
+	drvid_acpi_ac,
+	drvid_acpi_battery,
+	drvid_acpi_button,
+	drvid_acpi_event,
+	drvid_acpi_fan,
+	drvid_acpi_processor_driver,
+	drvid_acpi_reserve_resources,
+	drvid_acpi_sbs,
+	drvid_acpi_smb_hc,
+	drvid_acpi_thermal,
+	/* drivers/ata */
+	drvid_ahci,
+	drvid_ahci_imx,
+	drvid_ata,
+	drvid_ata_generic,
+	drvid_ata_piix,
+	drvid_pata_acpi,
+	drvid_pata_amd,
+	drvid_pata_jmicron,
+	drvid_pata_mpiix,
+	drvid_pata_oldpiix,
+	drvid_pata_sch,
+	drvid_pata_sis,
+	/* drivers/base */
+	drvid_firmware_class,
+	/* drivers/block */
+	drvid_loop,
+	/* drivers/bus */
+	drvid_omap_l3_noc,
+	drvid_omap_l3_smx,
+	drvid_omap_ocp2scp,
+	drvid_imx_weim,
+	/* drivers/char */
+	drvid_agpgart,
+	drvid_genrtc,
+	drvid_hpet,
+	drvid_misc,
+	drvid_nvram,
+	drvid_char_rtc,
+	/* drivers/char/hw_random */
+	drvid_hwrng,
+	drvid_omap3_rom_rng,
+	drvid_omap_rng,
+	/* drivers/clocksource */
+	drvid_acpi_pm_clocksource,
+	/* drivers/connector */
+	drvid_cn,
+	drvid_cn_proc,
+	/* drivers/cpufreq */
+	drvid_acpi_cpufreq,
+	drvid_cpufreq,
+	drvid_cpufreq_gov_dbs,
+	drvid_cpufreq_gov_performance,
+	drvid_cpufreq_ondemand,
+	drvid_cpufreq_powersave,
+	drvid_cpufreq_stats,
+	drvid_imx6q_cpufreq,
+	drvid_kirkwood_cpufreq,
+	drvid_omap_cpufreq,
+	/* drivers/cpuidle */
+	drvid_cpuidle,
+	drvid_cpuidle_arm,
+	drvid_kirkwood_cpuidle,
+	/* drivers/crypto */
+	drvid_crypto_user,
+	drvid_mv_crypto,
+	drvid_omap_aes,
+	drvid_omap_sham,
+	/* drivers/crypto/marvell */
+	drvid_marvell_cesa,
+	/* drivers/dma */
+	drvid_cpp41_dma,
+	drvid_dma_bus,
+	drvid_dma_channel_table,
+	drvid_imx_sdma,
+	drvid_mv_xor,
+	drvid_mxs_dma,
+	drvid_omap_dma,
+	/* drivers/firmware */
+	drvid_dmi,
+	/* drivers/gpio */
+	drvid_bgpio,
+	drvid_gpio_twl4030,
+	drvid_gpiolib_debugfs,
+	drvid_mvebu_gpio,
+	drvid_mxc_gpio,
+	drvid_omap_gpio,
+	drvid_tps65910_gpio,
+	/* drivers/gpu/drm */
+	drvid_drm,
+	drvid_drm_fb_helper,
+	drvid_mipi_dsi_bus,
+	/* drivers/gpu/amd/amdgpu */
+	drvid_amdgpu,
+	/* drivers/gpu/drm/i915 */
+	drvid_i915,
+	/* drivers/gpu/drm/radeon */
+	drvid_radeon,
+	/* drivers/gpu/drm/tilcdc */
+	drvid_tilcdc,
+	/* drivers/gpu/drm/ttm */
+	drvid_ttm,
+	/* drivers/gpu/vga */
+	drvid_vga_arb,
+	/* drivers/hid */
+	drvid_uhid,
+	/* drivers/hwmon */
+	drvid_hwmon,
+	/* drivers/hwspinlock */
+	drvid_omap_hwspinlock,
+	/* drivers/i2c */
+	drvid_i2c,
+	drvid_i2c_dev,
 
 	/*
 	 * I2C bus drivers will be ordered according to their ID (which
@@ -23,8 +230,85 @@ enum {
 	 * Therefor their IDs have to be in the following block.
 	 */
 	drvid_i2c_busses_start,
+	/* drivers/i2c/busses */
+	drvid_i2c_gpio,
+	drvid_i2c_imx,
+	drvid_i2c_mv64xxx,
+	drvid_i2c_omap,
+	drvid_tiny_usb,
 	drvid_i2c_busses_end,
 
+	/* drivers/iio/adc */
+	drvid_tiadc,
+	/* drivers/input */
+	drvid_evdev,
+	drvid_input,
+	drvid_joydev,
+	drvid_mousedev,
+	/* drivers/input/keyboard */
+	drvid_gpio_keys,
+	drvid_atkbd,
+	/* drivers/input/misc */
+	drvid_twl4030_pwrbutton,
+	drvid_uinput,
+	/* drivers/input/serio */
+	drvid_i8042,
+	drvid_serio,
+	drvid_serport,
+	drvid_serio_raw,
+	/* drivers/iommu */
+	drvid_amd_iommu_v2,
+	drvid_iommu,
+	drvid_iommu_dev,
+	drvid_ir_dev_scope,
+	drvid_omap_iommu,
+	/* drivers/leds */
+	drvid_gpio_led,
+	drvid_leds,
+	drvid_leds_regulator,
+	/* drivers/leds/trigger */
+	drvid_ledtrig_heartbeat,
+	/* drivers/mailbox */
+	drvid_omap_mbox,
+	/* drivers/md */
+	drvid_md,
+	/* drivers/media/i2c */
+	drvid_ir_kbd_i2c,
+	/* drivers/memory */
+	drvid_omap_gpmc,
+	/* drivers/mfd */
+	drvid_omap_usbtll,
+	drvid_ti_tscadc,
+	drvid_tps65217,
+	drvid_tps65910_i2c,
+	drvid_twl4030_audio,
+	drvid_twl4030_power,
+	drvid_twl_core,
+	drvid_usbhs_omap,
+	/* drivers/misc */
+	drvid_sram,
+	/* drivers/misc/eeprom */
+	drvid_at24,
+	/* drivers/mmc/card */
+	drvid_mmcblk,
+	/* drivers/mmc/core */
+	drvid_mmc,
+	/* drivers/mmc/host */
+	drvid_mxs_mmc,
+	drvid_mmc_omap,
+	drvid_omap_hsmmc,
+	drvid_sdhci,
+	drvid_sdhci_esdhc_imx,
+	/* drivers/mtd */
+	drvid_mtd,
+	drvid_ofpart,
+	/* drivers/mtd/nand */
+	drvid_omap_elm,
+	drvid_omap2_nand,
+	drvid_orion_nand,
+	/* drivers/net/bluetooth */
+	drvid_bt,
+
 	/*
 	 * Network drivers will be ordered according to the link order
 	 * (which means not necessarily according to their appearance
@@ -33,8 +317,303 @@ enum {
 	 * Therefor their IDs have to be in the following block.
 	 */
 	drvid_network_drivers_start,
+	/* drivers/net/ethernet/ti */
+	drvid_cpsw,
+	/* drivers/net/ethernet/freescale */
+	drvid_fec,
+	/* drivers/net/ethernet/intel */
+	drvid_e1000,
+	/* drivers/net/ethernet/marvell */
+	drvid_mv643xx_eth,
+	/* drivers/net/ethernet/realtek */
+	drvid_r8169,
 	drvid_network_drivers_end,
 
+	/* drivers/net/ethernet/ti */
+	drvid_cpsw_phy_sel,
+	drvid_davinci_mdio,
+	/* drivers/net/ethernet/marvell */
+	drvid_orion_mdio,
+	/* drivers/net/irda */
+	drvid_nsc_ircc,
+	drvid_smsc_ircc,
+	/* drivers/net/phy */
+	drvid_phy_net,
+	drvid_phy_lxt,
+	drvid_phy_realtek,
+	drvid_phy_smsc,
+	/* drivers/pci */
+	drvid_pci_acpi,
+	drvid_pcibus_class,
+	drvid_pci_driver,
+	drvid_pci_proc,
+	drvid_pci_quirks,
+	drvid_pci_slot,
+	drvid_pci_stub,
+	/* drivers/pci/hotplug */
+	drvid_pci_hotplug,
+	/* drivers/phy */
+	drvid_phy,
+	drvid_phy_mvebu_sata,
+	drvid_twl4030_usb,
+	/* drivers/pinctrl */
+	drvid_imx6q_pinctrl,
+	drvid_pcs,
+	/* drivers/pinctrl/mvebu */
+	drvid_kirkwood_pinctrl,
+	/* drivers/platform/x86 */
+	drvid_acpi_wmi,
+	drvid_asus_wmi,
+	drvid_eeepc_wmi,
+	/* drivers/pnp */
+	drvid_pnp,
+	drvid_pnp_system,
+	/* drivers/pnp/pnpacpi */
+	drvid_pnpacpi,
+	/* drivers/power */
+	drvid_power_supply_class,
+	drvid_twl4030_bci,
+	/* drivers/power/reset */
+	drvid_imx_poweroff,
+	drvid_poweroff_gpio,
+	/* drivers/pwm */
+	drvid_ecap_pwm,
+	drvid_ehrpwm_pwm,
+	drvid_imx_pwm,
+	drvid_pwm_debugfs,
+	drvid_pwmss,
+	/* drivers/regulator */
+	drvid_anatop_regulator,
+	drvid_regulator,
+	drvid_regulator_fixed_voltage,
+	drvid_tps_65023,
+	drvid_tps65910,
+	drvid_twlreg,
+	/* drivers/remoteproc */
+	drvid_remoteproc,
+	drvid_wkup_m3_rproc,
+	/* drivers/rtc */
+	drvid_rtc,
+	drvid_rtc_cmos,
+	drvid_rtc_mxc,
+	drvid_rtc_omap,
+	drvid_rtc_ds1307,
+	drvid_rtc_hid_sensor_time,
+	drvid_rtc_snvs,
+	drvid_rtc_twl,
+	/* drivers/scsi */
+	drvid_scsi_mod,
+	drvid_sd_mod,
+	/* drivers/spi */
+	drvid_omap2_mcspi,
+	drvid_spi_imx,
+	/* drivers/thermal */
+	drvid_thermal,
+	/* drivers/tty */
+	drvid_pty,
+	drvid_sysrq,
+	drvid_tty,
+	/* drivers/tty/serial */
+	drvid_imx_uart,
+	drvid_lpuart,
+	drvid_of_serial,
+	drvid_omap_serial,
+	/* drivers/tty/serial/8250 */
+	drvid_omap8250,
+	drvid_serial,
+	drvid_serial_pci,
+	/* drivers/uio */
+	drvid_uio_pdrv_genirq,
+	/* drivers/usb/core */
+	drvid_usb,
+	/* drivers/usb/host */
+	drvid_ehci_hcd,
+	drvid_ehci_omap,
+	drvid_ehci_orion,
+	drvid_ehci_pci,
+	drvid_ohci_hcd,
+	drvid_ohci_omap3,
+	drvid_uhci_hcd,
+	/* drivers/usb/musb */
+	drvid_musb_dsps,
+	drvid_musb_hdrc,
+	drvid_omap2430,
+	/* drivers/usb/phy */
+	drvid_am335x_control,
+	drvid_am335x_phy,
+	drvid_gpio_vbus,
+	drvid_mxs_phy,
+	drvid_usb_phy_generic,
+	/* drivers/usb/storage */
+	drvid_ums_cypress,
+	drvid_usb_storage,
+	/* drivers/video/backlight */
+	drvid_backlight_class,
+	drvid_lcd_class,
+	drvid_platform_lcd,
+	drvid_pwm_backlight,
+	drvid_tps65217_bl,
+	/* drivers/video/console */
+	drvid_fb_console,
+	/* drivers/video/fbdev/core */
+	drvid_fbmem,
+	/* drivers/video/fbdev/omap2 */
+	drvid_omapvrfb,
+	/* drivers/watchdog */
+	drvid_imx2_wdt,
+	drvid_it87_wdt,
+	drvid_iTCO_wdt,
+	drvid_omap_wdt,
+	drvid_softdog,
+	drvid_twl4030_wdt,
+	drvid_watchdog,
+	/* fs */
+	drvid_anon_inode,
+	drvid_binfmt_misc,
+	drvid_binfmt_script,
+	drvid_binfmt_elf,
+	drvid_binfmt_elf_compat,
+	drvid_eventpoll,
+	drvid_mbcache,
+	drvid_pipe_fs,
+	drvid_proc_filesystems,
+	/* fs/btrfs */
+	drvid_btrfs,
+	/* fs/debugfs */
+	drvid_debugfs,
+	/* fs/ext4 */
+	drvid_ext4,
+	/* fs/fat */
+	drvid_msdos,
+	drvid_fat,
+	drvid_vfat,
+	/* fs/fuse */
+	drvid_fuse,
+	/* fs/jbd2 */
+	drvid_jbd2,
+	/* fs/lockd */
+	drvid_lockd,
+	/* fs/nfs */
+	drvid_grace,
+	drvid_nfs,
+	drvid_nfsv2,
+	drvid_nfsv3,
+	drvid_nfsv4,
+	drvid_nfs_layout_nfsv41_files,
+	drvid_blocklayoutdriver,
+	drvid_flexfilelayout,
+	drvid_nfs_layout_flexfiles,
+	/* fs/nfsd */
+	drvid_nfsd,
+	/* fs/proc */
+	drvid_proc_cmdline,
+	drvid_proc_consoles,
+	drvid_proc_cpuinfo,
+	drvid_proc_devices,
+	drvid_proc_interrupts,
+	drvid_proc_kcore,
+	drvid_proc_kmsg,
+	drvid_proc_loadavg,
+	drvid_proc_meminfo,
+	drvid_proc_page,
+	drvid_proc_softirqs,
+	drvid_proc_stat,
+	drvid_proc_uptime,
+	drvid_proc_version,
+	/* fs/ubifs */
+	drvid_ubifs,
+	/* ipc */
+	drvid_ipc,
+	drvid_ipc_sysctl,
+	drvid_mqueue_fs,
+	/* kernel */
+	drvid_configs,
+	drvid_proc_dma,
+	drvid_proc_modules,
+	drvid_futex,
+	drvid_load_system_certificate_list,
+	drvid_system_trusted_keyring_init,
+	drvid_wq_sysfs,
+	/* kernel/power */
+	drvid_pm,
+	drvid_pm_disk,
+	drvid_pm_sysrq,
+	drvid_snapshot_device,
+	/* kernel/sched */
+	drvid_proc_schedstat,
+	/* kernel/time */
+	drvid_clocksource_done_booting,
+	drvid_clocksource_sysfs,
+	/* lib */
+	drvid_crc_t10dif_mod,
+	drvid_crc32test,
+	drvid_kobject_uevent,
+	drvid_libcrc32c,
+	/* lib/raid6 */
+	drvid_raid6_pq,
+	/* mm */
+	drvid_bdi,
+	drvid_bdi_class,
+	drvid_proc_vmalloc,
+	drvid_procswaps,
+	/* net */
+	drvid_sock,
+	/* net/core */
+	drvid_fib_rules,
+	drvid_neigh,
+	drvid_net_dev,
+	drvid_net_inuse,
+	drvid_net_ns,
+	drvid_netpoll,
+	drvid_proto,
+	drvid_sysctl_core,
+	/* net/ethernet */
+	drvid_eth_offload,
+	/* net/ipv4 */
+	drvid_inet,
+	drvid_ipv4_netfilter,
+	drvid_ipv4_offload,
+	/* net/ipv6 */
+	drvid_inet6,
+	drvid_ipv6_offload,
+	/* net/netlink */
+	drvid_netlink,
+	drvid_netlink_proto,
+	/* net/packet */
+	drvid_packet,
+	/* net/rfkill */
+	drvid_rfkill,
+	drvid_rfkill_gpio,
+	/* net/sched */
+	drvid_pktsched,
+	/* net/sunrpc */
+	drvid_sunrpc,
+	drvid_auth_rpcgss,
+	drvid_rpcsec_gss_krb5,
+	/* net/unix */
+	drvid_af_unix,
+	/* net/wireless */
+	drvid_cfg80211,
+	drvid_wireless_nlevent,
+	/* net/xfrm */
+	drvid_xfrm_user,
+	/* security/keys */
+	drvid_key_proc,
+	/* sound/drivers/mpu401 */
+	drvid_snd_mpu401,
+	drvid_snd_mpu401_uart,
+	/* sound/soc */
+	drvid_snd_soc,
+	/* sound/soc/codecs */
+	drvid_hdmi_audio_codec,
+	drvid_twl4030_codec,
+	/* sound/soc/fsl */
+	drvid_imx_audmux,
+	/* sound/soc/omap */
+	drvid_omap_hdmi,
+	drvid_omap_mcbsp,
+	drvid_omap_twl4030,
+
 	drvid_max
 };
 
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 11/14] init: deps: annotate various initcalls
  2015-10-17 17:14 [PATCH 0/14] init: deps: dependency based (parallelized) init Alexander Holler
                   ` (9 preceding siblings ...)
  2015-10-17 17:14 ` [PATCH 10/14] init: deps: IDs for annotated initcalls Alexander Holler
@ 2015-10-17 17:14 ` Alexander Holler
  2015-10-17 18:47   ` Linus Torvalds
  2015-10-17 17:14 ` [PATCH 12/14] dt: dts: deps: kirkwood: dockstar: add dependency ehci -> usb power regulator Alexander Holler
                   ` (4 subsequent siblings)
  15 siblings, 1 reply; 59+ messages in thread
From: Alexander Holler @ 2015-10-17 17:14 UTC (permalink / raw)
  To: linux-kernel
  Cc: Linus Torvalds, Andrew Morton, Greg Kroah-Hartman, Russell King,
	Grant Likely, Alexander Holler

This is a large patch, NOT meant for merging into mainline.

It's meant to give a quick start in order to evaluate the feature
of using dependencies to order and parallelize the Linux kernels init.

Because I obviously don't know all details of all subsystems I had to
touch, many dependencies might be missing or wrong, should be handled
with care and should be reviewed by the maintainers of the respective
subsystem.

That means this all these changes are the result of a quick & dirty scan
of the respective sources, done to quickly get a usable base of
dependencies in order to test and check out if and how the concept works.

Be aware that I've done these changes based on my custom kernel configs
and eleminating initcalls (grep __initcall System.map) used in my custom
kernels. That means it's very likely that you will need to annotated more
initcalls and add more dependencies for your kernel (configuration) in
order to not end up with a crash at boot.

As this patch is not meant for mainline, please address comments regarding
formalism like long lines or C++ comments to a bureaucrat of your choice
or /dev/null, but, please, not me.

Signed-off-by: Alexander Holler <holler@ahsoftware.de>
---
 arch/arm/common/edma.c                        |  3 +--
 arch/arm/crypto/aes-ce-glue.c                 |  7 ++++++-
 arch/arm/crypto/aes_glue.c                    |  7 ++++++-
 arch/arm/crypto/aesbs-glue.c                  |  7 ++++++-
 arch/arm/crypto/sha1_glue.c                   |  6 +++++-
 arch/arm/crypto/sha1_neon_glue.c              |  7 ++++++-
 arch/arm/kernel/dma.c                         |  2 +-
 arch/arm/kernel/setup.c                       | 10 +++++++++-
 arch/arm/kernel/swp_emulate.c                 |  7 ++++++-
 arch/arm/mach-imx/gpc.c                       |  2 +-
 arch/arm/mach-imx/mmdc.c                      |  2 +-
 arch/arm/mach-omap2/i2c.c                     |  9 ++++++++-
 arch/arm/mm/alignment.c                       |  7 ++++++-
 arch/arm/mm/dma-mapping.c                     | 16 ++++++++++++++--
 arch/arm/plat-omap/dmtimer.c                  |  8 +++++++-
 arch/x86/crypto/aes_glue.c                    |  7 ++++++-
 arch/x86/kernel/acpi/boot.c                   |  8 +++++++-
 arch/x86/kernel/acpi/cstate.c                 |  2 +-
 arch/x86/kernel/apm_32.c                      |  8 +++++++-
 arch/x86/kernel/cpu/mcheck/mce.c              | 17 +++++++++++++++--
 arch/x86/kernel/cpu/mcheck/therm_throt.c      |  8 +++++++-
 arch/x86/kernel/cpu/microcode/core.c          |  8 +++++++-
 arch/x86/kernel/hpet.c                        |  2 +-
 arch/x86/kernel/pci-dma.c                     | 14 +++++++++++++-
 arch/x86/kernel/pmc_atom.c                    |  7 ++++++-
 arch/x86/kernel/reboot.c                      |  8 +++++++-
 arch/x86/kernel/rtc.c                         | 10 +++++++++-
 arch/x86/kernel/setup.c                       |  2 +-
 arch/x86/kernel/tsc.c                         | 16 ++++++++++++++--
 arch/x86/pci/i386.c                           |  8 +++++++-
 arch/x86/pci/init.c                           |  9 ++++++++-
 arch/x86/pci/legacy.c                         | 12 +++++++++++-
 block/bio.c                                   |  8 +++++++-
 block/blk-integrity.c                         |  8 +++++++-
 block/blk-ioc.c                               |  3 ++-
 block/blk-iopoll.c                            |  2 +-
 block/blk-mq.c                                | 12 +++++++++++-
 block/blk-settings.c                          |  2 +-
 block/blk-softirq.c                           |  2 +-
 block/bsg.c                                   |  7 ++++++-
 block/cfq-iosched.c                           |  2 +-
 block/deadline-iosched.c                      |  2 +-
 block/genhd.c                                 | 15 +++++++++++++--
 block/noop-iosched.c                          |  7 ++++++-
 block/scsi_ioctl.c                            |  8 +++++++-
 crypto/aes_generic.c                          |  7 ++++++-
 crypto/algapi.c                               |  2 +-
 crypto/algboss.c                              |  2 +-
 crypto/asymmetric_keys/asymmetric_type.c      |  2 +-
 crypto/asymmetric_keys/x509_public_key.c      |  7 ++++++-
 crypto/authenc.c                              |  2 +-
 crypto/authencesn.c                           |  2 +-
 crypto/cbc.c                                  |  7 ++++++-
 crypto/chainiv.c                              |  7 ++++++-
 crypto/crc32c_generic.c                       |  7 ++++++-
 crypto/crct10dif_generic.c                    |  7 ++++++-
 crypto/cryptd.c                               |  7 ++++++-
 crypto/crypto_user.c                          |  7 ++++++-
 crypto/crypto_wq.c                            |  7 ++++++-
 crypto/deflate.c                              |  7 ++++++-
 crypto/des_generic.c                          |  7 ++++++-
 crypto/ecb.c                                  |  2 +-
 crypto/eseqiv.c                               |  2 +-
 crypto/hmac.c                                 |  2 +-
 crypto/lzo.c                                  |  7 ++++++-
 crypto/mcryptd.c                              |  7 ++++++-
 crypto/md5.c                                  |  7 ++++++-
 crypto/michael_mic.c                          |  6 +++++-
 crypto/sha1_generic.c                         |  7 ++++++-
 crypto/sha256_generic.c                       |  7 ++++++-
 crypto/sha512_generic.c                       |  7 ++++++-
 crypto/xor.c                                  |  2 +-
 drivers/acpi/ac.c                             | 11 ++++++++++-
 drivers/acpi/battery.c                        |  8 +++++++-
 drivers/acpi/bus.c                            | 10 +++++++++-
 drivers/acpi/button.c                         |  8 +++++++-
 drivers/acpi/event.c                          | 10 +++++++++-
 drivers/acpi/fan.c                            |  9 ++++++++-
 drivers/acpi/osl.c                            |  7 ++++++-
 drivers/acpi/processor_driver.c               |  8 +++++++-
 drivers/acpi/sbs.c                            | 10 +++++++++-
 drivers/acpi/sbshc.c                          |  8 +++++++-
 drivers/acpi/thermal.c                        | 10 +++++++++-
 drivers/ata/ahci_imx.c                        |  8 +++++++-
 drivers/ata/ahci_platform.c                   |  8 +++++++-
 drivers/ata/ata_generic.c                     | 11 ++++++++++-
 drivers/ata/ata_piix.c                        | 11 ++++++++++-
 drivers/ata/libata-core.c                     |  7 ++++++-
 drivers/ata/pata_acpi.c                       | 11 ++++++++++-
 drivers/ata/pata_amd.c                        | 11 ++++++++++-
 drivers/ata/pata_jmicron.c                    | 11 ++++++++++-
 drivers/ata/pata_mpiix.c                      | 11 ++++++++++-
 drivers/ata/pata_oldpiix.c                    | 11 ++++++++++-
 drivers/ata/pata_sch.c                        | 11 ++++++++++-
 drivers/ata/pata_sis.c                        | 11 ++++++++++-
 drivers/base/firmware_class.c                 |  7 ++++++-
 drivers/block/loop.c                          |  7 ++++++-
 drivers/bus/imx-weim.c                        |  2 +-
 drivers/bus/omap-ocp2scp.c                    |  2 +-
 drivers/bus/omap_l3_noc.c                     |  2 +-
 drivers/bus/omap_l3_smx.c                     |  2 +-
 drivers/char/agp/backend.c                    |  8 ++++++--
 drivers/char/genrtc.c                         |  6 +++++-
 drivers/char/hpet.c                           | 10 +++++++++-
 drivers/char/hw_random/core.c                 |  7 ++++++-
 drivers/char/hw_random/omap-rng.c             | 10 ++++++++--
 drivers/char/hw_random/omap3-rom-rng.c        |  7 ++++++-
 drivers/char/misc.c                           |  2 +-
 drivers/char/nvram.c                          |  7 ++++++-
 drivers/char/rtc.c                            |  8 +++++++-
 drivers/clocksource/acpi_pm.c                 |  9 ++++++++-
 drivers/connector/cn_proc.c                   |  7 ++++++-
 drivers/connector/connector.c                 |  7 ++++++-
 drivers/cpufreq/acpi-cpufreq.c                |  8 +++++++-
 drivers/cpufreq/cpufreq.c                     |  2 +-
 drivers/cpufreq/cpufreq_conservative.c        |  9 +++++++--
 drivers/cpufreq/cpufreq_ondemand.c            |  9 +++++++--
 drivers/cpufreq/cpufreq_performance.c         |  7 ++++++-
 drivers/cpufreq/cpufreq_powersave.c           |  9 +++++++--
 drivers/cpufreq/cpufreq_stats.c               |  7 ++++++-
 drivers/cpufreq/imx6q-cpufreq.c               |  8 +++++++-
 drivers/cpufreq/kirkwood-cpufreq.c            |  7 ++++++-
 drivers/cpufreq/omap-cpufreq.c                |  8 +++++++-
 drivers/cpuidle/cpuidle-arm.c                 |  9 +++++++--
 drivers/cpuidle/cpuidle-kirkwood.c            |  7 ++++++-
 drivers/cpuidle/cpuidle.c                     |  2 +-
 drivers/crypto/marvell/cesa.c                 |  8 +++++++-
 drivers/crypto/mv_cesa.c                      |  7 ++++++-
 drivers/crypto/omap-aes.c                     |  7 ++++++-
 drivers/crypto/omap-sham.c                    |  8 +++++++-
 drivers/dma/cppi41.c                          |  8 +++++++-
 drivers/dma/dmaengine.c                       |  8 +++++++-
 drivers/dma/imx-sdma.c                        |  8 +++++++-
 drivers/dma/mv_xor.c                          |  9 ++++++++-
 drivers/dma/mxs-dma.c                         |  9 ++++++++-
 drivers/dma/omap-dma.c                        |  9 ++++++++-
 drivers/firmware/dmi_scan.c                   |  8 +++++++-
 drivers/gpio/gpio-generic.c                   |  2 +-
 drivers/gpio/gpio-mvebu.c                     |  2 +-
 drivers/gpio/gpio-mxc.c                       |  2 +-
 drivers/gpio/gpio-omap.c                      |  8 +++++++-
 drivers/gpio/gpio-tps65910.c                  |  2 +-
 drivers/gpio/gpio-twl4030.c                   |  2 +-
 drivers/gpio/gpiolib.c                        |  8 +++++++-
 drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c       | 11 ++++++++++-
 drivers/gpu/drm/drm_drv.c                     | 13 ++++++++++++-
 drivers/gpu/drm/drm_fb_helper.c               |  7 ++++++-
 drivers/gpu/drm/drm_mipi_dsi.c                | 13 +++++++++++++
 drivers/gpu/drm/i915/i915_drv.c               |  7 ++++++-
 drivers/gpu/drm/radeon/radeon_drv.c           | 11 ++++++++++-
 drivers/gpu/drm/tilcdc/tilcdc_drv.c           |  7 ++++++-
 drivers/gpu/drm/ttm/ttm_module.c              |  7 ++++++-
 drivers/gpu/vga/vgaarb.c                      | 12 +++++++++++-
 drivers/hid/uhid.c                            |  7 ++++++-
 drivers/hwmon/hwmon.c                         |  8 +++++++-
 drivers/hwspinlock/omap_hwspinlock.c          |  8 +++++++-
 drivers/i2c/busses/i2c-gpio.c                 |  8 +++++++-
 drivers/i2c/busses/i2c-imx.c                  |  8 +++++++-
 drivers/i2c/busses/i2c-mv64xxx.c              |  7 ++++++-
 drivers/i2c/busses/i2c-omap.c                 |  9 ++++++++-
 drivers/i2c/busses/i2c-tiny-usb.c             |  8 +++++++-
 drivers/i2c/i2c-core.c                        |  2 +-
 drivers/i2c/i2c-dev.c                         |  7 ++++++-
 drivers/iio/adc/ti_am335x_adc.c               |  2 +-
 drivers/input/evdev.c                         |  7 ++++++-
 drivers/input/input.c                         |  2 +-
 drivers/input/joydev.c                        |  7 ++++++-
 drivers/input/keyboard/atkbd.c                |  9 ++++++++-
 drivers/input/keyboard/gpio_keys.c            |  7 ++++++-
 drivers/input/misc/twl4030-pwrbutton.c        |  9 ++++++++-
 drivers/input/misc/uinput.c                   |  8 +++++++-
 drivers/input/mousedev.c                      |  8 +++++++-
 drivers/input/serio/i8042.c                   | 10 +++++++++-
 drivers/input/serio/serio.c                   |  2 +-
 drivers/input/serio/serio_raw.c               |  8 +++++++-
 drivers/input/serio/serport.c                 |  7 ++++++-
 drivers/iommu/amd_iommu_v2.c                  |  7 ++++++-
 drivers/iommu/intel_irq_remapping.c           | 12 +++++++++++-
 drivers/iommu/iommu-sysfs.c                   |  8 +++++++-
 drivers/iommu/iommu.c                         |  2 +-
 drivers/iommu/omap-iommu.c                    |  9 ++++++++-
 drivers/leds/led-class.c                      |  2 +-
 drivers/leds/leds-gpio.c                      |  7 ++++++-
 drivers/leds/leds-regulator.c                 |  7 ++++++-
 drivers/leds/trigger/ledtrig-heartbeat.c      |  7 ++++++-
 drivers/mailbox/omap-mailbox.c                |  2 +-
 drivers/md/md.c                               |  7 ++++++-
 drivers/md/raid5.c                            |  5 +++++
 drivers/media/i2c/ir-kbd-i2c.c                |  7 ++++++-
 drivers/memory/omap-gpmc.c                    |  2 +-
 drivers/mfd/omap-usb-host.c                   |  2 +-
 drivers/mfd/omap-usb-tll.c                    |  2 +-
 drivers/mfd/ti_am335x_tscadc.c                |  2 +-
 drivers/mfd/tps65217.c                        | 10 +++++++++-
 drivers/mfd/tps65910.c                        |  9 ++++++++-
 drivers/mfd/twl-core.c                        |  8 +++++++-
 drivers/mfd/twl4030-audio.c                   |  7 ++++++-
 drivers/mfd/twl4030-power.c                   |  7 ++++++-
 drivers/misc/eeprom/at24.c                    |  8 +++++++-
 drivers/misc/sram.c                           |  2 ++
 drivers/mmc/card/block.c                      |  7 ++++++-
 drivers/mmc/core/core.c                       |  7 ++++++-
 drivers/mmc/host/mxs-mmc.c                    |  7 ++++++-
 drivers/mmc/host/omap.c                       |  7 ++++++-
 drivers/mmc/host/omap_hsmmc.c                 |  7 ++++++-
 drivers/mmc/host/sdhci-esdhc-imx.c            |  7 ++++++-
 drivers/mmc/host/sdhci.c                      |  7 ++++++-
 drivers/mtd/mtdcore.c                         |  7 ++++++-
 drivers/mtd/nand/omap2.c                      |  8 +++++++-
 drivers/mtd/nand/omap_elm.c                   |  2 +-
 drivers/mtd/nand/orion_nand.c                 |  8 +++++++-
 drivers/mtd/ofpart.c                          |  2 +-
 drivers/net/ethernet/freescale/fec_main.c     |  9 ++++++++-
 drivers/net/ethernet/intel/e1000/e1000_main.c | 10 +++++++++-
 drivers/net/ethernet/marvell/mv643xx_eth.c    | 11 ++++++++++-
 drivers/net/ethernet/marvell/mvmdio.c         |  7 ++++++-
 drivers/net/ethernet/realtek/r8169.c          | 10 +++++++++-
 drivers/net/ethernet/ti/cpsw-phy-sel.c        |  7 ++++++-
 drivers/net/ethernet/ti/cpsw.c                | 10 +++++++++-
 drivers/net/ethernet/ti/davinci_mdio.c        |  9 ++++++++-
 drivers/net/irda/nsc-ircc.c                   |  7 ++++++-
 drivers/net/irda/smsc-ircc2.c                 |  6 +++++-
 drivers/net/phy/lxt.c                         |  7 ++++++-
 drivers/net/phy/phy_device.c                  |  2 +-
 drivers/net/phy/realtek.c                     |  7 ++++++-
 drivers/net/phy/smsc.c                        |  7 ++++++-
 drivers/pci/hotplug/pci_hotplug_core.c        | 11 ++++++++++-
 drivers/pci/pci-acpi.c                        |  8 +++++++-
 drivers/pci/pci-driver.c                      |  8 +++++++-
 drivers/pci/pci-stub.c                        | 10 +++++++++-
 drivers/pci/probe.c                           |  2 +-
 drivers/pci/proc.c                            | 11 ++++++++++-
 drivers/pci/quirks.c                          |  9 ++++++++-
 drivers/pci/slot.c                            |  8 +++++++-
 drivers/phy/phy-core.c                        |  2 +-
 drivers/phy/phy-mvebu-sata.c                  |  8 +++++++-
 drivers/phy/phy-twl4030-usb.c                 |  8 +++++++-
 drivers/pinctrl/freescale/pinctrl-imx6q.c     |  2 +-
 drivers/pinctrl/mvebu/pinctrl-kirkwood.c      |  2 +-
 drivers/pinctrl/pinctrl-single.c              |  2 +-
 drivers/platform/x86/asus-wmi.c               | 13 ++++++++++++-
 drivers/platform/x86/eeepc-wmi.c              |  8 +++++++-
 drivers/platform/x86/wmi.c                    |  7 ++++++-
 drivers/pnp/core.c                            |  2 +-
 drivers/pnp/pnpacpi/core.c                    |  8 +++++++-
 drivers/pnp/system.c                          |  7 ++++++-
 drivers/power/power_supply_core.c             |  2 +-
 drivers/power/reset/gpio-poweroff.c           |  2 +-
 drivers/power/reset/imx-snvs-poweroff.c       |  2 +-
 drivers/power/twl4030_charger.c               |  2 +-
 drivers/pwm/core.c                            |  7 ++++++-
 drivers/pwm/pwm-imx.c                         |  2 +-
 drivers/pwm/pwm-tiecap.c                      |  2 +-
 drivers/pwm/pwm-tiehrpwm.c                    |  2 +-
 drivers/pwm/pwm-tipwmss.c                     |  2 +-
 drivers/regulator/anatop-regulator.c          |  9 ++++++++-
 drivers/regulator/core.c                      |  7 ++++++-
 drivers/regulator/fixed.c                     |  9 ++++++++-
 drivers/regulator/tps65023-regulator.c        |  9 ++++++++-
 drivers/regulator/tps65910-regulator.c        |  8 +++++++-
 drivers/regulator/twl-regulator.c             | 10 ++++++++--
 drivers/remoteproc/remoteproc_core.c          |  8 +++++++-
 drivers/remoteproc/wkup_m3_rproc.c            |  7 ++++++-
 drivers/rtc/class.c                           |  2 +-
 drivers/rtc/rtc-cmos.c                        |  9 ++++++++-
 drivers/rtc/rtc-ds1307.c                      |  7 ++++++-
 drivers/rtc/rtc-hid-sensor-time.c             |  8 +++++++-
 drivers/rtc/rtc-mxc.c                         |  7 ++++++-
 drivers/rtc/rtc-omap.c                        |  7 ++++++-
 drivers/rtc/rtc-snvs.c                        |  8 +++++++-
 drivers/rtc/rtc-twl.c                         |  7 ++++++-
 drivers/scsi/scsi.c                           |  8 +++++++-
 drivers/scsi/sd.c                             |  8 +++++++-
 drivers/spi/spi-imx.c                         |  2 +-
 drivers/spi/spi-omap2-mcspi.c                 |  2 +-
 drivers/thermal/thermal_core.c                |  8 +++++++-
 drivers/tty/pty.c                             |  8 +++++++-
 drivers/tty/serial/8250/8250_core.c           |  9 ++++++++-
 drivers/tty/serial/8250/8250_omap.c           |  8 +++++++-
 drivers/tty/serial/8250/8250_pci.c            | 11 ++++++++++-
 drivers/tty/serial/fsl_lpuart.c               |  7 ++++++-
 drivers/tty/serial/imx.c                      |  7 ++++++-
 drivers/tty/serial/of_serial.c                |  7 ++++++-
 drivers/tty/serial/omap-serial.c              |  7 ++++++-
 drivers/tty/sysrq.c                           |  8 +++++++-
 drivers/tty/tty_io.c                          |  2 +-
 drivers/uio/uio_pdrv_genirq.c                 |  2 +-
 drivers/usb/core/usb.c                        | 11 ++++++++++-
 drivers/usb/host/ehci-hcd.c                   |  8 +++++++-
 drivers/usb/host/ehci-omap.c                  |  8 +++++++-
 drivers/usb/host/ehci-orion.c                 |  8 +++++++-
 drivers/usb/host/ehci-pci.c                   | 12 +++++++++++-
 drivers/usb/host/ohci-hcd.c                   |  9 ++++++++-
 drivers/usb/host/ohci-omap3.c                 |  8 +++++++-
 drivers/usb/host/uhci-hcd.c                   |  8 +++++++-
 drivers/usb/musb/musb_core.c                  |  2 +-
 drivers/usb/musb/musb_dsps.c                  |  2 +-
 drivers/usb/musb/omap2430.c                   |  2 +-
 drivers/usb/phy/phy-am335x-control.c          |  2 +-
 drivers/usb/phy/phy-am335x.c                  |  2 +-
 drivers/usb/phy/phy-generic.c                 |  2 +-
 drivers/usb/phy/phy-gpio-vbus-usb.c           |  2 +-
 drivers/usb/phy/phy-mxs-usb.c                 |  2 +-
 drivers/usb/storage/cypress_atacb.c           |  7 ++++++-
 drivers/usb/storage/usb.c                     |  8 +++++++-
 drivers/video/backlight/backlight.c           |  8 +++++++-
 drivers/video/backlight/lcd.c                 |  7 ++++++-
 drivers/video/backlight/platform_lcd.c        |  8 +++++++-
 drivers/video/backlight/pwm_bl.c              |  7 ++++++-
 drivers/video/backlight/tps65217_bl.c         |  8 +++++++-
 drivers/video/console/fbcon.c                 |  8 +++++++-
 drivers/video/fbdev/core/fbmem.c              |  4 ++--
 drivers/video/fbdev/omap2/vrfb.c              |  7 ++++++-
 drivers/watchdog/iTCO_wdt.c                   |  7 ++++++-
 drivers/watchdog/imx2_wdt.c                   |  7 ++++++-
 drivers/watchdog/it87_wdt.c                   |  7 ++++++-
 drivers/watchdog/omap_wdt.c                   |  7 ++++++-
 drivers/watchdog/softdog.c                    |  7 ++++++-
 drivers/watchdog/twl4030_wdt.c                |  7 ++++++-
 drivers/watchdog/watchdog_core.c              |  7 ++++++-
 fs/anon_inodes.c                              |  3 +--
 fs/binfmt_elf.c                               |  2 +-
 fs/binfmt_misc.c                              |  2 +-
 fs/binfmt_script.c                            |  2 +-
 fs/btrfs/super.c                              | 14 +++++++++++++-
 fs/compat_binfmt_elf.c                        |  2 +-
 fs/debugfs/inode.c                            |  3 ++-
 fs/eventpoll.c                                |  2 +-
 fs/ext4/super.c                               | 10 +++++++++-
 fs/fat/inode.c                                |  2 +-
 fs/fat/namei_msdos.c                          |  7 ++++++-
 fs/fat/namei_vfat.c                           |  7 ++++++-
 fs/filesystems.c                              |  2 +-
 fs/fuse/inode.c                               |  7 ++++++-
 fs/jbd2/journal.c                             |  2 +-
 fs/lockd/svc.c                                |  8 +++++++-
 fs/mbcache.c                                  |  2 +-
 fs/nfs/blocklayout/blocklayout.c              | 11 ++++++++++-
 fs/nfs/filelayout/filelayout.c                | 11 ++++++++++-
 fs/nfs/flexfilelayout/flexfilelayout.c        | 11 ++++++++++-
 fs/nfs/inode.c                                | 10 +++++++++-
 fs/nfs/nfs2super.c                            | 10 +++++++++-
 fs/nfs/nfs3super.c                            | 10 +++++++++-
 fs/nfs_common/grace.c                         |  8 +++++++-
 fs/nfsd/nfsctl.c                              | 12 +++++++++++-
 fs/pipe.c                                     |  2 +-
 fs/proc/cmdline.c                             |  2 +-
 fs/proc/consoles.c                            |  2 +-
 fs/proc/cpuinfo.c                             |  2 +-
 fs/proc/devices.c                             |  2 +-
 fs/proc/interrupts.c                          |  2 +-
 fs/proc/kcore.c                               |  2 +-
 fs/proc/kmsg.c                                |  2 +-
 fs/proc/loadavg.c                             |  2 +-
 fs/proc/meminfo.c                             |  2 +-
 fs/proc/page.c                                |  2 +-
 fs/proc/softirqs.c                            |  2 +-
 fs/proc/stat.c                                |  2 +-
 fs/proc/uptime.c                              |  2 +-
 fs/proc/version.c                             |  2 +-
 fs/ubifs/super.c                              | 11 ++++++++++-
 ipc/ipc_sysctl.c                              |  7 ++++++-
 ipc/mqueue.c                                  |  7 ++++++-
 ipc/util.c                                    |  8 +++++++-
 kernel/configs.c                              |  2 +-
 kernel/dma.c                                  |  2 +-
 kernel/futex.c                                |  2 +-
 kernel/module.c                               |  2 +-
 kernel/power/hibernate.c                      |  7 ++++++-
 kernel/power/main.c                           |  7 ++++++-
 kernel/power/poweroff.c                       |  2 +-
 kernel/power/user.c                           |  7 ++++++-
 kernel/sched/stats.c                          |  2 +-
 kernel/system_keyring.c                       | 15 +++++++++++++--
 kernel/time/clocksource.c                     |  9 +++++++--
 kernel/workqueue.c                            |  2 +-
 lib/crc-t10dif.c                              |  2 +-
 lib/crc32.c                                   |  2 +-
 lib/kobject_uevent.c                          |  6 +++++-
 lib/libcrc32c.c                               |  7 ++++++-
 lib/raid6/algos.c                             |  2 +-
 mm/backing-dev.c                              | 17 +++++++++++++++--
 mm/swapfile.c                                 |  2 +-
 mm/vmalloc.c                                  |  2 +-
 net/bluetooth/af_bluetooth.c                  |  7 ++++++-
 net/core/dev.c                                |  8 +++++++-
 net/core/fib_rules.c                          |  8 +++++++-
 net/core/neighbour.c                          |  6 +++++-
 net/core/net_namespace.c                      |  2 +-
 net/core/netpoll.c                            |  8 +++++++-
 net/core/sock.c                               |  4 ++--
 net/core/sysctl_net_core.c                    |  7 ++++++-
 net/ethernet/eth.c                            |  7 ++++++-
 net/ipv4/af_inet.c                            | 25 +++++++++++++++++++++++--
 net/ipv4/netfilter.c                          |  2 +-
 net/ipv6/af_inet6.c                           | 18 +++++++++++++++++-
 net/ipv6/ip6_offload.c                        |  7 ++++++-
 net/netlink/af_netlink.c                      |  8 +++++++-
 net/netlink/genetlink.c                       |  7 ++++++-
 net/packet/af_packet.c                        |  8 +++++++-
 net/rfkill/core.c                             |  8 +++++++-
 net/rfkill/rfkill-gpio.c                      |  7 ++++++-
 net/sched/sch_api.c                           |  7 ++++++-
 net/socket.c                                  |  7 ++++++-
 net/sunrpc/auth_gss/auth_gss.c                |  7 ++++++-
 net/sunrpc/auth_gss/gss_krb5_mech.c           |  9 ++++++++-
 net/sunrpc/sunrpc_syms.c                      |  8 +++++++-
 net/unix/af_unix.c                            |  8 +++++++-
 net/wireless/core.c                           | 10 +++++++++-
 net/wireless/wext-core.c                      |  7 ++++++-
 net/xfrm/xfrm_user.c                          |  8 +++++++-
 security/keys/proc.c                          |  2 +-
 sound/drivers/mpu401/mpu401.c                 |  8 +++++++-
 sound/drivers/mpu401/mpu401_uart.c            |  2 +-
 sound/soc/codecs/hdmi.c                       |  7 ++++++-
 sound/soc/codecs/twl4030.c                    |  7 ++++++-
 sound/soc/fsl/imx-audmux.c                    |  9 ++++++++-
 sound/soc/omap/omap-hdmi-audio.c              |  7 ++++++-
 sound/soc/omap/omap-mcbsp.c                   |  7 ++++++-
 sound/soc/omap/omap-twl4030.c                 |  9 ++++++++-
 sound/soc/soc-core.c                          |  8 +++++++-
 421 files changed, 2340 insertions(+), 437 deletions(-)

diff --git a/arch/arm/common/edma.c b/arch/arm/common/edma.c
index 873dbfc..d5d2459 100644
--- a/arch/arm/common/edma.c
+++ b/arch/arm/common/edma.c
@@ -1872,5 +1872,4 @@ static int __init edma_init(void)
 {
 	return platform_driver_probe(&edma_driver, edma_probe);
 }
-arch_initcall(edma_init);
-
+annotated_initcall_drv(arch, edma_init, drvid_edma, NULL, edma_driver.driver);
diff --git a/arch/arm/crypto/aes-ce-glue.c b/arch/arm/crypto/aes-ce-glue.c
index b445a5d..d9bcb89 100644
--- a/arch/arm/crypto/aes-ce-glue.c
+++ b/arch/arm/crypto/aes-ce-glue.c
@@ -520,5 +520,10 @@ static void __exit aes_exit(void)
 	crypto_unregister_algs(aes_algs, ARRAY_SIZE(aes_algs));
 }
 
-module_init(aes_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_cryptomgr,
+	0
+};
+
+annotated_module_init(aes_init, drvid_aes_ce_arm, dependencies);
 module_exit(aes_exit);
diff --git a/arch/arm/crypto/aes_glue.c b/arch/arm/crypto/aes_glue.c
index 0409b8f..c814fe5 100644
--- a/arch/arm/crypto/aes_glue.c
+++ b/arch/arm/crypto/aes_glue.c
@@ -88,7 +88,12 @@ static void __exit aes_fini(void)
 	crypto_unregister_alg(&aes_alg);
 }
 
-module_init(aes_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_cryptomgr,
+	0
+};
+
+annotated_module_init(aes_init, drvid_aes_arm, dependencies);
 module_exit(aes_fini);
 
 MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm (ASM)");
diff --git a/arch/arm/crypto/aesbs-glue.c b/arch/arm/crypto/aesbs-glue.c
index 6d68529..d3de8d5 100644
--- a/arch/arm/crypto/aesbs-glue.c
+++ b/arch/arm/crypto/aesbs-glue.c
@@ -429,7 +429,12 @@ static void __exit aesbs_mod_exit(void)
 	crypto_unregister_algs(aesbs_algs, ARRAY_SIZE(aesbs_algs));
 }
 
-module_init(aesbs_mod_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_cryptomgr,
+	0
+};
+
+annotated_module_init(aesbs_mod_init, drvid_aesbs, dependencies);
 module_exit(aesbs_mod_exit);
 
 MODULE_DESCRIPTION("Bit sliced AES in CBC/CTR/XTS modes using NEON");
diff --git a/arch/arm/crypto/sha1_glue.c b/arch/arm/crypto/sha1_glue.c
index 6fc73bf..db3370a 100644
--- a/arch/arm/crypto/sha1_glue.c
+++ b/arch/arm/crypto/sha1_glue.c
@@ -85,8 +85,12 @@ static void __exit sha1_mod_fini(void)
 	crypto_unregister_shash(&alg);
 }
 
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_cryptomgr,
+	0
+};
 
-module_init(sha1_mod_init);
+annotated_module_init(sha1_mod_init, drvid_sha1_mod, dependencies);
 module_exit(sha1_mod_fini);
 
 MODULE_LICENSE("GPL");
diff --git a/arch/arm/crypto/sha1_neon_glue.c b/arch/arm/crypto/sha1_neon_glue.c
index 4e22f12..deb0714 100644
--- a/arch/arm/crypto/sha1_neon_glue.c
+++ b/arch/arm/crypto/sha1_neon_glue.c
@@ -102,7 +102,12 @@ static void __exit sha1_neon_mod_fini(void)
 	crypto_unregister_shash(&alg);
 }
 
-module_init(sha1_neon_mod_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_cryptomgr,
+	0
+};
+
+annotated_module_init(sha1_neon_mod_init, drvid_sha1_neon, dependencies);
 module_exit(sha1_neon_mod_fini);
 
 MODULE_LICENSE("GPL");
diff --git a/arch/arm/kernel/dma.c b/arch/arm/kernel/dma.c
index e651c4d..e441091 100644
--- a/arch/arm/kernel/dma.c
+++ b/arch/arm/kernel/dma.c
@@ -294,5 +294,5 @@ static int __init proc_dma_init(void)
 	return 0;
 }
 
-__initcall(proc_dma_init);
+annotated_initcall(device, proc_dma_init, drvid_proc_dma_arm, NULL);
 #endif
diff --git a/arch/arm/kernel/setup.c b/arch/arm/kernel/setup.c
index 36c18b7..5edb36f 100644
--- a/arch/arm/kernel/setup.c
+++ b/arch/arm/kernel/setup.c
@@ -838,6 +838,14 @@ static int __init customize_machine(void)
 #endif
 	return 0;
 }
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_sram, // needed on imx
+	drvid_pm,
+	0
+};
+
+//annotated_initcall(arch, customize_machine, drvid_customize_machine, dependencies);
 arch_initcall(customize_machine);
 
 static int __init init_machine_late(void)
@@ -1033,7 +1041,7 @@ static int __init proc_cpu_init(void)
 		return -ENOMEM;
 	return 0;
 }
-fs_initcall(proc_cpu_init);
+annotated_initcall(fs, proc_cpu_init, drvid_proc_cpu, NULL);
 #endif
 
 static const char *hwcap_str[] = {
diff --git a/arch/arm/kernel/swp_emulate.c b/arch/arm/kernel/swp_emulate.c
index 1361756..5bfcc5e 100644
--- a/arch/arm/kernel/swp_emulate.c
+++ b/arch/arm/kernel/swp_emulate.c
@@ -266,4 +266,9 @@ static int __init swp_emulation_init(void)
 	return 0;
 }
 
-late_initcall(swp_emulation_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_proc_cpu,
+	0
+};
+
+annotated_initcall(late, swp_emulation_init, drvid_swp_emulation, dependencies);
diff --git a/arch/arm/mach-imx/gpc.c b/arch/arm/mach-imx/gpc.c
index 8c4467f..2f1ce25 100644
--- a/arch/arm/mach-imx/gpc.c
+++ b/arch/arm/mach-imx/gpc.c
@@ -468,4 +468,4 @@ static int __init imx_pgc_init(void)
 {
 	return platform_driver_register(&imx_gpc_driver);
 }
-subsys_initcall(imx_pgc_init);
+annotated_initcall_drv(subsys, imx_pgc_init, drvid_imx_gpc, NULL, imx_gpc_driver.driver);
diff --git a/arch/arm/mach-imx/mmdc.c b/arch/arm/mach-imx/mmdc.c
index db9621c..ac193cc6 100644
--- a/arch/arm/mach-imx/mmdc.c
+++ b/arch/arm/mach-imx/mmdc.c
@@ -87,4 +87,4 @@ static int __init imx_mmdc_init(void)
 {
 	return platform_driver_register(&imx_mmdc_driver);
 }
-postcore_initcall(imx_mmdc_init);
+annotated_initcall_drv(postcore, imx_mmdc_init, drvid_imx_mmdc, NULL, imx_mmdc_driver.driver);
diff --git a/arch/arm/mach-omap2/i2c.c b/arch/arm/mach-omap2/i2c.c
index b9d8e47..183d515 100644
--- a/arch/arm/mach-omap2/i2c.c
+++ b/arch/arm/mach-omap2/i2c.c
@@ -188,4 +188,11 @@ static  int __init omap_i2c_cmdline(void)
 {
 	return omap_register_i2c_bus_cmdline();
 }
-omap_subsys_initcall(omap_i2c_cmdline);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_i2c,
+	0
+};
+
+annotated_omap_initcall(subsys, omap_i2c_cmdline, drvid_omap_i2c_cmdline, dependencies);
+//omap_subsys_initcall(omap_i2c_cmdline);
diff --git a/arch/arm/mm/alignment.c b/arch/arm/mm/alignment.c
index 9769f1e..bbae986 100644
--- a/arch/arm/mm/alignment.c
+++ b/arch/arm/mm/alignment.c
@@ -1005,4 +1005,9 @@ static int __init alignment_init(void)
 	return 0;
 }
 
-fs_initcall(alignment_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_proc_cpu,
+	0
+};
+
+annotated_initcall(fs, alignment_init, drvid_alignment, dependencies);
diff --git a/arch/arm/mm/dma-mapping.c b/arch/arm/mm/dma-mapping.c
index cba12f3..0d7f32c 100644
--- a/arch/arm/mm/dma-mapping.c
+++ b/arch/arm/mm/dma-mapping.c
@@ -392,7 +392,13 @@ out:
 /*
  * CMA is activated by core_initcall, so we must be called after it.
  */
-postcore_initcall(atomic_pool_init);
+/*
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	//drvid_cma, // TODO
+	0
+};
+*/
+annotated_initcall(postcore, atomic_pool_init, drvid_atomic_pool, NULL);
 
 struct dma_contig_early_reserve {
 	phys_addr_t base;
@@ -1029,7 +1035,13 @@ static int __init dma_debug_do_init(void)
 	dma_debug_init(PREALLOC_DMA_DEBUG_ENTRIES);
 	return 0;
 }
-fs_initcall(dma_debug_do_init);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_atomic_pool,
+	0
+};
+
+annotated_initcall(fs, dma_debug_do_init, drvid_dma_debug, dependencies);
 
 #ifdef CONFIG_ARM_DMA_USE_IOMMU
 
diff --git a/arch/arm/plat-omap/dmtimer.c b/arch/arm/plat-omap/dmtimer.c
index 8ca94d3..d96fd61 100644
--- a/arch/arm/plat-omap/dmtimer.c
+++ b/arch/arm/plat-omap/dmtimer.c
@@ -957,7 +957,13 @@ static struct platform_driver omap_dm_timer_driver = {
 };
 
 early_platform_init("earlytimer", &omap_dm_timer_driver);
-module_platform_driver(omap_dm_timer_driver);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_pm,
+	0
+};
+
+annotated_module_platform_driver(omap_dm_timer_driver, drvid_omap_dm_timer, dependencies);
 
 MODULE_DESCRIPTION("OMAP Dual-Mode Timer Driver");
 MODULE_LICENSE("GPL");
diff --git a/arch/x86/crypto/aes_glue.c b/arch/x86/crypto/aes_glue.c
index e26984f..bf45e7e 100644
--- a/arch/x86/crypto/aes_glue.c
+++ b/arch/x86/crypto/aes_glue.c
@@ -61,7 +61,12 @@ static void __exit aes_fini(void)
 	crypto_unregister_alg(&aes_alg);
 }
 
-module_init(aes_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_cryptomgr,
+	0
+};
+
+annotated_module_init(aes_init, drvid_aes_x86, dependencies);
 module_exit(aes_fini);
 
 MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm, asm optimized");
diff --git a/arch/x86/kernel/acpi/boot.c b/arch/x86/kernel/acpi/boot.c
index 9393896..d59b740 100644
--- a/arch/x86/kernel/acpi/boot.c
+++ b/arch/x86/kernel/acpi/boot.c
@@ -911,7 +911,13 @@ static __init int hpet_insert_resource(void)
 	return insert_resource(&iomem_resource, hpet_res);
 }
 
-late_initcall(hpet_insert_resource);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_hpet_late,
+	drvid_hpet,
+	0
+};
+
+annotated_initcall(late, hpet_insert_resource, drvid_hpet_insert_resource, dependencies);
 
 #else
 #define	acpi_parse_hpet	NULL
diff --git a/arch/x86/kernel/acpi/cstate.c b/arch/x86/kernel/acpi/cstate.c
index 4b28159..280a041 100644
--- a/arch/x86/kernel/acpi/cstate.c
+++ b/arch/x86/kernel/acpi/cstate.c
@@ -179,5 +179,5 @@ static void __exit ffh_cstate_exit(void)
 	cpu_cstate_entry = NULL;
 }
 
-arch_initcall(ffh_cstate_init);
+annotated_initcall(arch, ffh_cstate_init, drvid_ffh_cstate, NULL);
 __exitcall(ffh_cstate_exit);
diff --git a/arch/x86/kernel/apm_32.c b/arch/x86/kernel/apm_32.c
index 927ec92..db7c293 100644
--- a/arch/x86/kernel/apm_32.c
+++ b/arch/x86/kernel/apm_32.c
@@ -2416,7 +2416,13 @@ static void __exit apm_exit(void)
 	}
 }
 
-module_init(apm_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_misc,
+	drvid_dmi,
+	0
+};
+
+annotated_module_init(apm_init, drvid_apm, dependencies);
 module_exit(apm_exit);
 
 MODULE_AUTHOR("Stephen Rothwell");
diff --git a/arch/x86/kernel/cpu/mcheck/mce.c b/arch/x86/kernel/cpu/mcheck/mce.c
index df919ff..528d52f3 100644
--- a/arch/x86/kernel/cpu/mcheck/mce.c
+++ b/arch/x86/kernel/cpu/mcheck/mce.c
@@ -2529,7 +2529,13 @@ err_out:
 
 	return err;
 }
-device_initcall_sync(mcheck_init_device);
+
+static const unsigned dependencies0[] __initconst __maybe_unused = {
+	drvid_misc,
+	0
+};
+
+annotated_initcall_sync(device, mcheck_init_device, drvid_mcheck, dependencies0);
 
 /*
  * Old style boot options parsing. Only for compatibility.
@@ -2591,5 +2597,12 @@ static int __init mcheck_debugfs_init(void)
 
 	return 0;
 }
-late_initcall(mcheck_debugfs_init);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_mcheck,
+	drvid_debugfs,
+	0
+};
+
+annotated_initcall(late, mcheck_debugfs_init, drvid_mcheck_debugfs, dependencies);
 #endif
diff --git a/arch/x86/kernel/cpu/mcheck/therm_throt.c b/arch/x86/kernel/cpu/mcheck/therm_throt.c
index 1af51b1..7851594 100644
--- a/arch/x86/kernel/cpu/mcheck/therm_throt.c
+++ b/arch/x86/kernel/cpu/mcheck/therm_throt.c
@@ -325,7 +325,13 @@ static __init int thermal_throttle_init_device(void)
 
 	return 0;
 }
-device_initcall(thermal_throttle_init_device);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_thermal,
+	0
+};
+
+annotated_initcall(device, thermal_throttle_init_device, drvid_thermal_throttle, dependencies);
 
 #endif /* CONFIG_SYSFS */
 
diff --git a/arch/x86/kernel/cpu/microcode/core.c b/arch/x86/kernel/cpu/microcode/core.c
index 6236a54..32a1653 100644
--- a/arch/x86/kernel/cpu/microcode/core.c
+++ b/arch/x86/kernel/cpu/microcode/core.c
@@ -561,7 +561,13 @@ static int __init microcode_init(void)
 	return error;
 
 }
-module_init(microcode_init);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_misc,
+	0
+};
+
+annotated_module_init(microcode_init, drvid_microcode, dependencies);
 
 static void __exit microcode_exit(void)
 {
diff --git a/arch/x86/kernel/hpet.c b/arch/x86/kernel/hpet.c
index 10757d0..187007d 100644
--- a/arch/x86/kernel/hpet.c
+++ b/arch/x86/kernel/hpet.c
@@ -922,7 +922,7 @@ static __init int hpet_late_init(void)
 
 	return 0;
 }
-fs_initcall(hpet_late_init);
+annotated_initcall(fs, hpet_late_init, drvid_hpet_late, NULL);
 
 void hpet_disable(void)
 {
diff --git a/arch/x86/kernel/pci-dma.c b/arch/x86/kernel/pci-dma.c
index 353972c..0502482 100644
--- a/arch/x86/kernel/pci-dma.c
+++ b/arch/x86/kernel/pci-dma.c
@@ -311,8 +311,20 @@ static int __init pci_iommu_init(void)
 
 	return 0;
 }
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_pci_subsys,
+	drvid_pcibios_assign_resources,
+	drvid_pnpacpi, // optional
+	drvid_pci_quirks, // optional
+	//drvid_iommu,
+	drvid_iommu_dev,
+	//drvid_amd_iommu_v2,
+	0
+};
+
 /* Must execute after PCI subsystem */
-rootfs_initcall(pci_iommu_init);
+annotated_initcall(rootfs, pci_iommu_init, drvid_pci_iommu, dependencies);
 
 #ifdef CONFIG_PCI
 /* Many VIA bridges seem to corrupt data for DAC. Disable it here */
diff --git a/arch/x86/kernel/pmc_atom.c b/arch/x86/kernel/pmc_atom.c
index d66a4fe..2902e1d 100644
--- a/arch/x86/kernel/pmc_atom.c
+++ b/arch/x86/kernel/pmc_atom.c
@@ -363,7 +363,12 @@ static int __init pmc_atom_init(void)
 	return -ENODEV;
 }
 
-module_init(pmc_atom_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_debugfs,
+	0
+};
+
+annotated_module_init(pmc_atom_init, drvid_pmc_atom, dependencies);
 /* no module_exit, this driver shouldn't be unloaded */
 
 MODULE_AUTHOR("Aubrey Li <aubrey.li@linux.intel.com>");
diff --git a/arch/x86/kernel/reboot.c b/arch/x86/kernel/reboot.c
index 86db4bc..eceb029 100644
--- a/arch/x86/kernel/reboot.c
+++ b/arch/x86/kernel/reboot.c
@@ -434,7 +434,13 @@ static int __init reboot_init(void)
 
 	return 0;
 }
-core_initcall(reboot_init);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_dmi,
+	0
+};
+
+annotated_initcall(core, reboot_init, drvid_reboot, dependencies);
 
 static inline void kb_wait(void)
 {
diff --git a/arch/x86/kernel/rtc.c b/arch/x86/kernel/rtc.c
index cd96852..b28811c 100644
--- a/arch/x86/kernel/rtc.c
+++ b/arch/x86/kernel/rtc.c
@@ -206,4 +206,12 @@ static __init int add_rtc_cmos(void)
 
 	return 0;
 }
-device_initcall(add_rtc_cmos);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_rtc,
+	drvid_pnp_system,
+	drvid_pnpacpi, // optional
+	0
+};
+
+annotated_initcall(device, add_rtc_cmos, drvid_rtc_cmos_x86, dependencies);
diff --git a/arch/x86/kernel/setup.c b/arch/x86/kernel/setup.c
index 80f874b..5f21f5b 100644
--- a/arch/x86/kernel/setup.c
+++ b/arch/x86/kernel/setup.c
@@ -1288,4 +1288,4 @@ static int __init register_kernel_offset_dumper(void)
 					&kernel_offset_notifier);
 	return 0;
 }
-__initcall(register_kernel_offset_dumper);
+annotated_initcall(device, register_kernel_offset_dumper, drvid_kernel_offset_dumper, NULL);
diff --git a/arch/x86/kernel/tsc.c b/arch/x86/kernel/tsc.c
index 7437b41..7702c7b 100644
--- a/arch/x86/kernel/tsc.c
+++ b/arch/x86/kernel/tsc.c
@@ -950,7 +950,12 @@ static int __init cpufreq_tsc(void)
 	return 0;
 }
 
-core_initcall(cpufreq_tsc);
+static const unsigned dependencies0[] __initconst __maybe_unused = {
+	drvid_cpufreq,
+	0
+};
+
+annotated_initcall(core, cpufreq_tsc, drvid_cpufreq_tsc, dependencies0);
 
 #endif /* CONFIG_CPU_FREQ */
 
@@ -1166,7 +1171,14 @@ static int __init init_tsc_clocksource(void)
  * We use device_initcall here, to ensure we run after the hpet
  * is fully initialized, which may occur at fs_initcall time.
  */
-device_initcall(init_tsc_clocksource);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_clocksource_done_booting,
+	drvid_hpet,
+	0
+};
+
+annotated_initcall(device, init_tsc_clocksource, drvid_tsc_clocksource, dependencies);
 
 void __init tsc_init(void)
 {
diff --git a/arch/x86/pci/i386.c b/arch/x86/pci/i386.c
index 0a9f2ca..1b93058 100644
--- a/arch/x86/pci/i386.c
+++ b/arch/x86/pci/i386.c
@@ -365,11 +365,17 @@ static int __init pcibios_assign_resources(void)
 	return 0;
 }
 
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_pci_subsys,
+	drvid_pnpacpi,
+	0
+};
+
 /**
  * called in fs_initcall (one below subsys_initcall),
  * give a chance for motherboard reserve resources
  */
-fs_initcall(pcibios_assign_resources);
+annotated_initcall(fs, pcibios_assign_resources, drvid_pcibios_assign_resources, dependencies);
 
 void pcibios_resource_survey_bus(struct pci_bus *bus)
 {
diff --git a/arch/x86/pci/init.c b/arch/x86/pci/init.c
index adb62aa..9045ec9 100644
--- a/arch/x86/pci/init.c
+++ b/arch/x86/pci/init.c
@@ -41,4 +41,11 @@ static __init int pci_arch_init(void)
 
 	return 0;
 }
-arch_initcall(pci_arch_init);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_pci_acpi, // optional
+	drvid_pci_driver,
+	0
+};
+
+annotated_initcall(arch, pci_arch_init, drvid_pci_arch, dependencies);
diff --git a/arch/x86/pci/legacy.c b/arch/x86/pci/legacy.c
index 5b662c0..937edaa 100644
--- a/arch/x86/pci/legacy.c
+++ b/arch/x86/pci/legacy.c
@@ -69,4 +69,14 @@ int __init pci_subsys_init(void)
 
 	return 0;
 }
-subsys_initcall(pci_subsys_init);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	//drvid_pci_acpi,
+	drvid_pci_arch,
+	drvid_pci_slot, // optional
+	drvid_acpi, // optional
+	drvid_dmi,
+	0
+};
+
+annotated_initcall(subsys, pci_subsys_init, drvid_pci_subsys, dependencies);
diff --git a/block/bio.c b/block/bio.c
index d6e5ba3..3796515 100644
--- a/block/bio.c
+++ b/block/bio.c
@@ -2108,4 +2108,10 @@ static int __init init_bio(void)
 
 	return 0;
 }
-subsys_initcall(init_bio);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_bdi,
+	0
+};
+
+annotated_initcall(subsys, init_bio, drvid_bio, dependencies);
diff --git a/block/blk-integrity.c b/block/blk-integrity.c
index f548b64..b55e89a 100644
--- a/block/blk-integrity.c
+++ b/block/blk-integrity.c
@@ -378,7 +378,13 @@ static int __init blk_dev_integrity_init(void)
 					     0, SLAB_PANIC, NULL);
 	return 0;
 }
-subsys_initcall(blk_dev_integrity_init);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_blk_mq,
+	0
+};
+
+annotated_initcall(subsys, blk_dev_integrity_init, drvid_blk_dev_integrity, dependencies);
 
 static void blk_integrity_release(struct kobject *kobj)
 {
diff --git a/block/blk-ioc.c b/block/blk-ioc.c
index 1a27f45..cd1e0d2 100644
--- a/block/blk-ioc.c
+++ b/block/blk-ioc.c
@@ -404,4 +404,5 @@ static int __init blk_ioc_init(void)
 			sizeof(struct io_context), 0, SLAB_PANIC, NULL);
 	return 0;
 }
-subsys_initcall(blk_ioc_init);
+
+annotated_initcall(subsys, blk_ioc_init, drvid_blk_ioc, NULL);
diff --git a/block/blk-iopoll.c b/block/blk-iopoll.c
index 0736729..1d93c51 100644
--- a/block/blk-iopoll.c
+++ b/block/blk-iopoll.c
@@ -221,4 +221,4 @@ static __init int blk_iopoll_setup(void)
 	register_hotcpu_notifier(&blk_iopoll_cpu_notifier);
 	return 0;
 }
-subsys_initcall(blk_iopoll_setup);
+annotated_initcall(subsys, blk_iopoll_setup, drvid_blk_iopoll, NULL);
diff --git a/block/blk-mq.c b/block/blk-mq.c
index 176262e..65b54a5 100644
--- a/block/blk-mq.c
+++ b/block/blk-mq.c
@@ -2307,4 +2307,14 @@ static int __init blk_mq_init(void)
 
 	return 0;
 }
-subsys_initcall(blk_mq_init);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_bio,
+	drvid_blk_ioc,
+	drvid_blk_iopoll,
+	drvid_blk_settings,
+	drvid_blk_softirq,
+	0
+};
+
+annotated_initcall(subsys, blk_mq_init, drvid_blk_mq, dependencies);
diff --git a/block/blk-settings.c b/block/blk-settings.c
index e0057d0..547e782 100644
--- a/block/blk-settings.c
+++ b/block/blk-settings.c
@@ -858,4 +858,4 @@ static int __init blk_settings_init(void)
 	blk_max_pfn = max_pfn - 1;
 	return 0;
 }
-subsys_initcall(blk_settings_init);
+annotated_initcall(subsys, blk_settings_init, drvid_blk_settings, NULL);
diff --git a/block/blk-softirq.c b/block/blk-softirq.c
index 53b1737..4947d5b 100644
--- a/block/blk-softirq.c
+++ b/block/blk-softirq.c
@@ -183,4 +183,4 @@ static __init int blk_softirq_init(void)
 	register_hotcpu_notifier(&blk_cpu_notifier);
 	return 0;
 }
-subsys_initcall(blk_softirq_init);
+annotated_initcall(subsys, blk_softirq_init, drvid_blk_softirq, NULL);
diff --git a/block/bsg.c b/block/bsg.c
index d214e92..17dac4a 100644
--- a/block/bsg.c
+++ b/block/bsg.c
@@ -1094,4 +1094,9 @@ MODULE_AUTHOR("Jens Axboe");
 MODULE_DESCRIPTION(BSG_DESCRIPTION);
 MODULE_LICENSE("GPL");
 
-device_initcall(bsg_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_blk_scsi_ioctl,
+	0
+};
+
+annotated_initcall(device, bsg_init, drvid_bsg, dependencies);
diff --git a/block/cfq-iosched.c b/block/cfq-iosched.c
index c62bb2e..f92d45b 100644
--- a/block/cfq-iosched.c
+++ b/block/cfq-iosched.c
@@ -4746,7 +4746,7 @@ static void __exit cfq_exit(void)
 	kmem_cache_destroy(cfq_pool);
 }
 
-module_init(cfq_init);
+annotated_module_init(cfq_init, drvid_cfq_iosched, NULL);
 module_exit(cfq_exit);
 
 MODULE_AUTHOR("Jens Axboe");
diff --git a/block/deadline-iosched.c b/block/deadline-iosched.c
index a753df2..5331a16 100644
--- a/block/deadline-iosched.c
+++ b/block/deadline-iosched.c
@@ -468,7 +468,7 @@ static void __exit deadline_exit(void)
 	elv_unregister(&iosched_deadline);
 }
 
-module_init(deadline_init);
+annotated_module_init(deadline_init, drvid_deadline_iosched, NULL);
 module_exit(deadline_exit);
 
 MODULE_AUTHOR("Jens Axboe");
diff --git a/block/genhd.c b/block/genhd.c
index 59a1395..842017f 100644
--- a/block/genhd.c
+++ b/block/genhd.c
@@ -916,7 +916,12 @@ static int __init genhd_device_init(void)
 	return 0;
 }
 
-subsys_initcall(genhd_device_init);
+static const unsigned dependencies0[] __initconst __maybe_unused = {
+	drvid_bdi,
+	0
+};
+
+annotated_initcall(subsys, genhd_device_init, drvid_genhd, dependencies0);
 
 static ssize_t disk_range_show(struct device *dev,
 			       struct device_attribute *attr, char *buf)
@@ -1213,7 +1218,13 @@ static int __init proc_genhd_init(void)
 	proc_create("partitions", 0, NULL, &proc_partitions_operations);
 	return 0;
 }
-module_init(proc_genhd_init);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_genhd,
+	0
+};
+
+annotated_module_init(proc_genhd_init, drvid_proc_genhd, dependencies);
 #endif /* CONFIG_PROC_FS */
 
 dev_t blk_lookup_devt(const char *name, int partno)
diff --git a/block/noop-iosched.c b/block/noop-iosched.c
index 3de89d4..71cd484 100644
--- a/block/noop-iosched.c
+++ b/block/noop-iosched.c
@@ -115,7 +115,12 @@ static void __exit noop_exit(void)
 	elv_unregister(&elevator_noop);
 }
 
-module_init(noop_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_blk_mq,
+	0
+};
+
+annotated_initcall_sync(fs, noop_init, drvid_noop, NULL);
 module_exit(noop_exit);
 
 
diff --git a/block/scsi_ioctl.c b/block/scsi_ioctl.c
index dda653c..bdaf98c 100644
--- a/block/scsi_ioctl.c
+++ b/block/scsi_ioctl.c
@@ -745,4 +745,10 @@ static int __init blk_scsi_ioctl_init(void)
 	blk_set_cmd_filter_defaults(&blk_default_cmd_filter);
 	return 0;
 }
-fs_initcall(blk_scsi_ioctl_init);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_blk_mq,
+	0
+};
+
+annotated_initcall(fs, blk_scsi_ioctl_init, drvid_blk_scsi_ioctl, dependencies);
diff --git a/crypto/aes_generic.c b/crypto/aes_generic.c
index 3dd1011..133609e 100644
--- a/crypto/aes_generic.c
+++ b/crypto/aes_generic.c
@@ -1469,7 +1469,12 @@ static void __exit aes_fini(void)
 	crypto_unregister_alg(&aes_alg);
 }
 
-module_init(aes_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_cryptomgr,
+	0
+};
+
+annotated_module_init(aes_init, drvid_aes_generic, dependencies);
 module_exit(aes_fini);
 
 MODULE_DESCRIPTION("Rijndael (AES) Cipher Algorithm");
diff --git a/crypto/algapi.c b/crypto/algapi.c
index 3c079b7..0e204a2 100644
--- a/crypto/algapi.c
+++ b/crypto/algapi.c
@@ -996,7 +996,7 @@ static void __exit crypto_algapi_exit(void)
 	crypto_exit_proc();
 }
 
-module_init(crypto_algapi_init);
+annotated_module_init(crypto_algapi_init, drvid_crypto_algapi, NULL);
 module_exit(crypto_algapi_exit);
 
 MODULE_LICENSE("GPL");
diff --git a/crypto/algboss.c b/crypto/algboss.c
index 76fc0b2..d250d6f 100644
--- a/crypto/algboss.c
+++ b/crypto/algboss.c
@@ -301,7 +301,7 @@ static void __exit cryptomgr_exit(void)
 	BUG_ON(err);
 }
 
-subsys_initcall(cryptomgr_init);
+annotated_initcall(subsys, cryptomgr_init, drvid_cryptomgr, NULL);
 module_exit(cryptomgr_exit);
 
 MODULE_LICENSE("GPL");
diff --git a/crypto/asymmetric_keys/asymmetric_type.c b/crypto/asymmetric_keys/asymmetric_type.c
index b0e4ed2..2c486b0 100644
--- a/crypto/asymmetric_keys/asymmetric_type.c
+++ b/crypto/asymmetric_keys/asymmetric_type.c
@@ -410,5 +410,5 @@ static void __exit asymmetric_key_cleanup(void)
 	unregister_key_type(&key_type_asymmetric);
 }
 
-module_init(asymmetric_key_init);
+annotated_module_init(asymmetric_key_init, drvid_asymmetric_key, NULL);
 module_exit(asymmetric_key_cleanup);
diff --git a/crypto/asymmetric_keys/x509_public_key.c b/crypto/asymmetric_keys/x509_public_key.c
index 24f17e6..48db7b9 100644
--- a/crypto/asymmetric_keys/x509_public_key.c
+++ b/crypto/asymmetric_keys/x509_public_key.c
@@ -370,7 +370,12 @@ static void __exit x509_key_exit(void)
 	unregister_asymmetric_key_parser(&x509_key_parser);
 }
 
-module_init(x509_key_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_asymmetric_key,
+	0
+};
+
+annotated_module_init(x509_key_init, drvid_x509, dependencies);
 module_exit(x509_key_exit);
 
 MODULE_DESCRIPTION("X.509 certificate parser");
diff --git a/crypto/authenc.c b/crypto/authenc.c
index 3e85229..4ea9d69 100644
--- a/crypto/authenc.c
+++ b/crypto/authenc.c
@@ -717,7 +717,7 @@ static void __exit crypto_authenc_module_exit(void)
 	crypto_unregister_template(&crypto_authenc_tmpl);
 }
 
-module_init(crypto_authenc_module_init);
+annotated_module_init(crypto_authenc_module_init, drvid_authenc, NULL);
 module_exit(crypto_authenc_module_exit);
 
 MODULE_LICENSE("GPL");
diff --git a/crypto/authencesn.c b/crypto/authencesn.c
index b8efe36..b14ce83 100644
--- a/crypto/authencesn.c
+++ b/crypto/authencesn.c
@@ -789,7 +789,7 @@ static void __exit crypto_authenc_esn_module_exit(void)
 	crypto_unregister_template(&crypto_authenc_esn_tmpl);
 }
 
-module_init(crypto_authenc_esn_module_init);
+annotated_module_init(crypto_authenc_esn_module_init, drvid_authencesn, NULL);
 module_exit(crypto_authenc_esn_module_exit);
 
 MODULE_LICENSE("GPL");
diff --git a/crypto/cbc.c b/crypto/cbc.c
index 780ee27..6400d2e 100644
--- a/crypto/cbc.c
+++ b/crypto/cbc.c
@@ -284,7 +284,12 @@ static void __exit crypto_cbc_module_exit(void)
 	crypto_unregister_template(&crypto_cbc_tmpl);
 }
 
-module_init(crypto_cbc_module_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_cryptomgr,
+	0
+};
+
+annotated_module_init(crypto_cbc_module_init, drvid_cbc, dependencies);
 module_exit(crypto_cbc_module_exit);
 
 MODULE_LICENSE("GPL");
diff --git a/crypto/chainiv.c b/crypto/chainiv.c
index b434001..74e63922 100644
--- a/crypto/chainiv.c
+++ b/crypto/chainiv.c
@@ -309,7 +309,12 @@ static void chainiv_module_exit(void)
 	crypto_unregister_template(&chainiv_tmpl);
 }
 
-module_init(chainiv_module_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_crypto_wq,
+	0
+};
+
+annotated_module_init(chainiv_module_init, drvid_chainiv, dependencies);
 module_exit(chainiv_module_exit);
 
 MODULE_LICENSE("GPL");
diff --git a/crypto/crc32c_generic.c b/crypto/crc32c_generic.c
index 06f1b60..e5474da 100644
--- a/crypto/crc32c_generic.c
+++ b/crypto/crc32c_generic.c
@@ -164,7 +164,12 @@ static void __exit crc32c_mod_fini(void)
 	crypto_unregister_shash(&alg);
 }
 
-module_init(crc32c_mod_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_cryptomgr,
+	0
+};
+
+annotated_module_init(crc32c_mod_init, drvid_crc32c, dependencies);
 module_exit(crc32c_mod_fini);
 
 MODULE_AUTHOR("Clay Haapala <chaapala@cisco.com>");
diff --git a/crypto/crct10dif_generic.c b/crypto/crct10dif_generic.c
index c1229614..0f8b5be 100644
--- a/crypto/crct10dif_generic.c
+++ b/crypto/crct10dif_generic.c
@@ -118,7 +118,12 @@ static void __exit crct10dif_mod_fini(void)
 	crypto_unregister_shash(&alg);
 }
 
-module_init(crct10dif_mod_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_cryptomgr,
+	0
+};
+
+annotated_module_init(crct10dif_mod_init, drvid_crct10dif, dependencies);
 module_exit(crct10dif_mod_fini);
 
 MODULE_AUTHOR("Tim Chen <tim.c.chen@linux.intel.com>");
diff --git a/crypto/cryptd.c b/crypto/cryptd.c
index 22ba81f..da7969a 100644
--- a/crypto/cryptd.c
+++ b/crypto/cryptd.c
@@ -1010,7 +1010,12 @@ static void __exit cryptd_exit(void)
 	crypto_unregister_template(&cryptd_tmpl);
 }
 
-subsys_initcall(cryptd_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_crypto_wq,
+	0
+};
+
+annotated_initcall(subsys, cryptd_init, drvid_cryptd, dependencies);
 module_exit(cryptd_exit);
 
 MODULE_LICENSE("GPL");
diff --git a/crypto/crypto_user.c b/crypto/crypto_user.c
index 08ea286..6ffc6d4 100644
--- a/crypto/crypto_user.c
+++ b/crypto/crypto_user.c
@@ -580,7 +580,12 @@ static void __exit crypto_user_exit(void)
 	netlink_kernel_release(crypto_nlsk);
 }
 
-module_init(crypto_user_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_netlink,
+	0
+};
+
+annotated_module_init(crypto_user_init, drvid_crypto_user, dependencies);
 module_exit(crypto_user_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Steffen Klassert <steffen.klassert@secunet.com>");
diff --git a/crypto/crypto_wq.c b/crypto/crypto_wq.c
index 2f1b8d1..59738f0 100644
--- a/crypto/crypto_wq.c
+++ b/crypto/crypto_wq.c
@@ -33,7 +33,12 @@ static void __exit crypto_wq_exit(void)
 	destroy_workqueue(kcrypto_wq);
 }
 
-subsys_initcall(crypto_wq_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_wq_sysfs,
+	0
+};
+
+annotated_initcall(subsys, crypto_wq_init, drvid_crypto_wq, dependencies);
 module_exit(crypto_wq_exit);
 
 MODULE_LICENSE("GPL");
diff --git a/crypto/deflate.c b/crypto/deflate.c
index 95d8d37..cca5124 100644
--- a/crypto/deflate.c
+++ b/crypto/deflate.c
@@ -216,7 +216,12 @@ static void __exit deflate_mod_fini(void)
 	crypto_unregister_alg(&alg);
 }
 
-module_init(deflate_mod_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_cryptomgr,
+	0
+};
+
+annotated_module_init(deflate_mod_init, drvid_deflate, dependencies);
 module_exit(deflate_mod_fini);
 
 MODULE_LICENSE("GPL");
diff --git a/crypto/des_generic.c b/crypto/des_generic.c
index a717205..73ba888 100644
--- a/crypto/des_generic.c
+++ b/crypto/des_generic.c
@@ -993,7 +993,12 @@ static void __exit des_generic_mod_fini(void)
 	crypto_unregister_algs(des_algs, ARRAY_SIZE(des_algs));
 }
 
-module_init(des_generic_mod_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_cryptomgr,
+	0
+};
+
+annotated_module_init(des_generic_mod_init, drvid_des_generic, dependencies);
 module_exit(des_generic_mod_fini);
 
 MODULE_LICENSE("GPL");
diff --git a/crypto/ecb.c b/crypto/ecb.c
index 12011af..816418a 100644
--- a/crypto/ecb.c
+++ b/crypto/ecb.c
@@ -180,7 +180,7 @@ static void __exit crypto_ecb_module_exit(void)
 	crypto_unregister_template(&crypto_ecb_tmpl);
 }
 
-module_init(crypto_ecb_module_init);
+annotated_module_init(crypto_ecb_module_init, drvid_ecb, NULL);
 module_exit(crypto_ecb_module_exit);
 
 MODULE_LICENSE("GPL");
diff --git a/crypto/eseqiv.c b/crypto/eseqiv.c
index 16dda72..a84c0e8 100644
--- a/crypto/eseqiv.c
+++ b/crypto/eseqiv.c
@@ -234,7 +234,7 @@ static void __exit eseqiv_module_exit(void)
 	crypto_unregister_template(&eseqiv_tmpl);
 }
 
-module_init(eseqiv_module_init);
+annotated_module_init(eseqiv_module_init, drvid_eseqiv, NULL);
 module_exit(eseqiv_module_exit);
 
 MODULE_LICENSE("GPL");
diff --git a/crypto/hmac.c b/crypto/hmac.c
index 72e38c0..d41d507 100644
--- a/crypto/hmac.c
+++ b/crypto/hmac.c
@@ -263,7 +263,7 @@ static void __exit hmac_module_exit(void)
 	crypto_unregister_template(&hmac_tmpl);
 }
 
-module_init(hmac_module_init);
+annotated_initcall_sync(fs, hmac_module_init, drvid_hmac, NULL);
 module_exit(hmac_module_exit);
 
 MODULE_LICENSE("GPL");
diff --git a/crypto/lzo.c b/crypto/lzo.c
index 4b3e925..f19fdc3 100644
--- a/crypto/lzo.c
+++ b/crypto/lzo.c
@@ -102,7 +102,12 @@ static void __exit lzo_mod_fini(void)
 	crypto_unregister_alg(&alg);
 }
 
-module_init(lzo_mod_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_cryptomgr,
+	0
+};
+
+annotated_module_init(lzo_mod_init, drvid_lzo, dependencies);
 module_exit(lzo_mod_fini);
 
 MODULE_LICENSE("GPL");
diff --git a/crypto/mcryptd.c b/crypto/mcryptd.c
index fe5b495a..f90fa28 100644
--- a/crypto/mcryptd.c
+++ b/crypto/mcryptd.c
@@ -719,7 +719,12 @@ static void __exit mcryptd_exit(void)
 	free_percpu(mcryptd_flist);
 }
 
-subsys_initcall(mcryptd_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_crypto_wq,
+	0
+};
+
+annotated_initcall(subsys, mcryptd_init, drvid_mcryptd, dependencies);
 module_exit(mcryptd_exit);
 
 MODULE_LICENSE("GPL");
diff --git a/crypto/md5.c b/crypto/md5.c
index 33d17e9..2c4583d 100644
--- a/crypto/md5.c
+++ b/crypto/md5.c
@@ -163,7 +163,12 @@ static void __exit md5_mod_fini(void)
 	crypto_unregister_shash(&alg);
 }
 
-module_init(md5_mod_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_cryptomgr,
+	0
+};
+
+annotated_module_init(md5_mod_init, drvid_md5, dependencies);
 module_exit(md5_mod_fini);
 
 MODULE_LICENSE("GPL");
diff --git a/crypto/michael_mic.c b/crypto/michael_mic.c
index 46195e0..94a6a86 100644
--- a/crypto/michael_mic.c
+++ b/crypto/michael_mic.c
@@ -177,8 +177,12 @@ static void __exit michael_mic_exit(void)
 	crypto_unregister_shash(&alg);
 }
 
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_cryptomgr,
+	0
+};
 
-module_init(michael_mic_init);
+annotated_module_init(michael_mic_init, drvid_michael_mic, dependencies);
 module_exit(michael_mic_exit);
 
 MODULE_LICENSE("GPL v2");
diff --git a/crypto/sha1_generic.c b/crypto/sha1_generic.c
index 39e3acc..47b19f9 100644
--- a/crypto/sha1_generic.c
+++ b/crypto/sha1_generic.c
@@ -85,7 +85,12 @@ static void __exit sha1_generic_mod_fini(void)
 	crypto_unregister_shash(&alg);
 }
 
-module_init(sha1_generic_mod_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_cryptomgr,
+	0
+};
+
+annotated_initcall_sync(fs, sha1_generic_mod_init, drvid_sha1_generic, dependencies);
 module_exit(sha1_generic_mod_fini);
 
 MODULE_LICENSE("GPL");
diff --git a/crypto/sha256_generic.c b/crypto/sha256_generic.c
index 7843116..0eda295 100644
--- a/crypto/sha256_generic.c
+++ b/crypto/sha256_generic.c
@@ -285,7 +285,12 @@ static void __exit sha256_generic_mod_fini(void)
 	crypto_unregister_shashes(sha256_algs, ARRAY_SIZE(sha256_algs));
 }
 
-module_init(sha256_generic_mod_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_cryptomgr,
+	0
+};
+
+annotated_module_init(sha256_generic_mod_init, drvid_sha256_generic, dependencies);
 module_exit(sha256_generic_mod_fini);
 
 MODULE_LICENSE("GPL");
diff --git a/crypto/sha512_generic.c b/crypto/sha512_generic.c
index eba965d..491a903 100644
--- a/crypto/sha512_generic.c
+++ b/crypto/sha512_generic.c
@@ -201,7 +201,12 @@ static void __exit sha512_generic_mod_fini(void)
 	crypto_unregister_shashes(sha512_algs, ARRAY_SIZE(sha512_algs));
 }
 
-module_init(sha512_generic_mod_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_cryptomgr,
+	0
+};
+
+annotated_module_init(sha512_generic_mod_init, drvid_sha512_generic, dependencies);
 module_exit(sha512_generic_mod_fini);
 
 MODULE_LICENSE("GPL");
diff --git a/crypto/xor.c b/crypto/xor.c
index 35d6b3a..54ebe35 100644
--- a/crypto/xor.c
+++ b/crypto/xor.c
@@ -165,5 +165,5 @@ static __exit void xor_exit(void) { }
 MODULE_LICENSE("GPL");
 
 /* when built-in xor.o must initialize before drivers/md/md.o */
-core_initcall(calibrate_xor_blocks);
+annotated_initcall(core, calibrate_xor_blocks, drvid_xor, NULL);
 module_exit(xor_exit);
diff --git a/drivers/acpi/ac.c b/drivers/acpi/ac.c
index 9b5354a..64d2352 100644
--- a/drivers/acpi/ac.c
+++ b/drivers/acpi/ac.c
@@ -458,5 +458,14 @@ static void __exit acpi_ac_exit(void)
 	acpi_unlock_ac_dir(acpi_ac_dir);
 #endif
 }
-module_init(acpi_ac_init);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_acpi,
+	drvid_pm,
+	drvid_power_supply_class,
+	drvid_dmi,
+	0
+};
+
+annotated_module_init(acpi_ac_init, drvid_acpi_ac, dependencies);
 module_exit(acpi_ac_exit);
diff --git a/drivers/acpi/battery.c b/drivers/acpi/battery.c
index b3628cc..57ddb97 100644
--- a/drivers/acpi/battery.c
+++ b/drivers/acpi/battery.c
@@ -1327,5 +1327,11 @@ static void __exit acpi_battery_exit(void)
 #endif
 }
 
-module_init(acpi_battery_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_acpi,
+	drvid_pm,
+	0
+};
+
+annotated_module_init(acpi_battery_init, drvid_acpi_battery, dependencies);
 module_exit(acpi_battery_exit);
diff --git a/drivers/acpi/bus.c b/drivers/acpi/bus.c
index 513e7230e..acd4d2e 100644
--- a/drivers/acpi/bus.c
+++ b/drivers/acpi/bus.c
@@ -703,4 +703,12 @@ static int __init acpi_init(void)
 	return 0;
 }
 
-subsys_initcall(acpi_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_pci_slot, // optional
+	drvid_pci_arch, // x86
+	drvid_debugfs,
+	0
+};
+
+annotated_initcall(subsys, acpi_init, drvid_acpi, dependencies);
+//subsys_initcall(acpi_init);
diff --git a/drivers/acpi/button.c b/drivers/acpi/button.c
index 6d5d183..0b8372f 100644
--- a/drivers/acpi/button.c
+++ b/drivers/acpi/button.c
@@ -450,4 +450,10 @@ static int acpi_button_remove(struct acpi_device *device)
 	return 0;
 }
 
-module_acpi_driver(acpi_button_driver);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_acpi,
+	drvid_input,
+	0
+};
+
+annotated_module_acpi_driver(acpi_button_driver, drvid_acpi_button, dependencies);
diff --git a/drivers/acpi/event.c b/drivers/acpi/event.c
index e24ea4e..84e3ab1 100644
--- a/drivers/acpi/event.c
+++ b/drivers/acpi/event.c
@@ -180,4 +180,12 @@ static int __init acpi_event_init(void)
 	return 0;
 }
 
-fs_initcall(acpi_event_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_acpi,
+	drvid_acpi_wmi,
+	drvid_pci_subsys,
+	drvid_netlink,
+	0
+};
+
+annotated_initcall(fs, acpi_event_init, drvid_acpi_event, dependencies);
diff --git a/drivers/acpi/fan.c b/drivers/acpi/fan.c
index bea0bba..e2e7a25 100644
--- a/drivers/acpi/fan.c
+++ b/drivers/acpi/fan.c
@@ -418,4 +418,11 @@ static int acpi_fan_resume(struct device *dev)
 }
 #endif
 
-module_platform_driver(acpi_fan_driver);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_acpi,
+	drvid_pm,
+	drvid_thermal,
+	0
+};
+
+annotated_module_platform_driver(acpi_fan_driver, drvid_acpi_fan, dependencies);
diff --git a/drivers/acpi/osl.c b/drivers/acpi/osl.c
index 3b8963f..3f7d526 100644
--- a/drivers/acpi/osl.c
+++ b/drivers/acpi/osl.c
@@ -214,7 +214,12 @@ static int __init acpi_reserve_resources(void)
 
 	return 0;
 }
-fs_initcall_sync(acpi_reserve_resources);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_acpi_event,
+	0
+};
+
+annotated_initcall_sync(fs, acpi_reserve_resources, drvid_acpi_reserve_resources, dependencies);
 
 void acpi_os_printf(const char *fmt, ...)
 {
diff --git a/drivers/acpi/processor_driver.c b/drivers/acpi/processor_driver.c
index d9f7158..ec960ab 100644
--- a/drivers/acpi/processor_driver.c
+++ b/drivers/acpi/processor_driver.c
@@ -301,7 +301,13 @@ static void __exit acpi_processor_driver_exit(void)
 	driver_unregister(&acpi_processor_driver);
 }
 
-module_init(acpi_processor_driver_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_acpi,
+	drvid_cpufreq,
+	0
+};
+
+annotated_module_init(acpi_processor_driver_init, drvid_acpi_processor_driver, dependencies);
 module_exit(acpi_processor_driver_exit);
 
 MODULE_ALIAS("processor");
diff --git a/drivers/acpi/sbs.c b/drivers/acpi/sbs.c
index 01504c8..584c97c 100644
--- a/drivers/acpi/sbs.c
+++ b/drivers/acpi/sbs.c
@@ -769,5 +769,13 @@ static void __exit acpi_sbs_exit(void)
 	return;
 }
 
-module_init(acpi_sbs_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_acpi,
+	drvid_dmi,
+	drvid_pm,
+	drvid_power_supply_class,
+	0
+};
+
+annotated_module_init(acpi_sbs_init, drvid_acpi_sbs, dependencies);
 module_exit(acpi_sbs_exit);
diff --git a/drivers/acpi/sbshc.c b/drivers/acpi/sbshc.c
index bf034f8..a70278c 100644
--- a/drivers/acpi/sbshc.c
+++ b/drivers/acpi/sbshc.c
@@ -331,7 +331,13 @@ static int acpi_smbus_hc_remove(struct acpi_device *device)
 	return 0;
 }
 
-module_acpi_driver(acpi_smb_hc_driver);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_acpi,
+	drvid_dmi,
+	0
+};
+
+annotated_module_acpi_driver(acpi_smb_hc_driver, drvid_acpi_smb_hc, dependencies);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Alexey Starikovskiy");
diff --git a/drivers/acpi/thermal.c b/drivers/acpi/thermal.c
index 6d4e44e..658f290 100644
--- a/drivers/acpi/thermal.c
+++ b/drivers/acpi/thermal.c
@@ -1284,5 +1284,13 @@ static void __exit acpi_thermal_exit(void)
 	return;
 }
 
-module_init(acpi_thermal_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_acpi,
+	drvid_dmi,
+	drvid_pm,
+	drvid_thermal,
+	0
+};
+
+annotated_module_init(acpi_thermal_init, drvid_acpi_thermal, dependencies);
 module_exit(acpi_thermal_exit);
diff --git a/drivers/ata/ahci_imx.c b/drivers/ata/ahci_imx.c
index 3f3a7db..a93f864 100644
--- a/drivers/ata/ahci_imx.c
+++ b/drivers/ata/ahci_imx.c
@@ -686,7 +686,13 @@ static struct platform_driver imx_ahci_driver = {
 		.pm = &ahci_imx_pm_ops,
 	},
 };
-module_platform_driver(imx_ahci_driver);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_ahci,
+	0
+};
+
+annotated_module_platform_driver(imx_ahci_driver, drvid_ahci_imx, dependencies);
 
 MODULE_DESCRIPTION("Freescale i.MX AHCI SATA platform driver");
 MODULE_AUTHOR("Richard Zhu <Hong-Xing.Zhu@freescale.com>");
diff --git a/drivers/ata/ahci_platform.c b/drivers/ata/ahci_platform.c
index 1befb11..b790d7b 100644
--- a/drivers/ata/ahci_platform.c
+++ b/drivers/ata/ahci_platform.c
@@ -97,7 +97,13 @@ static struct platform_driver ahci_driver = {
 		.pm = &ahci_pm_ops,
 	},
 };
-module_platform_driver(ahci_driver);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_ata,
+	0
+};
+
+annotated_module_platform_driver(ahci_driver, drvid_ahci, dependencies);
 
 MODULE_DESCRIPTION("AHCI SATA platform driver");
 MODULE_AUTHOR("Anton Vorontsov <avorontsov@ru.mvista.com>");
diff --git a/drivers/ata/ata_generic.c b/drivers/ata/ata_generic.c
index 9ff545c..ba0d693 100644
--- a/drivers/ata/ata_generic.c
+++ b/drivers/ata/ata_generic.c
@@ -247,7 +247,16 @@ static struct pci_driver ata_generic_pci_driver = {
 #endif
 };
 
-module_pci_driver(ata_generic_pci_driver);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_ata,
+	drvid_pci_subsys,
+	drvid_pcibios_assign_resources,
+	drvid_pnpacpi, // optional
+	drvid_pci_quirks, // optional
+	0
+};
+
+annotated_module_pci_driver(ata_generic_pci_driver, drvid_ata_generic, dependencies);
 
 MODULE_AUTHOR("Alan Cox");
 MODULE_DESCRIPTION("low-level driver for generic ATA");
diff --git a/drivers/ata/ata_piix.c b/drivers/ata/ata_piix.c
index ffbe625..132de06 100644
--- a/drivers/ata/ata_piix.c
+++ b/drivers/ata/ata_piix.c
@@ -1801,5 +1801,14 @@ static void __exit piix_exit(void)
 	pci_unregister_driver(&piix_pci_driver);
 }
 
-module_init(piix_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_ata,
+	drvid_pci_subsys,
+	drvid_pcibios_assign_resources,
+	drvid_pnpacpi, // optional
+	drvid_pci_quirks, // optional
+	0
+};
+
+annotated_module_init(piix_init, drvid_ata_piix, dependencies);
 module_exit(piix_exit);
diff --git a/drivers/ata/libata-core.c b/drivers/ata/libata-core.c
index 790e0de..8107fd9 100644
--- a/drivers/ata/libata-core.c
+++ b/drivers/ata/libata-core.c
@@ -6665,7 +6665,12 @@ static void __exit ata_exit(void)
 	kfree(ata_force_tbl);
 }
 
-subsys_initcall(ata_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_scsi_mod,
+	0
+};
+
+annotated_initcall(subsys, ata_init, drvid_ata, dependencies);
 module_exit(ata_exit);
 
 static DEFINE_RATELIMIT_STATE(ratelimit, HZ / 5, 1);
diff --git a/drivers/ata/pata_acpi.c b/drivers/ata/pata_acpi.c
index b70fce2..77c9691 100644
--- a/drivers/ata/pata_acpi.c
+++ b/drivers/ata/pata_acpi.c
@@ -271,7 +271,16 @@ static struct pci_driver pacpi_pci_driver = {
 #endif
 };
 
-module_pci_driver(pacpi_pci_driver);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_ata,
+	drvid_pci_subsys,
+	drvid_pcibios_assign_resources,
+	drvid_pnpacpi, // optional
+	drvid_pci_quirks, // optional
+	0
+};
+
+annotated_module_pci_driver(pacpi_pci_driver, drvid_pata_acpi, dependencies);
 
 MODULE_AUTHOR("Alan Cox");
 MODULE_DESCRIPTION("SCSI low-level driver for ATA in ACPI mode");
diff --git a/drivers/ata/pata_amd.c b/drivers/ata/pata_amd.c
index 8d4d959..a95b886 100644
--- a/drivers/ata/pata_amd.c
+++ b/drivers/ata/pata_amd.c
@@ -631,7 +631,16 @@ static struct pci_driver amd_pci_driver = {
 #endif
 };
 
-module_pci_driver(amd_pci_driver);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_ata,
+	drvid_pci_subsys,
+	drvid_pcibios_assign_resources,
+	drvid_pnpacpi, // optional
+	drvid_pci_quirks, // optional
+	0
+};
+
+annotated_module_pci_driver(amd_pci_driver, drvid_pata_amd, dependencies);
 
 MODULE_AUTHOR("Alan Cox");
 MODULE_DESCRIPTION("low-level driver for AMD and Nvidia PATA IDE");
diff --git a/drivers/ata/pata_jmicron.c b/drivers/ata/pata_jmicron.c
index 4d1a5d2..d9469e4 100644
--- a/drivers/ata/pata_jmicron.c
+++ b/drivers/ata/pata_jmicron.c
@@ -163,7 +163,16 @@ static struct pci_driver jmicron_pci_driver = {
 #endif
 };
 
-module_pci_driver(jmicron_pci_driver);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_ata,
+	drvid_pci_subsys,
+	drvid_pcibios_assign_resources,
+	drvid_pnpacpi, // optional
+	drvid_pci_quirks, // optional
+	0
+};
+
+annotated_module_pci_driver(jmicron_pci_driver, drvid_pata_jmicron, dependencies);
 
 MODULE_AUTHOR("Alan Cox");
 MODULE_DESCRIPTION("SCSI low-level driver for Jmicron PATA ports");
diff --git a/drivers/ata/pata_mpiix.c b/drivers/ata/pata_mpiix.c
index 202b4d6..7fe0b0a 100644
--- a/drivers/ata/pata_mpiix.c
+++ b/drivers/ata/pata_mpiix.c
@@ -229,7 +229,16 @@ static struct pci_driver mpiix_pci_driver = {
 #endif
 };
 
-module_pci_driver(mpiix_pci_driver);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_ata,
+	drvid_pci_subsys,
+	drvid_pcibios_assign_resources,
+	drvid_pnpacpi, // optional
+	drvid_pci_quirks, // optional
+	0
+};
+
+annotated_module_pci_driver(mpiix_pci_driver, drvid_pata_mpiix, dependencies);
 
 MODULE_AUTHOR("Alan Cox");
 MODULE_DESCRIPTION("low-level driver for Intel MPIIX");
diff --git a/drivers/ata/pata_oldpiix.c b/drivers/ata/pata_oldpiix.c
index b9bf78b..b07e680 100644
--- a/drivers/ata/pata_oldpiix.c
+++ b/drivers/ata/pata_oldpiix.c
@@ -264,7 +264,16 @@ static struct pci_driver oldpiix_pci_driver = {
 #endif
 };
 
-module_pci_driver(oldpiix_pci_driver);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_ata,
+	drvid_pci_subsys,
+	drvid_pcibios_assign_resources,
+	drvid_pnpacpi, // optional
+	drvid_pci_quirks, // optional
+	0
+};
+
+annotated_module_pci_driver(oldpiix_pci_driver, drvid_pata_oldpiix, dependencies);
 
 MODULE_AUTHOR("Alan Cox");
 MODULE_DESCRIPTION("SCSI low-level driver for early PIIX series controllers");
diff --git a/drivers/ata/pata_sch.c b/drivers/ata/pata_sch.c
index b920c34..99b4d0c 100644
--- a/drivers/ata/pata_sch.c
+++ b/drivers/ata/pata_sch.c
@@ -177,4 +177,13 @@ static int sch_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
 	return ata_pci_bmdma_init_one(pdev, ppi, &sch_sht, NULL, 0);
 }
 
-module_pci_driver(sch_pci_driver);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_ata,
+	drvid_pci_subsys,
+	drvid_pcibios_assign_resources,
+	drvid_pnpacpi, // optional
+	drvid_pci_quirks, // optional
+	0
+};
+
+annotated_module_pci_driver(sch_pci_driver, drvid_pata_sch, dependencies);
diff --git a/drivers/ata/pata_sis.c b/drivers/ata/pata_sis.c
index 626f989..f75c5be 100644
--- a/drivers/ata/pata_sis.c
+++ b/drivers/ata/pata_sis.c
@@ -905,7 +905,16 @@ static struct pci_driver sis_pci_driver = {
 #endif
 };
 
-module_pci_driver(sis_pci_driver);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_ata,
+	drvid_pci_subsys,
+	drvid_pcibios_assign_resources,
+	drvid_pnpacpi, // optional
+	drvid_pci_quirks, // optional
+	0
+};
+
+annotated_module_pci_driver(sis_pci_driver, drvid_pata_sis, dependencies);
 
 MODULE_AUTHOR("Alan Cox");
 MODULE_DESCRIPTION("SCSI low-level driver for SiS ATA");
diff --git a/drivers/base/firmware_class.c b/drivers/base/firmware_class.c
index 894bda1..ce00543 100644
--- a/drivers/base/firmware_class.c
+++ b/drivers/base/firmware_class.c
@@ -1723,5 +1723,10 @@ static void __exit firmware_class_exit(void)
 #endif
 }
 
-fs_initcall(firmware_class_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_pm,
+	0
+};
+
+annotated_initcall(fs, firmware_class_init, drvid_firmware_class, dependencies);
 module_exit(firmware_class_exit);
diff --git a/drivers/block/loop.c b/drivers/block/loop.c
index f7a4c9d..0d6cc1a 100644
--- a/drivers/block/loop.c
+++ b/drivers/block/loop.c
@@ -1877,7 +1877,12 @@ static void __exit loop_exit(void)
 	misc_deregister(&loop_misc);
 }
 
-module_init(loop_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_genhd,
+	0
+};
+
+annotated_module_init(loop_init, drvid_loop, dependencies);
 module_exit(loop_exit);
 
 #ifndef MODULE
diff --git a/drivers/bus/imx-weim.c b/drivers/bus/imx-weim.c
index e98d15e..5047477 100644
--- a/drivers/bus/imx-weim.c
+++ b/drivers/bus/imx-weim.c
@@ -210,7 +210,7 @@ static struct platform_driver weim_driver = {
 		.of_match_table	= weim_id_table,
 	},
 };
-module_platform_driver_probe(weim_driver, weim_probe);
+annotated_module_platform_driver_probe(weim_driver, weim_probe, drvid_imx_weim, NULL);
 
 MODULE_AUTHOR("Freescale Semiconductor Inc.");
 MODULE_DESCRIPTION("i.MX EIM Controller Driver");
diff --git a/drivers/bus/omap-ocp2scp.c b/drivers/bus/omap-ocp2scp.c
index 9f18569..9e17e9d 100644
--- a/drivers/bus/omap-ocp2scp.c
+++ b/drivers/bus/omap-ocp2scp.c
@@ -115,7 +115,7 @@ static struct platform_driver omap_ocp2scp_driver = {
 	},
 };
 
-module_platform_driver(omap_ocp2scp_driver);
+annotated_module_platform_driver(omap_ocp2scp_driver, drvid_omap_ocp2scp, NULL);
 
 MODULE_ALIAS("platform: omap-ocp2scp");
 MODULE_AUTHOR("Texas Instruments Inc.");
diff --git a/drivers/bus/omap_l3_noc.c b/drivers/bus/omap_l3_noc.c
index 5012e3a..88f60a6 100644
--- a/drivers/bus/omap_l3_noc.c
+++ b/drivers/bus/omap_l3_noc.c
@@ -368,7 +368,7 @@ static int __init omap_l3_init(void)
 {
 	return platform_driver_register(&omap_l3_driver);
 }
-postcore_initcall_sync(omap_l3_init);
+annotated_initcall_drv_sync(postcore, omap_l3_init, drvid_omap_l3_noc, NULL, omap_l3_driver.driver);
 
 static void __exit omap_l3_exit(void)
 {
diff --git a/drivers/bus/omap_l3_smx.c b/drivers/bus/omap_l3_smx.c
index 360a5c0..87c4426 100644
--- a/drivers/bus/omap_l3_smx.c
+++ b/drivers/bus/omap_l3_smx.c
@@ -302,7 +302,7 @@ static int __init omap3_l3_init(void)
 {
 	return platform_driver_register(&omap3_l3_driver);
 }
-postcore_initcall_sync(omap3_l3_init);
+annotated_initcall_drv_sync(postcore, omap3_l3_init, drvid_omap_l3_smx, NULL, omap3_l3_driver.driver);
 
 static void __exit omap3_l3_exit(void)
 {
diff --git a/drivers/char/agp/backend.c b/drivers/char/agp/backend.c
index 38ffb28..dc019f4 100644
--- a/drivers/char/agp/backend.c
+++ b/drivers/char/agp/backend.c
@@ -361,6 +361,10 @@ MODULE_DESCRIPTION("AGP GART driver");
 MODULE_LICENSE("GPL and additional rights");
 MODULE_ALIAS_MISCDEV(AGPGART_MINOR);
 
-module_init(agp_init);
-module_exit(agp_exit);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_misc,
+	0
+};
 
+annotated_module_init(agp_init, drvid_agpgart, dependencies);
+module_exit(agp_exit);
diff --git a/drivers/char/genrtc.c b/drivers/char/genrtc.c
index 4f94375..ba52f03 100644
--- a/drivers/char/genrtc.c
+++ b/drivers/char/genrtc.c
@@ -530,8 +530,12 @@ static void __exit rtc_generic_exit(void)
 	misc_deregister(&rtc_gen_dev);
 }
 
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_misc,
+	0
+};
 
-module_init(rtc_generic_init);
+annotated_module_init(rtc_generic_init, drvid_genrtc, dependencies);
 module_exit(rtc_generic_exit);
 
 MODULE_AUTHOR("Richard Zidlicky");
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c
index 5c0baa9..0be167f 100644
--- a/drivers/char/hpet.c
+++ b/drivers/char/hpet.c
@@ -1098,7 +1098,15 @@ static void __exit hpet_exit(void)
 	return;
 }
 
-module_init(hpet_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_hpet_late,
+	drvid_misc,
+	drvid_acpi,
+	drvid_acpi_reserve_resources,
+	0
+};
+
+annotated_module_init(hpet_init, drvid_hpet, dependencies);
 module_exit(hpet_exit);
 MODULE_AUTHOR("Bob Picco <Robert.Picco@hp.com>");
 MODULE_LICENSE("GPL");
diff --git a/drivers/char/hw_random/core.c b/drivers/char/hw_random/core.c
index 5643b65..052a464 100644
--- a/drivers/char/hw_random/core.c
+++ b/drivers/char/hw_random/core.c
@@ -583,7 +583,12 @@ static void __exit hwrng_modexit(void)
 	unregister_miscdev();
 }
 
-module_init(hwrng_modinit);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_misc,
+	0
+};
+
+annotated_module_init(hwrng_modinit, drvid_hwrng, dependencies);
 module_exit(hwrng_modexit);
 
 MODULE_DESCRIPTION("H/W Random Number Generator (RNG) driver");
diff --git a/drivers/char/hw_random/omap-rng.c b/drivers/char/hw_random/omap-rng.c
index 8a1432e..fd05cb5 100644
--- a/drivers/char/hw_random/omap-rng.c
+++ b/drivers/char/hw_random/omap-rng.c
@@ -453,8 +453,14 @@ static struct platform_driver omap_rng_driver = {
 	.probe		= omap_rng_probe,
 	.remove		= omap_rng_remove,
 };
-
-module_platform_driver(omap_rng_driver);
+/*
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_hwrng,
+	0
+};
+*/
+//module_platform_driver_deps(omap_rng_driver, drvid_omap_rng, dependencies);
+annotated_module_platform_driver(omap_rng_driver, drvid_omap_rng, NULL);
 MODULE_ALIAS("platform:omap_rng");
 MODULE_AUTHOR("Deepak Saxena (and others)");
 MODULE_LICENSE("GPL");
diff --git a/drivers/char/hw_random/omap3-rom-rng.c b/drivers/char/hw_random/omap3-rom-rng.c
index a405cdc..397f3fe 100644
--- a/drivers/char/hw_random/omap3-rom-rng.c
+++ b/drivers/char/hw_random/omap3-rom-rng.c
@@ -131,7 +131,12 @@ static struct platform_driver omap3_rom_rng_driver = {
 	.remove		= omap3_rom_rng_remove,
 };
 
-module_platform_driver(omap3_rom_rng_driver);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_hwrng,
+	0
+};
+
+annotated_module_platform_driver(omap3_rom_rng_driver, drvid_omap3_rom_rng, dependencies);
 
 MODULE_ALIAS("platform:omap3-rom-rng");
 MODULE_AUTHOR("Juha Yrjola");
diff --git a/drivers/char/misc.c b/drivers/char/misc.c
index fdb0f9b..1f736a6 100644
--- a/drivers/char/misc.c
+++ b/drivers/char/misc.c
@@ -303,4 +303,4 @@ fail_remove:
 	remove_proc_entry("misc", NULL);
 	return err;
 }
-subsys_initcall(misc_init);
+annotated_initcall(subsys, misc_init, drvid_misc, NULL);
diff --git a/drivers/char/nvram.c b/drivers/char/nvram.c
index 9df78e2..26e40d6 100644
--- a/drivers/char/nvram.c
+++ b/drivers/char/nvram.c
@@ -473,7 +473,12 @@ static void __exit nvram_cleanup_module(void)
 	misc_deregister(&nvram_dev);
 }
 
-module_init(nvram_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_misc,
+	0
+};
+
+annotated_module_init(nvram_init, drvid_nvram, dependencies);
 module_exit(nvram_cleanup_module);
 
 /*
diff --git a/drivers/char/rtc.c b/drivers/char/rtc.c
index 3525996..f75676f 100644
--- a/drivers/char/rtc.c
+++ b/drivers/char/rtc.c
@@ -1155,7 +1155,13 @@ static void __exit rtc_exit(void)
 #endif /* CONFIG_SPARC32 */
 }
 
-module_init(rtc_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_misc,
+	drvid_hpet,
+	0
+};
+
+annotated_module_init(rtc_init, drvid_char_rtc, dependencies);
 module_exit(rtc_exit);
 
 #ifdef RTC_IRQ
diff --git a/drivers/clocksource/acpi_pm.c b/drivers/clocksource/acpi_pm.c
index 6eab889..1601d84 100644
--- a/drivers/clocksource/acpi_pm.c
+++ b/drivers/clocksource/acpi_pm.c
@@ -222,10 +222,17 @@ static int __init init_acpi_pm_clocksource(void)
 						PMTMR_TICKS_PER_SEC);
 }
 
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_acpi,
+	drvid_clocksource_done_booting,
+	drvid_pci_quirks, // is that what is meant with PCI fixups?
+	0
+};
+
 /* We use fs_initcall because we want the PCI fixups to have run
  * but we still need to load before device_initcall
  */
-fs_initcall(init_acpi_pm_clocksource);
+annotated_initcall(fs, init_acpi_pm_clocksource, drvid_acpi_pm_clocksource, dependencies);
 
 /*
  * Allow an override of the IOPort. Stupid BIOSes do not tell us about
diff --git a/drivers/connector/cn_proc.c b/drivers/connector/cn_proc.c
index 15d06fc..778ad1f 100644
--- a/drivers/connector/cn_proc.c
+++ b/drivers/connector/cn_proc.c
@@ -390,4 +390,9 @@ static int __init cn_proc_init(void)
 	return 0;
 }
 
-module_init(cn_proc_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_cn,
+	0
+};
+
+annotated_module_init(cn_proc_init, drvid_cn_proc, dependencies);
diff --git a/drivers/connector/connector.c b/drivers/connector/connector.c
index 30f5228..b08321f 100644
--- a/drivers/connector/connector.c
+++ b/drivers/connector/connector.c
@@ -318,5 +318,10 @@ static void cn_fini(void)
 	netlink_kernel_release(dev->nls);
 }
 
-subsys_initcall(cn_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_netlink,
+	0
+};
+
+annotated_initcall(subsys, cn_init, drvid_cn, dependencies);
 module_exit(cn_fini);
diff --git a/drivers/cpufreq/acpi-cpufreq.c b/drivers/cpufreq/acpi-cpufreq.c
index 0136dfc..ac897f6 100644
--- a/drivers/cpufreq/acpi-cpufreq.c
+++ b/drivers/cpufreq/acpi-cpufreq.c
@@ -992,7 +992,13 @@ MODULE_PARM_DESC(acpi_pstate_strict,
 	"value 0 or non-zero. non-zero -> strict ACPI checks are "
 	"performed during frequency changes.");
 
-late_initcall(acpi_cpufreq_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_acpi,
+	drvid_cpufreq,
+	0
+};
+
+annotated_initcall(late, acpi_cpufreq_init, drvid_acpi_cpufreq, dependencies);
 module_exit(acpi_cpufreq_exit);
 
 static const struct x86_cpu_id acpi_cpufreq_ids[] = {
diff --git a/drivers/cpufreq/cpufreq.c b/drivers/cpufreq/cpufreq.c
index 7a3c30c..4026d51 100644
--- a/drivers/cpufreq/cpufreq.c
+++ b/drivers/cpufreq/cpufreq.c
@@ -2626,4 +2626,4 @@ static int __init cpufreq_core_init(void)
 
 	return 0;
 }
-core_initcall(cpufreq_core_init);
+annotated_initcall(core, cpufreq_core_init, drvid_cpufreq, NULL);
diff --git a/drivers/cpufreq/cpufreq_conservative.c b/drivers/cpufreq/cpufreq_conservative.c
index c86a10c..9a4c5fb 100644
--- a/drivers/cpufreq/cpufreq_conservative.c
+++ b/drivers/cpufreq/cpufreq_conservative.c
@@ -404,9 +404,14 @@ MODULE_DESCRIPTION("'cpufreq_conservative' - A dynamic cpufreq governor for "
 		"optimised for use in a battery environment");
 MODULE_LICENSE("GPL");
 
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_cpufreq,
+	0
+};
+
 #ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_CONSERVATIVE
-fs_initcall(cpufreq_gov_dbs_init);
+annotated_initcall(fs, cpufreq_gov_dbs_init, drvid_cpufreq_gov_dbs, dependencies);
 #else
-module_init(cpufreq_gov_dbs_init);
+annotated_module_init(cpufreq_gov_dbs_init, drvid_cpufreq_gov_dbs, dependencies);
 #endif
 module_exit(cpufreq_gov_dbs_exit);
diff --git a/drivers/cpufreq/cpufreq_ondemand.c b/drivers/cpufreq/cpufreq_ondemand.c
index 3c1e10f..822ac2c 100644
--- a/drivers/cpufreq/cpufreq_ondemand.c
+++ b/drivers/cpufreq/cpufreq_ondemand.c
@@ -623,9 +623,14 @@ MODULE_DESCRIPTION("'cpufreq_ondemand' - A dynamic cpufreq governor for "
 	"Low Latency Frequency Transition capable processors");
 MODULE_LICENSE("GPL");
 
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_cpufreq,
+	0
+};
+
 #ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_ONDEMAND
-fs_initcall(cpufreq_gov_dbs_init);
+annotated_initcall(fs, cpufreq_gov_dbs_init, drvid_cpufreq_ondemand, dependencies);
 #else
-module_init(cpufreq_gov_dbs_init);
+annotated_module_init(cpufreq_gov_dbs_init, drvid_cpufreq_ondemand, dependencies);
 #endif
 module_exit(cpufreq_gov_dbs_exit);
diff --git a/drivers/cpufreq/cpufreq_performance.c b/drivers/cpufreq/cpufreq_performance.c
index cf117de..821d71a 100644
--- a/drivers/cpufreq/cpufreq_performance.c
+++ b/drivers/cpufreq/cpufreq_performance.c
@@ -56,5 +56,10 @@ MODULE_AUTHOR("Dominik Brodowski <linux@brodo.de>");
 MODULE_DESCRIPTION("CPUfreq policy governor 'performance'");
 MODULE_LICENSE("GPL");
 
-fs_initcall(cpufreq_gov_performance_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_cpufreq,
+	0
+};
+
+annotated_initcall(fs, cpufreq_gov_performance_init, drvid_cpufreq_gov_performance, dependencies);
 module_exit(cpufreq_gov_performance_exit);
diff --git a/drivers/cpufreq/cpufreq_powersave.c b/drivers/cpufreq/cpufreq_powersave.c
index e3b874c..09f8c04 100644
--- a/drivers/cpufreq/cpufreq_powersave.c
+++ b/drivers/cpufreq/cpufreq_powersave.c
@@ -56,9 +56,14 @@ MODULE_AUTHOR("Dominik Brodowski <linux@brodo.de>");
 MODULE_DESCRIPTION("CPUfreq policy governor 'powersave'");
 MODULE_LICENSE("GPL");
 
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_cpufreq,
+	0
+};
+
 #ifdef CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE
-fs_initcall(cpufreq_gov_powersave_init);
+annotated_initcall(fs, cpufreq_gov_powersave_init, drvid_cpufreq_powersave, dependencies);
 #else
-module_init(cpufreq_gov_powersave_init);
+annotated_module_init(cpufreq_gov_powersave_init, drvid_cpufreq_powersave, dependencies);
 #endif
 module_exit(cpufreq_gov_powersave_exit);
diff --git a/drivers/cpufreq/cpufreq_stats.c b/drivers/cpufreq/cpufreq_stats.c
index 5e370a3..0b90ed1 100644
--- a/drivers/cpufreq/cpufreq_stats.c
+++ b/drivers/cpufreq/cpufreq_stats.c
@@ -353,5 +353,10 @@ MODULE_AUTHOR("Zou Nan hai <nanhai.zou@intel.com>");
 MODULE_DESCRIPTION("Export cpufreq stats via sysfs");
 MODULE_LICENSE("GPL");
 
-module_init(cpufreq_stats_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_cpufreq,
+	0
+};
+
+annotated_module_init(cpufreq_stats_init, drvid_cpufreq_stats, dependencies);
 module_exit(cpufreq_stats_exit);
diff --git a/drivers/cpufreq/imx6q-cpufreq.c b/drivers/cpufreq/imx6q-cpufreq.c
index 380a90d..635c2cb 100644
--- a/drivers/cpufreq/imx6q-cpufreq.c
+++ b/drivers/cpufreq/imx6q-cpufreq.c
@@ -361,7 +361,13 @@ static struct platform_driver imx6q_cpufreq_platdrv = {
 	.probe		= imx6q_cpufreq_probe,
 	.remove		= imx6q_cpufreq_remove,
 };
-module_platform_driver(imx6q_cpufreq_platdrv);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_cpufreq,
+	0
+};
+
+annotated_module_platform_driver(imx6q_cpufreq_platdrv, drvid_imx6q_cpufreq, dependencies);
 
 MODULE_AUTHOR("Shawn Guo <shawn.guo@linaro.org>");
 MODULE_DESCRIPTION("Freescale i.MX6Q cpufreq driver");
diff --git a/drivers/cpufreq/kirkwood-cpufreq.c b/drivers/cpufreq/kirkwood-cpufreq.c
index be42f10..1e23348 100644
--- a/drivers/cpufreq/kirkwood-cpufreq.c
+++ b/drivers/cpufreq/kirkwood-cpufreq.c
@@ -186,7 +186,12 @@ static struct platform_driver kirkwood_cpufreq_platform_driver = {
 	},
 };
 
-module_platform_driver(kirkwood_cpufreq_platform_driver);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_cpufreq,
+	0
+};
+
+annotated_module_platform_driver(kirkwood_cpufreq_platform_driver, drvid_kirkwood_cpufreq, dependencies);
 
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Andrew Lunn <andrew@lunn.ch");
diff --git a/drivers/cpufreq/omap-cpufreq.c b/drivers/cpufreq/omap-cpufreq.c
index e3866e0..9a6df7d 100644
--- a/drivers/cpufreq/omap-cpufreq.c
+++ b/drivers/cpufreq/omap-cpufreq.c
@@ -199,7 +199,13 @@ static struct platform_driver omap_cpufreq_platdrv = {
 	.probe		= omap_cpufreq_probe,
 	.remove		= omap_cpufreq_remove,
 };
-module_platform_driver(omap_cpufreq_platdrv);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_cpufreq,
+	0
+};
+
+annotated_module_platform_driver(omap_cpufreq_platdrv, drvid_omap_cpufreq, dependencies);
 
 MODULE_DESCRIPTION("cpufreq driver for OMAP SoCs");
 MODULE_LICENSE("GPL");
diff --git a/drivers/cpuidle/cpuidle-arm.c b/drivers/cpuidle/cpuidle-arm.c
index 545069d..a8161b5 100644
--- a/drivers/cpuidle/cpuidle-arm.c
+++ b/drivers/cpuidle/cpuidle-arm.c
@@ -18,7 +18,6 @@
 #include <linux/module.h>
 #include <linux/of.h>
 #include <linux/slab.h>
-
 #include <asm/cpuidle.h>
 
 #include "dt_idle_states.h"
@@ -160,4 +159,10 @@ out_fail:
 
 	return ret;
 }
-device_initcall(arm_idle_init);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_cpuidle,
+	0
+};
+
+annotated_module_init(arm_idle_init, drvid_cpuidle_arm, dependencies);
diff --git a/drivers/cpuidle/cpuidle-kirkwood.c b/drivers/cpuidle/cpuidle-kirkwood.c
index d23d8f4..154e844 100644
--- a/drivers/cpuidle/cpuidle-kirkwood.c
+++ b/drivers/cpuidle/cpuidle-kirkwood.c
@@ -79,7 +79,12 @@ static struct platform_driver kirkwood_cpuidle_driver = {
 		   },
 };
 
-module_platform_driver(kirkwood_cpuidle_driver);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_cpuidle,
+	0
+};
+
+annotated_module_platform_driver(kirkwood_cpuidle_driver, drvid_kirkwood_cpuidle, dependencies);
 
 MODULE_AUTHOR("Andrew Lunn <andrew@lunn.ch>");
 MODULE_DESCRIPTION("Kirkwood cpu idle driver");
diff --git a/drivers/cpuidle/cpuidle.c b/drivers/cpuidle/cpuidle.c
index 48b7228..65dd8dd 100644
--- a/drivers/cpuidle/cpuidle.c
+++ b/drivers/cpuidle/cpuidle.c
@@ -655,4 +655,4 @@ static int __init cpuidle_init(void)
 }
 
 module_param(off, int, 0444);
-core_initcall(cpuidle_init);
+annotated_initcall(core, cpuidle_init, drvid_cpuidle, NULL);
diff --git a/drivers/crypto/marvell/cesa.c b/drivers/crypto/marvell/cesa.c
index 1c6f98d..b563279 100644
--- a/drivers/crypto/marvell/cesa.c
+++ b/drivers/crypto/marvell/cesa.c
@@ -538,7 +538,13 @@ static struct platform_driver marvell_cesa = {
 		.of_match_table = mv_cesa_of_match_table,
 	},
 };
-module_platform_driver(marvell_cesa);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_cryptomgr,
+	0
+};
+
+annotated_module_platform_driver(marvell_cesa, drvid_marvell_cesa, dependencies);
 
 MODULE_ALIAS("platform:mv_crypto");
 MODULE_AUTHOR("Boris Brezillon <boris.brezillon@free-electrons.com>");
diff --git a/drivers/crypto/mv_cesa.c b/drivers/crypto/mv_cesa.c
index e6b658f..b708064 100644
--- a/drivers/crypto/mv_cesa.c
+++ b/drivers/crypto/mv_cesa.c
@@ -1213,7 +1213,12 @@ static struct platform_driver marvell_crypto = {
 };
 MODULE_ALIAS("platform:mv_crypto");
 
-module_platform_driver(marvell_crypto);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_cryptomgr,
+	0
+};
+
+annotated_module_platform_driver(marvell_crypto, drvid_mv_crypto, dependencies);
 
 MODULE_AUTHOR("Sebastian Andrzej Siewior <sebastian@breakpoint.cc>");
 MODULE_DESCRIPTION("Support for Marvell's cryptographic engine");
diff --git a/drivers/crypto/omap-aes.c b/drivers/crypto/omap-aes.c
index 9a28b7e..86e143b 100644
--- a/drivers/crypto/omap-aes.c
+++ b/drivers/crypto/omap-aes.c
@@ -1327,7 +1327,12 @@ static struct platform_driver omap_aes_driver = {
 	},
 };
 
-module_platform_driver(omap_aes_driver);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_cryptomgr,
+	0
+};
+
+annotated_module_platform_driver(omap_aes_driver, drvid_omap_aes, dependencies);
 
 MODULE_DESCRIPTION("OMAP AES hw acceleration support.");
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/crypto/omap-sham.c b/drivers/crypto/omap-sham.c
index b2024c95..21446c9 100644
--- a/drivers/crypto/omap-sham.c
+++ b/drivers/crypto/omap-sham.c
@@ -2057,7 +2057,13 @@ static struct platform_driver omap_sham_driver = {
 	},
 };
 
-module_platform_driver(omap_sham_driver);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_pm,
+	drvid_cryptomgr,
+	0
+};
+
+annotated_module_platform_driver(omap_sham_driver, drvid_omap_sham, dependencies);
 
 MODULE_DESCRIPTION("OMAP SHA1/MD5 hw acceleration support.");
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/dma/cppi41.c b/drivers/dma/cppi41.c
index ceedafb..832433f 100644
--- a/drivers/dma/cppi41.c
+++ b/drivers/dma/cppi41.c
@@ -1079,6 +1079,12 @@ static struct platform_driver cpp41_dma_driver = {
 	},
 };
 
-module_platform_driver(cpp41_dma_driver);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_dma_bus,
+	drvid_pm,
+	0
+};
+
+annotated_module_platform_driver(cpp41_dma_driver, drvid_cpp41_dma, dependencies);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Sebastian Andrzej Siewior <bigeasy@linutronix.de>");
diff --git a/drivers/dma/dmaengine.c b/drivers/dma/dmaengine.c
index 3ff284c..d4f7e42 100644
--- a/drivers/dma/dmaengine.c
+++ b/drivers/dma/dmaengine.c
@@ -347,6 +347,7 @@ static int __init dma_channel_table_init(void)
 	return err;
 }
 arch_initcall(dma_channel_table_init);
+//annotated_initcall(arch, dma_channel_table_init, drvid_dma_channel_table, NULL);
 
 /**
  * dma_find_channel - find a channel to carry out the operation
@@ -1199,6 +1200,11 @@ static int __init dma_bus_init(void)
 		return err;
 	return class_register(&dma_devclass);
 }
-arch_initcall(dma_bus_init);
 
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_dma_channel_table,
+	0
+};
 
+arch_initcall(dma_bus_init);
+//annotated_initcall(arch, dma_bus_init, drvid_dma_bus, dependencies);
diff --git a/drivers/dma/imx-sdma.c b/drivers/dma/imx-sdma.c
index 77b6aab..63966e4 100644
--- a/drivers/dma/imx-sdma.c
+++ b/drivers/dma/imx-sdma.c
@@ -1650,7 +1650,13 @@ static struct platform_driver sdma_driver = {
 	.probe		= sdma_probe,
 };
 
-module_platform_driver(sdma_driver);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_dma_bus,
+	drvid_firmware_class,
+	0
+};
+
+annotated_module_platform_driver(sdma_driver, drvid_imx_sdma, dependencies);
 
 MODULE_AUTHOR("Sascha Hauer, Pengutronix <s.hauer@pengutronix.de>");
 MODULE_DESCRIPTION("i.MX SDMA driver");
diff --git a/drivers/dma/mv_xor.c b/drivers/dma/mv_xor.c
index f1325f6..8cf8df2 100644
--- a/drivers/dma/mv_xor.c
+++ b/drivers/dma/mv_xor.c
@@ -1295,7 +1295,14 @@ static int __init mv_xor_init(void)
 {
 	return platform_driver_register(&mv_xor_driver);
 }
-module_init(mv_xor_init);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_dma_bus,
+	0
+};
+
+annotated_module_init_drv(mv_xor_init, drvid_mv_xor, dependencies,
+				mv_xor_driver.driver);
 
 /* it's currently unsafe to unload this module */
 #if 0
diff --git a/drivers/dma/mxs-dma.c b/drivers/dma/mxs-dma.c
index 60de352..4b8bd8e 100644
--- a/drivers/dma/mxs-dma.c
+++ b/drivers/dma/mxs-dma.c
@@ -884,4 +884,11 @@ static int __init mxs_dma_module_init(void)
 {
 	return platform_driver_probe(&mxs_dma_driver, mxs_dma_probe);
 }
-subsys_initcall(mxs_dma_module_init);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_dma_bus,
+	0
+};
+
+annotated_initcall_drv(subsys, mxs_dma_module_init, drvid_mxs_dma, dependencies,
+			mxs_dma_driver.driver);
diff --git a/drivers/dma/omap-dma.c b/drivers/dma/omap-dma.c
index 249445c..ed87cbf 100644
--- a/drivers/dma/omap-dma.c
+++ b/drivers/dma/omap-dma.c
@@ -1285,7 +1285,14 @@ static int omap_dma_init(void)
 {
 	return platform_driver_register(&omap_dma_driver);
 }
-subsys_initcall(omap_dma_init);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_dma_bus,
+	0
+};
+
+annotated_initcall_drv(subsys, omap_dma_init, drvid_omap_dma, dependencies,
+			omap_dma_driver.driver);
 
 static void __exit omap_dma_exit(void)
 {
diff --git a/drivers/firmware/dmi_scan.c b/drivers/firmware/dmi_scan.c
index ac1ce4a..e36c998 100644
--- a/drivers/firmware/dmi_scan.c
+++ b/drivers/firmware/dmi_scan.c
@@ -714,7 +714,13 @@ static int __init dmi_init(void)
 
 	return ret;
 }
-subsys_initcall(dmi_init);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_firmware_class,
+	0
+};
+
+annotated_initcall(subsys, dmi_init, drvid_dmi, dependencies);
 
 /**
  * dmi_set_dump_stack_arch_desc - set arch description for dump_stack()
diff --git a/drivers/gpio/gpio-generic.c b/drivers/gpio/gpio-generic.c
index 9bda372..21cb251 100644
--- a/drivers/gpio/gpio-generic.c
+++ b/drivers/gpio/gpio-generic.c
@@ -670,7 +670,7 @@ static struct platform_driver bgpio_driver = {
 	.remove = bgpio_pdev_remove,
 };
 
-module_platform_driver(bgpio_driver);
+annotated_module_platform_driver(bgpio_driver, drvid_bgpio, NULL);
 
 #endif /* CONFIG_GPIO_GENERIC_PLATFORM */
 
diff --git a/drivers/gpio/gpio-mvebu.c b/drivers/gpio/gpio-mvebu.c
index 1a54205..ce04ba5 100644
--- a/drivers/gpio/gpio-mvebu.c
+++ b/drivers/gpio/gpio-mvebu.c
@@ -860,4 +860,4 @@ static struct platform_driver mvebu_gpio_driver = {
 	.suspend        = mvebu_gpio_suspend,
 	.resume         = mvebu_gpio_resume,
 };
-module_platform_driver(mvebu_gpio_driver);
+annotated_module_platform_driver(mvebu_gpio_driver, drvid_mvebu_gpio, NULL);
diff --git a/drivers/gpio/gpio-mxc.c b/drivers/gpio/gpio-mxc.c
index ec1eb1b..62505cd 100644
--- a/drivers/gpio/gpio-mxc.c
+++ b/drivers/gpio/gpio-mxc.c
@@ -506,7 +506,7 @@ static int __init gpio_mxc_init(void)
 {
 	return platform_driver_register(&mxc_gpio_driver);
 }
-postcore_initcall(gpio_mxc_init);
+annotated_initcall_drv(postcore, gpio_mxc_init, drvid_mxc_gpio, NULL, mxc_gpio_driver.driver);
 
 MODULE_AUTHOR("Freescale Semiconductor, "
 	      "Daniel Mack <danielncaiaq.de>, "
diff --git a/drivers/gpio/gpio-omap.c b/drivers/gpio/gpio-omap.c
index 61a731f..723ad33 100644
--- a/drivers/gpio/gpio-omap.c
+++ b/drivers/gpio/gpio-omap.c
@@ -1642,7 +1642,13 @@ static int __init omap_gpio_drv_reg(void)
 {
 	return platform_driver_register(&omap_gpio_driver);
 }
-postcore_initcall(omap_gpio_drv_reg);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_pm,
+	0
+};
+
+annotated_initcall_drv(postcore, omap_gpio_drv_reg, drvid_omap_gpio, dependencies, omap_gpio_driver.driver);
 
 static void __exit omap_gpio_exit(void)
 {
diff --git a/drivers/gpio/gpio-tps65910.c b/drivers/gpio/gpio-tps65910.c
index 88f1f5f..973897b 100644
--- a/drivers/gpio/gpio-tps65910.c
+++ b/drivers/gpio/gpio-tps65910.c
@@ -205,7 +205,7 @@ static int __init tps65910_gpio_init(void)
 {
 	return platform_driver_register(&tps65910_gpio_driver);
 }
-subsys_initcall(tps65910_gpio_init);
+annotated_initcall_drv(subsys, tps65910_gpio_init, drvid_tps65910_gpio, NULL, tps65910_gpio_driver.driver);
 
 static void __exit tps65910_gpio_exit(void)
 {
diff --git a/drivers/gpio/gpio-twl4030.c b/drivers/gpio/gpio-twl4030.c
index 9e1dbb9..717fa18 100644
--- a/drivers/gpio/gpio-twl4030.c
+++ b/drivers/gpio/gpio-twl4030.c
@@ -615,7 +615,7 @@ static int __init gpio_twl4030_init(void)
 {
 	return platform_driver_register(&gpio_twl4030_driver);
 }
-subsys_initcall(gpio_twl4030_init);
+annotated_initcall_drv(subsys, gpio_twl4030_init, drvid_gpio_twl4030, NULL, gpio_twl4030_driver.driver);
 
 static void __exit gpio_twl4030_exit(void)
 {
diff --git a/drivers/gpio/gpiolib.c b/drivers/gpio/gpiolib.c
index bf4bd1d..738545f 100644
--- a/drivers/gpio/gpiolib.c
+++ b/drivers/gpio/gpiolib.c
@@ -2386,6 +2386,12 @@ static int __init gpiolib_debugfs_init(void)
 				NULL, NULL, &gpiolib_operations);
 	return 0;
 }
-subsys_initcall(gpiolib_debugfs_init);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_debugfs,
+	0
+};
+
+annotated_initcall(subsys, gpiolib_debugfs_init, drvid_gpiolib_debugfs, dependencies);
 
 #endif	/* DEBUG_FS */
diff --git a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
index 56da962..e43d69f 100644
--- a/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
+++ b/drivers/gpu/drm/amd/amdgpu/amdgpu_drv.c
@@ -537,7 +537,16 @@ static void __exit amdgpu_exit(void)
 	amdgpu_unregister_atpx_handler();
 }
 
-module_init(amdgpu_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_drm,
+	drvid_pm,
+	drvid_firmware_class,
+	drvid_ttm,
+	drvid_hwmon,
+	0
+};
+
+annotated_module_init(amdgpu_init, drvid_amdgpu, dependencies);
 module_exit(amdgpu_exit);
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
diff --git a/drivers/gpu/drm/drm_drv.c b/drivers/gpu/drm/drm_drv.c
index b7bf4ce..552f0c0 100644
--- a/drivers/gpu/drm/drm_drv.c
+++ b/drivers/gpu/drm/drm_drv.c
@@ -894,5 +894,16 @@ static void __exit drm_core_exit(void)
 	idr_destroy(&drm_minors_idr);
 }
 
-module_init(drm_core_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_debugfs,
+	drvid_i2c,
+	drvid_agpgart,
+	drvid_pci_subsys,
+	drvid_pcibios_assign_resources,
+	drvid_pnpacpi, // optional
+	drvid_pci_quirks, // optional
+	0
+};
+
+annotated_module_init(drm_core_init, drvid_drm, dependencies);
 module_exit(drm_core_exit);
diff --git a/drivers/gpu/drm/drm_fb_helper.c b/drivers/gpu/drm/drm_fb_helper.c
index cac4229..c3091de 100644
--- a/drivers/gpu/drm/drm_fb_helper.c
+++ b/drivers/gpu/drm/drm_fb_helper.c
@@ -1834,5 +1834,10 @@ static int __init drm_fb_helper_modinit(void)
 	return 0;
 }
 
-module_init(drm_fb_helper_modinit);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_drm,
+	0
+};
+
+annotated_module_init(drm_fb_helper_modinit, drvid_drm_fb_helper, dependencies);
 #endif
diff --git a/drivers/gpu/drm/drm_mipi_dsi.c b/drivers/gpu/drm/drm_mipi_dsi.c
index 2d5ca8ee..d399abf 100644
--- a/drivers/gpu/drm/drm_mipi_dsi.c
+++ b/drivers/gpu/drm/drm_mipi_dsi.c
@@ -926,6 +926,19 @@ static int __init mipi_dsi_bus_init(void)
 {
 	return bus_register(&mipi_dsi_bus_type);
 }
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+//	drvid_acpi,
+//	drvid_pci_acpi,
+//	drvid_pci_driver,
+/*
+	drvid_pci_quirks,
+	drvid_pci_slot,
+*/
+	0
+};
+
+//annotated_initcall(postcore, mipi_dsi_bus_init, drvid_mipi_dsi_bus, dependencies);
 postcore_initcall(mipi_dsi_bus_init);
 
 MODULE_AUTHOR("Andrzej Hajda <a.hajda@samsung.com>");
diff --git a/drivers/gpu/drm/i915/i915_drv.c b/drivers/gpu/drm/i915/i915_drv.c
index 603146e..73c8b88 100644
--- a/drivers/gpu/drm/i915/i915_drv.c
+++ b/drivers/gpu/drm/i915/i915_drv.c
@@ -1776,7 +1776,12 @@ static void __exit i915_exit(void)
 	drm_pci_exit(&driver, &i915_pci_driver);
 }
 
-module_init(i915_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_drm,
+	0
+};
+
+annotated_module_init(i915_init, drvid_i915, dependencies);
 module_exit(i915_exit);
 
 MODULE_AUTHOR("Tungsten Graphics, Inc.");
diff --git a/drivers/gpu/drm/radeon/radeon_drv.c b/drivers/gpu/drm/radeon/radeon_drv.c
index 5751446..ce21f32 100644
--- a/drivers/gpu/drm/radeon/radeon_drv.c
+++ b/drivers/gpu/drm/radeon/radeon_drv.c
@@ -680,7 +680,16 @@ static void __exit radeon_exit(void)
 	radeon_unregister_atpx_handler();
 }
 
-module_init(radeon_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_drm,
+	drvid_pm,
+	drvid_firmware_class,
+	drvid_ttm,
+	drvid_hwmon,
+	0
+};
+
+annotated_module_init(radeon_init, drvid_radeon, dependencies);
 module_exit(radeon_exit);
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
diff --git a/drivers/gpu/drm/tilcdc/tilcdc_drv.c b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
index 0f283a3..c02b793 100644
--- a/drivers/gpu/drm/tilcdc/tilcdc_drv.c
+++ b/drivers/gpu/drm/tilcdc/tilcdc_drv.c
@@ -715,7 +715,12 @@ static void __exit tilcdc_drm_fini(void)
 	tilcdc_tfp410_fini();
 }
 
-module_init(tilcdc_drm_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_drm,
+	0
+};
+
+annotated_module_init_drv(tilcdc_drm_init, drvid_tilcdc, dependencies, tilcdc_platform_driver.driver);
 module_exit(tilcdc_drm_fini);
 
 MODULE_AUTHOR("Rob Clark <robdclark@gmail.com");
diff --git a/drivers/gpu/drm/ttm/ttm_module.c b/drivers/gpu/drm/ttm/ttm_module.c
index 66fc639..14ca449 100644
--- a/drivers/gpu/drm/ttm/ttm_module.c
+++ b/drivers/gpu/drm/ttm/ttm_module.c
@@ -94,7 +94,12 @@ static void __exit ttm_exit(void)
 	wait_event(exit_q, atomic_read(&device_released) == 1);
 }
 
-module_init(ttm_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_drm,
+	0
+};
+
+annotated_module_init(ttm_init, drvid_ttm, dependencies);
 module_exit(ttm_exit);
 
 MODULE_AUTHOR("Thomas Hellstrom, Jerome Glisse");
diff --git a/drivers/gpu/vga/vgaarb.c b/drivers/gpu/vga/vgaarb.c
index 7bcbf86..8a78f60 100644
--- a/drivers/gpu/vga/vgaarb.c
+++ b/drivers/gpu/vga/vgaarb.c
@@ -1354,4 +1354,14 @@ static int __init vga_arb_device_init(void)
 	}
 	return rc;
 }
-subsys_initcall(vga_arb_device_init);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_misc,
+	drvid_pci_subsys,
+	drvid_pcibios_assign_resources,
+	drvid_pnpacpi, // optional
+	drvid_pci_quirks, // optional
+	0
+};
+
+annotated_initcall(subsys, vga_arb_device_init, drvid_vga_arb, dependencies);
diff --git a/drivers/hid/uhid.c b/drivers/hid/uhid.c
index e094c57..6b64eb5 100644
--- a/drivers/hid/uhid.c
+++ b/drivers/hid/uhid.c
@@ -775,7 +775,12 @@ static void __exit uhid_exit(void)
 	misc_deregister(&uhid_misc);
 }
 
-module_init(uhid_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_misc,
+	0
+};
+
+annotated_module_init(uhid_init, drvid_uhid, dependencies);
 module_exit(uhid_exit);
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("David Herrmann <dh.herrmann@gmail.com>");
diff --git a/drivers/hwmon/hwmon.c b/drivers/hwmon/hwmon.c
index a26c385..f4d14d3 100644
--- a/drivers/hwmon/hwmon.c
+++ b/drivers/hwmon/hwmon.c
@@ -278,7 +278,13 @@ static void __exit hwmon_exit(void)
 	class_unregister(&hwmon_class);
 }
 
-subsys_initcall(hwmon_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_pci_arch, // x86
+	drvid_pci_driver,
+	0
+};
+
+annotated_initcall(subsys, hwmon_init, drvid_hwmon, dependencies);
 module_exit(hwmon_exit);
 
 MODULE_AUTHOR("Mark M. Hoffman <mhoffman@lightlink.com>");
diff --git a/drivers/hwspinlock/omap_hwspinlock.c b/drivers/hwspinlock/omap_hwspinlock.c
index ad2f8ca..b91d5ac 100644
--- a/drivers/hwspinlock/omap_hwspinlock.c
+++ b/drivers/hwspinlock/omap_hwspinlock.c
@@ -196,8 +196,14 @@ static int __init omap_hwspinlock_init(void)
 {
 	return platform_driver_register(&omap_hwspinlock_driver);
 }
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_pm,
+	0
+};
+
 /* board init code might need to reserve hwspinlocks for predefined purposes */
-postcore_initcall(omap_hwspinlock_init);
+annotated_initcall_drv(postcore, omap_hwspinlock_init, drvid_omap_hwspinlock, dependencies, omap_hwspinlock_driver.driver);
 
 static void __exit omap_hwspinlock_exit(void)
 {
diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c
index 34cfc0e..aef6448 100644
--- a/drivers/i2c/busses/i2c-gpio.c
+++ b/drivers/i2c/busses/i2c-gpio.c
@@ -276,7 +276,13 @@ static int __init i2c_gpio_init(void)
 
 	return ret;
 }
-subsys_initcall(i2c_gpio_init);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_i2c,
+	0
+};
+
+annotated_initcall_drv(subsys, i2c_gpio_init, drvid_i2c_gpio, dependencies, i2c_gpio_driver.driver);
 
 static void __exit i2c_gpio_exit(void)
 {
diff --git a/drivers/i2c/busses/i2c-imx.c b/drivers/i2c/busses/i2c-imx.c
index 785aa67..7501824 100644
--- a/drivers/i2c/busses/i2c-imx.c
+++ b/drivers/i2c/busses/i2c-imx.c
@@ -1110,7 +1110,13 @@ static int __init i2c_adap_imx_init(void)
 {
 	return platform_driver_register(&i2c_imx_driver);
 }
-subsys_initcall(i2c_adap_imx_init);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_i2c,
+	0
+};
+
+annotated_initcall_drv(subsys, i2c_adap_imx_init, drvid_i2c_imx, dependencies, i2c_imx_driver.driver);
 
 static void __exit i2c_adap_imx_exit(void)
 {
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
index 30059c1..fe8ed85 100644
--- a/drivers/i2c/busses/i2c-mv64xxx.c
+++ b/drivers/i2c/busses/i2c-mv64xxx.c
@@ -996,7 +996,12 @@ static struct platform_driver mv64xxx_i2c_driver = {
 	},
 };
 
-module_platform_driver(mv64xxx_i2c_driver);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_i2c,
+	0
+};
+
+annotated_module_platform_driver(mv64xxx_i2c_driver, drvid_i2c_mv64xxx, dependencies);
 
 MODULE_AUTHOR("Mark A. Greer <mgreer@mvista.com>");
 MODULE_DESCRIPTION("Marvell mv64xxx host bridge i2c ctlr driver");
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
index fc9bf7f..a5c548d 100644
--- a/drivers/i2c/busses/i2c-omap.c
+++ b/drivers/i2c/busses/i2c-omap.c
@@ -1541,7 +1541,14 @@ omap_i2c_init_driver(void)
 {
 	return platform_driver_register(&omap_i2c_driver);
 }
-subsys_initcall(omap_i2c_init_driver);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_i2c,
+	drvid_pm,
+	0
+};
+
+annotated_initcall_drv(subsys, omap_i2c_init_driver, drvid_i2c_omap, dependencies, omap_i2c_driver.driver);
 
 static void __exit omap_i2c_exit_driver(void)
 {
diff --git a/drivers/i2c/busses/i2c-tiny-usb.c b/drivers/i2c/busses/i2c-tiny-usb.c
index 0ed77ee..74f4cb7 100644
--- a/drivers/i2c/busses/i2c-tiny-usb.c
+++ b/drivers/i2c/busses/i2c-tiny-usb.c
@@ -281,7 +281,13 @@ static struct usb_driver i2c_tiny_usb_driver = {
 	.id_table	= i2c_tiny_usb_table,
 };
 
-module_usb_driver(i2c_tiny_usb_driver);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_i2c,
+	drvid_usb,
+	0
+};
+
+annotated_module_usb_driver(i2c_tiny_usb_driver, drvid_tiny_usb, dependencies);
 
 /* ----- end of usb layer ------------------------------------------------ */
 
diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
index c83e4d1..ba34c1e 100644
--- a/drivers/i2c/i2c-core.c
+++ b/drivers/i2c/i2c-core.c
@@ -1963,7 +1963,7 @@ static void __exit i2c_exit(void)
 /* We must initialize early, because some subsystems register i2c drivers
  * in subsys_initcall() code, but are linked (and initialized) before i2c.
  */
-postcore_initcall(i2c_init);
+annotated_initcall(postcore, i2c_init, drvid_i2c, NULL);
 module_exit(i2c_exit);
 
 /* ----------------------------------------------------
diff --git a/drivers/i2c/i2c-dev.c b/drivers/i2c/i2c-dev.c
index 71c7a39..59f9b2f 100644
--- a/drivers/i2c/i2c-dev.c
+++ b/drivers/i2c/i2c-dev.c
@@ -666,5 +666,10 @@ MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl> and "
 MODULE_DESCRIPTION("I2C /dev entries driver");
 MODULE_LICENSE("GPL");
 
-module_init(i2c_dev_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_i2c,
+	0
+};
+
+annotated_module_init(i2c_dev_init, drvid_i2c_dev, dependencies);
 module_exit(i2c_dev_exit);
diff --git a/drivers/iio/adc/ti_am335x_adc.c b/drivers/iio/adc/ti_am335x_adc.c
index 942320e..3ef673e 100644
--- a/drivers/iio/adc/ti_am335x_adc.c
+++ b/drivers/iio/adc/ti_am335x_adc.c
@@ -591,7 +591,7 @@ static struct platform_driver tiadc_driver = {
 	.probe	= tiadc_probe,
 	.remove	= tiadc_remove,
 };
-module_platform_driver(tiadc_driver);
+annotated_module_platform_driver(tiadc_driver, drvid_tiadc, NULL);
 
 MODULE_DESCRIPTION("TI ADC controller driver");
 MODULE_AUTHOR("Rachna Patil <rachna@ti.com>");
diff --git a/drivers/input/evdev.c b/drivers/input/evdev.c
index 08d4964..caacbdd 100644
--- a/drivers/input/evdev.c
+++ b/drivers/input/evdev.c
@@ -1245,7 +1245,12 @@ static void __exit evdev_exit(void)
 	input_unregister_handler(&evdev_handler);
 }
 
-module_init(evdev_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_input,
+	0
+};
+
+annotated_module_init(evdev_init, drvid_evdev, dependencies);
 module_exit(evdev_exit);
 
 MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
diff --git a/drivers/input/input.c b/drivers/input/input.c
index 78d2499..6053db9 100644
--- a/drivers/input/input.c
+++ b/drivers/input/input.c
@@ -2431,5 +2431,5 @@ static void __exit input_exit(void)
 	class_unregister(&input_class);
 }
 
-subsys_initcall(input_init);
+annotated_initcall(subsys, input_init, drvid_input, NULL);
 module_exit(input_exit);
diff --git a/drivers/input/joydev.c b/drivers/input/joydev.c
index 1d247bc..5d6cc5a 100644
--- a/drivers/input/joydev.c
+++ b/drivers/input/joydev.c
@@ -1013,5 +1013,10 @@ static void __exit joydev_exit(void)
 	input_unregister_handler(&joydev_handler);
 }
 
-module_init(joydev_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_input,
+	0
+};
+
+annotated_module_init(joydev_init, drvid_joydev, dependencies);
 module_exit(joydev_exit);
diff --git a/drivers/input/keyboard/atkbd.c b/drivers/input/keyboard/atkbd.c
index ec876b5..50d2e33 100644
--- a/drivers/input/keyboard/atkbd.c
+++ b/drivers/input/keyboard/atkbd.c
@@ -1817,5 +1817,12 @@ static void __exit atkbd_exit(void)
 	serio_unregister_driver(&atkbd_drv);
 }
 
-module_init(atkbd_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_dmi,
+	drvid_input,
+	drvid_serio,
+	0
+};
+
+annotated_module_init(atkbd_init, drvid_atkbd, dependencies);
 module_exit(atkbd_exit);
diff --git a/drivers/input/keyboard/gpio_keys.c b/drivers/input/keyboard/gpio_keys.c
index ddf4045..2b01094 100644
--- a/drivers/input/keyboard/gpio_keys.c
+++ b/drivers/input/keyboard/gpio_keys.c
@@ -855,7 +855,12 @@ static void __exit gpio_keys_exit(void)
 	platform_driver_unregister(&gpio_keys_device_driver);
 }
 
-late_initcall(gpio_keys_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_input,
+	0
+};
+
+annotated_initcall_drv(late, gpio_keys_init, drvid_gpio_keys, dependencies, gpio_keys_device_driver.driver);
 module_exit(gpio_keys_exit);
 
 MODULE_LICENSE("GPL");
diff --git a/drivers/input/misc/twl4030-pwrbutton.c b/drivers/input/misc/twl4030-pwrbutton.c
index 603fc2f..8a0f484 100644
--- a/drivers/input/misc/twl4030-pwrbutton.c
+++ b/drivers/input/misc/twl4030-pwrbutton.c
@@ -106,7 +106,14 @@ static struct platform_driver twl4030_pwrbutton_driver = {
 		.of_match_table = of_match_ptr(twl4030_pwrbutton_dt_match_table),
 	},
 };
-module_platform_driver(twl4030_pwrbutton_driver);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_twl_core,
+	drvid_input,
+	0
+};
+
+annotated_module_platform_driver(twl4030_pwrbutton_driver, drvid_twl4030_pwrbutton, dependencies);
 
 MODULE_ALIAS("platform:twl4030_pwrbutton");
 MODULE_DESCRIPTION("Triton2 Power Button");
diff --git a/drivers/input/misc/uinput.c b/drivers/input/misc/uinput.c
index 421e29e..098332a 100644
--- a/drivers/input/misc/uinput.c
+++ b/drivers/input/misc/uinput.c
@@ -939,5 +939,11 @@ MODULE_DESCRIPTION("User level driver support for input subsystem");
 MODULE_LICENSE("GPL");
 MODULE_VERSION("0.3");
 
-module_init(uinput_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_input,
+	drvid_misc,
+	0
+};
+
+annotated_module_init(uinput_init, drvid_uinput, dependencies);
 module_exit(uinput_exit);
diff --git a/drivers/input/mousedev.c b/drivers/input/mousedev.c
index b604564..a5d02cb 100644
--- a/drivers/input/mousedev.c
+++ b/drivers/input/mousedev.c
@@ -1124,5 +1124,11 @@ static void __exit mousedev_exit(void)
 	mousedev_destroy(mousedev_mix);
 }
 
-module_init(mousedev_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_input,
+	drvid_misc,
+	0
+};
+
+annotated_module_init(mousedev_init, drvid_mousedev, dependencies);
 module_exit(mousedev_exit);
diff --git a/drivers/input/serio/i8042.c b/drivers/input/serio/i8042.c
index cb5ece7..9c74afb 100644
--- a/drivers/input/serio/i8042.c
+++ b/drivers/input/serio/i8042.c
@@ -1546,5 +1546,13 @@ static void __exit i8042_exit(void)
 	panic_blink = NULL;
 }
 
-module_init(i8042_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	//drvid_pnp,
+	drvid_pnp_system,
+	drvid_pnpacpi,
+	drvid_serio,
+	0
+};
+
+annotated_module_init(i8042_init, drvid_i8042, dependencies);
 module_exit(i8042_exit);
diff --git a/drivers/input/serio/serio.c b/drivers/input/serio/serio.c
index a05a517..92fae98 100644
--- a/drivers/input/serio/serio.c
+++ b/drivers/input/serio/serio.c
@@ -1054,5 +1054,5 @@ static void __exit serio_exit(void)
 	cancel_work_sync(&serio_event_work);
 }
 
-subsys_initcall(serio_init);
+annotated_initcall(subsys, serio_init, drvid_serio, NULL);
 module_exit(serio_exit);
diff --git a/drivers/input/serio/serio_raw.c b/drivers/input/serio/serio_raw.c
index 71ef5d6..76e5213 100644
--- a/drivers/input/serio/serio_raw.c
+++ b/drivers/input/serio/serio_raw.c
@@ -441,4 +441,10 @@ static struct serio_driver serio_raw_drv = {
 	.manual_bind	= true,
 };
 
-module_serio_driver(serio_raw_drv);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_serio,
+	drvid_misc,
+	0
+};
+
+annotated_module_serio_driver(serio_raw_drv, drvid_serio_raw, dependencies);
diff --git a/drivers/input/serio/serport.c b/drivers/input/serio/serport.c
index 9c927d3..7b6217e 100644
--- a/drivers/input/serio/serport.c
+++ b/drivers/input/serio/serport.c
@@ -296,5 +296,10 @@ static void __exit serport_exit(void)
 	tty_unregister_ldisc(N_MOUSE);
 }
 
-module_init(serport_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_serio,
+	0
+};
+
+annotated_module_init(serport_init, drvid_serport, dependencies);
 module_exit(serport_exit);
diff --git a/drivers/iommu/amd_iommu_v2.c b/drivers/iommu/amd_iommu_v2.c
index f7b875b..6868cea 100644
--- a/drivers/iommu/amd_iommu_v2.c
+++ b/drivers/iommu/amd_iommu_v2.c
@@ -984,5 +984,10 @@ static void __exit amd_iommu_v2_exit(void)
 	destroy_workqueue(iommu_wq);
 }
 
-module_init(amd_iommu_v2_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_iommu_dev,
+	0
+};
+
+annotated_module_init(amd_iommu_v2_init, drvid_amd_iommu_v2, dependencies);
 module_exit(amd_iommu_v2_exit);
diff --git a/drivers/iommu/intel_irq_remapping.c b/drivers/iommu/intel_irq_remapping.c
index f15692a..8960235 100644
--- a/drivers/iommu/intel_irq_remapping.c
+++ b/drivers/iommu/intel_irq_remapping.c
@@ -942,7 +942,17 @@ static int __init ir_dev_scope_init(void)
 
 	return ret;
 }
-rootfs_initcall(ir_dev_scope_init);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_iommu_dev,
+	drvid_pci_subsys,
+	drvid_pcibios_assign_resources,
+	drvid_pnpacpi, // optional
+	drvid_pci_quirks, // optional
+	0
+};
+
+annotated_initcall(rootfs, ir_dev_scope_init, drvid_ir_dev_scope, dependencies);
 
 static void disable_irq_remapping(void)
 {
diff --git a/drivers/iommu/iommu-sysfs.c b/drivers/iommu/iommu-sysfs.c
index 39b2d91..1795473 100644
--- a/drivers/iommu/iommu-sysfs.c
+++ b/drivers/iommu/iommu-sysfs.c
@@ -47,7 +47,13 @@ static int __init iommu_dev_init(void)
 {
 	return class_register(&iommu_class);
 }
-postcore_initcall(iommu_dev_init);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_iommu,
+	0
+};
+
+annotated_initcall(postcore, iommu_dev_init, drvid_iommu_dev, dependencies);
 
 /*
  * Create an IOMMU device and return a pointer to it.  IOMMU specific
diff --git a/drivers/iommu/iommu.c b/drivers/iommu/iommu.c
index f286090..5c833cb 100644
--- a/drivers/iommu/iommu.c
+++ b/drivers/iommu/iommu.c
@@ -1468,7 +1468,7 @@ static int __init iommu_init(void)
 
 	return 0;
 }
-core_initcall(iommu_init);
+annotated_initcall(core, iommu_init, drvid_iommu, NULL);
 
 int iommu_domain_get_attr(struct iommu_domain *domain,
 			  enum iommu_attr attr, void *data)
diff --git a/drivers/iommu/omap-iommu.c b/drivers/iommu/omap-iommu.c
index a22c33d..cdefba6 100644
--- a/drivers/iommu/omap-iommu.c
+++ b/drivers/iommu/omap-iommu.c
@@ -1405,8 +1405,15 @@ static int __init omap_iommu_init(void)
 
 	return platform_driver_register(&omap_iommu_driver);
 }
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_iommu_dev,
+	drvid_debugfs,
+	0
+};
+
 /* must be ready before omap3isp is probed */
-subsys_initcall(omap_iommu_init);
+annotated_initcall_drv(subsys, omap_iommu_init, drvid_omap_iommu, dependencies, omap_iommu_driver.driver);
 
 static void __exit omap_iommu_exit(void)
 {
diff --git a/drivers/leds/led-class.c b/drivers/leds/led-class.c
index beabfbc..99368a7 100644
--- a/drivers/leds/led-class.c
+++ b/drivers/leds/led-class.c
@@ -399,7 +399,7 @@ static void __exit leds_exit(void)
 	class_destroy(leds_class);
 }
 
-subsys_initcall(leds_init);
+annotated_initcall(subsys, leds_init, drvid_leds, NULL);
 module_exit(leds_exit);
 
 MODULE_AUTHOR("John Lenz, Richard Purdie");
diff --git a/drivers/leds/leds-gpio.c b/drivers/leds/leds-gpio.c
index af1876a..5f4f816 100644
--- a/drivers/leds/leds-gpio.c
+++ b/drivers/leds/leds-gpio.c
@@ -300,7 +300,12 @@ static struct platform_driver gpio_led_driver = {
 	},
 };
 
-module_platform_driver(gpio_led_driver);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_leds,
+	0
+};
+
+annotated_module_platform_driver(gpio_led_driver, drvid_gpio_led, dependencies);
 
 MODULE_AUTHOR("Raphael Assenat <raph@8d.com>, Trent Piepho <tpiepho@freescale.com>");
 MODULE_DESCRIPTION("GPIO LED driver");
diff --git a/drivers/leds/leds-regulator.c b/drivers/leds/leds-regulator.c
index ffc2139..960110a 100644
--- a/drivers/leds/leds-regulator.c
+++ b/drivers/leds/leds-regulator.c
@@ -218,7 +218,12 @@ static struct platform_driver regulator_led_driver = {
 	.remove = regulator_led_remove,
 };
 
-module_platform_driver(regulator_led_driver);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_leds,
+	0
+};
+
+annotated_module_platform_driver(regulator_led_driver, drvid_leds_regulator, dependencies);
 
 MODULE_AUTHOR("Antonio Ospite <ospite@studenti.unina.it>");
 MODULE_DESCRIPTION("Regulator driven LED driver");
diff --git a/drivers/leds/trigger/ledtrig-heartbeat.c b/drivers/leds/trigger/ledtrig-heartbeat.c
index fea6871..81c1076 100644
--- a/drivers/leds/trigger/ledtrig-heartbeat.c
+++ b/drivers/leds/trigger/ledtrig-heartbeat.c
@@ -153,7 +153,12 @@ static void __exit heartbeat_trig_exit(void)
 	led_trigger_unregister(&heartbeat_led_trigger);
 }
 
-module_init(heartbeat_trig_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_leds,
+	0
+};
+
+annotated_module_init(heartbeat_trig_init, drvid_ledtrig_heartbeat, dependencies);
 module_exit(heartbeat_trig_exit);
 
 MODULE_AUTHOR("Atsushi Nemoto <anemo@mba.ocn.ne.jp>");
diff --git a/drivers/mailbox/omap-mailbox.c b/drivers/mailbox/omap-mailbox.c
index a3dbfd9..e3b110a 100644
--- a/drivers/mailbox/omap-mailbox.c
+++ b/drivers/mailbox/omap-mailbox.c
@@ -883,7 +883,7 @@ static int __init omap_mbox_init(void)
 
 	return platform_driver_register(&omap_mbox_driver);
 }
-subsys_initcall(omap_mbox_init);
+annotated_initcall_drv(subsys, omap_mbox_init, drvid_omap_mbox, NULL, omap_mbox_driver.driver);
 
 static void __exit omap_mbox_exit(void)
 {
diff --git a/drivers/md/md.c b/drivers/md/md.c
index e25f00f..f7479bd 100644
--- a/drivers/md/md.c
+++ b/drivers/md/md.c
@@ -9037,7 +9037,12 @@ static __exit void md_exit(void)
 	destroy_workqueue(md_wq);
 }
 
-subsys_initcall(md_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_xor,
+	0
+};
+
+annotated_initcall(subsys, md_init, drvid_md, dependencies);
 module_exit(md_exit)
 
 static int get_ro(char *buffer, struct kernel_param *kp)
diff --git a/drivers/md/raid5.c b/drivers/md/raid5.c
index f757023..6fbdbd0 100644
--- a/drivers/md/raid5.c
+++ b/drivers/md/raid5.c
@@ -7851,6 +7851,11 @@ static void raid5_exit(void)
 	destroy_workqueue(raid5_wq);
 }
 
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_wq_sysfs,
+	0
+};
+
 module_init(raid5_init);
 module_exit(raid5_exit);
 MODULE_LICENSE("GPL");
diff --git a/drivers/media/i2c/ir-kbd-i2c.c b/drivers/media/i2c/ir-kbd-i2c.c
index 175a761..3f27442 100644
--- a/drivers/media/i2c/ir-kbd-i2c.c
+++ b/drivers/media/i2c/ir-kbd-i2c.c
@@ -488,7 +488,12 @@ static struct i2c_driver ir_kbd_driver = {
 	.id_table       = ir_kbd_id,
 };
 
-module_i2c_driver(ir_kbd_driver);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_i2c,
+	0
+};
+
+annotated_module_i2c_driver(ir_kbd_driver, drvid_ir_kbd_i2c, dependencies);
 
 /* ----------------------------------------------------------------------- */
 
diff --git a/drivers/memory/omap-gpmc.c b/drivers/memory/omap-gpmc.c
index 9426276..9b32f93 100644
--- a/drivers/memory/omap-gpmc.c
+++ b/drivers/memory/omap-gpmc.c
@@ -2217,7 +2217,7 @@ static __exit void gpmc_exit(void)
 
 }
 
-postcore_initcall(gpmc_init);
+annotated_initcall_drv(postcore, gpmc_init, drvid_omap_gpmc, NULL, gpmc_driver.driver);
 module_exit(gpmc_exit);
 
 static irqreturn_t gpmc_handle_irq(int irq, void *dev)
diff --git a/drivers/mfd/omap-usb-host.c b/drivers/mfd/omap-usb-host.c
index 1d924d1..0ee78b8 100644
--- a/drivers/mfd/omap-usb-host.c
+++ b/drivers/mfd/omap-usb-host.c
@@ -896,7 +896,7 @@ static int __init omap_usbhs_drvinit(void)
  * This usbhs core driver should be initialized after
  * usb tll driver
  */
-fs_initcall_sync(omap_usbhs_drvinit);
+annotated_initcall_drv_sync(fs, omap_usbhs_drvinit, drvid_usbhs_omap, NULL, usbhs_omap_driver.driver);
 
 static void __exit omap_usbhs_drvexit(void)
 {
diff --git a/drivers/mfd/omap-usb-tll.c b/drivers/mfd/omap-usb-tll.c
index b7b3e8e..5221a90 100644
--- a/drivers/mfd/omap-usb-tll.c
+++ b/drivers/mfd/omap-usb-tll.c
@@ -475,7 +475,7 @@ static int __init omap_usbtll_drvinit(void)
  * The usbtll driver should be initialized before
  * the usbhs core driver probe function is called.
  */
-fs_initcall(omap_usbtll_drvinit);
+annotated_initcall_drv(fs, omap_usbtll_drvinit, drvid_omap_usbtll, NULL, usbtll_omap_driver.driver);
 
 static void __exit omap_usbtll_drvexit(void)
 {
diff --git a/drivers/mfd/ti_am335x_tscadc.c b/drivers/mfd/ti_am335x_tscadc.c
index e4e4b22..f8857b0 100644
--- a/drivers/mfd/ti_am335x_tscadc.c
+++ b/drivers/mfd/ti_am335x_tscadc.c
@@ -373,7 +373,7 @@ static struct platform_driver ti_tscadc_driver = {
 
 };
 
-module_platform_driver(ti_tscadc_driver);
+annotated_module_platform_driver(ti_tscadc_driver, drvid_ti_tscadc, NULL);
 
 MODULE_DESCRIPTION("TI touchscreen / ADC MFD controller driver");
 MODULE_AUTHOR("Rachna Patil <rachna@ti.com>");
diff --git a/drivers/mfd/tps65217.c b/drivers/mfd/tps65217.c
index 7d1cfc1..d1665ee 100644
--- a/drivers/mfd/tps65217.c
+++ b/drivers/mfd/tps65217.c
@@ -260,7 +260,15 @@ static int __init tps65217_init(void)
 {
 	return i2c_add_driver(&tps65217_driver);
 }
-subsys_initcall(tps65217_init);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_i2c,
+	drvid_input,
+	drvid_regulator,
+	0
+};
+
+annotated_initcall_drv(subsys, tps65217_init, drvid_tps65217, dependencies, tps65217_driver.driver);
 
 static void __exit tps65217_exit(void)
 {
diff --git a/drivers/mfd/tps65910.c b/drivers/mfd/tps65910.c
index 7612d89..36f2723 100644
--- a/drivers/mfd/tps65910.c
+++ b/drivers/mfd/tps65910.c
@@ -557,7 +557,14 @@ static int __init tps65910_i2c_init(void)
 	return i2c_add_driver(&tps65910_i2c_driver);
 }
 /* init early so consumer devices can complete system boot */
-subsys_initcall(tps65910_i2c_init);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_i2c,
+	drvid_tps65910,
+	0
+};
+
+annotated_initcall_drv(subsys, tps65910_i2c_init, drvid_tps65910_i2c, dependencies, tps65910_i2c_driver.driver);
 
 static void __exit tps65910_i2c_exit(void)
 {
diff --git a/drivers/mfd/twl-core.c b/drivers/mfd/twl-core.c
index 489674a..17228dd 100644
--- a/drivers/mfd/twl-core.c
+++ b/drivers/mfd/twl-core.c
@@ -1271,7 +1271,13 @@ static struct i2c_driver twl_driver = {
 	.remove		= twl_remove,
 };
 
-module_i2c_driver(twl_driver);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_i2c,
+	drvid_gpio_twl4030,
+	0
+};
+
+annotated_module_i2c_driver(twl_driver, drvid_twl_core, dependencies);
 
 MODULE_AUTHOR("Texas Instruments, Inc.");
 MODULE_DESCRIPTION("I2C Core interface for TWL");
diff --git a/drivers/mfd/twl4030-audio.c b/drivers/mfd/twl4030-audio.c
index 0a16064..882c2ef 100644
--- a/drivers/mfd/twl4030-audio.c
+++ b/drivers/mfd/twl4030-audio.c
@@ -290,7 +290,12 @@ static struct platform_driver twl4030_audio_driver = {
 	.remove		= twl4030_audio_remove,
 };
 
-module_platform_driver(twl4030_audio_driver);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_twl_core,
+	0
+};
+
+annotated_module_platform_driver(twl4030_audio_driver, drvid_twl4030_audio, dependencies);
 
 MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>");
 MODULE_DESCRIPTION("TWL4030 audio block MFD driver");
diff --git a/drivers/mfd/twl4030-power.c b/drivers/mfd/twl4030-power.c
index 04b5398..97d9592 100644
--- a/drivers/mfd/twl4030-power.c
+++ b/drivers/mfd/twl4030-power.c
@@ -970,7 +970,12 @@ static struct platform_driver twl4030_power_driver = {
 	.remove		= twl4030_power_remove,
 };
 
-module_platform_driver(twl4030_power_driver);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_twl_core,
+	0
+};
+
+annotated_module_platform_driver(twl4030_power_driver, drvid_twl4030_power, dependencies);
 
 MODULE_AUTHOR("Nokia Corporation");
 MODULE_AUTHOR("Texas Instruments, Inc.");
diff --git a/drivers/misc/eeprom/at24.c b/drivers/misc/eeprom/at24.c
index 6ded3dc..367abcd 100644
--- a/drivers/misc/eeprom/at24.c
+++ b/drivers/misc/eeprom/at24.c
@@ -703,7 +703,13 @@ static int __init at24_init(void)
 	io_limit = rounddown_pow_of_two(io_limit);
 	return i2c_add_driver(&at24_driver);
 }
-module_init(at24_init);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_i2c,
+	0
+};
+
+annotated_module_init_drv(at24_init, drvid_at24, dependencies, at24_driver.driver);
 
 static void __exit at24_exit(void)
 {
diff --git a/drivers/misc/sram.c b/drivers/misc/sram.c
index 15c33cc..26c6ffe 100644
--- a/drivers/misc/sram.c
+++ b/drivers/misc/sram.c
@@ -243,4 +243,6 @@ static int __init sram_init(void)
 	return platform_driver_register(&sram_driver);
 }
 
+//annotated_initcall_drv(postcore, sram_init, drvid_sram, NULL, sram_driver.driver);
+// Needed by the initcall customize_machine
 postcore_initcall(sram_init);
diff --git a/drivers/mmc/card/block.c b/drivers/mmc/card/block.c
index a1b820f..f4beb2c 100644
--- a/drivers/mmc/card/block.c
+++ b/drivers/mmc/card/block.c
@@ -2608,7 +2608,12 @@ static void __exit mmc_blk_exit(void)
 	unregister_blkdev(MMC_BLOCK_MAJOR, "mmc");
 }
 
-module_init(mmc_blk_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_mmc,
+	0
+};
+
+annotated_module_init(mmc_blk_init, drvid_mmcblk, dependencies);
 module_exit(mmc_blk_exit);
 
 MODULE_LICENSE("GPL");
diff --git a/drivers/mmc/core/core.c b/drivers/mmc/core/core.c
index 9e3fdbd..f6472b6 100644
--- a/drivers/mmc/core/core.c
+++ b/drivers/mmc/core/core.c
@@ -2829,7 +2829,12 @@ static void __exit mmc_exit(void)
 	destroy_workqueue(workqueue);
 }
 
-subsys_initcall(mmc_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_debugfs,
+	0
+};
+
+annotated_initcall(subsys, mmc_init, drvid_mmc, dependencies);
 module_exit(mmc_exit);
 
 MODULE_LICENSE("GPL");
diff --git a/drivers/mmc/host/mxs-mmc.c b/drivers/mmc/host/mxs-mmc.c
index d839147..2449792 100644
--- a/drivers/mmc/host/mxs-mmc.c
+++ b/drivers/mmc/host/mxs-mmc.c
@@ -737,7 +737,12 @@ static struct platform_driver mxs_mmc_driver = {
 	},
 };
 
-module_platform_driver(mxs_mmc_driver);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_mmc,
+	0
+};
+
+annotated_module_platform_driver(mxs_mmc_driver, drvid_mxs_mmc, dependencies);
 
 MODULE_DESCRIPTION("FREESCALE MXS MMC peripheral");
 MODULE_AUTHOR("Freescale Semiconductor");
diff --git a/drivers/mmc/host/omap.c b/drivers/mmc/host/omap.c
index 68dd6c7..70c364c 100644
--- a/drivers/mmc/host/omap.c
+++ b/drivers/mmc/host/omap.c
@@ -1498,7 +1498,12 @@ static struct platform_driver mmc_omap_driver = {
 	},
 };
 
-module_platform_driver(mmc_omap_driver);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_mmc,
+	0
+};
+
+annotated_module_platform_driver(mmc_omap_driver, drvid_mmc_omap, dependencies);
 MODULE_DESCRIPTION("OMAP Multimedia Card driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/drivers/mmc/host/omap_hsmmc.c b/drivers/mmc/host/omap_hsmmc.c
index 4d12032..759a642 100644
--- a/drivers/mmc/host/omap_hsmmc.c
+++ b/drivers/mmc/host/omap_hsmmc.c
@@ -2301,7 +2301,12 @@ static struct platform_driver omap_hsmmc_driver = {
 	},
 };
 
-module_platform_driver(omap_hsmmc_driver);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_mmc,
+	0
+};
+
+annotated_module_platform_driver(omap_hsmmc_driver, drvid_omap_hsmmc, dependencies);
 MODULE_DESCRIPTION("OMAP High Speed Multimedia Card driver");
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:" DRIVER_NAME);
diff --git a/drivers/mmc/host/sdhci-esdhc-imx.c b/drivers/mmc/host/sdhci-esdhc-imx.c
index c6b9f64..0131369 100644
--- a/drivers/mmc/host/sdhci-esdhc-imx.c
+++ b/drivers/mmc/host/sdhci-esdhc-imx.c
@@ -1202,7 +1202,12 @@ static struct platform_driver sdhci_esdhc_imx_driver = {
 	.remove		= sdhci_esdhc_imx_remove,
 };
 
-module_platform_driver(sdhci_esdhc_imx_driver);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_sdhci,
+	0
+};
+
+annotated_module_platform_driver(sdhci_esdhc_imx_driver, drvid_sdhci_esdhc_imx, dependencies);
 
 MODULE_DESCRIPTION("SDHCI driver for Freescale i.MX eSDHC");
 MODULE_AUTHOR("Wolfram Sang <kernel@pengutronix.de>");
diff --git a/drivers/mmc/host/sdhci.c b/drivers/mmc/host/sdhci.c
index b0c915a..4693783 100644
--- a/drivers/mmc/host/sdhci.c
+++ b/drivers/mmc/host/sdhci.c
@@ -3482,7 +3482,12 @@ static void __exit sdhci_drv_exit(void)
 {
 }
 
-module_init(sdhci_drv_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_mmc,
+	0
+};
+
+annotated_module_init(sdhci_drv_init, drvid_sdhci, dependencies);
 module_exit(sdhci_drv_exit);
 
 module_param(debug_quirks, uint, 0444);
diff --git a/drivers/mtd/mtdcore.c b/drivers/mtd/mtdcore.c
index 8bbbb75..b30a47d 100644
--- a/drivers/mtd/mtdcore.c
+++ b/drivers/mtd/mtdcore.c
@@ -1303,7 +1303,12 @@ static void __exit cleanup_mtd(void)
 	bdi_destroy(&mtd_bdi);
 }
 
-module_init(init_mtd);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_bdi,
+	0
+};
+
+annotated_initcall_sync(fs, init_mtd, drvid_mtd, dependencies);
 module_exit(cleanup_mtd);
 
 MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/nand/omap2.c b/drivers/mtd/nand/omap2.c
index 60fa899..9a7e62f 100644
--- a/drivers/mtd/nand/omap2.c
+++ b/drivers/mtd/nand/omap2.c
@@ -2079,7 +2079,13 @@ static struct platform_driver omap_nand_driver = {
 	},
 };
 
-module_platform_driver(omap_nand_driver);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_mtd,
+	drvid_ofpart,
+	0
+};
+
+annotated_module_platform_driver(omap_nand_driver, drvid_omap2_nand, dependencies);
 
 MODULE_ALIAS("platform:" DRIVER_NAME);
 MODULE_LICENSE("GPL");
diff --git a/drivers/mtd/nand/omap_elm.c b/drivers/mtd/nand/omap_elm.c
index 376bfe1..0311687 100644
--- a/drivers/mtd/nand/omap_elm.c
+++ b/drivers/mtd/nand/omap_elm.c
@@ -570,7 +570,7 @@ static struct platform_driver elm_driver = {
 	.remove	= elm_remove,
 };
 
-module_platform_driver(elm_driver);
+annotated_module_platform_driver(elm_driver, drvid_omap_elm, NULL);
 
 MODULE_DESCRIPTION("ELM driver for BCH error correction");
 MODULE_AUTHOR("Texas Instruments");
diff --git a/drivers/mtd/nand/orion_nand.c b/drivers/mtd/nand/orion_nand.c
index c3c6d30..754c1d4 100644
--- a/drivers/mtd/nand/orion_nand.c
+++ b/drivers/mtd/nand/orion_nand.c
@@ -211,7 +211,13 @@ static struct platform_driver orion_nand_driver = {
 	},
 };
 
-module_platform_driver_probe(orion_nand_driver, orion_nand_probe);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_mtd,
+	drvid_ofpart,
+	0
+};
+
+annotated_module_platform_driver_probe(orion_nand_driver, orion_nand_probe, drvid_orion_nand, dependencies);
 
 MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Tzachi Perelstein");
diff --git a/drivers/mtd/ofpart.c b/drivers/mtd/ofpart.c
index aa26c32..334ddb5 100644
--- a/drivers/mtd/ofpart.c
+++ b/drivers/mtd/ofpart.c
@@ -184,7 +184,7 @@ static void __exit ofpart_parser_exit(void)
 	deregister_mtd_parser(&ofoldpart_parser);
 }
 
-module_init(ofpart_parser_init);
+annotated_initcall_sync(fs, ofpart_parser_init, drvid_ofpart, NULL);
 module_exit(ofpart_parser_exit);
 
 MODULE_LICENSE("GPL");
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index de63266d..a020c39 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -3645,7 +3645,14 @@ static struct platform_driver fec_driver = {
 	.remove	= fec_drv_remove,
 };
 
-module_platform_driver(fec_driver);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_pm,
+	drvid_phy_net,
+	drvid_net_dev,
+	0
+};
+
+annotated_module_platform_driver(fec_driver, drvid_fec, dependencies);
 
 MODULE_ALIAS("platform:"DRIVER_NAME);
 MODULE_LICENSE("GPL");
diff --git a/drivers/net/ethernet/intel/e1000/e1000_main.c b/drivers/net/ethernet/intel/e1000/e1000_main.c
index 74dc150..a39b125 100644
--- a/drivers/net/ethernet/intel/e1000/e1000_main.c
+++ b/drivers/net/ethernet/intel/e1000/e1000_main.c
@@ -264,7 +264,15 @@ static int __init e1000_init_module(void)
 	return ret;
 }
 
-module_init(e1000_init_module);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_pm,
+	drvid_phy_net,
+	drvid_net_dev,
+	drvid_pci_driver,
+	0
+};
+
+annotated_module_init(e1000_init_module, drvid_e1000, dependencies);
 
 /**
  * e1000_exit_module - Driver Exit Cleanup Routine
diff --git a/drivers/net/ethernet/marvell/mv643xx_eth.c b/drivers/net/ethernet/marvell/mv643xx_eth.c
index d52639b..0da9130 100644
--- a/drivers/net/ethernet/marvell/mv643xx_eth.c
+++ b/drivers/net/ethernet/marvell/mv643xx_eth.c
@@ -3239,7 +3239,16 @@ static int __init mv643xx_eth_init_module(void)
 
 	return rc;
 }
-module_init(mv643xx_eth_init_module);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_phy_net,
+	drvid_net_dev,
+	0
+};
+
+annotated_module_init_drv(mv643xx_eth_init_module,
+			drvid_mv643xx_eth, dependencies,
+			mv643xx_eth_shared_driver.driver);
 
 static void __exit mv643xx_eth_cleanup_module(void)
 {
diff --git a/drivers/net/ethernet/marvell/mvmdio.c b/drivers/net/ethernet/marvell/mvmdio.c
index fc2fb25..66ec955 100644
--- a/drivers/net/ethernet/marvell/mvmdio.c
+++ b/drivers/net/ethernet/marvell/mvmdio.c
@@ -293,7 +293,12 @@ static struct platform_driver orion_mdio_driver = {
 	},
 };
 
-module_platform_driver(orion_mdio_driver);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_phy_net,
+	0
+};
+
+annotated_module_platform_driver(orion_mdio_driver, drvid_orion_mdio, dependencies);
 
 MODULE_DESCRIPTION("Marvell MDIO interface driver");
 MODULE_AUTHOR("Thomas Petazzoni <thomas.petazzoni@free-electrons.com>");
diff --git a/drivers/net/ethernet/realtek/r8169.c b/drivers/net/ethernet/realtek/r8169.c
index f790f61..aa23a03 100644
--- a/drivers/net/ethernet/realtek/r8169.c
+++ b/drivers/net/ethernet/realtek/r8169.c
@@ -8372,4 +8372,12 @@ static struct pci_driver rtl8169_pci_driver = {
 	.driver.pm	= RTL8169_PM_OPS,
 };
 
-module_pci_driver(rtl8169_pci_driver);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_pm,
+	drvid_phy_net,
+	drvid_net_dev,
+	drvid_pci_driver,
+	0
+};
+
+annotated_module_pci_driver(rtl8169_pci_driver, drvid_r8169, dependencies);
diff --git a/drivers/net/ethernet/ti/cpsw-phy-sel.c b/drivers/net/ethernet/ti/cpsw-phy-sel.c
index 0ea78326..a6c44fe 100644
--- a/drivers/net/ethernet/ti/cpsw-phy-sel.c
+++ b/drivers/net/ethernet/ti/cpsw-phy-sel.c
@@ -215,6 +215,11 @@ static struct platform_driver cpsw_phy_sel_driver = {
 	},
 };
 
-module_platform_driver(cpsw_phy_sel_driver);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_phy_net,
+	0
+};
+
+annotated_module_platform_driver(cpsw_phy_sel_driver, drvid_cpsw_phy_sel, dependencies);
 MODULE_AUTHOR("Mugunthan V N <mugunthanvnm@ti.com>");
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/net/ethernet/ti/cpsw.c b/drivers/net/ethernet/ti/cpsw.c
index d155bf2..c393b90 100644
--- a/drivers/net/ethernet/ti/cpsw.c
+++ b/drivers/net/ethernet/ti/cpsw.c
@@ -2524,7 +2524,15 @@ static int __init cpsw_init(void)
 {
 	return platform_driver_register(&cpsw_driver);
 }
-late_initcall(cpsw_init);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_pm,
+	drvid_cpsw_phy_sel,
+	drvid_net_dev,
+	0
+};
+
+annotated_initcall_drv(late, cpsw_init, drvid_cpsw, dependencies, cpsw_driver.driver);
 
 static void __exit cpsw_exit(void)
 {
diff --git a/drivers/net/ethernet/ti/davinci_mdio.c b/drivers/net/ethernet/ti/davinci_mdio.c
index c00084d..f02215b 100644
--- a/drivers/net/ethernet/ti/davinci_mdio.c
+++ b/drivers/net/ethernet/ti/davinci_mdio.c
@@ -493,7 +493,14 @@ static int __init davinci_mdio_init(void)
 {
 	return platform_driver_register(&davinci_mdio_driver);
 }
-device_initcall(davinci_mdio_init);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_pm,
+	drvid_phy_net,
+	0
+};
+
+annotated_initcall_drv(device, davinci_mdio_init, drvid_davinci_mdio, NULL, davinci_mdio_driver.driver);
 
 static void __exit davinci_mdio_exit(void)
 {
diff --git a/drivers/net/irda/nsc-ircc.c b/drivers/net/irda/nsc-ircc.c
index dc0dbd8..f6bb325 100644
--- a/drivers/net/irda/nsc-ircc.c
+++ b/drivers/net/irda/nsc-ircc.c
@@ -2404,6 +2404,11 @@ MODULE_PARM_DESC(dma, "DMA channels");
 module_param(dongle_id, int, 0);
 MODULE_PARM_DESC(dongle_id, "Type-id of used dongle");
 
-module_init(nsc_ircc_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_pnp,
+	0
+};
+
+annotated_module_init(nsc_ircc_init, drvid_nsc_ircc, dependencies);
 module_exit(nsc_ircc_cleanup);
 
diff --git a/drivers/net/irda/smsc-ircc2.c b/drivers/net/irda/smsc-ircc2.c
index b455ffe..6b07303 100644
--- a/drivers/net/irda/smsc-ircc2.c
+++ b/drivers/net/irda/smsc-ircc2.c
@@ -3021,6 +3021,10 @@ static int smsc_ircc_probe_transceiver_toshiba_sat1800(int fir_base)
 	return 0;
 }
 
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_pnp,
+	0
+};
 
-module_init(smsc_ircc_init);
+annotated_module_init(smsc_ircc_init, drvid_smsc_ircc, dependencies);
 module_exit(smsc_ircc_cleanup);
diff --git a/drivers/net/phy/lxt.c b/drivers/net/phy/lxt.c
index a3a5a70..707a495 100644
--- a/drivers/net/phy/lxt.c
+++ b/drivers/net/phy/lxt.c
@@ -312,7 +312,12 @@ static struct phy_driver lxt97x_driver[] = {
 	.driver		= { .owner = THIS_MODULE,},
 } };
 
-module_phy_driver(lxt97x_driver);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_phy_net,
+	0
+};
+
+annotated_module_phy_driver(lxt97x_driver, drvid_phy_lxt, dependencies);
 
 static struct mdio_device_id __maybe_unused lxt_tbl[] = {
 	{ 0x78100000, 0xfffffff0 },
diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
index 55f0178..882df3c 100644
--- a/drivers/net/phy/phy_device.c
+++ b/drivers/net/phy/phy_device.c
@@ -1411,5 +1411,5 @@ static void __exit phy_exit(void)
 	mdio_bus_exit();
 }
 
-subsys_initcall(phy_init);
+annotated_initcall(subsys, phy_init, drvid_phy_net, NULL);
 module_exit(phy_exit);
diff --git a/drivers/net/phy/realtek.c b/drivers/net/phy/realtek.c
index 4535361..2444524 100644
--- a/drivers/net/phy/realtek.c
+++ b/drivers/net/phy/realtek.c
@@ -166,7 +166,12 @@ static struct phy_driver realtek_drvs[] = {
 	},
 };
 
-module_phy_driver(realtek_drvs);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_phy_net,
+	0
+};
+
+annotated_module_phy_driver(realtek_drvs, drvid_phy_realtek, dependencies);
 
 static struct mdio_device_id __maybe_unused realtek_tbl[] = {
 	{ 0x001cc912, 0x001fffff },
diff --git a/drivers/net/phy/smsc.c b/drivers/net/phy/smsc.c
index 70b0895..04735b2 100644
--- a/drivers/net/phy/smsc.c
+++ b/drivers/net/phy/smsc.c
@@ -257,7 +257,12 @@ static struct phy_driver smsc_phy_driver[] = {
 	.driver		= { .owner = THIS_MODULE, }
 } };
 
-module_phy_driver(smsc_phy_driver);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_phy_net,
+	0
+};
+
+annotated_module_phy_driver(smsc_phy_driver, drvid_phy_smsc, dependencies);
 
 MODULE_DESCRIPTION("SMSC PHY driver");
 MODULE_AUTHOR("Herbert Valerio Riedel");
diff --git a/drivers/pci/hotplug/pci_hotplug_core.c b/drivers/pci/hotplug/pci_hotplug_core.c
index 56d8486..7609d79 100644
--- a/drivers/pci/hotplug/pci_hotplug_core.c
+++ b/drivers/pci/hotplug/pci_hotplug_core.c
@@ -545,7 +545,16 @@ static void __exit pci_hotplug_exit(void)
 	cpci_hotplug_exit();
 }
 
-module_init(pci_hotplug_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_pci_subsys,
+	drvid_pcibios_assign_resources,
+	drvid_pnpacpi, // optional
+	drvid_pci_quirks, // optional
+	drvid_pci_slot,
+	0
+};
+
+annotated_module_init(pci_hotplug_init, drvid_pci_hotplug, dependencies);
 module_exit(pci_hotplug_exit);
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
diff --git a/drivers/pci/pci-acpi.c b/drivers/pci/pci-acpi.c
index 314a625..d1aadca 100644
--- a/drivers/pci/pci-acpi.c
+++ b/drivers/pci/pci-acpi.c
@@ -713,4 +713,10 @@ static int __init acpi_pci_init(void)
 
 	return 0;
 }
-arch_initcall(acpi_pci_init);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_pci_driver,
+	0
+};
+
+annotated_initcall(arch, acpi_pci_init, drvid_pci_acpi, dependencies);
diff --git a/drivers/pci/pci-driver.c b/drivers/pci/pci-driver.c
index 3cb2210..a1c1f7a 100644
--- a/drivers/pci/pci-driver.c
+++ b/drivers/pci/pci-driver.c
@@ -1412,4 +1412,10 @@ static int __init pci_driver_init(void)
 {
 	return bus_register(&pci_bus_type);
 }
-postcore_initcall(pci_driver_init);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_pcibus_class,
+	0
+};
+
+annotated_initcall(postcore, pci_driver_init, drvid_pci_driver, dependencies);
diff --git a/drivers/pci/pci-stub.c b/drivers/pci/pci-stub.c
index 886fb35..e90584e 100644
--- a/drivers/pci/pci-stub.c
+++ b/drivers/pci/pci-stub.c
@@ -90,7 +90,15 @@ static void __exit pci_stub_exit(void)
 	pci_unregister_driver(&stub_driver);
 }
 
-module_init(pci_stub_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_pci_subsys,
+	drvid_pcibios_assign_resources,
+	drvid_pnpacpi, // optional
+	drvid_pci_quirks, // optional
+	0
+};
+
+annotated_module_init(pci_stub_init, drvid_pci_stub, dependencies);
 module_exit(pci_stub_exit);
 
 MODULE_LICENSE("GPL");
diff --git a/drivers/pci/probe.c b/drivers/pci/probe.c
index f6ae0d0..1400762 100644
--- a/drivers/pci/probe.c
+++ b/drivers/pci/probe.c
@@ -104,7 +104,7 @@ static int __init pcibus_class_init(void)
 {
 	return class_register(&pcibus_class);
 }
-postcore_initcall(pcibus_class_init);
+annotated_initcall(postcore, pcibus_class_init, drvid_pcibus_class, NULL);
 
 static u64 pci_size(u64 base, u64 maxbase, u64 mask)
 {
diff --git a/drivers/pci/proc.c b/drivers/pci/proc.c
index 3f155e7..53140ef 100644
--- a/drivers/pci/proc.c
+++ b/drivers/pci/proc.c
@@ -443,4 +443,13 @@ static int __init pci_proc_init(void)
 
 	return 0;
 }
-device_initcall(pci_proc_init);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_pci_subsys,
+	drvid_pcibios_assign_resources,
+	drvid_pnpacpi, // optional
+	drvid_pci_quirks, // optional
+	0
+};
+
+annotated_initcall(device, pci_proc_init, drvid_pci_proc, dependencies);
diff --git a/drivers/pci/quirks.c b/drivers/pci/quirks.c
index dbd1385..c1a4325 100644
--- a/drivers/pci/quirks.c
+++ b/drivers/pci/quirks.c
@@ -3343,7 +3343,14 @@ static int __init pci_apply_final_quirks(void)
 	return 0;
 }
 
-fs_initcall_sync(pci_apply_final_quirks);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_pci_subsys,
+	drvid_pcibios_assign_resources,
+	drvid_pnpacpi,
+	0
+};
+
+annotated_initcall_sync(fs, pci_apply_final_quirks, drvid_pci_quirks, dependencies);
 
 /*
  * Followings are device-specific reset methods which can be used to
diff --git a/drivers/pci/slot.c b/drivers/pci/slot.c
index 396c200..0bca701 100644
--- a/drivers/pci/slot.c
+++ b/drivers/pci/slot.c
@@ -394,4 +394,10 @@ static int pci_slot_init(void)
 	return 0;
 }
 
-subsys_initcall(pci_slot_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_pci_arch, // x86
+	drvid_pci_driver,
+	0
+};
+
+annotated_initcall(subsys, pci_slot_init, drvid_pci_slot, dependencies);
diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c
index fc48fac..d482079 100644
--- a/drivers/phy/phy-core.c
+++ b/drivers/phy/phy-core.c
@@ -930,7 +930,7 @@ static int __init phy_core_init(void)
 
 	return 0;
 }
-module_init(phy_core_init);
+annotated_module_init(phy_core_init, drvid_phy, NULL);
 
 static void __exit phy_core_exit(void)
 {
diff --git a/drivers/phy/phy-mvebu-sata.c b/drivers/phy/phy-mvebu-sata.c
index 03b94f9..4a79693 100644
--- a/drivers/phy/phy-mvebu-sata.c
+++ b/drivers/phy/phy-mvebu-sata.c
@@ -131,7 +131,13 @@ static struct platform_driver phy_mvebu_sata_driver = {
 		.of_match_table	= phy_mvebu_sata_of_match,
 	}
 };
-module_platform_driver(phy_mvebu_sata_driver);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_phy,
+	0
+};
+
+annotated_module_platform_driver(phy_mvebu_sata_driver, drvid_phy_mvebu_sata, dependencies);
 
 MODULE_AUTHOR("Andrew Lunn <andrew@lunn.ch>");
 MODULE_DESCRIPTION("Marvell MVEBU SATA PHY driver");
diff --git a/drivers/phy/phy-twl4030-usb.c b/drivers/phy/phy-twl4030-usb.c
index 3a707dd..18c44e7 100644
--- a/drivers/phy/phy-twl4030-usb.c
+++ b/drivers/phy/phy-twl4030-usb.c
@@ -801,7 +801,13 @@ static int __init twl4030_usb_init(void)
 {
 	return platform_driver_register(&twl4030_usb_driver);
 }
-subsys_initcall(twl4030_usb_init);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_phy,
+	0
+};
+
+annotated_initcall_drv(subsys, twl4030_usb_init, drvid_twl4030_usb, NULL, twl4030_usb_driver.driver);
 
 static void __exit twl4030_usb_exit(void)
 {
diff --git a/drivers/pinctrl/freescale/pinctrl-imx6q.c b/drivers/pinctrl/freescale/pinctrl-imx6q.c
index 4d1fcb8..b93996b 100644
--- a/drivers/pinctrl/freescale/pinctrl-imx6q.c
+++ b/drivers/pinctrl/freescale/pinctrl-imx6q.c
@@ -489,7 +489,7 @@ static int __init imx6q_pinctrl_init(void)
 {
 	return platform_driver_register(&imx6q_pinctrl_driver);
 }
-arch_initcall(imx6q_pinctrl_init);
+annotated_initcall_drv(arch, imx6q_pinctrl_init, drvid_imx6q_pinctrl, NULL, imx6q_pinctrl_driver.driver);
 
 static void __exit imx6q_pinctrl_exit(void)
 {
diff --git a/drivers/pinctrl/mvebu/pinctrl-kirkwood.c b/drivers/pinctrl/mvebu/pinctrl-kirkwood.c
index 0f07dc5..72da5f5 100644
--- a/drivers/pinctrl/mvebu/pinctrl-kirkwood.c
+++ b/drivers/pinctrl/mvebu/pinctrl-kirkwood.c
@@ -495,7 +495,7 @@ static struct platform_driver kirkwood_pinctrl_driver = {
 	.remove = kirkwood_pinctrl_remove,
 };
 
-module_platform_driver(kirkwood_pinctrl_driver);
+annotated_module_platform_driver(kirkwood_pinctrl_driver, drvid_kirkwood_pinctrl, NULL);
 
 MODULE_AUTHOR("Sebastian Hesselbarth <sebastian.hesselbarth@gmail.com>");
 MODULE_DESCRIPTION("Marvell Kirkwood pinctrl driver");
diff --git a/drivers/pinctrl/pinctrl-single.c b/drivers/pinctrl/pinctrl-single.c
index 0b8d480..f450e29 100644
--- a/drivers/pinctrl/pinctrl-single.c
+++ b/drivers/pinctrl/pinctrl-single.c
@@ -2026,7 +2026,7 @@ static struct platform_driver pcs_driver = {
 #endif
 };
 
-module_platform_driver(pcs_driver);
+annotated_module_platform_driver(pcs_driver, drvid_pcs, NULL);
 
 MODULE_AUTHOR("Tony Lindgren <tony@atomide.com>");
 MODULE_DESCRIPTION("One-register-per-pin type device tree based pinctrl driver");
diff --git a/drivers/platform/x86/asus-wmi.c b/drivers/platform/x86/asus-wmi.c
index efbc3f0..9f99208 100644
--- a/drivers/platform/x86/asus-wmi.c
+++ b/drivers/platform/x86/asus-wmi.c
@@ -2275,5 +2275,16 @@ static void __exit asus_wmi_exit(void)
 	pr_info("ASUS WMI generic driver unloaded\n");
 }
 
-module_init(asus_wmi_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_acpi_wmi,
+	drvid_debugfs,
+	drvid_input,
+	drvid_leds,
+	drvid_rfkill,
+	drvid_backlight_class,
+	drvid_hwmon,
+	0
+};
+
+annotated_module_init(asus_wmi_init, drvid_asus_wmi, dependencies);
 module_exit(asus_wmi_exit);
diff --git a/drivers/platform/x86/eeepc-wmi.c b/drivers/platform/x86/eeepc-wmi.c
index 14fd2ec..0fb1baa 100644
--- a/drivers/platform/x86/eeepc-wmi.c
+++ b/drivers/platform/x86/eeepc-wmi.c
@@ -274,5 +274,11 @@ static void __exit eeepc_wmi_exit(void)
 	asus_wmi_unregister_driver(&asus_wmi_driver);
 }
 
-module_init(eeepc_wmi_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_asus_wmi,
+	drvid_dmi,
+	0
+};
+
+annotated_module_init(eeepc_wmi_init, drvid_eeepc_wmi, dependencies);
 module_exit(eeepc_wmi_exit);
diff --git a/drivers/platform/x86/wmi.c b/drivers/platform/x86/wmi.c
index aac4757..fb6550d 100644
--- a/drivers/platform/x86/wmi.c
+++ b/drivers/platform/x86/wmi.c
@@ -965,5 +965,10 @@ static void __exit acpi_wmi_exit(void)
 	pr_info("Mapper unloaded\n");
 }
 
-subsys_initcall(acpi_wmi_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_acpi,
+	0
+};
+
+annotated_initcall(subsys, acpi_wmi_init, drvid_acpi_wmi, dependencies);
 module_exit(acpi_wmi_exit);
diff --git a/drivers/pnp/core.c b/drivers/pnp/core.c
index b54620e..aa3b972 100644
--- a/drivers/pnp/core.c
+++ b/drivers/pnp/core.c
@@ -243,7 +243,7 @@ static int __init pnp_init(void)
 	return bus_register(&pnp_bus_type);
 }
 
-subsys_initcall(pnp_init);
+annotated_initcall(subsys, pnp_init, drvid_pnp, NULL);
 
 int pnp_debug;
 
diff --git a/drivers/pnp/pnpacpi/core.c b/drivers/pnp/pnpacpi/core.c
index 5153d1d..0bb6709e 100644
--- a/drivers/pnp/pnpacpi/core.c
+++ b/drivers/pnp/pnpacpi/core.c
@@ -324,7 +324,13 @@ static int __init pnpacpi_init(void)
 	return 0;
 }
 
-fs_initcall(pnpacpi_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_pnp,
+	drvid_acpi,
+	0
+};
+
+annotated_initcall(fs, pnpacpi_init, drvid_pnpacpi, dependencies);
 
 static int __init pnpacpi_setup(char *str)
 {
diff --git a/drivers/pnp/system.c b/drivers/pnp/system.c
index 49c1720..6f7100d 100644
--- a/drivers/pnp/system.c
+++ b/drivers/pnp/system.c
@@ -109,4 +109,9 @@ static int __init pnp_system_init(void)
  * Reserve motherboard resources after PCI claim BARs,
  * but before PCI assign resources for uninitialized PCI devices
  */
-fs_initcall(pnp_system_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_pnp,
+	0
+};
+
+annotated_initcall(fs, pnp_system_init, drvid_pnp_system, dependencies);
diff --git a/drivers/power/power_supply_core.c b/drivers/power/power_supply_core.c
index 869284c..58891cc 100644
--- a/drivers/power/power_supply_core.c
+++ b/drivers/power/power_supply_core.c
@@ -970,7 +970,7 @@ static void __exit power_supply_class_exit(void)
 	class_destroy(power_supply_class);
 }
 
-subsys_initcall(power_supply_class_init);
+annotated_initcall(subsys, power_supply_class_init, drvid_power_supply_class, NULL);
 module_exit(power_supply_class_exit);
 
 MODULE_DESCRIPTION("Universal power supply monitor class");
diff --git a/drivers/power/reset/gpio-poweroff.c b/drivers/power/reset/gpio-poweroff.c
index be3d81f..e8419c3 100644
--- a/drivers/power/reset/gpio-poweroff.c
+++ b/drivers/power/reset/gpio-poweroff.c
@@ -94,7 +94,7 @@ static struct platform_driver gpio_poweroff_driver = {
 	},
 };
 
-module_platform_driver(gpio_poweroff_driver);
+annotated_module_platform_driver(gpio_poweroff_driver, drvid_poweroff_gpio, NULL);
 
 MODULE_AUTHOR("Jamie Lentin <jm@lentin.co.uk>");
 MODULE_DESCRIPTION("GPIO poweroff driver");
diff --git a/drivers/power/reset/imx-snvs-poweroff.c b/drivers/power/reset/imx-snvs-poweroff.c
index ad6ce50..a5b908c 100644
--- a/drivers/power/reset/imx-snvs-poweroff.c
+++ b/drivers/power/reset/imx-snvs-poweroff.c
@@ -63,4 +63,4 @@ static int __init imx_poweroff_init(void)
 {
 	return platform_driver_register(&imx_poweroff_driver);
 }
-device_initcall(imx_poweroff_init);
+annotated_initcall_drv(device, imx_poweroff_init, drvid_imx_poweroff, NULL, imx_poweroff_driver.driver);
diff --git a/drivers/power/twl4030_charger.c b/drivers/power/twl4030_charger.c
index 022b891..6e837dd 100644
--- a/drivers/power/twl4030_charger.c
+++ b/drivers/power/twl4030_charger.c
@@ -727,7 +727,7 @@ static struct platform_driver twl4030_bci_driver = {
 	.remove	= __exit_p(twl4030_bci_remove),
 };
 
-module_platform_driver_probe(twl4030_bci_driver, twl4030_bci_probe);
+annotated_module_platform_driver_probe(twl4030_bci_driver, twl4030_bci_probe, drvid_twl4030_bci, NULL);
 
 MODULE_AUTHOR("Gražvydas Ignotas");
 MODULE_DESCRIPTION("TWL4030 Battery Charger Interface driver");
diff --git a/drivers/pwm/core.c b/drivers/pwm/core.c
index 3a7769f..4d1a57a 100644
--- a/drivers/pwm/core.c
+++ b/drivers/pwm/core.c
@@ -925,5 +925,10 @@ static int __init pwm_debugfs_init(void)
 	return 0;
 }
 
-subsys_initcall(pwm_debugfs_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_debugfs,
+	0
+};
+
+annotated_initcall(subsys, pwm_debugfs_init, drvid_pwm_debugfs, dependencies);
 #endif /* CONFIG_DEBUG_FS */
diff --git a/drivers/pwm/pwm-imx.c b/drivers/pwm/pwm-imx.c
index 66d6f0c..a45833d 100644
--- a/drivers/pwm/pwm-imx.c
+++ b/drivers/pwm/pwm-imx.c
@@ -342,7 +342,7 @@ static struct platform_driver imx_pwm_driver = {
 	.remove		= imx_pwm_remove,
 };
 
-module_platform_driver(imx_pwm_driver);
+annotated_module_platform_driver(imx_pwm_driver, drvid_imx_pwm, NULL);
 
 MODULE_LICENSE("GPL v2");
 MODULE_AUTHOR("Sascha Hauer <s.hauer@pengutronix.de>");
diff --git a/drivers/pwm/pwm-tiecap.c b/drivers/pwm/pwm-tiecap.c
index e557bef..d10f652 100644
--- a/drivers/pwm/pwm-tiecap.c
+++ b/drivers/pwm/pwm-tiecap.c
@@ -338,7 +338,7 @@ static struct platform_driver ecap_pwm_driver = {
 	.remove = ecap_pwm_remove,
 };
 
-module_platform_driver(ecap_pwm_driver);
+annotated_module_platform_driver(ecap_pwm_driver, drvid_ecap_pwm, NULL);
 
 MODULE_DESCRIPTION("ECAP PWM driver");
 MODULE_AUTHOR("Texas Instruments");
diff --git a/drivers/pwm/pwm-tiehrpwm.c b/drivers/pwm/pwm-tiehrpwm.c
index 694b3cf..86c5614 100644
--- a/drivers/pwm/pwm-tiehrpwm.c
+++ b/drivers/pwm/pwm-tiehrpwm.c
@@ -606,7 +606,7 @@ static struct platform_driver ehrpwm_pwm_driver = {
 	.remove = ehrpwm_pwm_remove,
 };
 
-module_platform_driver(ehrpwm_pwm_driver);
+annotated_module_platform_driver(ehrpwm_pwm_driver, drvid_ehrpwm_pwm, NULL);
 
 MODULE_DESCRIPTION("EHRPWM PWM driver");
 MODULE_AUTHOR("Texas Instruments");
diff --git a/drivers/pwm/pwm-tipwmss.c b/drivers/pwm/pwm-tipwmss.c
index 5cf65a1..8f7c8e4 100644
--- a/drivers/pwm/pwm-tipwmss.c
+++ b/drivers/pwm/pwm-tipwmss.c
@@ -126,7 +126,7 @@ static struct platform_driver pwmss_driver = {
 	.remove	= pwmss_remove,
 };
 
-module_platform_driver(pwmss_driver);
+annotated_module_platform_driver(pwmss_driver, drvid_pwmss, NULL);
 
 MODULE_DESCRIPTION("PWM Subsystem driver");
 MODULE_AUTHOR("Texas Instruments");
diff --git a/drivers/regulator/anatop-regulator.c b/drivers/regulator/anatop-regulator.c
index 738adfa..53fbdc7 100644
--- a/drivers/regulator/anatop-regulator.c
+++ b/drivers/regulator/anatop-regulator.c
@@ -331,7 +331,14 @@ static int __init anatop_regulator_init(void)
 {
 	return platform_driver_register(&anatop_regulator_driver);
 }
-postcore_initcall(anatop_regulator_init);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_regulator,
+	0
+};
+
+annotated_initcall_drv(postcore, anatop_regulator_init,
+		drvid_anatop_regulator, dependencies, anatop_regulator_driver.driver);
 
 static void __exit anatop_regulator_exit(void)
 {
diff --git a/drivers/regulator/core.c b/drivers/regulator/core.c
index 78387a6..f87acb7 100644
--- a/drivers/regulator/core.c
+++ b/drivers/regulator/core.c
@@ -4144,8 +4144,13 @@ static int __init regulator_init(void)
 	return ret;
 }
 
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_debugfs,
+	0
+};
+
 /* init early to allow our consumers to complete system booting */
-core_initcall(regulator_init);
+annotated_initcall(core, regulator_init, drvid_regulator, dependencies);
 
 static int __init regulator_init_complete(void)
 {
diff --git a/drivers/regulator/fixed.c b/drivers/regulator/fixed.c
index ff62d69..a47bb3b 100644
--- a/drivers/regulator/fixed.c
+++ b/drivers/regulator/fixed.c
@@ -221,7 +221,14 @@ static int __init regulator_fixed_voltage_init(void)
 {
 	return platform_driver_register(&regulator_fixed_voltage_driver);
 }
-subsys_initcall(regulator_fixed_voltage_init);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_regulator,
+	0
+};
+
+annotated_initcall_drv(subsys, regulator_fixed_voltage_init,
+		drvid_regulator_fixed_voltage, dependencies, regulator_fixed_voltage_driver.driver);
 
 static void __exit regulator_fixed_voltage_exit(void)
 {
diff --git a/drivers/regulator/tps65023-regulator.c b/drivers/regulator/tps65023-regulator.c
index b941e56..4050d3b 100644
--- a/drivers/regulator/tps65023-regulator.c
+++ b/drivers/regulator/tps65023-regulator.c
@@ -420,7 +420,14 @@ static int __init tps_65023_init(void)
 {
 	return i2c_add_driver(&tps_65023_i2c_driver);
 }
-subsys_initcall(tps_65023_init);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_regulator,
+	drvid_i2c,
+	0
+};
+
+annotated_initcall_drv(subsys, tps_65023_init, drvid_tps_65023, dependencies, tps_65023_i2c_driver.driver);
 
 static void __exit tps_65023_cleanup(void)
 {
diff --git a/drivers/regulator/tps65910-regulator.c b/drivers/regulator/tps65910-regulator.c
index fb991ec..704d7ad 100644
--- a/drivers/regulator/tps65910-regulator.c
+++ b/drivers/regulator/tps65910-regulator.c
@@ -1255,7 +1255,13 @@ static int __init tps65910_init(void)
 {
 	return platform_driver_register(&tps65910_driver);
 }
-subsys_initcall(tps65910_init);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_regulator,
+	0
+};
+
+annotated_initcall_drv(subsys, tps65910_init, drvid_tps65910, dependencies, tps65910_driver.driver);
 
 static void __exit tps65910_cleanup(void)
 {
diff --git a/drivers/regulator/twl-regulator.c b/drivers/regulator/twl-regulator.c
index 955a6fb..a1e29dc 100644
--- a/drivers/regulator/twl-regulator.c
+++ b/drivers/regulator/twl-regulator.c
@@ -22,7 +22,6 @@
 #include <linux/regulator/of_regulator.h>
 #include <linux/i2c/twl.h>
 
-
 /*
  * The TWL4030/TW5030/TPS659x0/TWL6030 family chips include power management, a
  * USB OTG transceiver, an RTC, ADC, PWM, and lots more.  Some versions
@@ -1229,7 +1228,14 @@ static int __init twlreg_init(void)
 {
 	return platform_driver_register(&twlreg_driver);
 }
-subsys_initcall(twlreg_init);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_regulator,
+	drvid_twl_core,
+	0
+};
+
+annotated_initcall_drv(subsys, twlreg_init, drvid_twlreg, dependencies, twlreg_driver.driver);
 
 static void __exit twlreg_exit(void)
 {
diff --git a/drivers/remoteproc/remoteproc_core.c b/drivers/remoteproc/remoteproc_core.c
index 8b3130f..d39d985 100644
--- a/drivers/remoteproc/remoteproc_core.c
+++ b/drivers/remoteproc/remoteproc_core.c
@@ -1474,7 +1474,13 @@ static int __init remoteproc_init(void)
 
 	return 0;
 }
-module_init(remoteproc_init);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_debugfs,
+	0
+};
+
+annotated_module_init(remoteproc_init, drvid_remoteproc, dependencies);
 
 static void __exit remoteproc_exit(void)
 {
diff --git a/drivers/remoteproc/wkup_m3_rproc.c b/drivers/remoteproc/wkup_m3_rproc.c
index edf8181..d79a627 100644
--- a/drivers/remoteproc/wkup_m3_rproc.c
+++ b/drivers/remoteproc/wkup_m3_rproc.c
@@ -250,7 +250,12 @@ static struct platform_driver wkup_m3_rproc_driver = {
 	},
 };
 
-module_platform_driver(wkup_m3_rproc_driver);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_debugfs,
+	0
+};
+
+annotated_module_platform_driver(wkup_m3_rproc_driver, drvid_wkup_m3_rproc, dependencies);
 
 MODULE_LICENSE("GPL v2");
 MODULE_DESCRIPTION("TI Wakeup M3 remote processor control driver");
diff --git a/drivers/rtc/class.c b/drivers/rtc/class.c
index ea2a315..a440043 100644
--- a/drivers/rtc/class.c
+++ b/drivers/rtc/class.c
@@ -374,7 +374,7 @@ static void __exit rtc_exit(void)
 	ida_destroy(&rtc_ida);
 }
 
-subsys_initcall(rtc_init);
+annotated_initcall(subsys, rtc_init, drvid_rtc, NULL);
 module_exit(rtc_exit);
 
 MODULE_AUTHOR("Alessandro Zummo <a.zummo@towertech.it>");
diff --git a/drivers/rtc/rtc-cmos.c b/drivers/rtc/rtc-cmos.c
index a82556a..2ea84bc 100644
--- a/drivers/rtc/rtc-cmos.c
+++ b/drivers/rtc/rtc-cmos.c
@@ -1254,7 +1254,14 @@ static int __init cmos_init(void)
 #endif
 	return retval;
 }
-module_init(cmos_init);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_rtc,
+	drvid_pnp,
+	0
+};
+
+annotated_module_init(cmos_init, drvid_rtc_cmos, dependencies);
 
 static void __exit cmos_exit(void)
 {
diff --git a/drivers/rtc/rtc-ds1307.c b/drivers/rtc/rtc-ds1307.c
index 6e76de1..71b3866 100644
--- a/drivers/rtc/rtc-ds1307.c
+++ b/drivers/rtc/rtc-ds1307.c
@@ -1252,7 +1252,12 @@ static struct i2c_driver ds1307_driver = {
 	.id_table	= ds1307_id,
 };
 
-module_i2c_driver(ds1307_driver);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_rtc,
+	0
+};
+
+annotated_module_i2c_driver(ds1307_driver, drvid_rtc_ds1307, dependencies);
 
 MODULE_DESCRIPTION("RTC driver for DS1307 and similar chips");
 MODULE_LICENSE("GPL");
diff --git a/drivers/rtc/rtc-hid-sensor-time.c b/drivers/rtc/rtc-hid-sensor-time.c
index c398f74..c5d3279 100644
--- a/drivers/rtc/rtc-hid-sensor-time.c
+++ b/drivers/rtc/rtc-hid-sensor-time.c
@@ -335,7 +335,13 @@ static struct platform_driver hid_time_platform_driver = {
 	.probe		= hid_time_probe,
 	.remove		= hid_time_remove,
 };
-module_platform_driver(hid_time_platform_driver);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_rtc,
+	0
+};
+
+annotated_module_platform_driver(hid_time_platform_driver, drvid_rtc_hid_sensor_time, dependencies);
 
 MODULE_DESCRIPTION("HID Sensor Time");
 MODULE_AUTHOR("Alexander Holler <holler@ahsoftware.de>");
diff --git a/drivers/rtc/rtc-mxc.c b/drivers/rtc/rtc-mxc.c
index 5fc292c..dab9556 100644
--- a/drivers/rtc/rtc-mxc.c
+++ b/drivers/rtc/rtc-mxc.c
@@ -480,7 +480,12 @@ static struct platform_driver mxc_rtc_driver = {
 	.remove = mxc_rtc_remove,
 };
 
-module_platform_driver(mxc_rtc_driver)
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_rtc,
+	0
+};
+
+annotated_module_platform_driver(mxc_rtc_driver, drvid_rtc_mxc, dependencies)
 
 MODULE_AUTHOR("Daniel Mack <daniel@caiaq.de>");
 MODULE_DESCRIPTION("RTC driver for Freescale MXC");
diff --git a/drivers/rtc/rtc-omap.c b/drivers/rtc/rtc-omap.c
index 8b6355f..a325588 100644
--- a/drivers/rtc/rtc-omap.c
+++ b/drivers/rtc/rtc-omap.c
@@ -767,7 +767,12 @@ static struct platform_driver omap_rtc_driver = {
 	.id_table	= omap_rtc_id_table,
 };
 
-module_platform_driver(omap_rtc_driver);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_rtc,
+	0
+};
+
+annotated_module_platform_driver(omap_rtc_driver, drvid_rtc_omap, dependencies);
 
 MODULE_ALIAS("platform:omap_rtc");
 MODULE_AUTHOR("George G. Davis (and others)");
diff --git a/drivers/rtc/rtc-snvs.c b/drivers/rtc/rtc-snvs.c
index d87a85c..be6183c 100644
--- a/drivers/rtc/rtc-snvs.c
+++ b/drivers/rtc/rtc-snvs.c
@@ -384,7 +384,13 @@ static struct platform_driver snvs_rtc_driver = {
 	},
 	.probe		= snvs_rtc_probe,
 };
-module_platform_driver(snvs_rtc_driver);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_rtc,
+	0
+};
+
+annotated_module_platform_driver(snvs_rtc_driver, drvid_rtc_snvs, dependencies);
 
 MODULE_AUTHOR("Freescale Semiconductor, Inc.");
 MODULE_DESCRIPTION("Freescale SNVS RTC Driver");
diff --git a/drivers/rtc/rtc-twl.c b/drivers/rtc/rtc-twl.c
index 2dc787d..499fbb9 100644
--- a/drivers/rtc/rtc-twl.c
+++ b/drivers/rtc/rtc-twl.c
@@ -615,7 +615,12 @@ static struct platform_driver twl4030rtc_driver = {
 	},
 };
 
-module_platform_driver(twl4030rtc_driver);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_rtc,
+	0
+};
+
+annotated_module_platform_driver(twl4030rtc_driver, drvid_rtc_twl, dependencies);
 
 MODULE_AUTHOR("Texas Instruments, MontaVista Software");
 MODULE_LICENSE("GPL");
diff --git a/drivers/scsi/scsi.c b/drivers/scsi/scsi.c
index 207d6a7..c88dd19 100644
--- a/drivers/scsi/scsi.c
+++ b/drivers/scsi/scsi.c
@@ -1222,5 +1222,11 @@ static void __exit exit_scsi(void)
 	async_unregister_domain(&scsi_sd_probe_domain);
 }
 
-subsys_initcall(init_scsi);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_bsg,
+	drvid_netlink,
+	0
+};
+
+annotated_initcall(subsys, init_scsi, drvid_scsi_mod, dependencies);
 module_exit(exit_scsi);
diff --git a/drivers/scsi/sd.c b/drivers/scsi/sd.c
index a20da8c..628d8ed 100644
--- a/drivers/scsi/sd.c
+++ b/drivers/scsi/sd.c
@@ -3274,7 +3274,13 @@ static void __exit exit_sd(void)
 	}
 }
 
-module_init(init_sd);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_scsi_mod,
+	drvid_genhd,
+	0
+};
+
+annotated_module_init(init_sd, drvid_sd_mod, dependencies);
 module_exit(exit_sd);
 
 static void sd_print_sense_hdr(struct scsi_disk *sdkp,
diff --git a/drivers/spi/spi-imx.c b/drivers/spi/spi-imx.c
index f9deb84..38f28b0 100644
--- a/drivers/spi/spi-imx.c
+++ b/drivers/spi/spi-imx.c
@@ -1242,7 +1242,7 @@ static struct platform_driver spi_imx_driver = {
 	.probe = spi_imx_probe,
 	.remove = spi_imx_remove,
 };
-module_platform_driver(spi_imx_driver);
+annotated_module_platform_driver(spi_imx_driver, drvid_spi_imx, NULL);
 
 MODULE_DESCRIPTION("SPI Master Controller driver");
 MODULE_AUTHOR("Sascha Hauer, Pengutronix");
diff --git a/drivers/spi/spi-omap2-mcspi.c b/drivers/spi/spi-omap2-mcspi.c
index 3d09e0b..9322f63 100644
--- a/drivers/spi/spi-omap2-mcspi.c
+++ b/drivers/spi/spi-omap2-mcspi.c
@@ -1529,5 +1529,5 @@ static struct platform_driver omap2_mcspi_driver = {
 	.remove =	omap2_mcspi_remove,
 };
 
-module_platform_driver(omap2_mcspi_driver);
+annotated_module_platform_driver(omap2_mcspi_driver, drvid_omap2_mcspi, NULL);
 MODULE_LICENSE("GPL");
diff --git a/drivers/thermal/thermal_core.c b/drivers/thermal/thermal_core.c
index 4ca211b..03f2caf 100644
--- a/drivers/thermal/thermal_core.c
+++ b/drivers/thermal/thermal_core.c
@@ -2141,5 +2141,11 @@ static void __exit thermal_exit(void)
 	mutex_destroy(&thermal_governor_lock);
 }
 
-fs_initcall(thermal_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_netlink,
+	drvid_hwmon,
+	0
+};
+
+annotated_initcall(fs, thermal_init, drvid_thermal, dependencies);
 module_exit(thermal_exit);
diff --git a/drivers/tty/pty.c b/drivers/tty/pty.c
index 4d5e840..b28a16a 100644
--- a/drivers/tty/pty.c
+++ b/drivers/tty/pty.c
@@ -869,4 +869,10 @@ static int __init pty_init(void)
 	unix98_pty_init();
 	return 0;
 }
-module_init(pty_init);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_tty,
+	0
+};
+
+annotated_module_init(pty_init, drvid_pty, dependencies);
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index 37fff12..dbfa632 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -4012,7 +4012,14 @@ static void __exit serial8250_exit(void)
 #endif
 }
 
-module_init(serial8250_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_pnp,
+	drvid_tty,
+	0
+};
+
+/* Must be initialized before other dependent serial drivers */
+annotated_initcall_sync(fs, serial8250_init, drvid_serial, dependencies);
 module_exit(serial8250_exit);
 
 EXPORT_SYMBOL(serial8250_suspend_port);
diff --git a/drivers/tty/serial/8250/8250_omap.c b/drivers/tty/serial/8250/8250_omap.c
index b470df1..7064370 100644
--- a/drivers/tty/serial/8250/8250_omap.c
+++ b/drivers/tty/serial/8250/8250_omap.c
@@ -1396,7 +1396,13 @@ static struct platform_driver omap8250_platform_driver = {
 	.probe			= omap8250_probe,
 	.remove			= omap8250_remove,
 };
-module_platform_driver(omap8250_platform_driver);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_serial,
+	0
+};
+
+annotated_module_platform_driver(omap8250_platform_driver, drvid_omap8250, dependencies);
 
 MODULE_AUTHOR("Sebastian Andrzej Siewior");
 MODULE_DESCRIPTION("OMAP 8250 Driver");
diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index 46ddce4..0642ae6 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -5794,7 +5794,16 @@ static struct pci_driver serial_pci_driver = {
 	.err_handler	= &serial8250_err_handler,
 };
 
-module_pci_driver(serial_pci_driver);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_serial,
+	drvid_pci_subsys,
+	drvid_pcibios_assign_resources,
+	drvid_pnpacpi, // optional
+	drvid_pci_quirks, // optional
+	0
+};
+
+annotated_module_pci_driver(serial_pci_driver, drvid_serial_pci, dependencies);
 
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Generic 8250/16x50 PCI serial probe module");
diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index 08ce76f..3f87146 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -1937,7 +1937,12 @@ static void __exit lpuart_serial_exit(void)
 	uart_unregister_driver(&lpuart_reg);
 }
 
-module_init(lpuart_serial_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_tty,
+	0
+};
+
+annotated_module_init_drv(lpuart_serial_init, drvid_lpuart, dependencies, lpuart_driver.driver);
 module_exit(lpuart_serial_exit);
 
 MODULE_DESCRIPTION("Freescale lpuart serial port driver");
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index 54fdc78..fa45969 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -2024,7 +2024,12 @@ static void __exit imx_serial_exit(void)
 	uart_unregister_driver(&imx_reg);
 }
 
-module_init(imx_serial_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_tty,
+	0
+};
+
+annotated_module_init_drv(imx_serial_init, drvid_imx_uart, dependencies, serial_imx_driver.driver);
 module_exit(imx_serial_exit);
 
 MODULE_AUTHOR("Sascha Hauer");
diff --git a/drivers/tty/serial/of_serial.c b/drivers/tty/serial/of_serial.c
index 6823df9..f935496 100644
--- a/drivers/tty/serial/of_serial.c
+++ b/drivers/tty/serial/of_serial.c
@@ -360,7 +360,12 @@ static struct platform_driver of_platform_serial_driver = {
 	.remove = of_platform_serial_remove,
 };
 
-module_platform_driver(of_platform_serial_driver);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_serial,
+	0
+};
+
+annotated_module_platform_driver(of_platform_serial_driver, drvid_of_serial, dependencies);
 
 MODULE_AUTHOR("Arnd Bergmann <arnd@arndb.de>");
 MODULE_LICENSE("GPL");
diff --git a/drivers/tty/serial/omap-serial.c b/drivers/tty/serial/omap-serial.c
index 7a2172b..7a05a17 100644
--- a/drivers/tty/serial/omap-serial.c
+++ b/drivers/tty/serial/omap-serial.c
@@ -1889,7 +1889,12 @@ static void __exit serial_omap_exit(void)
 	uart_unregister_driver(&serial_omap_reg);
 }
 
-module_init(serial_omap_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_tty,
+	0
+};
+
+annotated_module_init_drv(serial_omap_init, drvid_omap_serial, dependencies, serial_omap_driver.driver);
 module_exit(serial_omap_exit);
 
 MODULE_DESCRIPTION("OMAP High Speed UART driver");
diff --git a/drivers/tty/sysrq.c b/drivers/tty/sysrq.c
index b5b4278..0240b12 100644
--- a/drivers/tty/sysrq.c
+++ b/drivers/tty/sysrq.c
@@ -1112,4 +1112,10 @@ static int __init sysrq_init(void)
 
 	return 0;
 }
-module_init(sysrq_init);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_input,
+	0
+};
+
+annotated_module_init(sysrq_init, drvid_sysrq, dependencies);
diff --git a/drivers/tty/tty_io.c b/drivers/tty/tty_io.c
index 57fc6ee..a0ce493 100644
--- a/drivers/tty/tty_io.c
+++ b/drivers/tty/tty_io.c
@@ -3547,7 +3547,7 @@ static int __init tty_class_init(void)
 	return 0;
 }
 
-postcore_initcall(tty_class_init);
+annotated_initcall(postcore, tty_class_init, drvid_tty, NULL);
 
 /* 3/2004 jmc: why do these devices exist? */
 static struct cdev tty_cdev, console_cdev;
diff --git a/drivers/uio/uio_pdrv_genirq.c b/drivers/uio/uio_pdrv_genirq.c
index f598ecd..70f41a2 100644
--- a/drivers/uio/uio_pdrv_genirq.c
+++ b/drivers/uio/uio_pdrv_genirq.c
@@ -271,7 +271,7 @@ static struct platform_driver uio_pdrv_genirq = {
 	},
 };
 
-module_platform_driver(uio_pdrv_genirq);
+annotated_module_platform_driver(uio_pdrv_genirq, drvid_uio_pdrv_genirq, NULL);
 
 MODULE_AUTHOR("Magnus Damm");
 MODULE_DESCRIPTION("Userspace I/O platform driver with generic IRQ handling");
diff --git a/drivers/usb/core/usb.c b/drivers/usb/core/usb.c
index 8d5b2f4..fd531e9 100644
--- a/drivers/usb/core/usb.c
+++ b/drivers/usb/core/usb.c
@@ -1116,6 +1116,15 @@ static void __exit usb_exit(void)
 	usb_debugfs_cleanup();
 }
 
-subsys_initcall(usb_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_debugfs,
+	drvid_pci_subsys,
+	drvid_pcibios_assign_resources,
+	drvid_pnpacpi, // optional
+	drvid_pci_quirks, // optional
+	0
+};
+
+annotated_initcall(subsys, usb_init, drvid_usb, dependencies);
 module_exit(usb_exit);
 MODULE_LICENSE("GPL");
diff --git a/drivers/usb/host/ehci-hcd.c b/drivers/usb/host/ehci-hcd.c
index c63d82c..b818b35 100644
--- a/drivers/usb/host/ehci-hcd.c
+++ b/drivers/usb/host/ehci-hcd.c
@@ -1372,7 +1372,13 @@ err_debug:
 	clear_bit(USB_EHCI_LOADED, &usb_hcds_loaded);
 	return retval;
 }
-module_init(ehci_hcd_init);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_usb,
+	0
+};
+
+annotated_module_init(ehci_hcd_init, drvid_ehci_hcd, dependencies);
 
 static void __exit ehci_hcd_cleanup(void)
 {
diff --git a/drivers/usb/host/ehci-omap.c b/drivers/usb/host/ehci-omap.c
index a24720b..c056cfe 100644
--- a/drivers/usb/host/ehci-omap.c
+++ b/drivers/usb/host/ehci-omap.c
@@ -310,7 +310,13 @@ static int __init ehci_omap_init(void)
 	ehci_init_driver(&ehci_omap_hc_driver, &ehci_omap_overrides);
 	return platform_driver_register(&ehci_hcd_omap_driver);
 }
-module_init(ehci_omap_init);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_ehci_hcd,
+	0
+};
+
+annotated_module_init_drv(ehci_omap_init, drvid_ehci_omap, dependencies, ehci_hcd_omap_driver.driver);
 
 static void __exit ehci_omap_cleanup(void)
 {
diff --git a/drivers/usb/host/ehci-orion.c b/drivers/usb/host/ehci-orion.c
index bfcbb9a..e622aec 100644
--- a/drivers/usb/host/ehci-orion.c
+++ b/drivers/usb/host/ehci-orion.c
@@ -333,7 +333,13 @@ static int __init ehci_orion_init(void)
 	ehci_init_driver(&ehci_orion_hc_driver, &orion_overrides);
 	return platform_driver_register(&ehci_orion_driver);
 }
-module_init(ehci_orion_init);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_ehci_hcd,
+	0
+};
+
+annotated_module_init_drv(ehci_orion_init, drvid_ehci_orion, dependencies, ehci_orion_driver.driver);
 
 static void __exit ehci_orion_cleanup(void)
 {
diff --git a/drivers/usb/host/ehci-pci.c b/drivers/usb/host/ehci-pci.c
index 2a5d2fd..63d20fc 100644
--- a/drivers/usb/host/ehci-pci.c
+++ b/drivers/usb/host/ehci-pci.c
@@ -421,7 +421,17 @@ static int __init ehci_pci_init(void)
 
 	return pci_register_driver(&ehci_pci_driver);
 }
-module_init(ehci_pci_init);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_ehci_hcd,
+	drvid_pci_subsys,
+	drvid_pcibios_assign_resources,
+	drvid_pnpacpi, // optional
+	drvid_pci_quirks, // optional
+	0
+};
+
+annotated_module_init_drv(ehci_pci_init, drvid_ehci_pci, dependencies, ehci_pci_driver.driver);
 
 static void __exit ehci_pci_cleanup(void)
 {
diff --git a/drivers/usb/host/ohci-hcd.c b/drivers/usb/host/ohci-hcd.c
index 760cb57..8867277 100644
--- a/drivers/usb/host/ohci-hcd.c
+++ b/drivers/usb/host/ohci-hcd.c
@@ -1353,7 +1353,14 @@ static int __init ohci_hcd_mod_init(void)
 	clear_bit(USB_OHCI_LOADED, &usb_hcds_loaded);
 	return retval;
 }
-module_init(ohci_hcd_mod_init);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_usb,
+	drvid_ehci_hcd,
+	0
+};
+
+annotated_module_init(ohci_hcd_mod_init, drvid_ohci_hci, dependencies);
 
 static void __exit ohci_hcd_mod_exit(void)
 {
diff --git a/drivers/usb/host/ohci-omap3.c b/drivers/usb/host/ohci-omap3.c
index ec15aeb..7bf96f2 100644
--- a/drivers/usb/host/ohci-omap3.c
+++ b/drivers/usb/host/ohci-omap3.c
@@ -197,7 +197,13 @@ static int __init ohci_omap3_init(void)
 	ohci_init_driver(&ohci_omap3_hc_driver, NULL);
 	return platform_driver_register(&ohci_hcd_omap3_driver);
 }
-module_init(ohci_omap3_init);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_ohci_hcd,
+	0
+};
+
+annotated_module_init_drv(ohci_omap3_init, drvid_ohci_omap3, dependencies, ohci_hcd_omap3_driver.driver);
 
 static void __exit ohci_omap3_cleanup(void)
 {
diff --git a/drivers/usb/host/uhci-hcd.c b/drivers/usb/host/uhci-hcd.c
index a7de8e8..5576bee 100644
--- a/drivers/usb/host/uhci-hcd.c
+++ b/drivers/usb/host/uhci-hcd.c
@@ -937,7 +937,13 @@ static void __exit uhci_hcd_cleanup(void)
 	clear_bit(USB_UHCI_LOADED, &usb_hcds_loaded);
 }
 
-module_init(uhci_hcd_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_usb,
+	drvid_ehci_hcd,
+	0
+};
+
+annotated_module_init(uhci_hcd_init, drvid_uhci_hcd, dependencies);
 module_exit(uhci_hcd_cleanup);
 
 MODULE_AUTHOR(DRIVER_AUTHOR);
diff --git a/drivers/usb/musb/musb_core.c b/drivers/usb/musb/musb_core.c
index 514a6cd..42262ae 100644
--- a/drivers/usb/musb/musb_core.c
+++ b/drivers/usb/musb/musb_core.c
@@ -2563,4 +2563,4 @@ static struct platform_driver musb_driver = {
 	.shutdown	= musb_shutdown,
 };
 
-module_platform_driver(musb_driver);
+annotated_module_platform_driver(musb_driver, drvid_musb_hdrc, NULL);
diff --git a/drivers/usb/musb/musb_dsps.c b/drivers/usb/musb/musb_dsps.c
index 1334a3d..895609f 100644
--- a/drivers/usb/musb/musb_dsps.c
+++ b/drivers/usb/musb/musb_dsps.c
@@ -939,4 +939,4 @@ MODULE_AUTHOR("Ravi B <ravibabu@ti.com>");
 MODULE_AUTHOR("Ajay Kumar Gupta <ajay.gupta@ti.com>");
 MODULE_LICENSE("GPL v2");
 
-module_platform_driver(dsps_usbss_driver);
+annotated_module_platform_driver(dsps_usbss_driver, drvid_musb_dsps, NULL);
diff --git a/drivers/usb/musb/omap2430.c b/drivers/usb/musb/omap2430.c
index 70f2b8a..9ab0b5f 100644
--- a/drivers/usb/musb/omap2430.c
+++ b/drivers/usb/musb/omap2430.c
@@ -725,7 +725,7 @@ static int __init omap2430_init(void)
 {
 	return platform_driver_register(&omap2430_driver);
 }
-subsys_initcall(omap2430_init);
+annotated_initcall_drv(subsys, omap2430_init, drvid_omap2430, NULL, omap2430_driver.driver);
 
 static void __exit omap2430_exit(void)
 {
diff --git a/drivers/usb/phy/phy-am335x-control.c b/drivers/usb/phy/phy-am335x-control.c
index 7b3035f..3b69884 100644
--- a/drivers/usb/phy/phy-am335x-control.c
+++ b/drivers/usb/phy/phy-am335x-control.c
@@ -180,5 +180,5 @@ static struct platform_driver am335x_control_driver = {
 	},
 };
 
-module_platform_driver(am335x_control_driver);
+annotated_module_platform_driver(am335x_control_driver, drvid_am335x_control, NULL);
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/phy/phy-am335x.c b/drivers/usb/phy/phy-am335x.c
index 90b67a4..82d23b8 100644
--- a/drivers/usb/phy/phy-am335x.c
+++ b/drivers/usb/phy/phy-am335x.c
@@ -142,5 +142,5 @@ static struct platform_driver am335x_phy_driver = {
 	},
 };
 
-module_platform_driver(am335x_phy_driver);
+annotated_module_platform_driver(am335x_phy_driver, drvid_am335x_phy, NULL);
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/usb/phy/phy-generic.c b/drivers/usb/phy/phy-generic.c
index deee68e..eff0216 100644
--- a/drivers/usb/phy/phy-generic.c
+++ b/drivers/usb/phy/phy-generic.c
@@ -360,7 +360,7 @@ static int __init usb_phy_generic_init(void)
 {
 	return platform_driver_register(&usb_phy_generic_driver);
 }
-subsys_initcall(usb_phy_generic_init);
+annotated_initcall_drv(subsys, usb_phy_generic_init, drvid_usb_phy_generic, NULL, usb_phy_generic_driver.driver);
 
 static void __exit usb_phy_generic_exit(void)
 {
diff --git a/drivers/usb/phy/phy-gpio-vbus-usb.c b/drivers/usb/phy/phy-gpio-vbus-usb.c
index f66120d..6695128 100644
--- a/drivers/usb/phy/phy-gpio-vbus-usb.c
+++ b/drivers/usb/phy/phy-gpio-vbus-usb.c
@@ -390,7 +390,7 @@ static struct platform_driver gpio_vbus_driver = {
 	.remove		= gpio_vbus_remove,
 };
 
-module_platform_driver(gpio_vbus_driver);
+annotated_module_platform_driver(gpio_vbus_driver, drvid_gpio_vbus, NULL);
 
 MODULE_DESCRIPTION("simple GPIO controlled OTG transceiver driver");
 MODULE_AUTHOR("Philipp Zabel");
diff --git a/drivers/usb/phy/phy-mxs-usb.c b/drivers/usb/phy/phy-mxs-usb.c
index 3fcc048..39d91b1 100644
--- a/drivers/usb/phy/phy-mxs-usb.c
+++ b/drivers/usb/phy/phy-mxs-usb.c
@@ -577,7 +577,7 @@ static int __init mxs_phy_module_init(void)
 {
 	return platform_driver_register(&mxs_phy_driver);
 }
-postcore_initcall(mxs_phy_module_init);
+annotated_initcall_drv(postcore, mxs_phy_module_init, drvid_mxs_phy, NULL, mxs_phy_driver.driver);
 
 static void __exit mxs_phy_module_exit(void)
 {
diff --git a/drivers/usb/storage/cypress_atacb.c b/drivers/usb/storage/cypress_atacb.c
index c80d3de..59ea823 100644
--- a/drivers/usb/storage/cypress_atacb.c
+++ b/drivers/usb/storage/cypress_atacb.c
@@ -290,4 +290,9 @@ static struct usb_driver cypress_driver = {
 	.no_dynamic_id = 1,
 };
 
-module_usb_stor_driver(cypress_driver, cypress_host_template, DRV_NAME);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_usb_storage,
+	0
+};
+
+annotated_module_usb_stor_driver(cypress_driver, cypress_host_template, DRV_NAME, drvid_ums_cypress, dependencies);
diff --git a/drivers/usb/storage/usb.c b/drivers/usb/storage/usb.c
index 43576ed..f0da741 100644
--- a/drivers/usb/storage/usb.c
+++ b/drivers/usb/storage/usb.c
@@ -1143,4 +1143,10 @@ static struct usb_driver usb_storage_driver = {
 	.soft_unbind =	1,
 };
 
-module_usb_stor_driver(usb_storage_driver, usb_stor_host_template, DRV_NAME);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_usb,
+	drvid_scsi_mod,
+	0
+};
+
+annotated_module_usb_stor_driver(usb_storage_driver, usb_stor_host_template, DRV_NAME, drvid_usb_storage, dependencies);
diff --git a/drivers/video/backlight/backlight.c b/drivers/video/backlight/backlight.c
index bddc8b1..4bdebfe 100644
--- a/drivers/video/backlight/backlight.c
+++ b/drivers/video/backlight/backlight.c
@@ -589,11 +589,17 @@ static int __init backlight_class_init(void)
 	return 0;
 }
 
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_pm,
+	drvid_fbmem,
+	0
+};
+
 /*
  * if this is compiled into the kernel, we need to ensure that the
  * class is registered before users of the class try to register lcd's
  */
-postcore_initcall(backlight_class_init);
+annotated_initcall(postcore, backlight_class_init, drvid_backlight_class, dependencies);
 module_exit(backlight_class_exit);
 
 MODULE_LICENSE("GPL");
diff --git a/drivers/video/backlight/lcd.c b/drivers/video/backlight/lcd.c
index 7de847d..f254fa2 100644
--- a/drivers/video/backlight/lcd.c
+++ b/drivers/video/backlight/lcd.c
@@ -352,11 +352,16 @@ static int __init lcd_class_init(void)
 	return 0;
 }
 
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_fbmem,
+	0
+};
+
 /*
  * if this is compiled into the kernel, we need to ensure that the
  * class is registered before users of the class try to register lcd's
  */
-postcore_initcall(lcd_class_init);
+annotated_initcall(postcore, lcd_class_init, drvid_lcd_class, dependencies);
 module_exit(lcd_class_exit);
 
 MODULE_LICENSE("GPL");
diff --git a/drivers/video/backlight/platform_lcd.c b/drivers/video/backlight/platform_lcd.c
index 872a3bf..acafe15 100644
--- a/drivers/video/backlight/platform_lcd.c
+++ b/drivers/video/backlight/platform_lcd.c
@@ -154,7 +154,13 @@ static struct platform_driver platform_lcd_driver = {
 	.probe		= platform_lcd_probe,
 };
 
-module_platform_driver(platform_lcd_driver);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_backlight_class,
+	drvid_lcd_class,
+	0
+};
+
+annotated_module_platform_driver(platform_lcd_driver, drvid_platform_lcd, dependencies);
 
 MODULE_AUTHOR("Ben Dooks <ben-linux@fluff.org>");
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/backlight/pwm_bl.c b/drivers/video/backlight/pwm_bl.c
index eff379b..5134fee 100644
--- a/drivers/video/backlight/pwm_bl.c
+++ b/drivers/video/backlight/pwm_bl.c
@@ -403,7 +403,12 @@ static struct platform_driver pwm_backlight_driver = {
 	.shutdown	= pwm_backlight_shutdown,
 };
 
-module_platform_driver(pwm_backlight_driver);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_backlight_class,
+	0
+};
+
+annotated_module_platform_driver(pwm_backlight_driver, drvid_pwm_backlight, dependencies);
 
 MODULE_DESCRIPTION("PWM based Backlight Driver");
 MODULE_LICENSE("GPL");
diff --git a/drivers/video/backlight/tps65217_bl.c b/drivers/video/backlight/tps65217_bl.c
index 61d72bf..3a46b41 100644
--- a/drivers/video/backlight/tps65217_bl.c
+++ b/drivers/video/backlight/tps65217_bl.c
@@ -327,7 +327,13 @@ static struct platform_driver tps65217_bl_driver = {
 	},
 };
 
-module_platform_driver(tps65217_bl_driver);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_backlight_class,
+	drvid_tps65217,
+	0
+};
+
+annotated_module_platform_driver(tps65217_bl_driver, drvid_tps65217_bl, dependencies);
 
 MODULE_DESCRIPTION("TPS65217 Backlight driver");
 MODULE_LICENSE("GPL v2");
diff --git a/drivers/video/console/fbcon.c b/drivers/video/console/fbcon.c
index 1aaf893..40b1ec7 100644
--- a/drivers/video/console/fbcon.c
+++ b/drivers/video/console/fbcon.c
@@ -3622,7 +3622,13 @@ static int __init fb_console_init(void)
 	return 0;
 }
 
-fs_initcall(fb_console_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_fbmem,
+	drvid_crc32test,
+	0
+};
+
+annotated_initcall(fs, fb_console_init, drvid_fb_console, dependencies);
 
 #ifdef MODULE
 
diff --git a/drivers/video/fbdev/core/fbmem.c b/drivers/video/fbdev/core/fbmem.c
index 0705d88..eeed0ab 100644
--- a/drivers/video/fbdev/core/fbmem.c
+++ b/drivers/video/fbdev/core/fbmem.c
@@ -1860,7 +1860,7 @@ fbmem_init(void)
 }
 
 #ifdef MODULE
-module_init(fbmem_init);
+annotated_module_init(fbmem_init, drvid_fbmem, NULL);
 static void __exit
 fbmem_exit(void)
 {
@@ -1873,7 +1873,7 @@ module_exit(fbmem_exit);
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("Framebuffer base");
 #else
-subsys_initcall(fbmem_init);
+annotated_initcall(subsys, fbmem_init, drvid_fbmem, NULL);
 #endif
 
 int fb_new_modelist(struct fb_info *info)
diff --git a/drivers/video/fbdev/omap2/vrfb.c b/drivers/video/fbdev/omap2/vrfb.c
index f346b02..e2d5916 100644
--- a/drivers/video/fbdev/omap2/vrfb.c
+++ b/drivers/video/fbdev/omap2/vrfb.c
@@ -392,7 +392,12 @@ static struct platform_driver vrfb_driver = {
 	.remove		= __exit_p(vrfb_remove),
 };
 
-module_platform_driver_probe(vrfb_driver, vrfb_probe);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_fbmem,
+	0
+};
+
+annotated_module_platform_driver_probe(vrfb_driver, vrfb_probe, drvid_omapvrfb, dependencies);
 
 MODULE_AUTHOR("Tomi Valkeinen <tomi.valkeinen@ti.com>");
 MODULE_DESCRIPTION("OMAP VRFB");
diff --git a/drivers/watchdog/iTCO_wdt.c b/drivers/watchdog/iTCO_wdt.c
index 3c3fd41..b683458 100644
--- a/drivers/watchdog/iTCO_wdt.c
+++ b/drivers/watchdog/iTCO_wdt.c
@@ -650,7 +650,12 @@ static void __exit iTCO_wdt_cleanup_module(void)
 	pr_info("Watchdog Module Unloaded\n");
 }
 
-module_init(iTCO_wdt_init_module);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_watchdog,
+	0
+};
+
+annotated_module_init(iTCO_wdt_init_module, drvid_iTCO_wdt, dependencies);
 module_exit(iTCO_wdt_cleanup_module);
 
 MODULE_AUTHOR("Wim Van Sebroeck <wim@iguana.be>");
diff --git a/drivers/watchdog/imx2_wdt.c b/drivers/watchdog/imx2_wdt.c
index 0bb1a1d..77ba64f 100644
--- a/drivers/watchdog/imx2_wdt.c
+++ b/drivers/watchdog/imx2_wdt.c
@@ -422,7 +422,12 @@ static struct platform_driver imx2_wdt_driver = {
 	},
 };
 
-module_platform_driver_probe(imx2_wdt_driver, imx2_wdt_probe);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_watchdog,
+	0
+};
+
+annotated_module_platform_driver_probe(imx2_wdt_driver, imx2_wdt_probe, drvid_imx2_wdt, dependencies);
 
 MODULE_AUTHOR("Wolfram Sang");
 MODULE_DESCRIPTION("Watchdog driver for IMX2 and later");
diff --git a/drivers/watchdog/it87_wdt.c b/drivers/watchdog/it87_wdt.c
index e54839b..969195b 100644
--- a/drivers/watchdog/it87_wdt.c
+++ b/drivers/watchdog/it87_wdt.c
@@ -789,7 +789,12 @@ static void __exit it87_wdt_exit(void)
 		release_region(base, 8);
 }
 
-module_init(it87_wdt_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_watchdog,
+	0
+};
+
+annotated_module_init(it87_wdt_init, drvid_it87_wdt, dependencies);
 module_exit(it87_wdt_exit);
 
 MODULE_AUTHOR("Oliver Schuster");
diff --git a/drivers/watchdog/omap_wdt.c b/drivers/watchdog/omap_wdt.c
index de911c7..bd724af 100644
--- a/drivers/watchdog/omap_wdt.c
+++ b/drivers/watchdog/omap_wdt.c
@@ -372,7 +372,12 @@ static struct platform_driver omap_wdt_driver = {
 	},
 };
 
-module_platform_driver(omap_wdt_driver);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_watchdog,
+	0
+};
+
+annotated_module_platform_driver(omap_wdt_driver, drvid_omap_wdt, dependencies);
 
 MODULE_AUTHOR("George G. Davis");
 MODULE_LICENSE("GPL");
diff --git a/drivers/watchdog/softdog.c b/drivers/watchdog/softdog.c
index 0dc5e323d..949eec3 100644
--- a/drivers/watchdog/softdog.c
+++ b/drivers/watchdog/softdog.c
@@ -200,7 +200,12 @@ static void __exit watchdog_exit(void)
 	unregister_reboot_notifier(&softdog_notifier);
 }
 
-module_init(watchdog_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_watchdog,
+	0
+};
+
+annotated_module_init(watchdog_init, drvid_softdog, dependencies);
 module_exit(watchdog_exit);
 
 MODULE_AUTHOR("Alan Cox");
diff --git a/drivers/watchdog/twl4030_wdt.c b/drivers/watchdog/twl4030_wdt.c
index 2c1db6f..224073e 100644
--- a/drivers/watchdog/twl4030_wdt.c
+++ b/drivers/watchdog/twl4030_wdt.c
@@ -145,7 +145,12 @@ static struct platform_driver twl4030_wdt_driver = {
 	},
 };
 
-module_platform_driver(twl4030_wdt_driver);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_watchdog,
+	0
+};
+
+annotated_module_platform_driver(twl4030_wdt_driver, drvid_twl4030_wdt, dependencies);
 
 MODULE_AUTHOR("Nokia Corporation");
 MODULE_LICENSE("GPL");
diff --git a/drivers/watchdog/watchdog_core.c b/drivers/watchdog/watchdog_core.c
index 1a80594..5697f1f 100644
--- a/drivers/watchdog/watchdog_core.c
+++ b/drivers/watchdog/watchdog_core.c
@@ -299,7 +299,12 @@ static void __exit watchdog_exit(void)
 	ida_destroy(&watchdog_ida);
 }
 
-subsys_initcall_sync(watchdog_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_misc,
+	0
+};
+
+annotated_initcall_sync(subsys, watchdog_init, drvid_watchdog, dependencies);
 module_exit(watchdog_exit);
 
 MODULE_AUTHOR("Alan Cox <alan@lxorguk.ukuu.org.uk>");
diff --git a/fs/anon_inodes.c b/fs/anon_inodes.c
index 80ef38c..cbafa5e 100644
--- a/fs/anon_inodes.c
+++ b/fs/anon_inodes.c
@@ -175,5 +175,4 @@ static int __init anon_inode_init(void)
 	return 0;
 }
 
-fs_initcall(anon_inode_init);
-
+annotated_initcall(fs, anon_inode_init, drvid_anon_inode, NULL);
diff --git a/fs/binfmt_elf.c b/fs/binfmt_elf.c
index 6b65996..2dec793 100644
--- a/fs/binfmt_elf.c
+++ b/fs/binfmt_elf.c
@@ -2321,6 +2321,6 @@ static void __exit exit_elf_binfmt(void)
 	unregister_binfmt(&elf_format);
 }
 
-core_initcall(init_elf_binfmt);
+annotated_initcall(core, init_elf_binfmt, drvid_binfmt_elf, NULL);
 module_exit(exit_elf_binfmt);
 MODULE_LICENSE("GPL");
diff --git a/fs/binfmt_misc.c b/fs/binfmt_misc.c
index 78f005f..3ea6bce 100644
--- a/fs/binfmt_misc.c
+++ b/fs/binfmt_misc.c
@@ -830,6 +830,6 @@ static void __exit exit_misc_binfmt(void)
 	unregister_filesystem(&bm_fs_type);
 }
 
-core_initcall(init_misc_binfmt);
+annotated_initcall(core, init_misc_binfmt, drvid_binfmt_misc, NULL);
 module_exit(exit_misc_binfmt);
 MODULE_LICENSE("GPL");
diff --git a/fs/binfmt_script.c b/fs/binfmt_script.c
index afdf4e3..3a1799b 100644
--- a/fs/binfmt_script.c
+++ b/fs/binfmt_script.c
@@ -124,6 +124,6 @@ static void __exit exit_script_binfmt(void)
 	unregister_binfmt(&script_format);
 }
 
-core_initcall(init_script_binfmt);
+annotated_initcall(core, init_script_binfmt, drvid_binfmt_script, NULL);
 module_exit(exit_script_binfmt);
 MODULE_LICENSE("GPL");
diff --git a/fs/btrfs/super.c b/fs/btrfs/super.c
index cd7ef34..ec730ab 100644
--- a/fs/btrfs/super.c
+++ b/fs/btrfs/super.c
@@ -2325,7 +2325,19 @@ static void __exit exit_btrfs_fs(void)
 	btrfs_hash_exit();
 }
 
-late_initcall(init_btrfs_fs);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_xor,
+	drvid_raid6_pq,
+	drvid_libcrc32c, /* according to commit 60efa5 */
+	drvid_misc,
+	drvid_debugfs,
+	drvid_alignment, // needed on ARM
+	drvid_bdi,
+	drvid_bio,
+	0
+};
+
+annotated_initcall(late, init_btrfs_fs, drvid_btrfs, dependencies);
 module_exit(exit_btrfs_fs)
 
 MODULE_LICENSE("GPL");
diff --git a/fs/compat_binfmt_elf.c b/fs/compat_binfmt_elf.c
index 4d24d17..f9fb006 100644
--- a/fs/compat_binfmt_elf.c
+++ b/fs/compat_binfmt_elf.c
@@ -138,7 +138,7 @@ static void cputime_to_compat_timeval(const cputime_t cputime,
 #define elf_format		compat_elf_format
 #define init_elf_binfmt		init_compat_elf_binfmt
 #define exit_elf_binfmt		exit_compat_elf_binfmt
-
+#define drvid_binfmt_elf	drvid_binfmt_elf_compat
 /*
  * We share all the actual code with the native (64-bit) version.
  */
diff --git a/fs/debugfs/inode.c b/fs/debugfs/inode.c
index c711be8..26f417d 100644
--- a/fs/debugfs/inode.c
+++ b/fs/debugfs/inode.c
@@ -727,5 +727,6 @@ static int __init debugfs_init(void)
 
 	return retval;
 }
-core_initcall(debugfs_init);
+
+annotated_initcall(core, debugfs_init, drvid_debugfs, NULL);
 
diff --git a/fs/eventpoll.c b/fs/eventpoll.c
index 1e009ca..f00e9e9 100644
--- a/fs/eventpoll.c
+++ b/fs/eventpoll.c
@@ -2130,4 +2130,4 @@ static int __init eventpoll_init(void)
 
 	return 0;
 }
-fs_initcall(eventpoll_init);
+annotated_initcall(fs, eventpoll_init, drvid_eventpoll, NULL);
diff --git a/fs/ext4/super.c b/fs/ext4/super.c
index a5e8c74..165b75c 100644
--- a/fs/ext4/super.c
+++ b/fs/ext4/super.c
@@ -5721,5 +5721,13 @@ static void __exit ext4_exit_fs(void)
 MODULE_AUTHOR("Remy Card, Stephen Tweedie, Andrew Morton, Andreas Dilger, Theodore Ts'o and others");
 MODULE_DESCRIPTION("Fourth Extended Filesystem");
 MODULE_LICENSE("GPL");
-module_init(ext4_init_fs)
+
+/* Taken from modules.dep */
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_mbcache,
+	drvid_jbd2,
+	0
+};
+
+annotated_module_init(ext4_init_fs, drvid_ext4, dependencies);
 module_exit(ext4_exit_fs)
diff --git a/fs/fat/inode.c b/fs/fat/inode.c
index 509411d..f1ade65 100644
--- a/fs/fat/inode.c
+++ b/fs/fat/inode.c
@@ -1845,7 +1845,7 @@ static void __exit exit_fat_fs(void)
 	fat_destroy_inodecache();
 }
 
-module_init(init_fat_fs)
+annotated_module_init(init_fat_fs, drvid_fat, NULL);
 module_exit(exit_fat_fs)
 
 MODULE_LICENSE("GPL");
diff --git a/fs/fat/namei_msdos.c b/fs/fat/namei_msdos.c
index b7e2b33..d505bc4 100644
--- a/fs/fat/namei_msdos.c
+++ b/fs/fat/namei_msdos.c
@@ -680,5 +680,10 @@ MODULE_LICENSE("GPL");
 MODULE_AUTHOR("Werner Almesberger");
 MODULE_DESCRIPTION("MS-DOS filesystem support");
 
-module_init(init_msdos_fs)
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_fat,
+	0
+};
+
+annotated_module_init(init_msdos_fs, drvid_msdos, dependencies);
 module_exit(exit_msdos_fs)
diff --git a/fs/fat/namei_vfat.c b/fs/fat/namei_vfat.c
index 7092584..025c4d8 100644
--- a/fs/fat/namei_vfat.c
+++ b/fs/fat/namei_vfat.c
@@ -1085,5 +1085,10 @@ MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("VFAT filesystem support");
 MODULE_AUTHOR("Gordon Chaffee");
 
-module_init(init_vfat_fs)
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_fat,
+	0
+};
+
+annotated_module_init(init_vfat_fs, drvid_vfat, dependencies);
 module_exit(exit_vfat_fs)
diff --git a/fs/filesystems.c b/fs/filesystems.c
index 5797d45..78c0773 100644
--- a/fs/filesystems.c
+++ b/fs/filesystems.c
@@ -253,7 +253,7 @@ static int __init proc_filesystems_init(void)
 	proc_create("filesystems", 0, NULL, &filesystems_proc_fops);
 	return 0;
 }
-module_init(proc_filesystems_init);
+annotated_module_init(proc_filesystems_init, drvid_proc_filesystems, NULL);
 #endif
 
 static struct file_system_type *__get_fs_type(const char *name, int len)
diff --git a/fs/fuse/inode.c b/fs/fuse/inode.c
index 2913db2..2dd5372 100644
--- a/fs/fuse/inode.c
+++ b/fs/fuse/inode.c
@@ -1372,5 +1372,10 @@ static void __exit fuse_exit(void)
 	fuse_dev_cleanup();
 }
 
-module_init(fuse_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_bdi,
+	0
+};
+
+annotated_module_init(fuse_init, drvid_fuse, dependencies);
 module_exit(fuse_exit);
diff --git a/fs/jbd2/journal.c b/fs/jbd2/journal.c
index 2721513..493ec69 100644
--- a/fs/jbd2/journal.c
+++ b/fs/jbd2/journal.c
@@ -2682,6 +2682,6 @@ static void __exit journal_exit(void)
 }
 
 MODULE_LICENSE("GPL");
-module_init(journal_init);
+annotated_module_init(journal_init, drvid_jbd2, NULL);
 module_exit(journal_exit);
 
diff --git a/fs/lockd/svc.c b/fs/lockd/svc.c
index 55505cb..483fd26 100644
--- a/fs/lockd/svc.c
+++ b/fs/lockd/svc.c
@@ -647,7 +647,13 @@ static void __exit exit_nlm(void)
 #endif
 }
 
-module_init(init_nlm);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_grace,
+	drvid_sunrpc,
+	0
+};
+
+annotated_module_init(init_nlm, drvid_lockd, dependencies);
 module_exit(exit_nlm);
 
 /*
diff --git a/fs/mbcache.c b/fs/mbcache.c
index 187477d..9b3db3f 100644
--- a/fs/mbcache.c
+++ b/fs/mbcache.c
@@ -853,6 +853,6 @@ static void __exit exit_mbcache(void)
 	unregister_shrinker(&mb_cache_shrinker);
 }
 
-module_init(init_mbcache)
+annotated_module_init(init_mbcache, drvid_mbcache, NULL);
 module_exit(exit_mbcache)
 
diff --git a/fs/nfs/blocklayout/blocklayout.c b/fs/nfs/blocklayout/blocklayout.c
index d2554fe..1128ad3 100644
--- a/fs/nfs/blocklayout/blocklayout.c
+++ b/fs/nfs/blocklayout/blocklayout.c
@@ -924,5 +924,14 @@ static void __exit nfs4blocklayout_exit(void)
 
 MODULE_ALIAS("nfs-layouttype4-3");
 
-module_init(nfs4blocklayout_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_nfsv4,
+	drvid_nfs,
+	drvid_lockd,
+	drvid_grace,
+	drvid_sunrpc,
+	0
+};
+
+annotated_module_init(nfs4blocklayout_init, drvid_blocklayoutdriver, dependencies);
 module_exit(nfs4blocklayout_exit);
diff --git a/fs/nfs/filelayout/filelayout.c b/fs/nfs/filelayout/filelayout.c
index b34f2e2..f8adc58 100644
--- a/fs/nfs/filelayout/filelayout.c
+++ b/fs/nfs/filelayout/filelayout.c
@@ -1159,5 +1159,14 @@ static void __exit nfs4filelayout_exit(void)
 
 MODULE_ALIAS("nfs-layouttype4-1");
 
-module_init(nfs4filelayout_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_nfsv4,
+	drvid_nfs,
+	drvid_lockd,
+	drvid_grace,
+	drvid_sunrpc,
+	0
+};
+
+annotated_module_init(nfs4filelayout_init, drvid_nfs_layout_nfsv41_files, dependencies);
 module_exit(nfs4filelayout_exit);
diff --git a/fs/nfs/flexfilelayout/flexfilelayout.c b/fs/nfs/flexfilelayout/flexfilelayout.c
index 14e3b1e..b066483 100644
--- a/fs/nfs/flexfilelayout/flexfilelayout.c
+++ b/fs/nfs/flexfilelayout/flexfilelayout.c
@@ -1978,5 +1978,14 @@ MODULE_ALIAS("nfs-layouttype4-4");
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("The NFSv4 flexfile layout driver");
 
-module_init(nfs4flexfilelayout_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_nfsv4,
+	drvid_nfs,
+	drvid_lockd,
+	drvid_grace,
+	drvid_sunrpc,
+	0
+};
+
+annotated_module_init(nfs4flexfilelayout_init, drvid_flexfilelayout, dependencies);
 module_exit(nfs4flexfilelayout_exit);
diff --git a/fs/nfs/inode.c b/fs/nfs/inode.c
index 4afbe13..7c19fdc 100644
--- a/fs/nfs/inode.c
+++ b/fs/nfs/inode.c
@@ -2060,5 +2060,13 @@ MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>");
 MODULE_LICENSE("GPL");
 module_param(enable_ino64, bool, 0644);
 
-module_init(init_nfs_fs)
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_lockd,
+	drvid_grace,
+	drvid_sunrpc,
+	drvid_bdi,
+	0
+};
+
+annotated_module_init(init_nfs_fs, drvid_nfs, dependencies);
 module_exit(exit_nfs_fs)
diff --git a/fs/nfs/nfs2super.c b/fs/nfs/nfs2super.c
index 0a9782c..a35d4a8 100644
--- a/fs/nfs/nfs2super.c
+++ b/fs/nfs/nfs2super.c
@@ -27,5 +27,13 @@ static void __exit exit_nfs_v2(void)
 
 MODULE_LICENSE("GPL");
 
-module_init(init_nfs_v2);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_nfs,
+	drvid_lockd,
+	drvid_grace,
+	drvid_sunrpc,
+	0
+};
+
+annotated_module_init(init_nfs_v2, drvid_nfsv2, dependencies);
 module_exit(exit_nfs_v2);
diff --git a/fs/nfs/nfs3super.c b/fs/nfs/nfs3super.c
index 5c4394e..9cd3189 100644
--- a/fs/nfs/nfs3super.c
+++ b/fs/nfs/nfs3super.c
@@ -31,5 +31,13 @@ static void __exit exit_nfs_v3(void)
 
 MODULE_LICENSE("GPL");
 
-module_init(init_nfs_v3);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_nfs,
+	drvid_lockd,
+	drvid_grace,
+	drvid_sunrpc,
+	0
+};
+
+annotated_module_init(init_nfs_v3, drvid_nfsv3, dependencies);
 module_exit(exit_nfs_v3);
diff --git a/fs/nfs_common/grace.c b/fs/nfs_common/grace.c
index ae6e58e..89f060b 100644
--- a/fs/nfs_common/grace.c
+++ b/fs/nfs_common/grace.c
@@ -109,5 +109,11 @@ exit_grace(void)
 
 MODULE_AUTHOR("Jeff Layton <jlayton@primarydata.com>");
 MODULE_LICENSE("GPL");
-module_init(init_grace)
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_net_ns,
+	0
+};
+
+annotated_module_init(init_grace, drvid_grace, dependencies);
 module_exit(exit_grace)
diff --git a/fs/nfsd/nfsctl.c b/fs/nfsd/nfsctl.c
index 9690cb4..48de652 100644
--- a/fs/nfsd/nfsctl.c
+++ b/fs/nfsd/nfsctl.c
@@ -1314,5 +1314,15 @@ static void __exit exit_nfsd(void)
 
 MODULE_AUTHOR("Olaf Kirch <okir@monad.swb.de>");
 MODULE_LICENSE("GPL");
-module_init(init_nfsd)
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_auth_rpcgss,
+	drvid_lockd,
+	drvid_grace,
+	drvid_sunrpc,
+	drvid_debugfs,
+	0
+};
+
+annotated_module_init(init_nfsd, drvid_nfsd, dependencies);
 module_exit(exit_nfsd)
diff --git a/fs/pipe.c b/fs/pipe.c
index 8865f79..70ae621 100644
--- a/fs/pipe.c
+++ b/fs/pipe.c
@@ -1122,4 +1122,4 @@ static int __init init_pipe_fs(void)
 	return err;
 }
 
-fs_initcall(init_pipe_fs);
+annotated_initcall(fs, init_pipe_fs, drvid_pipe_fs, NULL);
diff --git a/fs/proc/cmdline.c b/fs/proc/cmdline.c
index cbd82df..bd7390a 100644
--- a/fs/proc/cmdline.c
+++ b/fs/proc/cmdline.c
@@ -26,4 +26,4 @@ static int __init proc_cmdline_init(void)
 	proc_create("cmdline", 0, NULL, &cmdline_proc_fops);
 	return 0;
 }
-fs_initcall(proc_cmdline_init);
+annotated_initcall(fs, proc_cmdline_init, drvid_proc_cmdline, NULL);
diff --git a/fs/proc/consoles.c b/fs/proc/consoles.c
index 290ba85..f1fca53 100644
--- a/fs/proc/consoles.c
+++ b/fs/proc/consoles.c
@@ -109,4 +109,4 @@ static int __init proc_consoles_init(void)
 	proc_create("consoles", 0, NULL, &proc_consoles_operations);
 	return 0;
 }
-fs_initcall(proc_consoles_init);
+annotated_initcall(fs, proc_consoles_init, drvid_proc_consoles, NULL);
diff --git a/fs/proc/cpuinfo.c b/fs/proc/cpuinfo.c
index 06f4d31..56a201d 100644
--- a/fs/proc/cpuinfo.c
+++ b/fs/proc/cpuinfo.c
@@ -21,4 +21,4 @@ static int __init proc_cpuinfo_init(void)
 	proc_create("cpuinfo", 0, NULL, &proc_cpuinfo_operations);
 	return 0;
 }
-fs_initcall(proc_cpuinfo_init);
+annotated_initcall(fs, proc_cpuinfo_init, drvid_proc_cpuinfo, NULL);
diff --git a/fs/proc/devices.c b/fs/proc/devices.c
index 50493ed..a1e8653 100644
--- a/fs/proc/devices.c
+++ b/fs/proc/devices.c
@@ -67,4 +67,4 @@ static int __init proc_devices_init(void)
 	proc_create("devices", 0, NULL, &proc_devinfo_operations);
 	return 0;
 }
-fs_initcall(proc_devices_init);
+annotated_initcall(fs, proc_devices_init, drvid_proc_devices, NULL);
diff --git a/fs/proc/interrupts.c b/fs/proc/interrupts.c
index a352d57..8b1f61c 100644
--- a/fs/proc/interrupts.c
+++ b/fs/proc/interrupts.c
@@ -50,4 +50,4 @@ static int __init proc_interrupts_init(void)
 	proc_create("interrupts", 0, NULL, &proc_interrupts_operations);
 	return 0;
 }
-fs_initcall(proc_interrupts_init);
+annotated_initcall(fs, proc_interrupts_init, drvid_proc_interrupts, NULL);
diff --git a/fs/proc/kcore.c b/fs/proc/kcore.c
index 92e6726..51c4728 100644
--- a/fs/proc/kcore.c
+++ b/fs/proc/kcore.c
@@ -641,4 +641,4 @@ static int __init proc_kcore_init(void)
 
 	return 0;
 }
-fs_initcall(proc_kcore_init);
+annotated_initcall(fs, proc_kcore_init, drvid_proc_kcore, NULL);
diff --git a/fs/proc/kmsg.c b/fs/proc/kmsg.c
index 05f8dcd..d2c5699 100644
--- a/fs/proc/kmsg.c
+++ b/fs/proc/kmsg.c
@@ -61,4 +61,4 @@ static int __init proc_kmsg_init(void)
 	proc_create("kmsg", S_IRUSR, NULL, &proc_kmsg_operations);
 	return 0;
 }
-fs_initcall(proc_kmsg_init);
+annotated_initcall(fs, proc_kmsg_init, drvid_proc_kmsg, NULL);
diff --git a/fs/proc/loadavg.c b/fs/proc/loadavg.c
index aec66e6..767b34b 100644
--- a/fs/proc/loadavg.c
+++ b/fs/proc/loadavg.c
@@ -42,4 +42,4 @@ static int __init proc_loadavg_init(void)
 	proc_create("loadavg", 0, NULL, &loadavg_proc_fops);
 	return 0;
 }
-fs_initcall(proc_loadavg_init);
+annotated_initcall(fs, proc_loadavg_init, drvid_proc_loadavg, NULL);
diff --git a/fs/proc/meminfo.c b/fs/proc/meminfo.c
index d3ebf2e..0981b0f 100644
--- a/fs/proc/meminfo.c
+++ b/fs/proc/meminfo.c
@@ -231,4 +231,4 @@ static int __init proc_meminfo_init(void)
 	proc_create("meminfo", 0, NULL, &meminfo_proc_fops);
 	return 0;
 }
-fs_initcall(proc_meminfo_init);
+annotated_initcall(fs, proc_meminfo_init, drvid_proc_meminfo, NULL);
diff --git a/fs/proc/page.c b/fs/proc/page.c
index 7eee2d8..9d15bfe 100644
--- a/fs/proc/page.c
+++ b/fs/proc/page.c
@@ -231,4 +231,4 @@ static int __init proc_page_init(void)
 	proc_create("kpageflags", S_IRUSR, NULL, &proc_kpageflags_operations);
 	return 0;
 }
-fs_initcall(proc_page_init);
+annotated_initcall(fs, proc_page_init, drvid_proc_page, NULL);
diff --git a/fs/proc/softirqs.c b/fs/proc/softirqs.c
index ad8a77f..543c1bf 100644
--- a/fs/proc/softirqs.c
+++ b/fs/proc/softirqs.c
@@ -41,4 +41,4 @@ static int __init proc_softirqs_init(void)
 	proc_create("softirqs", 0, NULL, &proc_softirqs_operations);
 	return 0;
 }
-fs_initcall(proc_softirqs_init);
+annotated_initcall(fs, proc_softirqs_init, drvid_proc_softirqs, NULL);
diff --git a/fs/proc/stat.c b/fs/proc/stat.c
index 510413eb..adb734f 100644
--- a/fs/proc/stat.c
+++ b/fs/proc/stat.c
@@ -203,4 +203,4 @@ static int __init proc_stat_init(void)
 	proc_create("stat", 0, NULL, &proc_stat_operations);
 	return 0;
 }
-fs_initcall(proc_stat_init);
+annotated_initcall(fs, proc_stat_init, drvid_proc_stat, NULL);
diff --git a/fs/proc/uptime.c b/fs/proc/uptime.c
index 33de567..16c0eed 100644
--- a/fs/proc/uptime.c
+++ b/fs/proc/uptime.c
@@ -49,4 +49,4 @@ static int __init proc_uptime_init(void)
 	proc_create("uptime", 0, NULL, &uptime_proc_fops);
 	return 0;
 }
-fs_initcall(proc_uptime_init);
+annotated_initcall(fs, proc_uptime_init, drvid_proc_uptime, NULL);
diff --git a/fs/proc/version.c b/fs/proc/version.c
index d2154eb..511e41a 100644
--- a/fs/proc/version.c
+++ b/fs/proc/version.c
@@ -31,4 +31,4 @@ static int __init proc_version_init(void)
 	proc_create("version", 0, NULL, &version_proc_fops);
 	return 0;
 }
-fs_initcall(proc_version_init);
+annotated_initcall(fs, proc_version_init, drvid_proc_version, NULL);
diff --git a/fs/ubifs/super.c b/fs/ubifs/super.c
index 9547a278..6333034 100644
--- a/fs/ubifs/super.c
+++ b/fs/ubifs/super.c
@@ -2276,8 +2276,17 @@ out_slab:
 	kmem_cache_destroy(ubifs_inode_slab);
 	return err;
 }
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_debugfs,
+	drvid_bdi,
+	drvid_deflate,
+	drvid_lzo,
+	0
+};
+
 /* late_initcall to let compressors initialize first */
-late_initcall(ubifs_init);
+annotated_initcall(late, ubifs_init, drvid_ubifs, dependencies);
 
 static void __exit ubifs_exit(void)
 {
diff --git a/ipc/ipc_sysctl.c b/ipc/ipc_sysctl.c
index 8ad93c2..163613c 100644
--- a/ipc/ipc_sysctl.c
+++ b/ipc/ipc_sysctl.c
@@ -221,4 +221,9 @@ static int __init ipc_sysctl_init(void)
 	return 0;
 }
 
-device_initcall(ipc_sysctl_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_ipc,
+	0
+};
+
+annotated_initcall(device, ipc_sysctl_init, drvid_ipc_sysctl, dependencies);
diff --git a/ipc/mqueue.c b/ipc/mqueue.c
index 161a180..07deffb 100644
--- a/ipc/mqueue.c
+++ b/ipc/mqueue.c
@@ -1466,4 +1466,9 @@ out_sysctl:
 	return error;
 }
 
-device_initcall(init_mqueue_fs);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_proc_filesystems,
+	0
+};
+
+annotated_initcall(device, init_mqueue_fs, drvid_mqueue_fs, dependencies);
diff --git a/ipc/util.c b/ipc/util.c
index be42300..81e449a 100644
--- a/ipc/util.c
+++ b/ipc/util.c
@@ -88,7 +88,13 @@ static int __init ipc_init(void)
 	shm_init();
 	return 0;
 }
-device_initcall(ipc_init);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_proc_filesystems,
+	0
+};
+
+annotated_initcall(device, ipc_init, drvid_ipc, dependencies);
 
 /**
  * ipc_init_ids	- initialise ipc identifiers
diff --git a/kernel/configs.c b/kernel/configs.c
index c18b1f1..44d6b624 100644
--- a/kernel/configs.c
+++ b/kernel/configs.c
@@ -89,7 +89,7 @@ static void __exit ikconfig_cleanup(void)
 	remove_proc_entry("config.gz", NULL);
 }
 
-module_init(ikconfig_init);
+annotated_module_init(ikconfig_init, drvid_configs, NULL);
 module_exit(ikconfig_cleanup);
 
 #endif /* CONFIG_IKCONFIG_PROC */
diff --git a/kernel/dma.c b/kernel/dma.c
index 6c6262f..2cf2469 100644
--- a/kernel/dma.c
+++ b/kernel/dma.c
@@ -152,7 +152,7 @@ static int __init proc_dma_init(void)
 	return 0;
 }
 
-__initcall(proc_dma_init);
+annotated_initcall(device, proc_dma_init, drvid_proc_dma, NULL);
 #endif
 
 EXPORT_SYMBOL(request_dma);
diff --git a/kernel/futex.c b/kernel/futex.c
index c4a182f..da9f48a 100644
--- a/kernel/futex.c
+++ b/kernel/futex.c
@@ -3074,4 +3074,4 @@ static int __init futex_init(void)
 
 	return 0;
 }
-__initcall(futex_init);
+annotated_initcall(device, futex_init, drvid_futex, NULL);
diff --git a/kernel/module.c b/kernel/module.c
index b86b7bf..68f0b50 100644
--- a/kernel/module.c
+++ b/kernel/module.c
@@ -3943,7 +3943,7 @@ static int __init proc_modules_init(void)
 	proc_create("modules", 0, NULL, &proc_modules_operations);
 	return 0;
 }
-module_init(proc_modules_init);
+annotated_module_init(proc_modules_init, drvid_proc_modules, NULL);
 #endif
 
 /* Given an address, look for it in the module exception tables. */
diff --git a/kernel/power/hibernate.c b/kernel/power/hibernate.c
index 690f78f..ed70e63 100644
--- a/kernel/power/hibernate.c
+++ b/kernel/power/hibernate.c
@@ -1087,7 +1087,12 @@ static int __init pm_disk_init(void)
 	return sysfs_create_group(power_kobj, &attr_group);
 }
 
-core_initcall(pm_disk_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_pm,
+	0
+};
+
+annotated_initcall(core, pm_disk_init, drvid_pm_disk, dependencies);
 
 
 static int __init resume_setup(char *str)
diff --git a/kernel/power/main.c b/kernel/power/main.c
index 63d395b..08765ac 100644
--- a/kernel/power/main.c
+++ b/kernel/power/main.c
@@ -643,4 +643,9 @@ static int __init pm_init(void)
 	return pm_autosleep_init();
 }
 
-core_initcall(pm_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_debugfs,
+	0
+};
+
+annotated_initcall(core, pm_init, drvid_pm, dependencies);
diff --git a/kernel/power/poweroff.c b/kernel/power/poweroff.c
index 7ef6866..d075c44 100644
--- a/kernel/power/poweroff.c
+++ b/kernel/power/poweroff.c
@@ -43,4 +43,4 @@ static int __init pm_sysrq_init(void)
 	return 0;
 }
 
-subsys_initcall(pm_sysrq_init);
+annotated_initcall(subsys, pm_sysrq_init, drvid_pm_sysrq, NULL);
diff --git a/kernel/power/user.c b/kernel/power/user.c
index 526e891..21943cc 100644
--- a/kernel/power/user.c
+++ b/kernel/power/user.c
@@ -475,4 +475,9 @@ static int __init snapshot_device_init(void)
 	return misc_register(&snapshot_device);
 };
 
-device_initcall(snapshot_device_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_misc,
+	0
+};
+
+annotated_initcall(device, snapshot_device_init, drvid_snapshot_device, dependencies);
diff --git a/kernel/sched/stats.c b/kernel/sched/stats.c
index 87e2c9f..3350d7e 100644
--- a/kernel/sched/stats.c
+++ b/kernel/sched/stats.c
@@ -135,4 +135,4 @@ static int __init proc_schedstat_init(void)
 	proc_create("schedstat", 0, NULL, &proc_schedstat_operations);
 	return 0;
 }
-subsys_initcall(proc_schedstat_init);
+annotated_initcall(subsys, proc_schedstat_init, drvid_proc_schedstat, NULL);
diff --git a/kernel/system_keyring.c b/kernel/system_keyring.c
index 875f64e..5ff5510 100644
--- a/kernel/system_keyring.c
+++ b/kernel/system_keyring.c
@@ -47,7 +47,7 @@ static __init int system_trusted_keyring_init(void)
 /*
  * Must be initialised before we try and load the keys into the keyring.
  */
-device_initcall(system_trusted_keyring_init);
+annotated_initcall(device, system_trusted_keyring_init, drvid_system_trusted_keyring_init, NULL);
 
 /*
  * Load the compiled-in list of X.509 certificates.
@@ -103,4 +103,15 @@ dodgy_cert:
 	pr_err("Problem parsing in-kernel X.509 certificate list\n");
 	return 0;
 }
-late_initcall(load_system_certificate_list);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_system_trusted_keyring_init,
+	drvid_x509,
+	drvid_sha1_generic,
+	drvid_sha256_generic,
+	drvid_sha512_generic,
+	drvid_crypto_algapi,
+	0
+};
+
+annotated_initcall(late, load_system_certificate_list, drvid_load_system_certificate_list, dependencies);
diff --git a/kernel/time/clocksource.c b/kernel/time/clocksource.c
index 841b72f..7da6b96 100644
--- a/kernel/time/clocksource.c
+++ b/kernel/time/clocksource.c
@@ -630,7 +630,7 @@ static int __init clocksource_done_booting(void)
 	mutex_unlock(&clocksource_mutex);
 	return 0;
 }
-fs_initcall(clocksource_done_booting);
+annotated_initcall(fs, clocksource_done_booting, drvid_clocksource_done_booting, NULL);
 
 /*
  * Enqueue the clocksource sorted by rating
@@ -979,7 +979,12 @@ static int __init init_clocksource_sysfs(void)
 	return error;
 }
 
-device_initcall(init_clocksource_sysfs);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_clocksource_done_booting,
+	0
+};
+
+annotated_initcall(device, init_clocksource_sysfs, drvid_clocksource_sysfs, dependencies);
 #endif /* CONFIG_SYSFS */
 
 /**
diff --git a/kernel/workqueue.c b/kernel/workqueue.c
index a413acb..0c39fce 100644
--- a/kernel/workqueue.c
+++ b/kernel/workqueue.c
@@ -5070,7 +5070,7 @@ static int __init wq_sysfs_init(void)
 
 	return device_create_file(wq_subsys.dev_root, &wq_sysfs_cpumask_attr);
 }
-core_initcall(wq_sysfs_init);
+annotated_initcall(core, wq_sysfs_init, drvid_wq_sysfs, NULL);
 
 static void wq_device_release(struct device *dev)
 {
diff --git a/lib/crc-t10dif.c b/lib/crc-t10dif.c
index 1ad33e5..07aa046a 100644
--- a/lib/crc-t10dif.c
+++ b/lib/crc-t10dif.c
@@ -62,7 +62,7 @@ static void __exit crc_t10dif_mod_fini(void)
 	crypto_free_shash(crct10dif_tfm);
 }
 
-module_init(crc_t10dif_mod_init);
+annotated_module_init(crc_t10dif_mod_init, drvid_crc_t10dif_mod, NULL);
 module_exit(crc_t10dif_mod_fini);
 
 MODULE_DESCRIPTION("T10 DIF CRC calculation");
diff --git a/lib/crc32.c b/lib/crc32.c
index 9a907d4..61f358f 100644
--- a/lib/crc32.c
+++ b/lib/crc32.c
@@ -1169,6 +1169,6 @@ static void __exit crc32_exit(void)
 {
 }
 
-module_init(crc32test_init);
+annotated_module_init(crc32test_init, drvid_crc32test, NULL);
 module_exit(crc32_exit);
 #endif /* CONFIG_CRC32_SELFTEST */
diff --git a/lib/kobject_uevent.c b/lib/kobject_uevent.c
index f6c2c1e..d8c4f51 100644
--- a/lib/kobject_uevent.c
+++ b/lib/kobject_uevent.c
@@ -466,6 +466,10 @@ static int __init kobject_uevent_init(void)
 	return register_pernet_subsys(&uevent_net_ops);
 }
 
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_netlink_proto,
+	0
+};
 
-postcore_initcall(kobject_uevent_init);
+annotated_initcall(postcore, kobject_uevent_init, drvid_kobject_uevent, dependencies);
 #endif
diff --git a/lib/libcrc32c.c b/lib/libcrc32c.c
index 6a08ce7..717cf16 100644
--- a/lib/libcrc32c.c
+++ b/lib/libcrc32c.c
@@ -68,7 +68,12 @@ static void __exit libcrc32c_mod_fini(void)
 	crypto_free_shash(tfm);
 }
 
-module_init(libcrc32c_mod_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_crc32c,
+	0
+};
+
+annotated_module_init(libcrc32c_mod_init, drvid_libcrc32c, dependencies);
 module_exit(libcrc32c_mod_fini);
 
 MODULE_AUTHOR("Clay Haapala <chaapala@cisco.com>");
diff --git a/lib/raid6/algos.c b/lib/raid6/algos.c
index 975c6e0..3eac3f5 100644
--- a/lib/raid6/algos.c
+++ b/lib/raid6/algos.c
@@ -244,7 +244,7 @@ static void raid6_exit(void)
 	do { } while (0);
 }
 
-subsys_initcall(raid6_select_algo);
+annotated_initcall(subsys, raid6_select_algo, drvid_raid6_pq, NULL);
 module_exit(raid6_exit);
 MODULE_LICENSE("GPL");
 MODULE_DESCRIPTION("RAID6 Q-syndrome calculations");
diff --git a/mm/backing-dev.c b/mm/backing-dev.c
index dac5bf5..94bba65 100644
--- a/mm/backing-dev.c
+++ b/mm/backing-dev.c
@@ -239,7 +239,13 @@ static __init int bdi_class_init(void)
 	bdi_debug_init();
 	return 0;
 }
-postcore_initcall(bdi_class_init);
+
+static const unsigned dependencies0[] __initconst __maybe_unused = {
+	drvid_debugfs,
+	0
+};
+
+annotated_initcall(postcore, bdi_class_init, drvid_bdi_class, dependencies0);
 
 static int __init default_bdi_init(void)
 {
@@ -254,7 +260,14 @@ static int __init default_bdi_init(void)
 
 	return err;
 }
-subsys_initcall(default_bdi_init);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_bdi_class,
+	drvid_wq_sysfs,
+	0
+};
+
+annotated_initcall(subsys, default_bdi_init, drvid_bdi, dependencies);
 
 /*
  * This function is used when the first inode for this wb is marked dirty. It
diff --git a/mm/swapfile.c b/mm/swapfile.c
index 41e4581..984c246 100644
--- a/mm/swapfile.c
+++ b/mm/swapfile.c
@@ -2077,7 +2077,7 @@ static int __init procswaps_init(void)
 	proc_create("swaps", 0, NULL, &proc_swaps_operations);
 	return 0;
 }
-__initcall(procswaps_init);
+annotated_initcall(device, procswaps_init, drvid_procswaps, NULL);
 #endif /* CONFIG_PROC_FS */
 
 #ifdef MAX_SWAPFILES_CHECK
diff --git a/mm/vmalloc.c b/mm/vmalloc.c
index 2faaa29..9061475 100644
--- a/mm/vmalloc.c
+++ b/mm/vmalloc.c
@@ -2686,7 +2686,7 @@ static int __init proc_vmalloc_init(void)
 	proc_create("vmallocinfo", S_IRUSR, NULL, &proc_vmalloc_operations);
 	return 0;
 }
-module_init(proc_vmalloc_init);
+annotated_module_init(proc_vmalloc_init, drvid_proc_vmalloc, NULL);
 
 void get_vmalloc_info(struct vmalloc_info *vmi)
 {
diff --git a/net/bluetooth/af_bluetooth.c b/net/bluetooth/af_bluetooth.c
index 70f9d94..7f05a28 100644
--- a/net/bluetooth/af_bluetooth.c
+++ b/net/bluetooth/af_bluetooth.c
@@ -785,7 +785,12 @@ static void __exit bt_exit(void)
 	debugfs_remove_recursive(bt_debugfs);
 }
 
-subsys_initcall(bt_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_rfkill,
+	0
+};
+
+annotated_initcall(subsys, bt_init, drvid_bt, dependencies);
 module_exit(bt_exit);
 
 MODULE_AUTHOR("Marcel Holtmann <marcel@holtmann.org>");
diff --git a/net/core/dev.c b/net/core/dev.c
index a8e4dd4..79808ef 100644
--- a/net/core/dev.c
+++ b/net/core/dev.c
@@ -7645,4 +7645,10 @@ out:
 	return rc;
 }
 
-subsys_initcall(net_dev_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_sock,
+	drvid_netlink,
+	0
+};
+
+annotated_initcall(subsys, net_dev_init, drvid_net_dev, dependencies);
diff --git a/net/core/fib_rules.c b/net/core/fib_rules.c
index 0ad144f..cc02b4c 100644
--- a/net/core/fib_rules.c
+++ b/net/core/fib_rules.c
@@ -800,4 +800,10 @@ fail:
 	return err;
 }
 
-subsys_initcall(fib_rules_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_netlink,
+	drvid_net_dev,
+	0
+};
+
+annotated_initcall(subsys, fib_rules_init, drvid_fib_rules, dependencies);
diff --git a/net/core/neighbour.c b/net/core/neighbour.c
index 84195da..34e8991 100644
--- a/net/core/neighbour.c
+++ b/net/core/neighbour.c
@@ -3171,5 +3171,9 @@ static int __init neigh_init(void)
 	return 0;
 }
 
-subsys_initcall(neigh_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_net_dev,
+	0
+};
 
+annotated_initcall(subsys, neigh_init, drvid_neigh, dependencies);
diff --git a/net/core/net_namespace.c b/net/core/net_namespace.c
index 2c2eb1b..b4223d2 100644
--- a/net/core/net_namespace.c
+++ b/net/core/net_namespace.c
@@ -765,7 +765,7 @@ static int __init net_ns_init(void)
 	return 0;
 }
 
-pure_initcall(net_ns_init);
+annotated_initcall(pure, net_ns_init, drvid_net_ns, NULL);
 
 #ifdef CONFIG_NET_NS
 static int __register_pernet_operations(struct list_head *list,
diff --git a/net/core/netpoll.c b/net/core/netpoll.c
index c126a87..eca91c2 100644
--- a/net/core/netpoll.c
+++ b/net/core/netpoll.c
@@ -775,7 +775,13 @@ static int __init netpoll_init(void)
 	skb_queue_head_init(&skb_pool);
 	return 0;
 }
-core_initcall(netpoll_init);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_sock,
+	0
+};
+
+annotated_initcall(core, netpoll_init, drvid_netpoll, dependencies);
 
 static void rcu_cleanup_netpoll_info(struct rcu_head *rcu_head)
 {
diff --git a/net/core/sock.c b/net/core/sock.c
index 193901d..a9bf288 100644
--- a/net/core/sock.c
+++ b/net/core/sock.c
@@ -2684,7 +2684,7 @@ static __init int net_inuse_init(void)
 	return 0;
 }
 
-core_initcall(net_inuse_init);
+annotated_initcall(core, net_inuse_init, drvid_net_inuse, NULL);
 #else
 static DEFINE_PER_CPU(struct prot_inuse, prot_inuse);
 
@@ -2974,6 +2974,6 @@ static int __init proto_init(void)
 	return register_pernet_subsys(&proto_net_ops);
 }
 
-subsys_initcall(proto_init);
+annotated_initcall(subsys, proto_init, drvid_proto, NULL);
 
 #endif /* PROC_FS */
diff --git a/net/core/sysctl_net_core.c b/net/core/sysctl_net_core.c
index 95b6139..42b22cb 100644
--- a/net/core/sysctl_net_core.c
+++ b/net/core/sysctl_net_core.c
@@ -461,4 +461,9 @@ static __init int sysctl_core_init(void)
 	return register_pernet_subsys(&sysctl_core_ops);
 }
 
-fs_initcall(sysctl_core_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_sock,
+	0
+};
+
+annotated_initcall(fs, sysctl_core_init, drvid_sysctl_core, dependencies);
diff --git a/net/ethernet/eth.c b/net/ethernet/eth.c
index 77e0f0e..b6e0656 100644
--- a/net/ethernet/eth.c
+++ b/net/ethernet/eth.c
@@ -484,4 +484,9 @@ static int __init eth_offload_init(void)
 	return 0;
 }
 
-fs_initcall(eth_offload_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_net_dev,
+	0
+};
+
+annotated_initcall(fs, eth_offload_init, drvid_eth_offload, dependencies);
diff --git a/net/ipv4/af_inet.c b/net/ipv4/af_inet.c
index 9532ee8..0a7673b 100644
--- a/net/ipv4/af_inet.c
+++ b/net/ipv4/af_inet.c
@@ -1662,7 +1662,12 @@ static int __init ipv4_offload_init(void)
 	return 0;
 }
 
-fs_initcall(ipv4_offload_init);
+static const unsigned dependencies0[] __initconst __maybe_unused = {
+	drvid_inet,
+	0
+};
+
+annotated_initcall(fs, ipv4_offload_init, drvid_ipv4_offload, dependencies0);
 
 static struct packet_type ip_packet_type __read_mostly = {
 	.type = cpu_to_be16(ETH_P_IP),
@@ -1792,7 +1797,23 @@ out_unregister_tcp_proto:
 	goto out;
 }
 
-fs_initcall(inet_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_net_dev,
+	drvid_proto,
+	drvid_netlink, // optional
+	drvid_fib_rules, // optional
+	drvid_xfrm_user,
+	drvid_hmac,
+	drvid_md5,
+	drvid_sha1_generic,
+	drvid_cbc,
+	drvid_des_generic,
+	drvid_authenc,
+	drvid_authencesn,
+	0
+};
+
+annotated_initcall(fs, inet_init, drvid_inet, dependencies);
 
 /* ------------------------------------------------------------------------ */
 
diff --git a/net/ipv4/netfilter.c b/net/ipv4/netfilter.c
index 61eafc9..918dcc8 100644
--- a/net/ipv4/netfilter.c
+++ b/net/ipv4/netfilter.c
@@ -197,4 +197,4 @@ static int __init ipv4_netfilter_init(void)
 {
 	return nf_register_afinfo(&nf_ip_afinfo);
 }
-subsys_initcall(ipv4_netfilter_init);
+annotated_initcall(subsys, ipv4_netfilter_init, drvid_ipv4_netfilter, NULL);
diff --git a/net/ipv6/af_inet6.c b/net/ipv6/af_inet6.c
index 7de52b6..9f04016 100644
--- a/net/ipv6/af_inet6.c
+++ b/net/ipv6/af_inet6.c
@@ -1027,6 +1027,22 @@ out_unregister_tcp_proto:
 	proto_unregister(&tcpv6_prot);
 	goto out;
 }
-module_init(inet6_init);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_sock,
+	drvid_proto,
+	drvid_neigh,
+	drvid_xfrm_user,
+	drvid_hmac,
+	drvid_md5,
+	drvid_sha1_generic,
+	drvid_cbc,
+	drvid_des_generic,
+	drvid_authenc,
+	drvid_authencesn,
+	0
+};
+
+annotated_module_init(inet6_init, drvid_inet6, dependencies);
 
 MODULE_ALIAS_NETPROTO(PF_INET6);
diff --git a/net/ipv6/ip6_offload.c b/net/ipv6/ip6_offload.c
index 08b6204..323c6b6 100644
--- a/net/ipv6/ip6_offload.c
+++ b/net/ipv6/ip6_offload.c
@@ -312,4 +312,9 @@ static int __init ipv6_offload_init(void)
 	return 0;
 }
 
-fs_initcall(ipv6_offload_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_inet,
+	0
+};
+
+annotated_initcall(fs, ipv6_offload_init, drvid_ipv6_offload, dependencies);
diff --git a/net/netlink/af_netlink.c b/net/netlink/af_netlink.c
index 0857f72..e2215a8 100644
--- a/net/netlink/af_netlink.c
+++ b/net/netlink/af_netlink.c
@@ -3302,4 +3302,10 @@ panic:
 	panic("netlink_init: Cannot allocate nl_table\n");
 }
 
-core_initcall(netlink_proto_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_sock,
+	drvid_proto,
+	0
+};
+
+annotated_initcall(core, netlink_proto_init, drvid_netlink_proto, dependencies);
diff --git a/net/netlink/genetlink.c b/net/netlink/genetlink.c
index 2ed5f96..21d4a1a 100644
--- a/net/netlink/genetlink.c
+++ b/net/netlink/genetlink.c
@@ -1095,7 +1095,12 @@ problem:
 	panic("GENL: Cannot register controller: %d\n", err);
 }
 
-subsys_initcall(genl_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_netlink_proto,
+	0
+};
+
+annotated_initcall(subsys, genl_init, drvid_netlink, dependencies);
 
 static int genlmsg_mcast(struct sk_buff *skb, u32 portid, unsigned long group,
 			 gfp_t flags)
diff --git a/net/packet/af_packet.c b/net/packet/af_packet.c
index 7851b12..b43fca3 100644
--- a/net/packet/af_packet.c
+++ b/net/packet/af_packet.c
@@ -4283,7 +4283,13 @@ out:
 	return rc;
 }
 
-module_init(packet_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_proto,
+	drvid_net_dev,
+	0
+};
+
+annotated_module_init(packet_init, drvid_packet, dependencies);
 module_exit(packet_exit);
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_NETPROTO(PF_PACKET);
diff --git a/net/rfkill/core.c b/net/rfkill/core.c
index f12149a..f7418bc 100644
--- a/net/rfkill/core.c
+++ b/net/rfkill/core.c
@@ -1288,7 +1288,13 @@ static int __init rfkill_init(void)
  out:
 	return error;
 }
-subsys_initcall(rfkill_init);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_misc,
+	0
+};
+
+annotated_initcall(subsys, rfkill_init, drvid_rfkill, dependencies);
 
 static void __exit rfkill_exit(void)
 {
diff --git a/net/rfkill/rfkill-gpio.c b/net/rfkill/rfkill-gpio.c
index d5d58d9..9f65edc 100644
--- a/net/rfkill/rfkill-gpio.c
+++ b/net/rfkill/rfkill-gpio.c
@@ -184,7 +184,12 @@ static struct platform_driver rfkill_gpio_driver = {
 	},
 };
 
-module_platform_driver(rfkill_gpio_driver);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_rfkill,
+	0
+};
+
+annotated_module_platform_driver(rfkill_gpio_driver, drvid_rfkill_gpio, dependencies);
 
 MODULE_DESCRIPTION("gpio rfkill");
 MODULE_AUTHOR("NVIDIA");
diff --git a/net/sched/sch_api.c b/net/sched/sch_api.c
index f06aa01..b73dd1c 100644
--- a/net/sched/sch_api.c
+++ b/net/sched/sch_api.c
@@ -1958,4 +1958,9 @@ static int __init pktsched_init(void)
 	return 0;
 }
 
-subsys_initcall(pktsched_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_netlink_proto,
+	0
+};
+
+annotated_initcall(subsys, pktsched_init, drvid_pktsched, dependencies);
diff --git a/net/socket.c b/net/socket.c
index 9963a0b..f5442d6 100644
--- a/net/socket.c
+++ b/net/socket.c
@@ -2532,7 +2532,12 @@ out_fs:
 	goto out;
 }
 
-core_initcall(sock_init);	/* early initcall */
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_net_ns,
+	0
+};
+
+annotated_initcall(core, sock_init, drvid_sock, dependencies);	/* early initcall */
 
 #ifdef CONFIG_PROC_FS
 void socket_seq_show(struct seq_file *seq)
diff --git a/net/sunrpc/auth_gss/auth_gss.c b/net/sunrpc/auth_gss/auth_gss.c
index dace13d..07e6343 100644
--- a/net/sunrpc/auth_gss/auth_gss.c
+++ b/net/sunrpc/auth_gss/auth_gss.c
@@ -2093,5 +2093,10 @@ MODULE_PARM_DESC(key_expire_timeo, "Time (in seconds) at the end of a "
 		"credential keys lifetime where the NFS layer cleans up "
 		"prior to key expiration");
 
-module_init(init_rpcsec_gss)
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_sunrpc,
+	0
+};
+
+annotated_module_init(init_rpcsec_gss, drvid_auth_rpcgss, dependencies);
 module_exit(exit_rpcsec_gss)
diff --git a/net/sunrpc/auth_gss/gss_krb5_mech.c b/net/sunrpc/auth_gss/gss_krb5_mech.c
index 28db442..9331c42 100644
--- a/net/sunrpc/auth_gss/gss_krb5_mech.c
+++ b/net/sunrpc/auth_gss/gss_krb5_mech.c
@@ -784,5 +784,12 @@ static void __exit cleanup_kerberos_module(void)
 }
 
 MODULE_LICENSE("GPL");
-module_init(init_kerberos_module);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_sunrpc,
+	drvid_auth_rpcgss,
+	0
+};
+
+annotated_module_init(init_kerberos_module, drvid_rpcsec_gss_krb5, dependencies);
 module_exit(cleanup_kerberos_module);
diff --git a/net/sunrpc/sunrpc_syms.c b/net/sunrpc/sunrpc_syms.c
index ee5d3d2..9add018 100644
--- a/net/sunrpc/sunrpc_syms.c
+++ b/net/sunrpc/sunrpc_syms.c
@@ -132,5 +132,11 @@ cleanup_sunrpc(void)
 	rcu_barrier(); /* Wait for completion of call_rcu()'s */
 }
 MODULE_LICENSE("GPL");
-fs_initcall(init_sunrpc); /* Ensure we're initialised before nfs */
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_debugfs,
+	0
+};
+
+annotated_initcall(fs, init_sunrpc, drvid_sunrpc, dependencies); /* Ensure we're initialised before nfs */
 module_exit(cleanup_sunrpc);
diff --git a/net/unix/af_unix.c b/net/unix/af_unix.c
index 03ee4d3..cb2bec2 100644
--- a/net/unix/af_unix.c
+++ b/net/unix/af_unix.c
@@ -2663,11 +2663,17 @@ static void __exit af_unix_exit(void)
 	unregister_pernet_subsys(&unix_net_ops);
 }
 
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_sock,
+	drvid_proto,
+	0
+};
+
 /* Earlier than device_initcall() so that other drivers invoking
    request_module() don't end up in a loop when modprobe tries
    to use a UNIX socket. But later than subsys_initcall() because
    we depend on stuff initialised there */
-fs_initcall(af_unix_init);
+annotated_initcall(fs, af_unix_init, drvid_af_unix, dependencies);
 module_exit(af_unix_exit);
 
 MODULE_LICENSE("GPL");
diff --git a/net/wireless/core.c b/net/wireless/core.c
index 2a0bbd2..b5f18f6 100644
--- a/net/wireless/core.c
+++ b/net/wireless/core.c
@@ -1209,7 +1209,15 @@ out_fail_sysfs:
 out_fail_pernet:
 	return err;
 }
-subsys_initcall(cfg80211_init);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_rfkill,
+	drvid_debugfs,
+	drvid_net_dev,
+	0
+};
+
+annotated_initcall(subsys, cfg80211_init, drvid_cfg80211, dependencies);
 
 static void __exit cfg80211_exit(void)
 {
diff --git a/net/wireless/wext-core.c b/net/wireless/wext-core.c
index c8717c1..64dff84 100644
--- a/net/wireless/wext-core.c
+++ b/net/wireless/wext-core.c
@@ -363,7 +363,12 @@ static int __init wireless_nlevent_init(void)
 	return register_pernet_subsys(&wext_pernet_ops);
 }
 
-subsys_initcall(wireless_nlevent_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_netlink,
+	0
+};
+
+annotated_initcall(subsys, wireless_nlevent_init, drvid_wireless_nlevent, dependencies);
 
 /* Process events generated by the wireless layer or the driver. */
 static void wireless_nlevent_process(struct work_struct *work)
diff --git a/net/xfrm/xfrm_user.c b/net/xfrm/xfrm_user.c
index bd16c6c..6b0662e 100644
--- a/net/xfrm/xfrm_user.c
+++ b/net/xfrm/xfrm_user.c
@@ -3161,7 +3161,13 @@ static void __exit xfrm_user_exit(void)
 	unregister_pernet_subsys(&xfrm_user_net_ops);
 }
 
-module_init(xfrm_user_init);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_netlink,
+	drvid_deflate,
+	0
+};
+
+annotated_module_init(xfrm_user_init, drvid_xfrm_user, dependencies);
 module_exit(xfrm_user_exit);
 MODULE_LICENSE("GPL");
 MODULE_ALIAS_NET_PF_PROTO(PF_NETLINK, NETLINK_XFRM);
diff --git a/security/keys/proc.c b/security/keys/proc.c
index f0611a6..e323948 100644
--- a/security/keys/proc.c
+++ b/security/keys/proc.c
@@ -76,7 +76,7 @@ static int __init key_proc_init(void)
 	return 0;
 }
 
-__initcall(key_proc_init);
+annotated_initcall(device, key_proc_init, drvid_key_proc, NULL);
 
 /*
  * Implement "/proc/keys" to provide a list of the keys on the system that
diff --git a/sound/drivers/mpu401/mpu401.c b/sound/drivers/mpu401/mpu401.c
index fed7e7e..5ab73a6 100644
--- a/sound/drivers/mpu401/mpu401.c
+++ b/sound/drivers/mpu401/mpu401.c
@@ -283,5 +283,11 @@ static void __exit alsa_card_mpu401_exit(void)
 	snd_mpu401_unregister_all();
 }
 
-module_init(alsa_card_mpu401_init)
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_pnp,
+	drvid_snd_mpu401_uart,
+	0
+};
+
+annotated_module_init(alsa_card_mpu401_init, drvid_snd_mpu401, dependencies)
 module_exit(alsa_card_mpu401_exit)
diff --git a/sound/drivers/mpu401/mpu401_uart.c b/sound/drivers/mpu401/mpu401_uart.c
index 776596b..a66e9c5 100644
--- a/sound/drivers/mpu401/mpu401_uart.c
+++ b/sound/drivers/mpu401/mpu401_uart.c
@@ -630,5 +630,5 @@ static void __exit alsa_mpu401_uart_exit(void)
 {
 }
 
-module_init(alsa_mpu401_uart_init)
+annotated_module_init(alsa_mpu401_uart_init, drvid_snd_mpu401_uart, NULL);
 module_exit(alsa_mpu401_uart_exit)
diff --git a/sound/soc/codecs/hdmi.c b/sound/soc/codecs/hdmi.c
index bd42ad3..fa725d5 100644
--- a/sound/soc/codecs/hdmi.c
+++ b/sound/soc/codecs/hdmi.c
@@ -101,7 +101,12 @@ static struct platform_driver hdmi_codec_driver = {
 	.remove		= hdmi_codec_remove,
 };
 
-module_platform_driver(hdmi_codec_driver);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_snd_soc,
+	0
+};
+
+annotated_module_platform_driver(hdmi_codec_driver, drvid_hdmi_audio_codec, dependencies);
 
 MODULE_AUTHOR("Ricardo Neri <ricardo.neri@ti.com>");
 MODULE_DESCRIPTION("ASoC generic HDMI codec driver");
diff --git a/sound/soc/codecs/twl4030.c b/sound/soc/codecs/twl4030.c
index 90f5f04..e48847e 100644
--- a/sound/soc/codecs/twl4030.c
+++ b/sound/soc/codecs/twl4030.c
@@ -2233,7 +2233,12 @@ static struct platform_driver twl4030_codec_driver = {
 	},
 };
 
-module_platform_driver(twl4030_codec_driver);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_snd_soc,
+	0
+};
+
+annotated_module_platform_driver(twl4030_codec_driver, drvid_twl4030_codec, dependencies);
 
 MODULE_DESCRIPTION("ASoC TWL4030 codec driver");
 MODULE_AUTHOR("Steve Sakoman");
diff --git a/sound/soc/fsl/imx-audmux.c b/sound/soc/fsl/imx-audmux.c
index fc57da3..b46000e 100644
--- a/sound/soc/fsl/imx-audmux.c
+++ b/sound/soc/fsl/imx-audmux.c
@@ -364,7 +364,14 @@ static int __init imx_audmux_init(void)
 {
 	return platform_driver_register(&imx_audmux_driver);
 }
-subsys_initcall(imx_audmux_init);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_snd_soc,
+	drvid_debugfs,
+	0
+};
+
+annotated_initcall_drv(subsys, imx_audmux_init, drvid_imx_audmux, dependencies, imx_audmux_driver.driver);
 
 static void __exit imx_audmux_exit(void)
 {
diff --git a/sound/soc/omap/omap-hdmi-audio.c b/sound/soc/omap/omap-hdmi-audio.c
index aeef25c..56ba4bd 100644
--- a/sound/soc/omap/omap-hdmi-audio.c
+++ b/sound/soc/omap/omap-hdmi-audio.c
@@ -401,7 +401,12 @@ static struct platform_driver hdmi_audio_driver = {
 	.remove = omap_hdmi_audio_remove,
 };
 
-module_platform_driver(hdmi_audio_driver);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_snd_soc,
+	0
+};
+
+annotated_module_platform_driver(hdmi_audio_driver, drvid_omap_hdmi, dependencies);
 
 MODULE_AUTHOR("Jyri Sarha <jsarha@ti.com>");
 MODULE_DESCRIPTION("OMAP HDMI Audio Driver");
diff --git a/sound/soc/omap/omap-mcbsp.c b/sound/soc/omap/omap-mcbsp.c
index fd99d89..37ed8f9 100644
--- a/sound/soc/omap/omap-mcbsp.c
+++ b/sound/soc/omap/omap-mcbsp.c
@@ -849,7 +849,12 @@ static struct platform_driver asoc_mcbsp_driver = {
 	.remove = asoc_mcbsp_remove,
 };
 
-module_platform_driver(asoc_mcbsp_driver);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_debugfs,
+	0
+};
+
+annotated_module_platform_driver(asoc_mcbsp_driver, drvid_omap_mcbsp, dependencies);
 
 MODULE_AUTHOR("Jarkko Nikula <jarkko.nikula@bitmer.com>");
 MODULE_DESCRIPTION("OMAP I2S SoC Interface");
diff --git a/sound/soc/omap/omap-twl4030.c b/sound/soc/omap/omap-twl4030.c
index 7431314..1a4a486 100644
--- a/sound/soc/omap/omap-twl4030.c
+++ b/sound/soc/omap/omap-twl4030.c
@@ -358,7 +358,14 @@ static struct platform_driver omap_twl4030_driver = {
 	.probe = omap_twl4030_probe,
 };
 
-module_platform_driver(omap_twl4030_driver);
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_snd_soc,
+	drvid_twl_core,
+	drvid_twl4030_codec,
+	0
+};
+
+annotated_module_platform_driver(omap_twl4030_driver, drvid_omap_twl4030, dependencies);
 
 MODULE_AUTHOR("Peter Ujfalusi <peter.ujfalusi@ti.com>");
 MODULE_DESCRIPTION("ALSA SoC for TI SoC based boards with twl4030 codec");
diff --git a/sound/soc/soc-core.c b/sound/soc/soc-core.c
index 0e1e69c..95dcff6 100644
--- a/sound/soc/soc-core.c
+++ b/sound/soc/soc-core.c
@@ -3623,7 +3623,13 @@ static int __init snd_soc_init(void)
 
 	return platform_driver_register(&soc_driver);
 }
-module_init(snd_soc_init);
+
+static const unsigned dependencies[] __initconst __maybe_unused = {
+	drvid_debugfs,
+	0
+};
+
+annotated_module_init(snd_soc_init, drvid_snd_soc, dependencies);
 
 static void __exit snd_soc_exit(void)
 {
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 12/14] dt: dts: deps: kirkwood: dockstar: add dependency ehci -> usb power regulator
  2015-10-17 17:14 [PATCH 0/14] init: deps: dependency based (parallelized) init Alexander Holler
                   ` (10 preceding siblings ...)
  2015-10-17 17:14 ` [PATCH 11/14] init: deps: annotate various initcalls Alexander Holler
@ 2015-10-17 17:14 ` Alexander Holler
  2015-10-17 17:14 ` [PATCH 13/14] dt: dts: deps: imx6q: make some remote-endpoints non-dependencies Alexander Holler
                   ` (3 subsequent siblings)
  15 siblings, 0 replies; 59+ messages in thread
From: Alexander Holler @ 2015-10-17 17:14 UTC (permalink / raw)
  To: linux-kernel
  Cc: Linus Torvalds, Andrew Morton, Greg Kroah-Hartman, Russell King,
	Grant Likely, Alexander Holler

This serves as an example how easy it is to fix an initialization order
if the order depends on the DT. No source code changes will be necessary.

If you look at the dependency graph for the dockstar, you will see that
there is no dependency between ehci and the usb power regulator. This
ends up with the fact that the regulator will be initialized after ehci.

Fix this by adding one dependency to the .dts.

Signed-off-by: Alexander Holler <holler@ahsoftware.de>
---
 arch/arm/boot/dts/kirkwood-dockstar.dts | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm/boot/dts/kirkwood-dockstar.dts b/arch/arm/boot/dts/kirkwood-dockstar.dts
index 8497363..426d8840 100644
--- a/arch/arm/boot/dts/kirkwood-dockstar.dts
+++ b/arch/arm/boot/dts/kirkwood-dockstar.dts
@@ -107,3 +107,7 @@
 		phy-handle = <&ethphy0>;
 	};
 };
+
+&usb0 {
+	dependencies = <&usb_power>;
+};
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 13/14] dt: dts: deps: imx6q: make some remote-endpoints non-dependencies
  2015-10-17 17:14 [PATCH 0/14] init: deps: dependency based (parallelized) init Alexander Holler
                   ` (11 preceding siblings ...)
  2015-10-17 17:14 ` [PATCH 12/14] dt: dts: deps: kirkwood: dockstar: add dependency ehci -> usb power regulator Alexander Holler
@ 2015-10-17 17:14 ` Alexander Holler
  2015-10-17 17:14 ` [PATCH 14/14] dt: dts: deps: omap: beagle: " Alexander Holler
                   ` (2 subsequent siblings)
  15 siblings, 0 replies; 59+ messages in thread
From: Alexander Holler @ 2015-10-17 17:14 UTC (permalink / raw)
  To: linux-kernel
  Cc: Linus Torvalds, Andrew Morton, Greg Kroah-Hartman, Russell King,
	Grant Likely, Alexander Holler

This is necessary to remove dependency cycles introduced by
'remote-endpoints'.

Signed-off-by: Alexander Holler <holler@ahsoftware.de>
---
 arch/arm/boot/dts/imx6q.dtsi   | 2 ++
 arch/arm/boot/dts/imx6qdl.dtsi | 4 ++++
 2 files changed, 6 insertions(+)

diff --git a/arch/arm/boot/dts/imx6q.dtsi b/arch/arm/boot/dts/imx6q.dtsi
index 399103b..8db7f25 100644
--- a/arch/arm/boot/dts/imx6q.dtsi
+++ b/arch/arm/boot/dts/imx6q.dtsi
@@ -184,6 +184,7 @@
 
 				ipu2_di0_hdmi: endpoint@1 {
 					remote-endpoint = <&hdmi_mux_2>;
+					no-dependencies = <&hdmi_mux_2>;
 				};
 
 				ipu2_di0_mipi: endpoint@2 {
@@ -205,6 +206,7 @@
 
 				ipu2_di1_hdmi: endpoint@1 {
 					remote-endpoint = <&hdmi_mux_3>;
+					no-dependencies = <&hdmi_mux_3>;
 				};
 
 				ipu2_di1_mipi: endpoint@2 {
diff --git a/arch/arm/boot/dts/imx6qdl.dtsi b/arch/arm/boot/dts/imx6qdl.dtsi
index b57033e..db3d0d0 100644
--- a/arch/arm/boot/dts/imx6qdl.dtsi
+++ b/arch/arm/boot/dts/imx6qdl.dtsi
@@ -1150,10 +1150,12 @@
 
 				ipu1_di0_hdmi: endpoint@1 {
 					remote-endpoint = <&hdmi_mux_0>;
+					no-dependencies = <&hdmi_mux_0>;
 				};
 
 				ipu1_di0_mipi: endpoint@2 {
 					remote-endpoint = <&mipi_mux_0>;
+					no-dependencies = <&mipi_mux_0>;
 				};
 
 				ipu1_di0_lvds0: endpoint@3 {
@@ -1175,10 +1177,12 @@
 
 				ipu1_di1_hdmi: endpoint@1 {
 					remote-endpoint = <&hdmi_mux_1>;
+					no-dependencies = <&hdmi_mux_1>;
 				};
 
 				ipu1_di1_mipi: endpoint@2 {
 					remote-endpoint = <&mipi_mux_1>;
+					no-dependencies = <&mipi_mux_1>;
 				};
 
 				ipu1_di1_lvds0: endpoint@3 {
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* [PATCH 14/14] dt: dts: deps: omap: beagle: make some remote-endpoints non-dependencies
  2015-10-17 17:14 [PATCH 0/14] init: deps: dependency based (parallelized) init Alexander Holler
                   ` (12 preceding siblings ...)
  2015-10-17 17:14 ` [PATCH 13/14] dt: dts: deps: imx6q: make some remote-endpoints non-dependencies Alexander Holler
@ 2015-10-17 17:14 ` Alexander Holler
  2015-10-17 17:44 ` [PATCH 0/14] init: deps: dependency based (parallelized) init Greg Kroah-Hartman
  2015-11-06 16:07 ` Alexander Holler
  15 siblings, 0 replies; 59+ messages in thread
From: Alexander Holler @ 2015-10-17 17:14 UTC (permalink / raw)
  To: linux-kernel
  Cc: Linus Torvalds, Andrew Morton, Greg Kroah-Hartman, Russell King,
	Grant Likely, Alexander Holler

This is necessary to remove dependency cycles introduced by
'remote-endpoints'.

Signed-off-by: Alexander Holler <holler@ahsoftware.de>
---
 arch/arm/boot/dts/omap3-beagle.dts | 4 ++++
 1 file changed, 4 insertions(+)

diff --git a/arch/arm/boot/dts/omap3-beagle.dts b/arch/arm/boot/dts/omap3-beagle.dts
index a547411..78ba39e 100644
--- a/arch/arm/boot/dts/omap3-beagle.dts
+++ b/arch/arm/boot/dts/omap3-beagle.dts
@@ -101,6 +101,7 @@
 
 				tfp410_in: endpoint@0 {
 					remote-endpoint = <&dpi_out>;
+					no-dependencies = <&dpi_out>;
 				};
 			};
 
@@ -109,6 +110,7 @@
 
 				tfp410_out: endpoint@0 {
 					remote-endpoint = <&dvi_connector_in>;
+					no-dependencies = <&dvi_connector_in>;
 				};
 			};
 		};
@@ -150,6 +152,7 @@
 			etb_in: endpoint {
 				slave-mode;
 				remote-endpoint = <&etm_out>;
+				no-dependencies = <&etm_out>;
 			};
 		};
 	};
@@ -373,6 +376,7 @@
 	port {
 		venc_out: endpoint {
 			remote-endpoint = <&tv_connector_in>;
+			no-dependencies = <&tv_connector_in>;
 			ti,channels = <2>;
 		};
 	};
-- 
2.1.0


^ permalink raw reply related	[flat|nested] 59+ messages in thread

* Re: [PATCH 0/14] init: deps: dependency based (parallelized) init
  2015-10-17 17:14 [PATCH 0/14] init: deps: dependency based (parallelized) init Alexander Holler
                   ` (13 preceding siblings ...)
  2015-10-17 17:14 ` [PATCH 14/14] dt: dts: deps: omap: beagle: " Alexander Holler
@ 2015-10-17 17:44 ` Greg Kroah-Hartman
  2015-10-17 18:19   ` Alexander Holler
  2015-11-06 16:07 ` Alexander Holler
  15 siblings, 1 reply; 59+ messages in thread
From: Greg Kroah-Hartman @ 2015-10-17 17:44 UTC (permalink / raw)
  To: Alexander Holler
  Cc: linux-kernel, Linus Torvalds, Andrew Morton, Russell King,
	Grant Likely

On Sat, Oct 17, 2015 at 07:14:13PM +0200, Alexander Holler wrote:
> Hello,
> 
> here is the newest version of my patches to use a dependency based
> initialization order. It now works without DT too.
> 
> Background:
> 
> Currently initcalls are ordered by some levels and the link order. This
> means whenever a file is renamed, changes directory or a Makefile is
> modified the order with which initcalls are called might change. This
> might result in problems. Furthermore, the required dependencies are
> often not documented, sometimes there are comments in the source or in a
> commit message, but most often the knowledge why a specific initcall
> belongs to a specific initcall level isn't obvious without carefully
> examing he source. And initcalls are used by drivers and subsystems, and
> the count of both have grown quiet a lot in the last years. So it's
> rather difficult to maintain a proper link order.

Files move around very rarely, is this really an issue?

> Another problem is that the link order can't be modified dynamically at
> boot time to include dependencies dictated by the hardware. To circumvent
> this, a brute-force trial-and-error mechanism called deferred probes has
> been introduced, but this approach, while beeing KISS, has its own
> problems.

What problems does deferred probing have?  Why not just fix that if
there is issues with it, as it was supposed to solve this issue without
needing to annotate anything.

> To solve these problems I've written patches to use a topological sort at
> boot time which uses dependencies to calculate the order with which
> initcalls are called.
> 
> Why? What are the benefits (assuming correct dependencies are available)?
> 
> - It offers a clear in-source documentation for dependencies between
>   initcalls.
> - It is robust in regard to file or directory name changes and changes in
>   a Makefile.
> - If enabled, the order with which drivers for interfaces are called
>   (e.g. network interfaces, hard disks), can be defined independent of
>   the link order. These might result in more stable interface names or
>   numbers.
> - If enabled, it makes the the deferred probes obsolete, which might
>   result in faster boot times.
> - If enabled, it is possible to call initcalls in parallel. E.g. the
>   shipped kernel for Fedora 21 (4.1.7-100.fc21.x86_64) contains around
>   560 initcalls. These are all called in series. Also some of them use
>   asynchronous stuff by themself, most don't do.

But that shipped kernel boots to X in less than 2 seconds, so there
isn't really a speed issue here, right?

> Drawbacks:
> 
> - It requires a small amount of time to calculate the order a boot time.
>   But this time is most often smaller than the time saved by using
>   multiple cores to call initcalls or by not needing deferred probes.

How much time is needed?

> - Dependencies are required. For everything which can be build as a
>   module, looking at modules.dep might give some pointers. Looking at
>   the help from menuconfig also might give some pointers. But in the
>   end, the most preferable way would be if maintainers or other people
>   which have a deeper knowledge about the source and functionality
>   would add the dependencies.

How will a "normal" driver author figure out what those dependancies are
in order to be able to write them down?  That's my biggest objection
here, I have no idea how to add these, nor how to properly review such a
submission.  What about systems that have different ordering/dependancy
requirements for the same drivers due to different ways the hardware is
hooked up?  That is not going to work well here, unless I'm missing
something.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 10/14] init: deps: IDs for annotated initcalls
  2015-10-17 17:14 ` [PATCH 10/14] init: deps: IDs for annotated initcalls Alexander Holler
@ 2015-10-17 17:45   ` Greg Kroah-Hartman
  2015-10-17 17:55     ` Alexander Holler
  0 siblings, 1 reply; 59+ messages in thread
From: Greg Kroah-Hartman @ 2015-10-17 17:45 UTC (permalink / raw)
  To: Alexander Holler
  Cc: linux-kernel, Linus Torvalds, Andrew Morton, Russell King,
	Grant Likely

On Sat, Oct 17, 2015 at 07:14:23PM +0200, Alexander Holler wrote:
> These patch contains the IDs for initcalls I've annotated.
> 
> This patch is NOT meant for merging into mainline in its current form.
> 
> It should be discussed about how to add these IDs and in which form, if
> the feature ends up in mainline at all.
> 
> E.g. it could make sense to split this file into several files in order
> to avoid merge conflicts.
> 
> It also might make sense to prefill this file with IDs for many drivers.
> 
> E.g. the following script will use a modules.dep file to produce IDs for
> modules. It's meant to be used on a very complete modules.dep build through
> make allmodconfig && make -jN modules && make modules_install.

A file like this is going to be a nightmare to maintain and ensure that
it actually is correct, I don't see it as a viable solution, sorry.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 10/14] init: deps: IDs for annotated initcalls
  2015-10-17 17:45   ` Greg Kroah-Hartman
@ 2015-10-17 17:55     ` Alexander Holler
  2015-10-17 18:29       ` Greg Kroah-Hartman
  0 siblings, 1 reply; 59+ messages in thread
From: Alexander Holler @ 2015-10-17 17:55 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-kernel, Linus Torvalds, Andrew Morton, Russell King,
	Grant Likely

Am 17.10.2015 um 19:45 schrieb Greg Kroah-Hartman:
> On Sat, Oct 17, 2015 at 07:14:23PM +0200, Alexander Holler wrote:
>> These patch contains the IDs for initcalls I've annotated.
>>
>> This patch is NOT meant for merging into mainline in its current form.
>>
>> It should be discussed about how to add these IDs and in which form, if
>> the feature ends up in mainline at all.
>>
>> E.g. it could make sense to split this file into several files in order
>> to avoid merge conflicts.
>>
>> It also might make sense to prefill this file with IDs for many drivers.
>>
>> E.g. the following script will use a modules.dep file to produce IDs for
>> modules. It's meant to be used on a very complete modules.dep build through
>> make allmodconfig && make -jN modules && make modules_install.
>
> A file like this is going to be a nightmare to maintain and ensure that
> it actually is correct, I don't see it as a viable solution, sorry.

How often will drivers be added? The only changes on this file will 
happen if a driver will be added and then just one ID will be added.

As said above, the file could be filled with IDs for all existing 
modules, regardless if they are already annotated.

If that's a nightmare, I wonder what how you name the necessary stuff to 
maintain the link order through Makefiles.

But besides that, I'm totally open to any other idea how to identify a 
driver. For me, just using an enum looks like the most trivial way.

Alexander Holler


^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 0/14] init: deps: dependency based (parallelized) init
  2015-10-17 17:44 ` [PATCH 0/14] init: deps: dependency based (parallelized) init Greg Kroah-Hartman
@ 2015-10-17 18:19   ` Alexander Holler
  2015-10-17 18:38     ` Greg Kroah-Hartman
  0 siblings, 1 reply; 59+ messages in thread
From: Alexander Holler @ 2015-10-17 18:19 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-kernel, Linus Torvalds, Andrew Morton, Russell King,
	Grant Likely

Am 17.10.2015 um 19:44 schrieb Greg Kroah-Hartman:
> On Sat, Oct 17, 2015 at 07:14:13PM +0200, Alexander Holler wrote:
>> Hello,
>>
>> here is the newest version of my patches to use a dependency based
>> initialization order. It now works without DT too.
>>
>> Background:
>>
>> Currently initcalls are ordered by some levels and the link order. This
>> means whenever a file is renamed, changes directory or a Makefile is
>> modified the order with which initcalls are called might change. This
>> might result in problems. Furthermore, the required dependencies are
>> often not documented, sometimes there are comments in the source or in a
>> commit message, but most often the knowledge why a specific initcall
>> belongs to a specific initcall level isn't obvious without carefully
>> examing he source. And initcalls are used by drivers and subsystems, and
>> the count of both have grown quiet a lot in the last years. So it's
>> rather difficult to maintain a proper link order.
>
> Files move around very rarely, is this really an issue?

No idea. You are maintaining the staging area. ;)

>
>> Another problem is that the link order can't be modified dynamically at
>> boot time to include dependencies dictated by the hardware. To circumvent
>> this, a brute-force trial-and-error mechanism called deferred probes has
>> been introduced, but this approach, while beeing KISS, has its own
>> problems.
>
> What problems does deferred probing have?  Why not just fix that if
> there is issues with it, as it was supposed to solve this issue without
> needing to annotate anything.

I've not looked why deferred probes are sometimes causing such a large 
delay. But giving that it's brutforce and non-deterministic, some 
drivers might be probed a dozen times, or important drivers might be 
probed very late, forcing all previous probed drivers to be probed again 
(late). Just think at the case the link order is a, b, c but drivers 
have to be called in the order c, b, a.

>> To solve these problems I've written patches to use a topological sort at
>> boot time which uses dependencies to calculate the order with which
>> initcalls are called.
>>
>> Why? What are the benefits (assuming correct dependencies are available)?
>>
>> - It offers a clear in-source documentation for dependencies between
>>    initcalls.
>> - It is robust in regard to file or directory name changes and changes in
>>    a Makefile.
>> - If enabled, the order with which drivers for interfaces are called
>>    (e.g. network interfaces, hard disks), can be defined independent of
>>    the link order. These might result in more stable interface names or
>>    numbers.
>> - If enabled, it makes the the deferred probes obsolete, which might
>>    result in faster boot times.
>> - If enabled, it is possible to call initcalls in parallel. E.g. the
>>    shipped kernel for Fedora 21 (4.1.7-100.fc21.x86_64) contains around
>>    560 initcalls. These are all called in series. Also some of them use
>>    asynchronous stuff by themself, most don't do.
>
> But that shipped kernel boots to X in less than 2 seconds, so there
> isn't really a speed issue here, right?

It's noticeable if your phone, or any other thing you want to use (like 
your route planner, clock or whatever boots in one second instead of two 
when you turn it on.

>> Drawbacks:
>>
>> - It requires a small amount of time to calculate the order a boot time.
>>    But this time is most often smaller than the time saved by using
>>    multiple cores to call initcalls or by not needing deferred probes.
>
> How much time is needed?

I've measured 3ms on a slow ARM box.

>
>> - Dependencies are required. For everything which can be build as a
>>    module, looking at modules.dep might give some pointers. Looking at
>>    the help from menuconfig also might give some pointers. But in the
>>    end, the most preferable way would be if maintainers or other people
>>    which have a deeper knowledge about the source and functionality
>>    would add the dependencies.
>
> How will a "normal" driver author figure out what those dependancies are
> in order to be able to write them down?  That's my biggest objection

Most drivers are done c&p from an existing driver. And if someone adds 
new code, he should know what these new code is for and on what it depends.

> here, I have no idea how to add these, nor how to properly review such a
> submission.  What about systems that have different ordering/dependancy
> requirements for the same drivers due to different ways the hardware is
> hooked up?  That is not going to work well here, unless I'm missing
> something.

Hmm, how is that solved now?

If you have dependencies dictated by a special HW, this dependencies 
should come in by the HW description.

The deferred probe mechanism exists just since 1 or 2 years. And once 
you had to search the source of non-displayed error in a set of several 
dozens possible sources (because many errors are now non-errors but 
-517) you might learn to hate deferred probes as much as I do. I'm sorry 
for the harsh words in regard to deferred probes.

The way to use dependencies doesn't add new requirements, it just moves 
them away from the link order. Besides that these dependencies are 
making it possible to parallelize the stuff.

Alexander Holler

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 04/14] init: deps: order network interfaces by link order
  2015-10-17 17:14 ` [PATCH 04/14] init: deps: order network interfaces by link order Alexander Holler
@ 2015-10-17 18:23   ` Linus Torvalds
  2015-10-17 18:37     ` Alexander Holler
  0 siblings, 1 reply; 59+ messages in thread
From: Linus Torvalds @ 2015-10-17 18:23 UTC (permalink / raw)
  To: Alexander Holler
  Cc: Linux Kernel Mailing List, Andrew Morton, Greg Kroah-Hartman,
	Russell King, Grant Likely

On Sat, Oct 17, 2015 at 10:14 AM, Alexander Holler <holler@ahsoftware.de> wrote:
>
> Assuming three different ethernet-drivers, without any special code,
> the dependency graph would not require any special order inbetween them
> and would look like that:

This seems *fundamentally* wrong.

This is in no way specific to network drivers (or to disk drivers, or
to anything else).

So requiring extra logic for this implies that something is seriously wrong.

If two drivers aren't ordered by dependencies, they should always be
in link order, regardless of any hacks like these. If they're not,
things are wrong.

I think your problem is that you make that dependency thing a separate
ordering, so now it matters whether a driver has a dependency or not.

If something like this is to work, it has to work *with* the normal
ordering, not outside of it and then have these kinds of broken
special cases.

The normal init orderings (ie core -> postcore -> arch -> subsys -> fs
-> rootfs -> device -> late) should just be an extra dependency, I
think.

The way that you just insert the annotated dependencies in between
levels 6 and 7 ("device" and "late") can't be right. It means - for
example - that you can't have subsystems that have dependencies.

So I really think that if we do dependencies, then the current levels
have to be added as dependencies, so that "subsys_initcall(xyz)"
basically means "xyz depends on the 'subsys' event, and 'subsys_end'
depends on xyz". Then within that, you might have another bus driver
that in turn depends on 'xyz'.

Because right now afaik we do have dependencies like that, which we
sort out by link ordering (things like 'drm depends on pci' - I'm not
actually sure that one is true, but it might be).

                     Linus

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 10/14] init: deps: IDs for annotated initcalls
  2015-10-17 17:55     ` Alexander Holler
@ 2015-10-17 18:29       ` Greg Kroah-Hartman
  2015-10-17 18:46         ` Alexander Holler
  0 siblings, 1 reply; 59+ messages in thread
From: Greg Kroah-Hartman @ 2015-10-17 18:29 UTC (permalink / raw)
  To: Alexander Holler
  Cc: linux-kernel, Linus Torvalds, Andrew Morton, Russell King,
	Grant Likely

On Sat, Oct 17, 2015 at 07:55:17PM +0200, Alexander Holler wrote:
> Am 17.10.2015 um 19:45 schrieb Greg Kroah-Hartman:
> >On Sat, Oct 17, 2015 at 07:14:23PM +0200, Alexander Holler wrote:
> >>These patch contains the IDs for initcalls I've annotated.
> >>
> >>This patch is NOT meant for merging into mainline in its current form.
> >>
> >>It should be discussed about how to add these IDs and in which form, if
> >>the feature ends up in mainline at all.
> >>
> >>E.g. it could make sense to split this file into several files in order
> >>to avoid merge conflicts.
> >>
> >>It also might make sense to prefill this file with IDs for many drivers.
> >>
> >>E.g. the following script will use a modules.dep file to produce IDs for
> >>modules. It's meant to be used on a very complete modules.dep build through
> >>make allmodconfig && make -jN modules && make modules_install.
> >
> >A file like this is going to be a nightmare to maintain and ensure that
> >it actually is correct, I don't see it as a viable solution, sorry.
> 
> How often will drivers be added? The only changes on this file will happen
> if a driver will be added and then just one ID will be added.

Look at how many drivers we add every kernel release, it's a non-trivial
amount.

> As said above, the file could be filled with IDs for all existing modules,
> regardless if they are already annotated.
> 
> If that's a nightmare, I wonder what how you name the necessary stuff to
> maintain the link order through Makefiles.

There usually isn't a problem and the issue is that we link by
subsystem, so somehow it's all working fairly well.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 04/14] init: deps: order network interfaces by link order
  2015-10-17 18:23   ` Linus Torvalds
@ 2015-10-17 18:37     ` Alexander Holler
  2015-10-17 18:52       ` Linus Torvalds
                         ` (2 more replies)
  0 siblings, 3 replies; 59+ messages in thread
From: Alexander Holler @ 2015-10-17 18:37 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Linux Kernel Mailing List, Andrew Morton, Greg Kroah-Hartman,
	Russell King, Grant Likely

Am 17.10.2015 um 20:23 schrieb Linus Torvalds:
> On Sat, Oct 17, 2015 at 10:14 AM, Alexander Holler <holler@ahsoftware.de> wrote:
>>
>> Assuming three different ethernet-drivers, without any special code,
>> the dependency graph would not require any special order inbetween them
>> and would look like that:
>
> This seems *fundamentally* wrong.
>
> This is in no way specific to network drivers (or to disk drivers, or
> to anything else).
>
> So requiring extra logic for this implies that something is seriously wrong.
>
> If two drivers aren't ordered by dependencies, they should always be
> in link order, regardless of any hacks like these. If they're not,
> things are wrong.
>
> I think your problem is that you make that dependency thing a separate
> ordering, so now it matters whether a driver has a dependency or not.

I'm making dependencies the only ordering for annotated initcalls.

Otherwise it's impossible to call initcalls in parallel. I've seen a 
stable topological sort somewhere, but whenever you want to parallelize 
the initcalls, the stable ordering would be gone anyway. So I've decided 
not to look further at a stable topological sort.

> If something like this is to work, it has to work *with* the normal
> ordering, not outside of it and then have these kinds of broken
> special cases.
>
> The normal init orderings (ie core -> postcore -> arch -> subsys -> fs
> -> rootfs -> device -> late) should just be an extra dependency, I
> think.
>
> The way that you just insert the annotated dependencies in between
> levels 6 and 7 ("device" and "late") can't be right. It means - for
> example - that you can't have subsystems that have dependencies.

Sorry, but that's wrong.

I've choosen to place initcalls between 5 and 6 to make it easier to 
move both, subsystems as well as normal drivers to the (new) level with 
annotated initcalls. If you look at what I've already "annotated", you 
will see there are quiet a lot initcalls I've moved from below 6 to the 
new level.

> So I really think that if we do dependencies, then the current levels
> have to be added as dependencies, so that "subsys_initcall(xyz)"
> basically means "xyz depends on the 'subsys' event, and 'subsys_end'
> depends on xyz". Then within that, you might have another bus driver
> that in turn depends on 'xyz'.

It would be absolutely no problem to introduce "virtual" initcalls for 
any level, e.g. just

depencies = {
	everything_below
}

initcall foo()
{
	return 0;
}

annotated_initcall(foo, id, dependencies),

Regards,

Alexander Holler

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 0/14] init: deps: dependency based (parallelized) init
  2015-10-17 18:19   ` Alexander Holler
@ 2015-10-17 18:38     ` Greg Kroah-Hartman
  2015-10-17 19:43       ` Alexander Holler
  0 siblings, 1 reply; 59+ messages in thread
From: Greg Kroah-Hartman @ 2015-10-17 18:38 UTC (permalink / raw)
  To: Alexander Holler
  Cc: linux-kernel, Linus Torvalds, Andrew Morton, Russell King,
	Grant Likely

On Sat, Oct 17, 2015 at 08:19:09PM +0200, Alexander Holler wrote:
> >>Another problem is that the link order can't be modified dynamically at
> >>boot time to include dependencies dictated by the hardware. To circumvent
> >>this, a brute-force trial-and-error mechanism called deferred probes has
> >>been introduced, but this approach, while beeing KISS, has its own
> >>problems.
> >
> >What problems does deferred probing have?  Why not just fix that if
> >there is issues with it, as it was supposed to solve this issue without
> >needing to annotate anything.
> 
> I've not looked why deferred probes are sometimes causing such a large
> delay. But giving that it's brutforce and non-deterministic, some drivers
> might be probed a dozen times, or important drivers might be probed very
> late, forcing all previous probed drivers to be probed again (late). Just
> think at the case the link order is a, b, c but drivers have to be called in
> the order c, b, a.

So how long does that really take to call all probe functions in all
possible order?  Real numbers please.  We have the tools to determine
where at boot time delays are happening, please use them to find the
problem drivers.

> >>To solve these problems I've written patches to use a topological sort at
> >>boot time which uses dependencies to calculate the order with which
> >>initcalls are called.
> >>
> >>Why? What are the benefits (assuming correct dependencies are available)?
> >>
> >>- It offers a clear in-source documentation for dependencies between
> >>   initcalls.
> >>- It is robust in regard to file or directory name changes and changes in
> >>   a Makefile.
> >>- If enabled, the order with which drivers for interfaces are called
> >>   (e.g. network interfaces, hard disks), can be defined independent of
> >>   the link order. These might result in more stable interface names or
> >>   numbers.
> >>- If enabled, it makes the the deferred probes obsolete, which might
> >>   result in faster boot times.
> >>- If enabled, it is possible to call initcalls in parallel. E.g. the
> >>   shipped kernel for Fedora 21 (4.1.7-100.fc21.x86_64) contains around
> >>   560 initcalls. These are all called in series. Also some of them use
> >>   asynchronous stuff by themself, most don't do.
> >
> >But that shipped kernel boots to X in less than 2 seconds, so there
> >isn't really a speed issue here, right?
> 
> It's noticeable if your phone, or any other thing you want to use (like your
> route planner, clock or whatever boots in one second instead of two when you
> turn it on.

My phone's kernel boots in less time than I can notice it, it's
userspace that takes forever to start up.  And there are other solutions
for that, look at what Sony has done for years with the cameras they
ship with Linux on them and boot insanely quick.

Again, real numbers please, show us where in the current scheme we are
taking too much time and we can work to resolve that.

> >>Drawbacks:
> >>
> >>- It requires a small amount of time to calculate the order a boot time.
> >>   But this time is most often smaller than the time saved by using
> >>   multiple cores to call initcalls or by not needing deferred probes.
> >
> >How much time is needed?
> 
> I've measured 3ms on a slow ARM box.

And how much time does deferred probe take in comparison?

> >>- Dependencies are required. For everything which can be build as a
> >>   module, looking at modules.dep might give some pointers. Looking at
> >>   the help from menuconfig also might give some pointers. But in the
> >>   end, the most preferable way would be if maintainers or other people
> >>   which have a deeper knowledge about the source and functionality
> >>   would add the dependencies.
> >
> >How will a "normal" driver author figure out what those dependancies are
> >in order to be able to write them down?  That's my biggest objection
> 
> Most drivers are done c&p from an existing driver. And if someone adds new
> code, he should know what these new code is for and on what it depends.

Trust me, as someone who reviews more new drivers than anyone else,
people don't know, they blindly cut-and-paste from other drivers and
don't stop to think what they are doing.

> >here, I have no idea how to add these, nor how to properly review such a
> >submission.  What about systems that have different ordering/dependancy
> >requirements for the same drivers due to different ways the hardware is
> >hooked up?  That is not going to work well here, unless I'm missing
> >something.
> 
> Hmm, how is that solved now?
> 
> If you have dependencies dictated by a special HW, this dependencies should
> come in by the HW description.

Yes, device tree shows this.

> The deferred probe mechanism exists just since 1 or 2 years. And once you
> had to search the source of non-displayed error in a set of several dozens
> possible sources (because many errors are now non-errors but -517) you might
> learn to hate deferred probes as much as I do. I'm sorry for the harsh words
> in regard to deferred probes.

I don't like it much either, but it seems to work.  If lots of error
messages are annoying, and are what is really taking a long time (serial
output can be a real delay), then let's turn off the log messages to
make things go faster.

> The way to use dependencies doesn't add new requirements, it just moves them
> away from the link order. Besides that these dependencies are making it
> possible to parallelize the stuff.

We can paralleize probing today, that's been around for a very long
time, nothing is preventing you from enabling that for the drivers you
know will work properly that way right now.  Moving to a "all probing in
parallel" model has been proven to not really speed things up at all,
and in fact, slows things down due to cache and multiple process issues.
See the lkml archives for the work done many years ago around this issue
for the details.

Again, link order is a crude way to handle dependancies for built-in
drivers, I know that, which is why I accepted the deferred probing which
ensures that it will always work eventually.  You are moving from having
things in link-order to be manually specified in another manner,
preventing systems that have different dependancy requirements to never
be able to work.  And this last issue is the big one, deferred probing
is the only solution that will always work for all systems.

Again, work to speed up the problem drivers that you see taking too long
at probe time, that's the real solution here and is what others have
spent a lot of time doing, resulting in my sub-second desktop boot
times.  If embedded systems want to also achieve that, then fix the
drivers, reordering the probe order is not going to solve the boot speed
issue.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 10/14] init: deps: IDs for annotated initcalls
  2015-10-17 18:29       ` Greg Kroah-Hartman
@ 2015-10-17 18:46         ` Alexander Holler
  2015-10-19 13:12           ` Mark Brown
  0 siblings, 1 reply; 59+ messages in thread
From: Alexander Holler @ 2015-10-17 18:46 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-kernel, Linus Torvalds, Andrew Morton, Russell King,
	Grant Likely

Am 17.10.2015 um 20:29 schrieb Greg Kroah-Hartman:
> On Sat, Oct 17, 2015 at 07:55:17PM +0200, Alexander Holler wrote:
>> Am 17.10.2015 um 19:45 schrieb Greg Kroah-Hartman:
>>> On Sat, Oct 17, 2015 at 07:14:23PM +0200, Alexander Holler wrote:
>>>> These patch contains the IDs for initcalls I've annotated.
>>>>
>>>> This patch is NOT meant for merging into mainline in its current form.
>>>>
>>>> It should be discussed about how to add these IDs and in which form, if
>>>> the feature ends up in mainline at all.
>>>>
>>>> E.g. it could make sense to split this file into several files in order
>>>> to avoid merge conflicts.
>>>>
>>>> It also might make sense to prefill this file with IDs for many drivers.
>>>>
>>>> E.g. the following script will use a modules.dep file to produce IDs for
>>>> modules. It's meant to be used on a very complete modules.dep build through
>>>> make allmodconfig && make -jN modules && make modules_install.
>>>
>>> A file like this is going to be a nightmare to maintain and ensure that
>>> it actually is correct, I don't see it as a viable solution, sorry.
>>
>> How often will drivers be added? The only changes on this file will happen
>> if a driver will be added and then just one ID will be added.
>
> Look at how many drivers we add every kernel release, it's a non-trivial
> amount.

I still don't see your problem. As long as the IDs in the enum are 
ordered according to the directories, there won't be more merge 
conflicts than in the Makefile or Kconfig for that directory. And as 
mentioned, it's e.g. possible to split the one file into multiple ones, e.g.

enum driver_ids {

#include "foo"
#include "bar"

};

Of cource, the content of foo and bar might look a bit unusual.

>
>> As said above, the file could be filled with IDs for all existing modules,
>> regardless if they are already annotated.
>>
>> If that's a nightmare, I wonder what how you name the necessary stuff to
>> maintain the link order through Makefiles.
>
> There usually isn't a problem and the issue is that we link by
> subsystem, so somehow it's all working fairly well.

So why should that be worse with the one file?

But, like you, I don't like such a big enum.

It's just that I didn't thought much about another solution, and the 
time I've spend to think about something else which provides a usable 
ID, didn't end in a solution. So I would be happy if someone else would 
offer an idea.

Regards,

Alexander Holler

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 11/14] init: deps: annotate various initcalls
  2015-10-17 17:14 ` [PATCH 11/14] init: deps: annotate various initcalls Alexander Holler
@ 2015-10-17 18:47   ` Linus Torvalds
  2015-10-17 18:59     ` Alexander Holler
  0 siblings, 1 reply; 59+ messages in thread
From: Linus Torvalds @ 2015-10-17 18:47 UTC (permalink / raw)
  To: Alexander Holler
  Cc: Linux Kernel Mailing List, Andrew Morton, Greg Kroah-Hartman,
	Russell King, Grant Likely

On Sat, Oct 17, 2015 at 10:14 AM, Alexander Holler <holler@ahsoftware.de> wrote:
>
> diff --git a/arch/arm/common/edma.c b/arch/arm/common/edma.c
> index 873dbfc..d5d2459 100644
> --- a/arch/arm/common/edma.c
> +++ b/arch/arm/common/edma.c
> @@ -1872,5 +1872,4 @@ static int __init edma_init(void)
>  {
>         return platform_driver_probe(&edma_driver, edma_probe);
>  }
> -arch_initcall(edma_init);
> -
> +annotated_initcall_drv(arch, edma_init, drvid_edma, NULL, edma_driver.driver);
> diff --git a/arch/arm/crypto/aes-ce-glue.c b/arch/arm/crypto/aes-ce-glue.c
> index b445a5d..d9bcb89 100644
> --- a/arch/arm/crypto/aes-ce-glue.c
> +++ b/arch/arm/crypto/aes-ce-glue.c
> @@ -520,5 +520,10 @@ static void __exit aes_exit(void)
>         crypto_unregister_algs(aes_algs, ARRAY_SIZE(aes_algs));
>  }
>
> -module_init(aes_init);
> +static const unsigned dependencies[] __initconst __maybe_unused = {
> +       drvid_cryptomgr,
> +       0
> +};
> +
> +annotated_module_init(aes_init, drvid_aes_ce_arm, dependencies);
>  module_exit(aes_exit);

So I think this is kind of a sign of the same disease I mentioned
earlier: making dependencies "separate" from the init levels, now
means that you do the initialization of the dependencies *instead* of
the init level. And that smells bad and wrong, and causes this kind of
patch that is not only huge, but si unreadable and the end result
looks like crap too.

We've actually been quite good at having the module attributes all be
*separate* things that work together. So the code had

  module_init(aes_init);
  module_exit(aes_exit);

but also things like

  MODULE_DESCRIPTION("AES-ECB/CBC/CTR/XTS using ARMv8 Crypto Extensions");
  MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
  MODULE_LICENSE("GPL v2");

and that all helps improve readablity and keep things sane.

In contrast, turds like these are just pure and utter crap:

   static const unsigned dependencies[] __initconst __maybe_unused = {
          drvid_cryptomgr,
          0
   };
   annotated_module_init(aes_init, drvid_aes_ce_arm, dependencies);

and yes, I know that we have things like this for the driver ID lists
etc, but that doesn't make it better.

No, I think any dependency model should strive to make this really
really easy and separate, and do things like

   module_depends(cryptomgr);

and then just use that to fill in a link section or something like
that. And no, there's no way we will ever maintain a "list of
dependency identifiers". This is stuff that should be all about
scripting, or - better yet - just make the link section contain
strings so that you don't *need* any C level identifiers.

That would be trivial to do by just making the "module_depends()"
macro be something like

  #define _dependency(x,y) \
         static const  struct module_dependency_attribute \
         __used __attribute__ ((__section__ ("__dependencies")))  \
        * __dependency_attr =  { x,y }

  #define module_depends(x) \
        _dependency(#x, KBUILD_NAME)

  #define module_provides(x) \
        _dependency(KBUILD_NAME, #x)

And if a module depends on multiple other things, then you just have
multiple of those "module_depends()" things. There's some gcc trick to
generating numbered (per compilation unit) C identifiers (so that you
can have multiple of those "__dependency_attr" variables in the same
file), but I forget it right now.

And this is also where I think those "module_init()" vs
"subsys_init()" things come in. "module_init()" means that it's a
driver level thing, which would mean that module_init() implies

  module_depends(level7);
  module_provides(level7_end);

so that the module would automatically be sorted wrt the "driver" level.

Another advantage (apart from legibility of the source, and
integrating with the *existing* level-based dependencies) is that
using something like "module_depends()" and "module_provides()" means
that it should be easy to parse even outside of a C compiler, so you
could - if you want to - make all the dependencies be done not as part
of compiling the source, but as a separate scripting thing. That could
be useful for things like statistics and visualization tools that
don't want to actually build the kernel, but want to just show the
dependencies between different modules.

So no. I do *not* think big patches like this are acceptable. This
kind of patch - along with the patch that just adds the random
dependency identifier C enums - is exactly what we do *not* want. If
we do dependencies, they should all be small and local things, and
they should not *replace* the existing "module_init()" vs
"arch_init()" system, they should add on top of it.

                      Linus

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 04/14] init: deps: order network interfaces by link order
  2015-10-17 18:37     ` Alexander Holler
@ 2015-10-17 18:52       ` Linus Torvalds
  2015-10-17 19:01         ` Alexander Holler
  2015-10-17 18:55       ` Greg Kroah-Hartman
  2015-10-17 19:03       ` Linus Torvalds
  2 siblings, 1 reply; 59+ messages in thread
From: Linus Torvalds @ 2015-10-17 18:52 UTC (permalink / raw)
  To: Alexander Holler
  Cc: Linux Kernel Mailing List, Andrew Morton, Greg Kroah-Hartman,
	Russell King, Grant Likely

On Sat, Oct 17, 2015 at 11:37 AM, Alexander Holler <holler@ahsoftware.de> wrote:
>
> I'm making dependencies the only ordering for annotated initcalls.

Yeah, and quite frankly, that just means that I'm not going to merge it.

We do not do "flag-day" things. We've done them in the past, and it
has always been a major and unacceptable pain.

And if the dependency ordering is "outside" of the traditional
link-time ordering, then it is by definition a flag-day event. Every
time you add a dependency to even just *one* driver, it magically
changes ordering wrt all the other drivers, because now it's in a
different ordering domain.

So please reconsider. Or stop cc'ing me. Because "flag day" changes
really are not acceptable.

                       Linus

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 04/14] init: deps: order network interfaces by link order
  2015-10-17 18:37     ` Alexander Holler
  2015-10-17 18:52       ` Linus Torvalds
@ 2015-10-17 18:55       ` Greg Kroah-Hartman
  2015-10-17 19:03       ` Linus Torvalds
  2 siblings, 0 replies; 59+ messages in thread
From: Greg Kroah-Hartman @ 2015-10-17 18:55 UTC (permalink / raw)
  To: Alexander Holler
  Cc: Linus Torvalds, Linux Kernel Mailing List, Andrew Morton,
	Russell King, Grant Likely

On Sat, Oct 17, 2015 at 08:37:35PM +0200, Alexander Holler wrote:
> I'm making dependencies the only ordering for annotated initcalls.
> 
> Otherwise it's impossible to call initcalls in parallel.

We don't ever want to call initcalls in parallel, unless they can
properly handle it.  All drivers can tell the driver core to use
parallel probing if they know they can handle it.  See 'enum probe_type'
for this.

Trying to call initcalls or driver probes in parallel blindly has been
proven to both take a longer amount of time, and cause problems for
drivers that aren't expecting it.  The research on this was done years
ago when people were starting to work on booting quicker, and the end
result is what we have now where drivers that know they can handle this,
can tell the core to let them probe in this manner.

The outcome of this work is the sub-second boot time we have today.  If
your systems are taking longer to boot, then please look into the
drivers that are causing this, that is where the real issue is, not in
the core of the kernel.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 11/14] init: deps: annotate various initcalls
  2015-10-17 18:47   ` Linus Torvalds
@ 2015-10-17 18:59     ` Alexander Holler
  0 siblings, 0 replies; 59+ messages in thread
From: Alexander Holler @ 2015-10-17 18:59 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Linux Kernel Mailing List, Andrew Morton, Greg Kroah-Hartman,
	Russell King, Grant Likely

Am 17.10.2015 um 20:47 schrieb Linus Torvalds:
> On Sat, Oct 17, 2015 at 10:14 AM, Alexander Holler <holler@ahsoftware.de> wrote:
>>
>> diff --git a/arch/arm/common/edma.c b/arch/arm/common/edma.c
>> index 873dbfc..d5d2459 100644
>> --- a/arch/arm/common/edma.c
>> +++ b/arch/arm/common/edma.c
>> @@ -1872,5 +1872,4 @@ static int __init edma_init(void)
>>   {
>>          return platform_driver_probe(&edma_driver, edma_probe);
>>   }
>> -arch_initcall(edma_init);
>> -
>> +annotated_initcall_drv(arch, edma_init, drvid_edma, NULL, edma_driver.driver);
>> diff --git a/arch/arm/crypto/aes-ce-glue.c b/arch/arm/crypto/aes-ce-glue.c
>> index b445a5d..d9bcb89 100644
>> --- a/arch/arm/crypto/aes-ce-glue.c
>> +++ b/arch/arm/crypto/aes-ce-glue.c
>> @@ -520,5 +520,10 @@ static void __exit aes_exit(void)
>>          crypto_unregister_algs(aes_algs, ARRAY_SIZE(aes_algs));
>>   }
>>
>> -module_init(aes_init);
>> +static const unsigned dependencies[] __initconst __maybe_unused = {
>> +       drvid_cryptomgr,
>> +       0
>> +};
>> +
>> +annotated_module_init(aes_init, drvid_aes_ce_arm, dependencies);
>>   module_exit(aes_exit);
>
> So I think this is kind of a sign of the same disease I mentioned
> earlier: making dependencies "separate" from the init levels, now
> means that you do the initialization of the dependencies *instead* of
> the init level. And that smells bad and wrong, and causes this kind of
> patch that is not only huge, but si unreadable and the end result
> looks like crap too.
>
> We've actually been quite good at having the module attributes all be
> *separate* things that work together. So the code had
>
>    module_init(aes_init);
>    module_exit(aes_exit);
>
> but also things like
>
>    MODULE_DESCRIPTION("AES-ECB/CBC/CTR/XTS using ARMv8 Crypto Extensions");
>    MODULE_AUTHOR("Ard Biesheuvel <ard.biesheuvel@linaro.org>");
>    MODULE_LICENSE("GPL v2");
>
> and that all helps improve readablity and keep things sane.
>
> In contrast, turds like these are just pure and utter crap:
>
>     static const unsigned dependencies[] __initconst __maybe_unused = {
>            drvid_cryptomgr,
>            0
>     };
>     annotated_module_init(aes_init, drvid_aes_ce_arm, dependencies);
>
> and yes, I know that we have things like this for the driver ID lists
> etc, but that doesn't make it better.
>
> No, I think any dependency model should strive to make this really
> really easy and separate, and do things like
>
>     module_depends(cryptomgr);
>
> and then just use that to fill in a link section or something like
> that. And no, there's no way we will ever maintain a "list of
> dependency identifiers". This is stuff that should be all about
> scripting, or - better yet - just make the link section contain
> strings so that you don't *need* any C level identifiers.
>
> That would be trivial to do by just making the "module_depends()"
> macro be something like
>
>    #define _dependency(x,y) \
>           static const  struct module_dependency_attribute \
>           __used __attribute__ ((__section__ ("__dependencies")))  \
>          * __dependency_attr =  { x,y }
>
>    #define module_depends(x) \
>          _dependency(#x, KBUILD_NAME)
>
>    #define module_provides(x) \
>          _dependency(KBUILD_NAME, #x)
>
> And if a module depends on multiple other things, then you just have
> multiple of those "module_depends()" things. There's some gcc trick to
> generating numbered (per compilation unit) C identifiers (so that you
> can have multiple of those "__dependency_attr" variables in the same
> file), but I forget it right now.
>
> And this is also where I think those "module_init()" vs
> "subsys_init()" things come in. "module_init()" means that it's a
> driver level thing, which would mean that module_init() implies
>
>    module_depends(level7);
>    module_provides(level7_end);
>
> so that the module would automatically be sorted wrt the "driver" level.
>
> Another advantage (apart from legibility of the source, and
> integrating with the *existing* level-based dependencies) is that
> using something like "module_depends()" and "module_provides()" means
> that it should be easy to parse even outside of a C compiler, so you
> could - if you want to - make all the dependencies be done not as part
> of compiling the source, but as a separate scripting thing. That could
> be useful for things like statistics and visualization tools that
> don't want to actually build the kernel, but want to just show the
> dependencies between different modules.
>
> So no. I do *not* think big patches like this are acceptable. This
> kind of patch - along with the patch that just adds the random
> dependency identifier C enums - is exactly what we do *not* want. If
> we do dependencies, they should all be small and local things, and
> they should not *replace* the existing "module_init()" vs
> "arch_init()" system, they should add on top of it.

Thanks for the detailed answer and you are right.

But I had to start somehow and, unfortunately, I don't have the 
resources to fulfill your requirements.

Regards,

Alexander Holler

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 04/14] init: deps: order network interfaces by link order
  2015-10-17 18:52       ` Linus Torvalds
@ 2015-10-17 19:01         ` Alexander Holler
  2015-10-17 19:08           ` Linus Torvalds
  0 siblings, 1 reply; 59+ messages in thread
From: Alexander Holler @ 2015-10-17 19:01 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Linux Kernel Mailing List, Andrew Morton, Greg Kroah-Hartman,
	Russell King, Grant Likely

Am 17.10.2015 um 20:52 schrieb Linus Torvalds:
> On Sat, Oct 17, 2015 at 11:37 AM, Alexander Holler <holler@ahsoftware.de> wrote:
>>
>> I'm making dependencies the only ordering for annotated initcalls.
>
> Yeah, and quite frankly, that just means that I'm not going to merge it.
>
> We do not do "flag-day" things. We've done them in the past, and it
> has always been a major and unacceptable pain.

That isn't a flag day thing. It's a config option everyone can turn on 
and off whenever he wants.

>
> And if the dependency ordering is "outside" of the traditional
> link-time ordering, then it is by definition a flag-day event. Every
> time you add a dependency to even just *one* driver, it magically
> changes ordering wrt all the other drivers, because now it's in a
> different ordering domain.
>
> So please reconsider. Or stop cc'ing me. Because "flag day" changes
> really are not acceptable.

I'm choosing the second option. I will answer further mails on that 
topic, but will remove you from cc. Besides that I consider these 
patches as a total failure and will not post any further version.

Alexander Holler

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 04/14] init: deps: order network interfaces by link order
  2015-10-17 18:37     ` Alexander Holler
  2015-10-17 18:52       ` Linus Torvalds
  2015-10-17 18:55       ` Greg Kroah-Hartman
@ 2015-10-17 19:03       ` Linus Torvalds
  2015-10-17 19:07         ` Alexander Holler
  2 siblings, 1 reply; 59+ messages in thread
From: Linus Torvalds @ 2015-10-17 19:03 UTC (permalink / raw)
  To: Alexander Holler
  Cc: Linux Kernel Mailing List, Andrew Morton, Greg Kroah-Hartman,
	Russell King, Grant Likely

On Sat, Oct 17, 2015 at 11:37 AM, Alexander Holler <holler@ahsoftware.de> wrote:
>
> Otherwise it's impossible to call initcalls in parallel. I've seen a stable
> topological sort somewhere, but whenever you want to parallelize the
> initcalls, the stable ordering would be gone anyway. So I've decided not to
> look further at a stable topological sort.

So five seconds of googling gave me freely usable source code for a
stable topological sort, that also has a nice reported added
advantage:

 "An interesting property of a stable topological sort is that cyclic
dependencies are tolerated and resolved according to original order of
elements in sequence. This is a desirable feature for many
applications because it allows to sort any sequence with any
imaginable dependencies between the elements"

which seems to be *exactly* what you'd want, especially considering
that right now your patches add extra "no-dependency" markers exactly
because of the cyclical problem.

I think it was the #2 hit on google for "stable topological sort". I
didn't look closely at the source code, but it was not big.

And no, since we don't actually want to parallelize the initcalls
anyway (I had this discussion with you just a month ago), your
objections seem even more questionable. We have separate machinery for
"do this asynchronously", and we want to _keep_ that separate.

                 Linus

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 04/14] init: deps: order network interfaces by link order
  2015-10-17 19:03       ` Linus Torvalds
@ 2015-10-17 19:07         ` Alexander Holler
  0 siblings, 0 replies; 59+ messages in thread
From: Alexander Holler @ 2015-10-17 19:07 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Linux Kernel Mailing List, Andrew Morton, Greg Kroah-Hartman,
	Russell King, Grant Likely

Am 17.10.2015 um 21:03 schrieb Linus Torvalds:
> On Sat, Oct 17, 2015 at 11:37 AM, Alexander Holler <holler@ahsoftware.de> wrote:
>>
>> Otherwise it's impossible to call initcalls in parallel. I've seen a stable
>> topological sort somewhere, but whenever you want to parallelize the
>> initcalls, the stable ordering would be gone anyway. So I've decided not to
>> look further at a stable topological sort.
>
> So five seconds of googling gave me freely usable source code for a
> stable topological sort, that also has a nice reported added
> advantage:
>
>   "An interesting property of a stable topological sort is that cyclic
> dependencies are tolerated and resolved according to original order of
> elements in sequence. This is a desirable feature for many
> applications because it allows to sort any sequence with any
> imaginable dependencies between the elements"
>
> which seems to be *exactly* what you'd want, especially considering
> that right now your patches add extra "no-dependency" markers exactly
> because of the cyclical problem.

That's the stable topological sort I've mentioned the link to in the 
discussion with you.

>
> I think it was the #2 hit on google for "stable topological sort". I
> didn't look closely at the source code, but it was not big.
>
> And no, since we don't actually want to parallelize the initcalls
> anyway (I had this discussion with you just a month ago), your
> objections seem even more questionable. We have separate machinery for
> "do this asynchronously", and we want to _keep_ that separate.

I've understood that now.

Sorry for wasting your time.

Alexander Holler

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 04/14] init: deps: order network interfaces by link order
  2015-10-17 19:01         ` Alexander Holler
@ 2015-10-17 19:08           ` Linus Torvalds
  2015-10-17 19:14             ` Alexander Holler
  2015-10-17 21:32             ` Alexander Holler
  0 siblings, 2 replies; 59+ messages in thread
From: Linus Torvalds @ 2015-10-17 19:08 UTC (permalink / raw)
  To: Alexander Holler
  Cc: Linux Kernel Mailing List, Andrew Morton, Greg Kroah-Hartman,
	Russell King, Grant Likely

On Sat, Oct 17, 2015 at 12:01 PM, Alexander Holler <holler@ahsoftware.de> wrote:
>
> That isn't a flag day thing. It's a config option everyone can turn on and
> off whenever he wants.

That's a flag-day thing. We've done it (drm comes to mind - several times).

I'm disappointed, because I _know_ I pointed you in the direction of
stable sorting about a month ago. I really had hoped you'd have taken
that into account.

                      Linus

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 04/14] init: deps: order network interfaces by link order
  2015-10-17 19:08           ` Linus Torvalds
@ 2015-10-17 19:14             ` Alexander Holler
  2015-10-17 19:36               ` Greg Kroah-Hartman
  2015-10-17 19:37               ` Linus Torvalds
  2015-10-17 21:32             ` Alexander Holler
  1 sibling, 2 replies; 59+ messages in thread
From: Alexander Holler @ 2015-10-17 19:14 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Linux Kernel Mailing List, Andrew Morton, Greg Kroah-Hartman,
	Russell King, Grant Likely

Am 17.10.2015 um 21:08 schrieb Linus Torvalds:
> On Sat, Oct 17, 2015 at 12:01 PM, Alexander Holler <holler@ahsoftware.de> wrote:
>>
>> That isn't a flag day thing. It's a config option everyone can turn on and
>> off whenever he wants.
>
> That's a flag-day thing. We've done it (drm comes to mind - several times).
>
> I'm disappointed, because I _know_ I pointed you in the direction of
> stable sorting about a month ago. I really had hoped you'd have taken
> that into account.

It's impossible to take it into account because I don't want to miss the 
parallelize functionality. And without that, all the stuff doesn't offer 
enough benefits to be worse the effort but just adds some time necessary 
to do the sorting. It might solve the deferred probe problems, but 
without much benefit.

Regards,

Alexander Holler


^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 04/14] init: deps: order network interfaces by link order
  2015-10-17 19:14             ` Alexander Holler
@ 2015-10-17 19:36               ` Greg Kroah-Hartman
  2015-10-17 19:58                 ` Alexander Holler
  2015-10-18  4:59                 ` Alexander Holler
  2015-10-17 19:37               ` Linus Torvalds
  1 sibling, 2 replies; 59+ messages in thread
From: Greg Kroah-Hartman @ 2015-10-17 19:36 UTC (permalink / raw)
  To: Alexander Holler
  Cc: Linus Torvalds, Linux Kernel Mailing List, Andrew Morton,
	Russell King, Grant Likely

On Sat, Oct 17, 2015 at 09:14:34PM +0200, Alexander Holler wrote:
> Am 17.10.2015 um 21:08 schrieb Linus Torvalds:
> >On Sat, Oct 17, 2015 at 12:01 PM, Alexander Holler <holler@ahsoftware.de> wrote:
> >>
> >>That isn't a flag day thing. It's a config option everyone can turn on and
> >>off whenever he wants.
> >
> >That's a flag-day thing. We've done it (drm comes to mind - several times).
> >
> >I'm disappointed, because I _know_ I pointed you in the direction of
> >stable sorting about a month ago. I really had hoped you'd have taken
> >that into account.
> 
> It's impossible to take it into account because I don't want to miss the
> parallelize functionality. And without that, all the stuff doesn't offer
> enough benefits to be worse the effort but just adds some time necessary to
> do the sorting. It might solve the deferred probe problems, but without much
> benefit.

Again, parallelizing does not solve anything, and causes more problems
_and_ makes things take longer.  Try it, we have done it in the past and
proven this, it's pretty easy to test :)

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 04/14] init: deps: order network interfaces by link order
  2015-10-17 19:14             ` Alexander Holler
  2015-10-17 19:36               ` Greg Kroah-Hartman
@ 2015-10-17 19:37               ` Linus Torvalds
  1 sibling, 0 replies; 59+ messages in thread
From: Linus Torvalds @ 2015-10-17 19:37 UTC (permalink / raw)
  To: Alexander Holler
  Cc: Linux Kernel Mailing List, Andrew Morton, Greg Kroah-Hartman,
	Russell King, Grant Likely

On Sat, Oct 17, 2015 at 12:14 PM, Alexander Holler <holler@ahsoftware.de> wrote:
>
> It's impossible to take it into account because I don't want to miss the
> parallelize functionality. And without that, all the stuff doesn't offer
> enough benefits to be worse the effort but just adds some time necessary to
> do the sorting. It might solve the deferred probe problems, but without much
> benefit.

Quite frankly, the alleged advantage of parallelization of the init
sequence is *very* questionable.

But even if you were to want to parallelize things at that level, you'd still

 (a) want to make *that* a flag (to debug) and make it opt-in (so
you'd have another "this module can be done in parallel" marker)

 (b) end up with all the other drivers *not* being parallel, because
they were all written to not have everything happen at once.

 (c) want to avoid the whole flag-day things

so even then you'd want to sort everything using that topological
stable sort, so that you can sanely mix things, and then mark
individual drivers as "I'd like to run in parallel with the rest of
the init sequence".

The main thing that being parallel would change is likely that you'd
also have to add some kind of "I'm done" completion for each module
(or dependency point), so that things that depend on other things
(that have *started*) can explicitly wait for those other things to
actually end.

We have something like that for our "sync" points right now with the
whole asynchronous machinery. It's somewhat general (although I think
almost all users end up just doing "async_synchronize_full()", even
though we do have a cookie-based one) and I suspect the cookie-based
one could be used for individual drivers and their completions.

But I really think the whole "do initcalls in parallel" is a very bad
idea _regardless_ of anything else. We almost never actually have
initcalls that really take a lot of time, and when we do, we already
handle the big ones with the async machinery, which is actually a lot
more powerful and flexible than some "run initcalls in parallel",
exactly because you can run *parts* serially (like basic discovery),
and then run other parts asynchronously (like "spin up disk" or "wait
for power stable" or whatever - *after* you have discovered the
device).

So I personally think our async thing is much more powerful and useful
than some random "let's run initcalls in parallel".

                 Linus

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 0/14] init: deps: dependency based (parallelized) init
  2015-10-17 18:38     ` Greg Kroah-Hartman
@ 2015-10-17 19:43       ` Alexander Holler
  2015-10-17 20:20         ` Greg Kroah-Hartman
  0 siblings, 1 reply; 59+ messages in thread
From: Alexander Holler @ 2015-10-17 19:43 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-kernel, Tomeu Vizoso, Andrew Morton, Russell King,
	Grant Likely

Am 17.10.2015 um 20:38 schrieb Greg Kroah-Hartman:

> So how long does that really take to call all probe functions in all
> possible order?  Real numbers please.  We have the tools to determine
> where at boot time delays are happening, please use them to find the
> problem drivers.

No idea. You might ask Tomeu Vizoso (I've added him to cc) for details 
(or search for the thread "On-demand device registration" where he 
complained that his chromebook boots slow). I've just measured, that 
most my ARM boxes booted faster when I've used the ordering, instead of 
slower through the introduce overhead to order initcalls (without having 
parallelized the initcalls).

Posting times doesn't make much sense, as they heavily depend on the 
configuration. Instead I've posted patches so you can test it yourself.

But if you want a real time, my Netbook with a single core but HT Atom 
N270 boots in one second instead of two to "dmesg | grep Freeing".

Regards,

Alexander Holler

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 04/14] init: deps: order network interfaces by link order
  2015-10-17 19:36               ` Greg Kroah-Hartman
@ 2015-10-17 19:58                 ` Alexander Holler
  2015-10-17 21:20                   ` Alexander Holler
  2015-10-18  4:59                 ` Alexander Holler
  1 sibling, 1 reply; 59+ messages in thread
From: Alexander Holler @ 2015-10-17 19:58 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Linux Kernel Mailing List, Andrew Morton, Russell King,
	Grant Likely

Am 17.10.2015 um 21:36 schrieb Greg Kroah-Hartman:
> On Sat, Oct 17, 2015 at 09:14:34PM +0200, Alexander Holler wrote:
>> Am 17.10.2015 um 21:08 schrieb Linus Torvalds:
>>> On Sat, Oct 17, 2015 at 12:01 PM, Alexander Holler <holler@ahsoftware.de> wrote:
>>>>
>>>> That isn't a flag day thing. It's a config option everyone can turn on and
>>>> off whenever he wants.
>>>
>>> That's a flag-day thing. We've done it (drm comes to mind - several times).
>>>
>>> I'm disappointed, because I _know_ I pointed you in the direction of
>>> stable sorting about a month ago. I really had hoped you'd have taken
>>> that into account.
>>
>> It's impossible to take it into account because I don't want to miss the
>> parallelize functionality. And without that, all the stuff doesn't offer
>> enough benefits to be worse the effort but just adds some time necessary to
>> do the sorting. It might solve the deferred probe problems, but without much
>> benefit.
>
> Again, parallelizing does not solve anything, and causes more problems
> _and_ makes things take longer.  Try it, we have done it in the past and
> proven this, it's pretty easy to test :)

I've tested it, otherwise I wouldn't have posted the patches.

Unfortunately it's quiet a lot of work to add dependencies for everything.

So maybe I'm able to offer some better numbers in a year or such, when I 
was bored often enough to add more dependencies for initcalls.

Not to mention that small changes in the order can have quiet big 
differences in the boot time, so it's quiet hard to parallelize stuff 
(add dependencies) correctly like e.g. the pci/acpi/processor stuff. 
Especially because many reasons for the current order aren't mentioned 
in the source and are hard to see without specific knowledge about the HW.

Alexander Holler

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 0/14] init: deps: dependency based (parallelized) init
  2015-10-17 19:43       ` Alexander Holler
@ 2015-10-17 20:20         ` Greg Kroah-Hartman
  2015-10-17 20:37           ` Alexander Holler
  0 siblings, 1 reply; 59+ messages in thread
From: Greg Kroah-Hartman @ 2015-10-17 20:20 UTC (permalink / raw)
  To: Alexander Holler
  Cc: linux-kernel, Tomeu Vizoso, Andrew Morton, Russell King,
	Grant Likely

On Sat, Oct 17, 2015 at 09:43:17PM +0200, Alexander Holler wrote:
> Am 17.10.2015 um 20:38 schrieb Greg Kroah-Hartman:
> 
> >So how long does that really take to call all probe functions in all
> >possible order?  Real numbers please.  We have the tools to determine
> >where at boot time delays are happening, please use them to find the
> >problem drivers.
> 
> No idea. You might ask Tomeu Vizoso (I've added him to cc) for details (or
> search for the thread "On-demand device registration" where he complained
> that his chromebook boots slow). I've just measured, that most my ARM boxes
> booted faster when I've used the ordering, instead of slower through the
> introduce overhead to order initcalls (without having parallelized the
> initcalls).

I've already asked him, I don't like his patch series to try to resolve
this issue either :)

> Posting times doesn't make much sense, as they heavily depend on the
> configuration. Instead I've posted patches so you can test it yourself.
> 
> But if you want a real time, my Netbook with a single core but HT Atom N270
> boots in one second instead of two to "dmesg | grep Freeing".

Try running the boot time graphic tool to determine where that time is
spent, odds are you just need to enable a single driver to async it's
probe function and you should be fine.

Again, fix up the broken driver(s), don't paper over the issues with
core changes that are not necessary.

thanks,

greg k-h

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 0/14] init: deps: dependency based (parallelized) init
  2015-10-17 20:20         ` Greg Kroah-Hartman
@ 2015-10-17 20:37           ` Alexander Holler
  0 siblings, 0 replies; 59+ messages in thread
From: Alexander Holler @ 2015-10-17 20:37 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: linux-kernel, Tomeu Vizoso, Andrew Morton, Russell King,
	Grant Likely

Am 17.10.2015 um 22:20 schrieb Greg Kroah-Hartman:
> On Sat, Oct 17, 2015 at 09:43:17PM +0200, Alexander Holler wrote:
>> Am 17.10.2015 um 20:38 schrieb Greg Kroah-Hartman:
>>
>>> So how long does that really take to call all probe functions in all
>>> possible order?  Real numbers please.  We have the tools to determine
>>> where at boot time delays are happening, please use them to find the
>>> problem drivers.
>>
>> No idea. You might ask Tomeu Vizoso (I've added him to cc) for details (or
>> search for the thread "On-demand device registration" where he complained
>> that his chromebook boots slow). I've just measured, that most my ARM boxes
>> booted faster when I've used the ordering, instead of slower through the
>> introduce overhead to order initcalls (without having parallelized the
>> initcalls).
>
> I've already asked him, I don't like his patch series to try to resolve
> this issue either :)
>
>> Posting times doesn't make much sense, as they heavily depend on the
>> configuration. Instead I've posted patches so you can test it yourself.
>>
>> But if you want a real time, my Netbook with a single core but HT Atom N270
>> boots in one second instead of two to "dmesg | grep Freeing".
>
> Try running the boot time graphic tool to determine where that time is
> spent, odds are you just need to enable a single driver to async it's
> probe function and you should be fine.
>
> Again, fix up the broken driver(s), don't paper over the issues with
> core changes that are not necessary.

I assume you are aware of the 80/20 rule. So you might see the 
parallelize feature of topological sort as an attempt to do some of the 
work in the last 20 percent left.

Sorry, but I've no idea why you are now trying to pin the stuff I'm 
talking about to a specific issue.

Or to talk in more clear words:

The current initcall ordering is, in my humble opinion, a whole and 
mostly undocumented mess. And I'm pretty sure it will become worse, I 
just have to wait and see. And if every attempt to fix that will be 
killed as fast as my one ...

Anyway, thanks for comments.

Regards,

Alexander Holler

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 04/14] init: deps: order network interfaces by link order
  2015-10-17 19:58                 ` Alexander Holler
@ 2015-10-17 21:20                   ` Alexander Holler
  0 siblings, 0 replies; 59+ messages in thread
From: Alexander Holler @ 2015-10-17 21:20 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Linux Kernel Mailing List, Andrew Morton, Russell King,
	Grant Likely

Am 17.10.2015 um 21:58 schrieb Alexander Holler:

> Unfortunately it's quiet a lot of work to add dependencies for everything.

And (just in case of), also I'm a non-native English writer, I know the 
difference between quiet and quite. But, unfortunately, that doesn't 
prevent me to type it wrong. It's like "teh" instead of "the". 
Unfortunately I'm not very good in writing English fast without errors, 
but that doesn't mean I'm dumb (also many native English writers prefer 
to assume that).

Regards,

Alexander Holler

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 04/14] init: deps: order network interfaces by link order
  2015-10-17 19:08           ` Linus Torvalds
  2015-10-17 19:14             ` Alexander Holler
@ 2015-10-17 21:32             ` Alexander Holler
  1 sibling, 0 replies; 59+ messages in thread
From: Alexander Holler @ 2015-10-17 21:32 UTC (permalink / raw)
  To: Linus Torvalds
  Cc: Linux Kernel Mailing List, Andrew Morton, Greg Kroah-Hartman,
	Russell King, Grant Likely

Am 17.10.2015 um 21:08 schrieb Linus Torvalds:
> On Sat, Oct 17, 2015 at 12:01 PM, Alexander Holler <holler@ahsoftware.de> wrote:
>>
>> That isn't a flag day thing. It's a config option everyone can turn on and
>> off whenever he wants.
>
> That's a flag-day thing. We've done it (drm comes to mind - several times).
>
> I'm disappointed, because I _know_ I pointed you in the direction of
> stable sorting about a month ago. I really had hoped you'd have taken
> that into account.

Sorry, but I have to add another comment about that stable topological 
sort which can be easily found by searching the web.

As the author mentioned, he has done some search on that topic too and 
has found nothing. So, either I would have to trust his word (and his 
non-public proof) that it works or I would have to prove it myself.

Besides that he says it's based on bubble sort, which is known for its 
speed. So I would have had to write in C in order to see if the speed 
would be acceptable and would still be without any proof that it always 
works correctly.

Regards,

Alexander Holler

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 04/14] init: deps: order network interfaces by link order
  2015-10-17 19:36               ` Greg Kroah-Hartman
  2015-10-17 19:58                 ` Alexander Holler
@ 2015-10-18  4:59                 ` Alexander Holler
  2015-10-18  5:14                   ` Greg Kroah-Hartman
  1 sibling, 1 reply; 59+ messages in thread
From: Alexander Holler @ 2015-10-18  4:59 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Linux Kernel Mailing List, Andrew Morton, Russell King,
	Grant Likely

Am 17.10.2015 um 21:36 schrieb Greg Kroah-Hartman:

> Again, parallelizing does not solve anything, and causes more problems
> _and_ makes things take longer.  Try it, we have done it in the past and
> proven this, it's pretty easy to test :)

Just because I'm curious, may I ask how I would test that in the easy 
way you have in mind? I've just posted the results of my tests (the 
patch series) but I wonder what you do have in mind.

Regards,

Alexander Holler

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 04/14] init: deps: order network interfaces by link order
  2015-10-18  4:59                 ` Alexander Holler
@ 2015-10-18  5:14                   ` Greg Kroah-Hartman
  2015-10-18  5:20                     ` Alexander Holler
  0 siblings, 1 reply; 59+ messages in thread
From: Greg Kroah-Hartman @ 2015-10-18  5:14 UTC (permalink / raw)
  To: Alexander Holler
  Cc: Linux Kernel Mailing List, Andrew Morton, Russell King,
	Grant Likely

On Sun, Oct 18, 2015 at 06:59:22AM +0200, Alexander Holler wrote:
> Am 17.10.2015 um 21:36 schrieb Greg Kroah-Hartman:
> 
> >Again, parallelizing does not solve anything, and causes more problems
> >_and_ makes things take longer.  Try it, we have done it in the past and
> >proven this, it's pretty easy to test :)
> 
> Just because I'm curious, may I ask how I would test that in the easy way
> you have in mind? I've just posted the results of my tests (the patch
> series) but I wonder what you do have in mind.

Use the tool, scripts/bootgraph.pl to create a boot graph of your boot
sequence.  That should show you the drivers, or other areas, that are
causing your boot to be "slow".

Hope this helps,

greg k-h

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 04/14] init: deps: order network interfaces by link order
  2015-10-18  5:14                   ` Greg Kroah-Hartman
@ 2015-10-18  5:20                     ` Alexander Holler
  2015-10-18  5:59                       ` Greg Kroah-Hartman
  0 siblings, 1 reply; 59+ messages in thread
From: Alexander Holler @ 2015-10-18  5:20 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Linux Kernel Mailing List, Andrew Morton, Russell King,
	Grant Likely

Am 18.10.2015 um 07:14 schrieb Greg Kroah-Hartman:
> On Sun, Oct 18, 2015 at 06:59:22AM +0200, Alexander Holler wrote:
>> Am 17.10.2015 um 21:36 schrieb Greg Kroah-Hartman:
>>
>>> Again, parallelizing does not solve anything, and causes more problems
>>> _and_ makes things take longer.  Try it, we have done it in the past and
>>> proven this, it's pretty easy to test :)
>>
>> Just because I'm curious, may I ask how I would test that in the easy way
>> you have in mind? I've just posted the results of my tests (the patch
>> series) but I wonder what you do have in mind.
>
> Use the tool, scripts/bootgraph.pl to create a boot graph of your boot
> sequence.  That should show you the drivers, or other areas, that are
> causing your boot to be "slow".

So I've misunderstood you. I've read your paragraph as that it's easy to 
test parallelizing.

> Hope this helps,

Unfortunately no, but thanks anyway. ;)

Alexander Holler


^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 04/14] init: deps: order network interfaces by link order
  2015-10-18  5:20                     ` Alexander Holler
@ 2015-10-18  5:59                       ` Greg Kroah-Hartman
  2015-10-18 10:11                         ` Alexander Holler
  0 siblings, 1 reply; 59+ messages in thread
From: Greg Kroah-Hartman @ 2015-10-18  5:59 UTC (permalink / raw)
  To: Alexander Holler
  Cc: Linux Kernel Mailing List, Andrew Morton, Russell King,
	Grant Likely

On Sun, Oct 18, 2015 at 07:20:34AM +0200, Alexander Holler wrote:
> Am 18.10.2015 um 07:14 schrieb Greg Kroah-Hartman:
> >On Sun, Oct 18, 2015 at 06:59:22AM +0200, Alexander Holler wrote:
> >>Am 17.10.2015 um 21:36 schrieb Greg Kroah-Hartman:
> >>
> >>>Again, parallelizing does not solve anything, and causes more problems
> >>>_and_ makes things take longer.  Try it, we have done it in the past and
> >>>proven this, it's pretty easy to test :)
> >>
> >>Just because I'm curious, may I ask how I would test that in the easy way
> >>you have in mind? I've just posted the results of my tests (the patch
> >>series) but I wonder what you do have in mind.
> >
> >Use the tool, scripts/bootgraph.pl to create a boot graph of your boot
> >sequence.  That should show you the drivers, or other areas, that are
> >causing your boot to be "slow".
> 
> So I've misunderstood you. I've read your paragraph as that it's easy to
> test parallelizing.

Ah, ok, if you want to parallelize everything, add some logic in the
driver core where the probe() callback is made to spin that off into a
new thread for every call, and when it's done, clean up the thread.
That's what I did many years ago to try this all out, if you dig in the
lkml archives there's probably a patch somewhere that you can base the
work off of to test it yourself.

hope this helps,

greg k-h

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 04/14] init: deps: order network interfaces by link order
  2015-10-18  5:59                       ` Greg Kroah-Hartman
@ 2015-10-18 10:11                         ` Alexander Holler
  2015-10-19 10:57                           ` Alexander Holler
  0 siblings, 1 reply; 59+ messages in thread
From: Alexander Holler @ 2015-10-18 10:11 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Linux Kernel Mailing List, Andrew Morton, Russell King,
	Grant Likely

Am 18.10.2015 um 07:59 schrieb Greg Kroah-Hartman:
> On Sun, Oct 18, 2015 at 07:20:34AM +0200, Alexander Holler wrote:
>> Am 18.10.2015 um 07:14 schrieb Greg Kroah-Hartman:
>>> On Sun, Oct 18, 2015 at 06:59:22AM +0200, Alexander Holler wrote:
>>>> Am 17.10.2015 um 21:36 schrieb Greg Kroah-Hartman:
>>>>
>>>>> Again, parallelizing does not solve anything, and causes more problems
>>>>> _and_ makes things take longer.  Try it, we have done it in the past and
>>>>> proven this, it's pretty easy to test :)
>>>>
>>>> Just because I'm curious, may I ask how I would test that in the easy way
>>>> you have in mind? I've just posted the results of my tests (the patch
>>>> series) but I wonder what you do have in mind.
>>>
>>> Use the tool, scripts/bootgraph.pl to create a boot graph of your boot
>>> sequence.  That should show you the drivers, or other areas, that are
>>> causing your boot to be "slow".
>>
>> So I've misunderstood you. I've read your paragraph as that it's easy to
>> test parallelizing.
>
> Ah, ok, if you want to parallelize everything, add some logic in the
> driver core where the probe() callback is made to spin that off into a
> new thread for every call, and when it's done, clean up the thread.
> That's what I did many years ago to try this all out, if you dig in the
> lkml archives there's probably a patch somewhere that you can base the
> work off of to test it yourself.

Hmm, I don't think I will do that because that means to setup a new 
thread for every call. And it doesn't need much imagination (or 
experience) that this introduces quite some overhead.

But maybe it makes sense to try out what I'm doing in my patches, 
starting multiple threads once and then just giving them some work. Will 
keep that in mind, also I don't think I will post any patch in the next 
few years. ;)

Regards,

Alexander Holler

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 04/14] init: deps: order network interfaces by link order
  2015-10-18 10:11                         ` Alexander Holler
@ 2015-10-19 10:57                           ` Alexander Holler
  2015-10-19 11:31                             ` Alexander Holler
  0 siblings, 1 reply; 59+ messages in thread
From: Alexander Holler @ 2015-10-19 10:57 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Linux Kernel Mailing List, Andrew Morton, Russell King,
	Grant Likely

Am 18.10.2015 um 12:11 schrieb Alexander Holler:
> Am 18.10.2015 um 07:59 schrieb Greg Kroah-Hartman:
>> On Sun, Oct 18, 2015 at 07:20:34AM +0200, Alexander Holler wrote:
>>> Am 18.10.2015 um 07:14 schrieb Greg Kroah-Hartman:
>>>> On Sun, Oct 18, 2015 at 06:59:22AM +0200, Alexander Holler wrote:
>>>>> Am 17.10.2015 um 21:36 schrieb Greg Kroah-Hartman:
>>>>>
>>>>>> Again, parallelizing does not solve anything, and causes more
>>>>>> problems
>>>>>> _and_ makes things take longer.  Try it, we have done it in the
>>>>>> past and
>>>>>> proven this, it's pretty easy to test :)
>>>>>
>>>>> Just because I'm curious, may I ask how I would test that in the
>>>>> easy way
>>>>> you have in mind? I've just posted the results of my tests (the patch
>>>>> series) but I wonder what you do have in mind.
>>>>
>>>> Use the tool, scripts/bootgraph.pl to create a boot graph of your boot
>>>> sequence.  That should show you the drivers, or other areas, that are
>>>> causing your boot to be "slow".
>>>
>>> So I've misunderstood you. I've read your paragraph as that it's easy to
>>> test parallelizing.
>>
>> Ah, ok, if you want to parallelize everything, add some logic in the
>> driver core where the probe() callback is made to spin that off into a
>> new thread for every call, and when it's done, clean up the thread.
>> That's what I did many years ago to try this all out, if you dig in the
>> lkml archives there's probably a patch somewhere that you can base the
>> work off of to test it yourself.
>
> Hmm, I don't think I will do that because that means to setup a new
> thread for every call. And it doesn't need much imagination (or
> experience) that this introduces quite some overhead.
>
> But maybe it makes sense to try out what I'm doing in my patches,
> starting multiple threads once and then just giving them some work. Will

After a having second thought on your simple approach to parallelize 
stuff, I have to say that it just can't work because just starting a 
thread for every probe() totally ignores possible dependencies. 
Regardless if using one thread per probe() call or if feeding probe() 
calls to just a few threads.

Maybe that's why previous attempts to parallelize stuff failed. But 
that's just an assumption as I'm unaware of these previous attempts.

Regards,

Alexander Holler

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 04/14] init: deps: order network interfaces by link order
  2015-10-19 10:57                           ` Alexander Holler
@ 2015-10-19 11:31                             ` Alexander Holler
  2015-10-22  6:47                               ` Alexander Holler
  0 siblings, 1 reply; 59+ messages in thread
From: Alexander Holler @ 2015-10-19 11:31 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Linux Kernel Mailing List, Andrew Morton, Russell King,
	Grant Likely

Am 19.10.2015 um 12:57 schrieb Alexander Holler:
> Am 18.10.2015 um 12:11 schrieb Alexander Holler:
>> Am 18.10.2015 um 07:59 schrieb Greg Kroah-Hartman:
>>> On Sun, Oct 18, 2015 at 07:20:34AM +0200, Alexander Holler wrote:
>>>> Am 18.10.2015 um 07:14 schrieb Greg Kroah-Hartman:
>>>>> On Sun, Oct 18, 2015 at 06:59:22AM +0200, Alexander Holler wrote:
>>>>>> Am 17.10.2015 um 21:36 schrieb Greg Kroah-Hartman:
>>>>>>
>>>>>>> Again, parallelizing does not solve anything, and causes more
>>>>>>> problems
>>>>>>> _and_ makes things take longer.  Try it, we have done it in the
>>>>>>> past and
>>>>>>> proven this, it's pretty easy to test :)
>>>>>>
>>>>>> Just because I'm curious, may I ask how I would test that in the
>>>>>> easy way
>>>>>> you have in mind? I've just posted the results of my tests (the patch
>>>>>> series) but I wonder what you do have in mind.
>>>>>
>>>>> Use the tool, scripts/bootgraph.pl to create a boot graph of your boot
>>>>> sequence.  That should show you the drivers, or other areas, that are
>>>>> causing your boot to be "slow".
>>>>
>>>> So I've misunderstood you. I've read your paragraph as that it's
>>>> easy to
>>>> test parallelizing.
>>>
>>> Ah, ok, if you want to parallelize everything, add some logic in the
>>> driver core where the probe() callback is made to spin that off into a
>>> new thread for every call, and when it's done, clean up the thread.
>>> That's what I did many years ago to try this all out, if you dig in the
>>> lkml archives there's probably a patch somewhere that you can base the
>>> work off of to test it yourself.
>>
>> Hmm, I don't think I will do that because that means to setup a new
>> thread for every call. And it doesn't need much imagination (or
>> experience) that this introduces quite some overhead.
>>
>> But maybe it makes sense to try out what I'm doing in my patches,
>> starting multiple threads once and then just giving them some work. Will
>
> After a having second thought on your simple approach to parallelize
> stuff, I have to say that it just can't work because just starting a
> thread for every probe() totally ignores possible dependencies.
> Regardless if using one thread per probe() call or if feeding probe()
> calls to just a few threads.
>
> Maybe that's why previous attempts to parallelize stuff failed. But
> that's just an assumption as I'm unaware of these previous attempts.

Or to describe it more verbose, if DEBUG is turned on in 
init/dependencies.c (using my patches), it spits out a summary of groups 
with initcalls (probe() calls) which are independent from each other and 
therfore can be called in parallel. E.g. one of my systems this looks so:

[    0.288229] init: vertices: 429 edges 204 count 170
[    0.288295] init: group 0 length 66 (start 0)
[    0.288329] init: group 1 length 33 (start 66)
[    0.288364] init: group 2 length 13 (start 99)
[    0.288398] init: group 3 length 7 (start 112)
[    0.288432] init: group 4 length 9 (start 119)
[    0.288466] init: group 5 length 8 (start 128)
[    0.288500] init: group 6 length 11 (start 136)
[    0.288534] init: group 7 length 6 (start 147)
[    0.288569] init: group 8 length 4 (start 153)
[    0.288603] init: group 9 length 8 (start 157)
[    0.288637] init: group 10 length 3 (start 165)
[    0.288671] init: group 11 length 2 (start 168)
[    0.288705] init: using 4 threads to call annotated initcalls

That means the first group contains 66 initcalls which are called using 
4 threads, and, after those have finished, the second group with 33 
initcalls will be called in parallel (using the same 4 threads).

> Regards,
>
> Alexander Holler


^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 03/14] init: deps: dt: use (HW-specific) dependencies provided by the DT too
  2015-10-17 17:14 ` [PATCH 03/14] init: deps: dt: use (HW-specific) dependencies provided by the DT too Alexander Holler
@ 2015-10-19 12:37   ` Mark Brown
  2015-10-19 16:27     ` Rob Herring
  2015-10-19 17:10     ` Alexander Holler
  0 siblings, 2 replies; 59+ messages in thread
From: Mark Brown @ 2015-10-19 12:37 UTC (permalink / raw)
  To: Alexander Holler
  Cc: linux-kernel, Linus Torvalds, Andrew Morton, Greg Kroah-Hartman,
	Russell King, Grant Likely, Frank Rowand, Rob Herring,
	David Gibson

[-- Attachment #1: Type: text/plain, Size: 6152 bytes --]

On Sat, Oct 17, 2015 at 07:14:16PM +0200, Alexander Holler wrote:
> This patch adds dependencies provided by the hardware description in
> the used DT. This avoids the use of the deferred probe mechanism
> on most (if not all) DT based kernels.
> 
> Drawback is that the binary DT blob has to be enhanced with type
> information for phandles (which are used as dependencies) which
> needs a modified dtc.

You probably want to loop the DT and DTC maintainers in on this - adding
Frank, Rob and David and leaving context for their reference.  It would
probably help if you could explicitly say why the DTB needs to be
annotated and why this annotiation is best done via a DTC modification
(rather than doing something like add new properties, or just guessing
that any phandle reference is a dependency).

> 
> Signed-off-by: Alexander Holler <holler@ahsoftware.de>
> ---
>  drivers/of/base.c   | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/of.h  |   3 ++
>  init/dependencies.c |   4 ++
>  3 files changed, 121 insertions(+)
> 
> diff --git a/drivers/of/base.c b/drivers/of/base.c
> index 8b5a187..423ddff 100644
> --- a/drivers/of/base.c
> +++ b/drivers/of/base.c
> @@ -12,6 +12,8 @@
>   *  Reconsolidated from arch/x/kernel/prom.c by Stephen Rothwell and
>   *  Grant Likely.
>   *
> + *  The dependency related stuff was done by Alexander Holler.
> + *
>   *      This program is free software; you can redistribute it and/or
>   *      modify it under the terms of the GNU General Public License
>   *      as published by the Free Software Foundation; either version
> @@ -2308,3 +2310,115 @@ struct device_node *of_graph_get_remote_port(const struct device_node *node)
>  	return of_get_next_parent(np);
>  }
>  EXPORT_SYMBOL(of_graph_get_remote_port);
> +
> +#ifdef CONFIG_DEPENDENCIES
> +
> +static const struct _annotated_initcall * __init find_matching_driver(
> +	const struct _annotated_initcall *from, const struct device_node *node)
> +{
> +	while (++from != __annotated_initcall_end)
> +		if (from->driver &&
> +				__of_match_node(from->driver->of_match_table,
> +					node))
> +			return from;
> +	return NULL;
> +}
> +
> +static int __init add_dep_list(const struct device_node *node, unsigned drvid)
> +{
> +	const __be32 *list, *list_end;
> +	uint32_t ph;
> +	int size = 0;
> +	int rc = 0;
> +	const struct device_node *dep;
> +	const struct _annotated_initcall *ac;
> +
> +	list = __of_get_property(node, "dependencies", &size);
> +	if (!list || !size || size % sizeof(*list))
> +		return 0;
> +	list_end = list + size / sizeof(*list);
> +	while (list < list_end) {
> +		ph = be32_to_cpup(list++);
> +		if (unlikely(!ph)) {
> +			/* Should never happen */
> +			if (node->name)
> +				pr_warn("phandle == 0 for %s\n", node->name);
> +			continue;
> +		}
> +		dep = of_find_node_by_phandle(ph);
> +		if (unlikely(!dep)) {
> +			pr_err("No DT node for dependency with phandle 0x%x found\n",
> +				ph);
> +			continue;
> +		}
> +		ac = __annotated_initcall_start - 1;
> +		while ((ac = find_matching_driver(ac, dep))) {
> +			if (!ac->id)
> +				continue;
> +			rc = add_initcall_dependency(drvid, ac->id);
> +			if (rc)
> +				return rc;
> +		}
> +	}
> +
> +	return rc;
> +}
> +
> +static int __init add_deps(unsigned parent, const struct device_node *node)
> +{
> +	struct device_node *child;
> +	const struct _annotated_initcall *ac;
> +	int rc = 0;
> +	bool found_one_driver = false;
> +
> +	if (!__of_device_is_available(node))
> +		return 0;
> +	if (__of_get_property(node, "compatible", NULL)) {
> +		ac = __annotated_initcall_start - 1;
> +		while ((ac = find_matching_driver(ac, node))) {
> +			if (!ac->id)
> +				continue;
> +			found_one_driver = true;
> +			rc = add_initcall_dependency(ac->id, parent);
> +			if (unlikely(rc))
> +				return rc;
> +			rc = add_dep_list(node, ac->id);
> +			if (unlikely(rc))
> +				return rc;
> +			for_each_child_of_node(node, child) {
> +				rc = add_deps(ac->id, child);
> +				if (unlikely(rc))
> +					return rc;
> +			}
> +		}
> +		if (found_one_driver)
> +			return rc;
> +	}
> +	for_each_child_of_node(node, child) {
> +		rc = add_deps(parent, child);
> +		if (unlikely(rc))
> +			break;
> +	}
> +
> +	return rc;
> +}
> +
> +int __init of_add_dependencies(void)
> +{
> +	int rc = 0;
> +	struct device_node *child;
> +	struct device_node *root =  of_find_node_by_path("/");
> +
> +	if (unlikely(!root))
> +		return -EINVAL;
> +
> +	for_each_child_of_node(root, child) {
> +		rc = add_deps(0, child);
> +		if (unlikely(rc))
> +			break;
> +	}
> +	of_node_put(root);
> +
> +	return rc;
> +}
> +#endif /* CONFIG_DEPENDENCIES */
> diff --git a/include/linux/of.h b/include/linux/of.h
> index edc068d..e3b65c8 100644
> --- a/include/linux/of.h
> +++ b/include/linux/of.h
> @@ -1101,4 +1101,7 @@ static inline int of_overlay_destroy_all(void)
>  
>  #endif
>  
> +/* Inserts dependencies for drivers referenced in the loaded DT. */
> +int __init of_add_dependencies(void);
> +
>  #endif /* _LINUX_OF_H */
> diff --git a/init/dependencies.c b/init/dependencies.c
> index c47817c..b484f67 100644
> --- a/init/dependencies.c
> +++ b/init/dependencies.c
> @@ -17,6 +17,7 @@
>  #include <linux/device.h>
>  #include <linux/mod_devicetable.h>
>  #include <linux/init.h>
> +#include <linux/of.h>
>  
>  #if defined(CONFIG_DEPENDENCIES_PRINT_INIT_ORDER) \
>  	|| defined(CONFIG_DEPENDENCIES_PRINT_CALLS)
> @@ -335,6 +336,9 @@ static int __init build_order(void)
>  
>  	build_inventory();
>  	add_dependencies();
> +#ifdef CONFIG_OF
> +	of_add_dependencies();
> +#endif
>  	if (topological_sort())
>  		return -EINVAL; /* cycle found */
>  	pr_debug("init: vertices: %u edges %u count %u\n",
> -- 
> 2.1.0
> 
> --
> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
> the body of a message to majordomo@vger.kernel.org
> More majordomo info at  http://vger.kernel.org/majordomo-info.html
> Please read the FAQ at  http://www.tux.org/lkml/
> 

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 10/14] init: deps: IDs for annotated initcalls
  2015-10-17 18:46         ` Alexander Holler
@ 2015-10-19 13:12           ` Mark Brown
  2015-10-20 10:30             ` Alexander Holler
  0 siblings, 1 reply; 59+ messages in thread
From: Mark Brown @ 2015-10-19 13:12 UTC (permalink / raw)
  To: Alexander Holler
  Cc: Greg Kroah-Hartman, linux-kernel, Linus Torvalds, Andrew Morton,
	Russell King, Grant Likely

[-- Attachment #1: Type: text/plain, Size: 1615 bytes --]

On Sat, Oct 17, 2015 at 08:46:44PM +0200, Alexander Holler wrote:
> Am 17.10.2015 um 20:29 schrieb Greg Kroah-Hartman:
> >On Sat, Oct 17, 2015 at 07:55:17PM +0200, Alexander Holler wrote:
> >>Am 17.10.2015 um 19:45 schrieb Greg Kroah-Hartman:

> >>>A file like this is going to be a nightmare to maintain and ensure that
> >>>it actually is correct, I don't see it as a viable solution, sorry.

> >>How often will drivers be added? The only changes on this file will happen
> >>if a driver will be added and then just one ID will be added.

> >Look at how many drivers we add every kernel release, it's a non-trivial
> >amount.

> I still don't see your problem. As long as the IDs in the enum are ordered
> according to the directories, there won't be more merge conflicts than in
> the Makefile or Kconfig for that directory. And as mentioned, it's e.g.
> possible to split the one file into multiple ones, e.g.
> 
> enum driver_ids {
> 
> #include "foo"
> #include "bar"
> 
> };
> 
> Of cource, the content of foo and bar might look a bit unusual.

If it's a purely mechanical thing we really ought to be able to arrange
for it to be generated during the build rather than have to have more
typing.  If the values matter then people have to think about what they
are which is more effort and rather indirect.

> It's just that I didn't thought much about another solution, and the time
> I've spend to think about something else which provides a usable ID, didn't
> end in a solution. So I would be happy if someone else would offer an idea.

A checksum of the driver name?

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 473 bytes --]

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 03/14] init: deps: dt: use (HW-specific) dependencies provided by the DT too
  2015-10-19 12:37   ` Mark Brown
@ 2015-10-19 16:27     ` Rob Herring
  2015-10-19 17:24       ` Alexander Holler
  2015-10-19 17:10     ` Alexander Holler
  1 sibling, 1 reply; 59+ messages in thread
From: Rob Herring @ 2015-10-19 16:27 UTC (permalink / raw)
  To: Mark Brown
  Cc: Alexander Holler, linux-kernel@vger.kernel.org, Linus Torvalds,
	Andrew Morton, Greg Kroah-Hartman, Russell King, Grant Likely,
	Frank Rowand, David Gibson

On Mon, Oct 19, 2015 at 7:37 AM, Mark Brown <broonie@kernel.org> wrote:
> On Sat, Oct 17, 2015 at 07:14:16PM +0200, Alexander Holler wrote:
>> This patch adds dependencies provided by the hardware description in
>> the used DT. This avoids the use of the deferred probe mechanism
>> on most (if not all) DT based kernels.
>>
>> Drawback is that the binary DT blob has to be enhanced with type
>> information for phandles (which are used as dependencies) which
>> needs a modified dtc.
>
> You probably want to loop the DT and DTC maintainers in on this - adding
> Frank, Rob and David and leaving context for their reference.  It would
> probably help if you could explicitly say why the DTB needs to be
> annotated and why this annotiation is best done via a DTC modification
> (rather than doing something like add new properties, or just guessing
> that any phandle reference is a dependency).

My (and Grant's) prior responses can be found here[1]. I don't have
any context whether anything has changed since the previous version,
but it seems similar. So I have nothing new to add. I think I've made
it clear what solution I do like[2].

There is a need to annotate DTB's with type information, but that
needs to be looked at in context of all types, not just one specific
type.

Rob

[1] https://lkml.org/lkml/2014/5/14/839
[2] https://lkml.org/lkml/2015/10/15/337

>
>>
>> Signed-off-by: Alexander Holler <holler@ahsoftware.de>
>> ---
>>  drivers/of/base.c   | 114 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>>  include/linux/of.h  |   3 ++
>>  init/dependencies.c |   4 ++
>>  3 files changed, 121 insertions(+)
>>
>> diff --git a/drivers/of/base.c b/drivers/of/base.c
>> index 8b5a187..423ddff 100644
>> --- a/drivers/of/base.c
>> +++ b/drivers/of/base.c
>> @@ -12,6 +12,8 @@
>>   *  Reconsolidated from arch/x/kernel/prom.c by Stephen Rothwell and
>>   *  Grant Likely.
>>   *
>> + *  The dependency related stuff was done by Alexander Holler.
>> + *
>>   *      This program is free software; you can redistribute it and/or
>>   *      modify it under the terms of the GNU General Public License
>>   *      as published by the Free Software Foundation; either version
>> @@ -2308,3 +2310,115 @@ struct device_node *of_graph_get_remote_port(const struct device_node *node)
>>       return of_get_next_parent(np);
>>  }
>>  EXPORT_SYMBOL(of_graph_get_remote_port);
>> +
>> +#ifdef CONFIG_DEPENDENCIES
>> +
>> +static const struct _annotated_initcall * __init find_matching_driver(
>> +     const struct _annotated_initcall *from, const struct device_node *node)
>> +{
>> +     while (++from != __annotated_initcall_end)
>> +             if (from->driver &&
>> +                             __of_match_node(from->driver->of_match_table,
>> +                                     node))
>> +                     return from;
>> +     return NULL;
>> +}
>> +
>> +static int __init add_dep_list(const struct device_node *node, unsigned drvid)
>> +{
>> +     const __be32 *list, *list_end;
>> +     uint32_t ph;
>> +     int size = 0;
>> +     int rc = 0;
>> +     const struct device_node *dep;
>> +     const struct _annotated_initcall *ac;
>> +
>> +     list = __of_get_property(node, "dependencies", &size);
>> +     if (!list || !size || size % sizeof(*list))
>> +             return 0;
>> +     list_end = list + size / sizeof(*list);
>> +     while (list < list_end) {
>> +             ph = be32_to_cpup(list++);
>> +             if (unlikely(!ph)) {
>> +                     /* Should never happen */
>> +                     if (node->name)
>> +                             pr_warn("phandle == 0 for %s\n", node->name);
>> +                     continue;
>> +             }
>> +             dep = of_find_node_by_phandle(ph);
>> +             if (unlikely(!dep)) {
>> +                     pr_err("No DT node for dependency with phandle 0x%x found\n",
>> +                             ph);
>> +                     continue;
>> +             }
>> +             ac = __annotated_initcall_start - 1;
>> +             while ((ac = find_matching_driver(ac, dep))) {
>> +                     if (!ac->id)
>> +                             continue;
>> +                     rc = add_initcall_dependency(drvid, ac->id);
>> +                     if (rc)
>> +                             return rc;
>> +             }
>> +     }
>> +
>> +     return rc;
>> +}
>> +
>> +static int __init add_deps(unsigned parent, const struct device_node *node)
>> +{
>> +     struct device_node *child;
>> +     const struct _annotated_initcall *ac;
>> +     int rc = 0;
>> +     bool found_one_driver = false;
>> +
>> +     if (!__of_device_is_available(node))
>> +             return 0;
>> +     if (__of_get_property(node, "compatible", NULL)) {
>> +             ac = __annotated_initcall_start - 1;
>> +             while ((ac = find_matching_driver(ac, node))) {
>> +                     if (!ac->id)
>> +                             continue;
>> +                     found_one_driver = true;
>> +                     rc = add_initcall_dependency(ac->id, parent);
>> +                     if (unlikely(rc))
>> +                             return rc;
>> +                     rc = add_dep_list(node, ac->id);
>> +                     if (unlikely(rc))
>> +                             return rc;
>> +                     for_each_child_of_node(node, child) {
>> +                             rc = add_deps(ac->id, child);
>> +                             if (unlikely(rc))
>> +                                     return rc;
>> +                     }
>> +             }
>> +             if (found_one_driver)
>> +                     return rc;
>> +     }
>> +     for_each_child_of_node(node, child) {
>> +             rc = add_deps(parent, child);
>> +             if (unlikely(rc))
>> +                     break;
>> +     }
>> +
>> +     return rc;
>> +}
>> +
>> +int __init of_add_dependencies(void)
>> +{
>> +     int rc = 0;
>> +     struct device_node *child;
>> +     struct device_node *root =  of_find_node_by_path("/");
>> +
>> +     if (unlikely(!root))
>> +             return -EINVAL;
>> +
>> +     for_each_child_of_node(root, child) {
>> +             rc = add_deps(0, child);
>> +             if (unlikely(rc))
>> +                     break;
>> +     }
>> +     of_node_put(root);
>> +
>> +     return rc;
>> +}
>> +#endif /* CONFIG_DEPENDENCIES */
>> diff --git a/include/linux/of.h b/include/linux/of.h
>> index edc068d..e3b65c8 100644
>> --- a/include/linux/of.h
>> +++ b/include/linux/of.h
>> @@ -1101,4 +1101,7 @@ static inline int of_overlay_destroy_all(void)
>>
>>  #endif
>>
>> +/* Inserts dependencies for drivers referenced in the loaded DT. */
>> +int __init of_add_dependencies(void);
>> +
>>  #endif /* _LINUX_OF_H */
>> diff --git a/init/dependencies.c b/init/dependencies.c
>> index c47817c..b484f67 100644
>> --- a/init/dependencies.c
>> +++ b/init/dependencies.c
>> @@ -17,6 +17,7 @@
>>  #include <linux/device.h>
>>  #include <linux/mod_devicetable.h>
>>  #include <linux/init.h>
>> +#include <linux/of.h>
>>
>>  #if defined(CONFIG_DEPENDENCIES_PRINT_INIT_ORDER) \
>>       || defined(CONFIG_DEPENDENCIES_PRINT_CALLS)
>> @@ -335,6 +336,9 @@ static int __init build_order(void)
>>
>>       build_inventory();
>>       add_dependencies();
>> +#ifdef CONFIG_OF
>> +     of_add_dependencies();
>> +#endif
>>       if (topological_sort())
>>               return -EINVAL; /* cycle found */
>>       pr_debug("init: vertices: %u edges %u count %u\n",
>> --
>> 2.1.0
>>
>> --
>> To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
>> the body of a message to majordomo@vger.kernel.org
>> More majordomo info at  http://vger.kernel.org/majordomo-info.html
>> Please read the FAQ at  http://www.tux.org/lkml/
>>

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 03/14] init: deps: dt: use (HW-specific) dependencies provided by the DT too
  2015-10-19 12:37   ` Mark Brown
  2015-10-19 16:27     ` Rob Herring
@ 2015-10-19 17:10     ` Alexander Holler
  1 sibling, 0 replies; 59+ messages in thread
From: Alexander Holler @ 2015-10-19 17:10 UTC (permalink / raw)
  To: Mark Brown
  Cc: linux-kernel, Andrew Morton, Greg Kroah-Hartman, Russell King,
	Grant Likely, Frank Rowand, Rob Herring, David Gibson

Am 19.10.2015 um 14:37 schrieb Mark Brown:
> On Sat, Oct 17, 2015 at 07:14:16PM +0200, Alexander Holler wrote:
>> This patch adds dependencies provided by the hardware description in
>> the used DT. This avoids the use of the deferred probe mechanism
>> on most (if not all) DT based kernels.
>>
>> Drawback is that the binary DT blob has to be enhanced with type
>> information for phandles (which are used as dependencies) which
>> needs a modified dtc.
>
> You probably want to loop the DT and DTC maintainers in on this - adding
> Frank, Rob and David and leaving context for their reference.  It would
> probably help if you could explicitly say why the DTB needs to be
> annotated and why this annotiation is best done via a DTC modification

I've had them on the cc-list on the previous two evolutions of these 
patches, when the whole stuff was for DT only. The annotation is not for 
DTB but for initcalls. But maybe you mean with annotation the missing 
type information in DTBs, which is why I had to add a new property.

> (rather than doing something like add new properties, or just guessing
> that any phandle reference is a dependency).

Besides the remote-endpoints, which have been introduced after my first 
patch to use phandles as dependencies (1.5 years ago or so), every 
phandle also was a dependency.

But anyway, the stuff was ignored before and the current evolution of 
the patches will never see mainline (too).

So, just see the whole approach as failed. I don't have a problem with 
that. At least I do that and almost did that before, I've just posted 
the newest version of the approach because I see it as the final 
evolution and don't will work further on that stuff anymore.

Regards,

Alexander Holler

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 03/14] init: deps: dt: use (HW-specific) dependencies provided by the DT too
  2015-10-19 16:27     ` Rob Herring
@ 2015-10-19 17:24       ` Alexander Holler
  0 siblings, 0 replies; 59+ messages in thread
From: Alexander Holler @ 2015-10-19 17:24 UTC (permalink / raw)
  To: Rob Herring, Mark Brown
  Cc: linux-kernel@vger.kernel.org, Linus Torvalds, Andrew Morton,
	Greg Kroah-Hartman, Russell King, Grant Likely, Frank Rowand,
	David Gibson

Am 19.10.2015 um 18:27 schrieb Rob Herring:

> There is a need to annotate DTB's with type information, but that
> needs to be looked at in context of all types, not just one specific
> type.

With which I disagree. You will need type information if you don't have 
knowledge about the context, and the context is usually only known by 
the drivers.

Regards,

Alexander Holler


^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 10/14] init: deps: IDs for annotated initcalls
  2015-10-19 13:12           ` Mark Brown
@ 2015-10-20 10:30             ` Alexander Holler
  2015-10-20 10:42               ` Alexander Holler
  0 siblings, 1 reply; 59+ messages in thread
From: Alexander Holler @ 2015-10-20 10:30 UTC (permalink / raw)
  To: Mark Brown
  Cc: Greg Kroah-Hartman, linux-kernel, Linus Torvalds, Andrew Morton,
	Russell King, Grant Likely

Am 19.10.2015 um 15:12 schrieb Mark Brown:
> On Sat, Oct 17, 2015 at 08:46:44PM +0200, Alexander Holler wrote:
>> Am 17.10.2015 um 20:29 schrieb Greg Kroah-Hartman:
>>> On Sat, Oct 17, 2015 at 07:55:17PM +0200, Alexander Holler wrote:
>>>> Am 17.10.2015 um 19:45 schrieb Greg Kroah-Hartman:
>
>>>>> A file like this is going to be a nightmare to maintain and ensure that
>>>>> it actually is correct, I don't see it as a viable solution, sorry.
>
>>>> How often will drivers be added? The only changes on this file will happen
>>>> if a driver will be added and then just one ID will be added.
>
>>> Look at how many drivers we add every kernel release, it's a non-trivial
>>> amount.
>
>> I still don't see your problem. As long as the IDs in the enum are ordered
>> according to the directories, there won't be more merge conflicts than in
>> the Makefile or Kconfig for that directory. And as mentioned, it's e.g.
>> possible to split the one file into multiple ones, e.g.
>>
>> enum driver_ids {
>>
>> #include "foo"
>> #include "bar"
>>
>> };
>>
>> Of cource, the content of foo and bar might look a bit unusual.
>
> If it's a purely mechanical thing we really ought to be able to arrange
> for it to be generated during the build rather than have to have more
> typing.  If the values matter then people have to think about what they
> are which is more effort and rather indirect.
>
>> It's just that I didn't thought much about another solution, and the time
>> I've spend to think about something else which provides a usable ID, didn't
>> end in a solution. So I would be happy if someone else would offer an idea.
>
> A checksum of the driver name?

That requires the driver name, which is only available if the struct 
device_driver is available (which isn't always the case). And it would 
require time to build the checksums.

Another idea to split this one file into multiple ones would be to 
reserve blocks of IDs. E.g. use 10000-20000 for networking stuff, 
1000-1200 for I2C and so on.

Regards,

Alexander Holler

^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 10/14] init: deps: IDs for annotated initcalls
  2015-10-20 10:30             ` Alexander Holler
@ 2015-10-20 10:42               ` Alexander Holler
  2015-10-20 10:50                 ` Alexander Holler
  2015-10-20 10:57                 ` Alexander Holler
  0 siblings, 2 replies; 59+ messages in thread
From: Alexander Holler @ 2015-10-20 10:42 UTC (permalink / raw)
  To: Mark Brown
  Cc: Greg Kroah-Hartman, linux-kernel, Linus Torvalds, Andrew Morton,
	Russell King, Grant Likely

Am 20.10.2015 um 12:30 schrieb Alexander Holler:
> Am 19.10.2015 um 15:12 schrieb Mark Brown:
>> On Sat, Oct 17, 2015 at 08:46:44PM +0200, Alexander Holler wrote:
>>> Am 17.10.2015 um 20:29 schrieb Greg Kroah-Hartman:
>>>> On Sat, Oct 17, 2015 at 07:55:17PM +0200, Alexander Holler wrote:
>>>>> Am 17.10.2015 um 19:45 schrieb Greg Kroah-Hartman:
>>
>>>>>> A file like this is going to be a nightmare to maintain and ensure
>>>>>> that
>>>>>> it actually is correct, I don't see it as a viable solution, sorry.
>>
>>>>> How often will drivers be added? The only changes on this file will
>>>>> happen
>>>>> if a driver will be added and then just one ID will be added.
>>
>>>> Look at how many drivers we add every kernel release, it's a
>>>> non-trivial
>>>> amount.
>>
>>> I still don't see your problem. As long as the IDs in the enum are
>>> ordered
>>> according to the directories, there won't be more merge conflicts
>>> than in
>>> the Makefile or Kconfig for that directory. And as mentioned, it's e.g.
>>> possible to split the one file into multiple ones, e.g.
>>>
>>> enum driver_ids {
>>>
>>> #include "foo"
>>> #include "bar"
>>>
>>> };
>>>
>>> Of cource, the content of foo and bar might look a bit unusual.
>>
>> If it's a purely mechanical thing we really ought to be able to arrange
>> for it to be generated during the build rather than have to have more
>> typing.  If the values matter then people have to think about what they
>> are which is more effort and rather indirect.
>>
>>> It's just that I didn't thought much about another solution, and the
>>> time
>>> I've spend to think about something else which provides a usable ID,
>>> didn't
>>> end in a solution. So I would be happy if someone else would offer an
>>> idea.
>>
>> A checksum of the driver name?
>
> That requires the driver name, which is only available if the struct
> device_driver is available (which isn't always the case). And it would
> require time to build the checksums.
>
> Another idea to split this one file into multiple ones would be to
> reserve blocks of IDs. E.g. use 10000-20000 for networking stuff,
> 1000-1200 for I2C and so on.

In detail it could look like

driver_ids_base.h:

enum {
	drvid_i2c_base = 1000,
	drvid_networking_base = 1200,
	drvid_usb_base = 3000,
};

driver_ids_i2c.h:

# include "driver_ids_base.h"

enum {
	drvid_i2c_start = drvid_i2c_base,

	/* drivers/i2c */
	drvid_i2c,
	drvid_i2c_dev,
	drvid_i2c_busses_start,
	/* drivers/i2c/busses */
	drvid_i2c_gpio,
	(...)

	drvid_i2c_end
};

> Regards,
>
> Alexander Holler


^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 10/14] init: deps: IDs for annotated initcalls
  2015-10-20 10:42               ` Alexander Holler
@ 2015-10-20 10:50                 ` Alexander Holler
  2015-10-20 10:57                 ` Alexander Holler
  1 sibling, 0 replies; 59+ messages in thread
From: Alexander Holler @ 2015-10-20 10:50 UTC (permalink / raw)
  To: Mark Brown
  Cc: Greg Kroah-Hartman, linux-kernel, Linus Torvalds, Andrew Morton,
	Russell King, Grant Likely

Am 20.10.2015 um 12:42 schrieb Alexander Holler:
> Am 20.10.2015 um 12:30 schrieb Alexander Holler:
>> Am 19.10.2015 um 15:12 schrieb Mark Brown:
>>> On Sat, Oct 17, 2015 at 08:46:44PM +0200, Alexander Holler wrote:
>>>> Am 17.10.2015 um 20:29 schrieb Greg Kroah-Hartman:
>>>>> On Sat, Oct 17, 2015 at 07:55:17PM +0200, Alexander Holler wrote:
>>>>>> Am 17.10.2015 um 19:45 schrieb Greg Kroah-Hartman:
>>>
>>>>>>> A file like this is going to be a nightmare to maintain and ensure
>>>>>>> that
>>>>>>> it actually is correct, I don't see it as a viable solution, sorry.
>>>
>>>>>> How often will drivers be added? The only changes on this file will
>>>>>> happen
>>>>>> if a driver will be added and then just one ID will be added.
>>>
>>>>> Look at how many drivers we add every kernel release, it's a
>>>>> non-trivial
>>>>> amount.
>>>
>>>> I still don't see your problem. As long as the IDs in the enum are
>>>> ordered
>>>> according to the directories, there won't be more merge conflicts
>>>> than in
>>>> the Makefile or Kconfig for that directory. And as mentioned, it's e.g.
>>>> possible to split the one file into multiple ones, e.g.
>>>>
>>>> enum driver_ids {
>>>>
>>>> #include "foo"
>>>> #include "bar"
>>>>
>>>> };
>>>>
>>>> Of cource, the content of foo and bar might look a bit unusual.
>>>
>>> If it's a purely mechanical thing we really ought to be able to arrange
>>> for it to be generated during the build rather than have to have more
>>> typing.  If the values matter then people have to think about what they
>>> are which is more effort and rather indirect.
>>>
>>>> It's just that I didn't thought much about another solution, and the
>>>> time
>>>> I've spend to think about something else which provides a usable ID,
>>>> didn't
>>>> end in a solution. So I would be happy if someone else would offer an
>>>> idea.
>>>
>>> A checksum of the driver name?
>>
>> That requires the driver name, which is only available if the struct
>> device_driver is available (which isn't always the case). And it would
>> require time to build the checksums.
>>
>> Another idea to split this one file into multiple ones would be to
>> reserve blocks of IDs. E.g. use 10000-20000 for networking stuff,
>> 1000-1200 for I2C and so on.
>
> In detail it could look like
>
> driver_ids_base.h:
>
> enum {
>      drvid_i2c_base = 1000,
>      drvid_networking_base = 1200,
>      drvid_usb_base = 3000,
> };
>
> driver_ids_i2c.h:
>
> # include "driver_ids_base.h"
>
> enum {
>      drvid_i2c_start = drvid_i2c_base,
>
>      /* drivers/i2c */
>      drvid_i2c,
>      drvid_i2c_dev,
>      drvid_i2c_busses_start,
>      /* drivers/i2c/busses */
>      drvid_i2c_gpio,
>      (...)
>
>      drvid_i2c_end
> };

Maybe I should mention that these IDs don't have to be consistent across 
kernel version.

They are only used to identify drivers at runtime. Of course, it might 
make sense to keep them consistent, but that only would make it easier 
to speak about drivers/initcalls while mentioning only their ID (which 
imho isn't that good). For debugging purposes my patches are already 
automatically generating names out of this enum.

Regards,

Alexander Holler


^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 10/14] init: deps: IDs for annotated initcalls
  2015-10-20 10:42               ` Alexander Holler
  2015-10-20 10:50                 ` Alexander Holler
@ 2015-10-20 10:57                 ` Alexander Holler
  1 sibling, 0 replies; 59+ messages in thread
From: Alexander Holler @ 2015-10-20 10:57 UTC (permalink / raw)
  To: Mark Brown
  Cc: Greg Kroah-Hartman, linux-kernel, Linus Torvalds, Andrew Morton,
	Russell King, Grant Likely

Am 20.10.2015 um 12:42 schrieb Alexander Holler:

>> Another idea to split this one file into multiple ones would be to
>> reserve blocks of IDs. E.g. use 10000-20000 for networking stuff,
>> 1000-1200 for I2C and so on.
>
> In detail it could look like
>
> driver_ids_base.h:
>
> enum {
>      drvid_i2c_base = 1000,
>      drvid_networking_base = 1200,
>      drvid_usb_base = 3000,
> };
>
> driver_ids_i2c.h:
>
> # include "driver_ids_base.h"
>
> enum {
>      drvid_i2c_start = drvid_i2c_base,
>
>      /* drivers/i2c */
>      drvid_i2c,
>      drvid_i2c_dev,
>      drvid_i2c_busses_start,
>      /* drivers/i2c/busses */
>      drvid_i2c_gpio,
>      (...)
>
>      drvid_i2c_end
> };

Which, of course, should be enhanced with a compile time error if 
drvid_i2c_end >= drvid_networking_base.



^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 04/14] init: deps: order network interfaces by link order
  2015-10-19 11:31                             ` Alexander Holler
@ 2015-10-22  6:47                               ` Alexander Holler
  0 siblings, 0 replies; 59+ messages in thread
From: Alexander Holler @ 2015-10-22  6:47 UTC (permalink / raw)
  To: Greg Kroah-Hartman
  Cc: Linux Kernel Mailing List, Andrew Morton, Russell King,
	Grant Likely

Am 19.10.2015 um 13:31 schrieb Alexander Holler:
> Am 19.10.2015 um 12:57 schrieb Alexander Holler:
>> Am 18.10.2015 um 12:11 schrieb Alexander Holler:
>>> Am 18.10.2015 um 07:59 schrieb Greg Kroah-Hartman:
>>>> On Sun, Oct 18, 2015 at 07:20:34AM +0200, Alexander Holler wrote:
>>>>> Am 18.10.2015 um 07:14 schrieb Greg Kroah-Hartman:
>>>>>> On Sun, Oct 18, 2015 at 06:59:22AM +0200, Alexander Holler wrote:
>>>>>>> Am 17.10.2015 um 21:36 schrieb Greg Kroah-Hartman:
>>>>>>>
>>>>>>>> Again, parallelizing does not solve anything, and causes more
>>>>>>>> problems
>>>>>>>> _and_ makes things take longer.  Try it, we have done it in the
>>>>>>>> past and
>>>>>>>> proven this, it's pretty easy to test :)
>>>>>>>
>>>>>>> Just because I'm curious, may I ask how I would test that in the
>>>>>>> easy way
>>>>>>> you have in mind? I've just posted the results of my tests (the
>>>>>>> patch
>>>>>>> series) but I wonder what you do have in mind.
>>>>>>
>>>>>> Use the tool, scripts/bootgraph.pl to create a boot graph of your
>>>>>> boot
>>>>>> sequence.  That should show you the drivers, or other areas, that are
>>>>>> causing your boot to be "slow".
>>>>>
>>>>> So I've misunderstood you. I've read your paragraph as that it's
>>>>> easy to
>>>>> test parallelizing.
>>>>
>>>> Ah, ok, if you want to parallelize everything, add some logic in the
>>>> driver core where the probe() callback is made to spin that off into a
>>>> new thread for every call, and when it's done, clean up the thread.
>>>> That's what I did many years ago to try this all out, if you dig in the
>>>> lkml archives there's probably a patch somewhere that you can base the
>>>> work off of to test it yourself.
>>>
>>> Hmm, I don't think I will do that because that means to setup a new
>>> thread for every call. And it doesn't need much imagination (or
>>> experience) that this introduces quite some overhead.
>>>
>>> But maybe it makes sense to try out what I'm doing in my patches,
>>> starting multiple threads once and then just giving them some work. Will
>>
>> After a having second thought on your simple approach to parallelize
>> stuff, I have to say that it just can't work because just starting a
>> thread for every probe() totally ignores possible dependencies.
>> Regardless if using one thread per probe() call or if feeding probe()
>> calls to just a few threads.
>>
>> Maybe that's why previous attempts to parallelize stuff failed. But
>> that's just an assumption as I'm unaware of these previous attempts.
>
> Or to describe it more verbose, if DEBUG is turned on in
> init/dependencies.c (using my patches), it spits out a summary of groups
> with initcalls (probe() calls) which are independent from each other and
> therfore can be called in parallel. E.g. one of my systems this looks so:
>
> [    0.288229] init: vertices: 429 edges 204 count 170
> [    0.288295] init: group 0 length 66 (start 0)
> [    0.288329] init: group 1 length 33 (start 66)
> [    0.288364] init: group 2 length 13 (start 99)
> [    0.288398] init: group 3 length 7 (start 112)
> [    0.288432] init: group 4 length 9 (start 119)
> [    0.288466] init: group 5 length 8 (start 128)
> [    0.288500] init: group 6 length 11 (start 136)
> [    0.288534] init: group 7 length 6 (start 147)
> [    0.288569] init: group 8 length 4 (start 153)
> [    0.288603] init: group 9 length 8 (start 157)
> [    0.288637] init: group 10 length 3 (start 165)
> [    0.288671] init: group 11 length 2 (start 168)
> [    0.288705] init: using 4 threads to call annotated initcalls
>
> That means the first group contains 66 initcalls which are called using
> 4 threads, and, after those have finished, the second group with 33
> initcalls will be called in parallel (using the same 4 threads).

BTW. That also means that, for the above example, the worst case would 
mean an error rate of 61% if those 170 (annotated) initcalls would be 
started in parallel while ignoring dependencies.

But that's just meant as an (hopefully) interesting number when looking 
at the above numbers a bit different.

(I've understood that the patches aren't wanted.)

>> Regards,
>>
>> Alexander Holler


^ permalink raw reply	[flat|nested] 59+ messages in thread

* Re: [PATCH 0/14] init: deps: dependency based (parallelized) init
  2015-10-17 17:14 [PATCH 0/14] init: deps: dependency based (parallelized) init Alexander Holler
                   ` (14 preceding siblings ...)
  2015-10-17 17:44 ` [PATCH 0/14] init: deps: dependency based (parallelized) init Greg Kroah-Hartman
@ 2015-11-06 16:07 ` Alexander Holler
  15 siblings, 0 replies; 59+ messages in thread
From: Alexander Holler @ 2015-11-06 16:07 UTC (permalink / raw)
  To: linux-kernel
  Cc: Andrew Morton, Greg Kroah-Hartman, Russell King, Grant Likely

Hello,

in order to "conserve" the patches, I've setup a repository named 
parallelized_kernel_init at github.

I've just put patches for 4.3 into that repository, also I don't know if 
and how long I will use and maintain this series.

Regards,

Alexander Holler

^ permalink raw reply	[flat|nested] 59+ messages in thread

end of thread, other threads:[~2015-11-06 16:07 UTC | newest]

Thread overview: 59+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2015-10-17 17:14 [PATCH 0/14] init: deps: dependency based (parallelized) init Alexander Holler
2015-10-17 17:14 ` [PATCH 01/14] init: deps: introduce annotated initcalls Alexander Holler
2015-10-17 17:14 ` [PATCH 02/14] init: deps: use annotated initcalls for a dependency based (optionally parallelized) init Alexander Holler
2015-10-17 17:14 ` [PATCH 03/14] init: deps: dt: use (HW-specific) dependencies provided by the DT too Alexander Holler
2015-10-19 12:37   ` Mark Brown
2015-10-19 16:27     ` Rob Herring
2015-10-19 17:24       ` Alexander Holler
2015-10-19 17:10     ` Alexander Holler
2015-10-17 17:14 ` [PATCH 04/14] init: deps: order network interfaces by link order Alexander Holler
2015-10-17 18:23   ` Linus Torvalds
2015-10-17 18:37     ` Alexander Holler
2015-10-17 18:52       ` Linus Torvalds
2015-10-17 19:01         ` Alexander Holler
2015-10-17 19:08           ` Linus Torvalds
2015-10-17 19:14             ` Alexander Holler
2015-10-17 19:36               ` Greg Kroah-Hartman
2015-10-17 19:58                 ` Alexander Holler
2015-10-17 21:20                   ` Alexander Holler
2015-10-18  4:59                 ` Alexander Holler
2015-10-18  5:14                   ` Greg Kroah-Hartman
2015-10-18  5:20                     ` Alexander Holler
2015-10-18  5:59                       ` Greg Kroah-Hartman
2015-10-18 10:11                         ` Alexander Holler
2015-10-19 10:57                           ` Alexander Holler
2015-10-19 11:31                             ` Alexander Holler
2015-10-22  6:47                               ` Alexander Holler
2015-10-17 19:37               ` Linus Torvalds
2015-10-17 21:32             ` Alexander Holler
2015-10-17 18:55       ` Greg Kroah-Hartman
2015-10-17 19:03       ` Linus Torvalds
2015-10-17 19:07         ` Alexander Holler
2015-10-17 17:14 ` [PATCH 05/14] init: deps: order I2C bus drivers by their ID Alexander Holler
2015-10-17 17:14 ` [PATCH 06/14] dtc: deps: Automatically add new property 'dependencies' which contains a list of referenced phandles Alexander Holler
2015-10-17 17:14 ` [PATCH 07/14] dtc: deps: introduce new (virtual) property no-dependencies Alexander Holler
2015-10-17 17:14 ` [PATCH 08/14] dtc: deps: Add option to print initialization order Alexander Holler
2015-10-17 17:14 ` [PATCH 09/14] dtc: deps: Add option to print dependency graph as dot (Graphviz) Alexander Holler
2015-10-17 17:14 ` [PATCH 10/14] init: deps: IDs for annotated initcalls Alexander Holler
2015-10-17 17:45   ` Greg Kroah-Hartman
2015-10-17 17:55     ` Alexander Holler
2015-10-17 18:29       ` Greg Kroah-Hartman
2015-10-17 18:46         ` Alexander Holler
2015-10-19 13:12           ` Mark Brown
2015-10-20 10:30             ` Alexander Holler
2015-10-20 10:42               ` Alexander Holler
2015-10-20 10:50                 ` Alexander Holler
2015-10-20 10:57                 ` Alexander Holler
2015-10-17 17:14 ` [PATCH 11/14] init: deps: annotate various initcalls Alexander Holler
2015-10-17 18:47   ` Linus Torvalds
2015-10-17 18:59     ` Alexander Holler
2015-10-17 17:14 ` [PATCH 12/14] dt: dts: deps: kirkwood: dockstar: add dependency ehci -> usb power regulator Alexander Holler
2015-10-17 17:14 ` [PATCH 13/14] dt: dts: deps: imx6q: make some remote-endpoints non-dependencies Alexander Holler
2015-10-17 17:14 ` [PATCH 14/14] dt: dts: deps: omap: beagle: " Alexander Holler
2015-10-17 17:44 ` [PATCH 0/14] init: deps: dependency based (parallelized) init Greg Kroah-Hartman
2015-10-17 18:19   ` Alexander Holler
2015-10-17 18:38     ` Greg Kroah-Hartman
2015-10-17 19:43       ` Alexander Holler
2015-10-17 20:20         ` Greg Kroah-Hartman
2015-10-17 20:37           ` Alexander Holler
2015-11-06 16:07 ` Alexander Holler

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).