[RFC] early init and DT platform devices allocation/registration

Grant Likely grant.likely at secretlab.ca
Tue Jun 25 21:45:25 EST 2013


On Mon, Jun 24, 2013 at 5:33 PM, Lorenzo Pieralisi
<lorenzo.pieralisi at arm.com> wrote:
> Hi all,
>
> I am dealing with a lingering problem related to init and probing of platform
> devices early (before initcalls) in the kernel boot process. The problem,
> which is nothing new, is related to how platform devices are created in the
> kernel from DT and when they become available. Platform devices are created
> through (assuming any legacy static initialization is removed from the kernel)
>
> of_platform_populate()
>
> at arch_initcall time on ARM. This is a problem for drivers that need to be
> probed and initialized before arch_initcall (ie early_initcall) because
> the corresponding platform_device has not been created yet.
>
> To work around this awkward situation, a driver, instead of relying on
> platform driver probing mechanism, can get initialized using early_initcall
> mechanism and rely on DT helpers (ie of_iomap() and company) to initialize
> resources. The problem comes when the driver functions must rely on an API
> (eg regmap) that requires a struct device to function properly; since the
> platform_device has not been created yet at early_initcall time, the
> driver cannot rely on it. The only solution consists in allocating a
> platform_device on the fly at driver init through
>
> of_platform_device_create()
>
> and use that device to initialize the (eg regmap) API. There is an issue
> with this solution, basically a platform device is allocated twice for
> a given device node - compatible property (because of_platform_populate()
> allocates a platform device for a node containing a compatible string even if
> a platform device has already been allocated for that device node).
>
> The second solution relies on early platform devices. Early platform devices
> are added by mach code and driver probing is carried out using the early
> platform device probing mechanism
>
> early_platform_driver_probe()
>
> The drawback with this solution is, AFAIK, it does not play well with DT,
> since the platform device duplication issue is still there (ie
> of_platform_populate() will allocate a platform device which is a duplicate
> of the one allocated at early boot to make the early platform device
> initialization possible).
>
> Please correct me if I am wrong, just trying to untangle a problem that does
> not look easy to solve.
>
> How this problem is supposed to be solved in the kernel ?
>
> 1- drivers that are to be up and running at early_initcall time must not
>    rely on the device/driver model (but then they cannot use any API that
>    requires a struct device to function (eg regmap))
> 2- the driver should allocate a platform device at early initcall from
>    a DT compatible node. Do not know how to deal with platform device
>    duplication though, since of_platform_populate() will create another
>    platform device when the node is parsed

While I've resisted it in the past, I would be okay with adding struct
device pointer in the device_node structure. I've resisted because I
don't want drivers following the device_node pointer and making an
assumption about what /kind/ of device is pointed to by it. However,
this is an important use case and it makes it feasible to use an early
platform device with of_platform_populate.

Alternately, if others chime in and think it is too risky to have the
device pointer in the device node, we could simply add a flag to the
device_node which indicates the node has been parsed by
of_platform_populate.

There would need to be some careful coding to make sure that any call
to early platform device creation sets the pointer in the device node
correctly.

I would also make it a requirement that any early platform device
*must* be converted into a 'real' platform device during initcall
time. That includes being possible to be freed correctly. Static early
platform device definitions should not be allowed, otherwise there
needs to be a special case for the platform device release hook. I
really don't want that.

Something else that needs to be investigated is how the device
hierarchy will be affected by using early_platform_device. We still
want the platform_device to appear in the same place in the hierarchy
regardless of whether or not it was created 'early'. the question is
how to make sure that actually happens.

> 3- driver should rely on early platform device/driver, but this does not
>    solve (?) the platform device duplication problem either, it will happen
>    when of_platform_populate() parses the DT and creates devices on the fly
>
> In theory there are other solutions such as:
>
> (a) declaring the platform device statically in arm/mach-* code and do not
>     define the device node in dts, basically going back in time to ARM legacy
>     kernel mechanism for this kind of devices

As stated above, no. Static device definitions are not a good idea,
and it doesn't scale in a multiplatform kernel world.

> (b) add a way to of_platform_populate() to exclude some compatible strings
>     from being matched

This method will probably be too error prone. It would be better to
add the check in of_platform_populate to skip nodes that have already
been populated. I can't think of any use-cases where we would want
of_platform_populate to process a single node more than once.

>
> Honestly there is not a solution I can say I like and maybe I am trying to
> solve a problem that has already been solved, apologies if so, that's why
> I am asking on the list to people with more knowledge than me on the subject.

No, it hasn't been solved yet, but it is worth solving. Either that or
figure out how to do of_platform_populate much earlier.

g.


More information about the devicetree-discuss mailing list