Device init sequence rework #64022
Labels
Architecture Review
Discussion in the Architecture WG required
area: Device Model
RFC
Request For Comments: want input from the community
Introduction
Nowadays, devices rely on the
init.h
(i.e.SYS_INIT
) infrastructure to get initialized automatically. Theinit.h
infrastructure is a basic mechanism that allows to register an init function when the system is initialized (beforemain
). It provides with multiple initialization levels:PRE_KERNEL_*
,POST_KERNEL
, etc., and within each level a numeric priority (0-99). Using this information, each registered init entry is sorted by the linker so that the Kernel can later iterateover them in the correct order. This all sounds nice and simple, but when it comes to devices, this mechanism has proven to be insufficient.
Before starting with the changes proposed in this patch, let's first dig into the implementation details of the current model. When devices are defined, using any of the
DEVICE_*DEFINE
macros, they also create an init entry using the internalinit.h
APIs (seeZ_DEVICE_INIT_ENTRY_DEFINE
). This entry, stores a pointer to the device init call and to the device itself. As the reader can imagine, this implies a coupling betweeninit.h
anddevice.h
. The only link between a device and an init entry is the device pointer stored in the init entry. This allows the Kernel init machinery to call the initfunction with the right device pointer. However, there is no direct relationship between a device and its init function, that is,
struct device
does not keep the device init function reference. This is not a problem nowadays, but it could be a problem if features like deferred initialization or init/de-init have to be implemented. However, in reality, this is a secondary problem. The most problematic issue we have today is that devices are mixed withSYS_INIT
calls. They are all part of the same init block, and are treated equally. So for example, one can theoretically have a system where the init sequence can be like:Problem description
The current approach is problematic because:
(1) Init calls can depend on devices, but dependency is not tracked anywhere. So the user must check that init priorities are correct to avoid runtime failures.
(2) Device drivers can have multiple instances, and each instance may require a different set of priorities, while
SYS_INIT
calls are singletons.(3) Devices don't likely need so many init priorities, some need to be discussed (SMP, PRE_KERNEL_1/2) - partly remediated by #62865
(1) is particularly important because init calls do not have a specific purpose. They usage ranges from SoC init code, to system services. So it's unpredictable what can happen in there. (2) is a tangential topic, actually not fixed by this patch, even though it helps.
Proposed change
So it's about providing devices with their own init infrastructure,
minimizing the coupling with init.h. The idea is to group devices in a
separate section. Therefore, the list above would look like:
This means that it is no longer possible to mix init calls and devices within the same level. Therefore, how does it work now? Within each level, devices are initialized first, then init calls. It is done this way because it looks like init calls tend to depend on devices and not vice versa. I may be wrong, so we may need to add something like "POST_KERNEL_EARLY" (before devices), and "POST_KERNEL_LATE" (after devices). In the simplest scenario, the init order would look something like this:
After this change, we could start using devicetree ordinals, by reducing the source of problems to the init level only. For example, there could be pre-kernel and post-kernel devices only. Maybe init level could be removed entirely. The other side effect of this change is that
struct device
stores the device init call, so we can potentially do things like defer device initialization or implement things like init/de-init. They all come with their own complexity, of course, but this patch could be a step forward.Some existing SYS_INIT calls should also be moved to platform hooks, executed at a specific point. This is the case e.g. for SoC hooks, where the priority is ignored in most cases (set to 0).
Dependencies
We need all device dependencies to be tracked in devicetree to use ordinals successfully. This is not the case in all situations nowadays, e.g. with regulators. Some will be easy to spot and fix, some will likely end up being discovered at runtime. It would also be beneficial to introduce new platform hooks to reduce usage of SYS_INITs in cases where flexibility is not required (e.g. SoC init hooks).
Concerns and Unresolved Questions
This is a breaking change, so we need to make sure changes made can solve existing scenarios, or, offer alternatives. This is why it is important to analyze lots of use cases before moving forward with this proposal.
Alternatives
The text was updated successfully, but these errors were encountered: