-
Notifications
You must be signed in to change notification settings - Fork 6.9k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Refactor device structures #23407
Refactor device structures #23407
Conversation
271be45
to
ee00b5d
Compare
Some checks failed. Please fix and resubmit. checkpatch issues
Tip: The bot edits this comment instead of posting a new one, so you can check the comment's history to see earlier messages. |
855c639
to
b7e4ea0
Compare
@nashif no idea why these timeouts are happening (on msp2_an385 and msp2_an521). It work just fine on my machine. Any clue? |
e5deb1d
to
55fe2a4
Compare
16b177a
to
2dd22aa
Compare
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks a lot for sharing this.
I have some questions about the way system initialization is changing. For now I've only thought through the device parts, but I will think a bit more about dependencies that software services have on devices and how that could fit here.
*/ | ||
struct init_entry { | ||
int (*init)(struct device *dev); | ||
struct device *dev; |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Seems like this could be moved into device.h entirely, if it is really device specific. Any point to keep it here?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Because init_entry stuff is not device specific, actually. It's "generic". Note that, if required, in future we could have a union {} around the dev, and a marker about the type on the init. (Though I don't any requirement for that yet. But it's possible)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Then why not just have this be a void *arg
and be done with it?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I don't want to do casting on such low level parts. First because it will not give you any gain from memory point of view and is less readable. Plus, next phase (with the device status reporting stuff) will be to "const-ify" all struct device everywhere, with all that implies.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I get the point about "less readable", but casting a struct device *
to a struct notdevice *
violates MISRA 11.3, which is a required constraint, compared to 11.5 which only advises against casting a void *
to a struct device *
. So maybe it really is better as:
struct device_init_entry {
int (*init)(struct void *p);
void *p;
};
But I'm not sure if the future constifying makes that irrelevant.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I propose that this issue is resolved by the previous comment block and documentation that a null device pointer field/argument indicates that the init function does not take any arguments.
(Clarification: It takes a null argument, but never a non-null one referencing a non-device object.)
include/init.h
Outdated
* Must be one of the following symbols, which are listed in the order | ||
* they are performed by the kernel: | ||
* \n | ||
* \li PRE_KERNEL_1: Used for devices that have no dependencies, such as those |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I am still not sure why PRE_KERNEL_1 and PRE_KERNEL_2 are meaningful. They used to be necessary, but now that we have proper dependency tracking in devicetree they do not seem needed. Further, their definitions here are about dependencies, but they don't really seem meaningful to me, since dependencies are a bit nuanced even with\in the SoC: e.g. peripheral devices can depend on clock devices, etc.
Other than keeping legacy code working (which is not an objective of this effort), is there a reason to keep these levels? They seem to me to do more harm than good, but I don't know all the use cases, of course.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This PR is not about changing the levels, so no harm here.
Anyway, note that each level have priority only between 0 to 99. That limits a bit the sorting possibility (devices ordering is made on level, then priority and finally their name). That was basically the reason of splitting the pre kernel level in 2, historically, if I remember well.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This PR is not about changing the levels, so no harm here.
Are you open to the discussion of removing those levels later then? I ask because this PR seems to be specifically about refactoring initialization, and that's what the levels are part of.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
No it's refactoring device structures only. Not levels, not the initialization (it's exactly the same process, I did not change anything there).
I would not change anything about the level yet. For the good reason that it is not yet a major issue, compared to the rest. level/prio dts generation is imo of a lesser priority compared to dts device instance generation (because if that's made right, then level/prio generation will be super trivial to do)
Let's proceed step by step (and make sure people go along each of these changes)
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Are you open to the discussion of removing those levels later then?
Why do you want to remove them? those are not exclusive to device initialization or setup. A basic feature those levels provide is giving the developer the possibility to run code at any step of the booting process, sometimes you have to do HW initialization that is not managed by a driver or DTS and you need that at early stage. Removing those level will break many application and a useful interface.
Driver initialization priorities need to be improved and should utilise DTS for that, however, this is orthogonal and unrelated IMO. The driver priority happens on top of the existing scheme, does not replace it.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Can you point to a definition for _1 vs. _2 that isn't in terms of device dependencies? Right now that's how they're defined. That's a hack. We have real dependencies from DT now.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This is just a bug in the documentation, nobody bothered to change this and was long there and before device tree. So the fact it talks about devices does not mean this is 1:1 match with devicetree. Right now this is used for drivers, services and hardware initialization of different sorts that is not managed by DT, I am sure some of this can be optimized to be devicetree "devices" but we should not limit this to device tree, there is a need for this in the tree currently and there was always a need, the reason it is there.
I suggest the following change...
--- a/include/device.h
+++ b/include/device.h
@@ -57,25 +57,31 @@ extern "C" {
* Must be one of the following symbols, which are listed in the order
* they are performed by the kernel:
* \n
- * \li PRE_KERNEL_1: Used for devices that have no dependencies, such as those
- * that rely solely on hardware present in the processor/SOC. These devices
+ * \li PRE_KERNEL_1: Used for units that have no dependencies, such as those
+ * that rely solely on hardware present in the processor/SOC. These units
* cannot use any kernel services during configuration, since they are not
* yet available.
* \n
- * \li PRE_KERNEL_2: Used for devices that rely on the initialization of devices
- * initialized as part of the PRE_KERNEL_1 level. These devices cannot use any
- * kernel services during configuration, since they are not yet available.
+ * \li PRE_KERNEL_2: Used for units that rely on the initialization of other
+ * units initialized as part of the PRE_KERNEL_1 level. These units cannot
+ * use any kernel services during configuration, since they are not yet
+ * available.
* \n
- * \li POST_KERNEL: Used for devices that require kernel services during
+ * \li POST_KERNEL: Used for units that require kernel services during
* configuration.
* \n
- * \li POST_KERNEL_SMP: Used for devices that require kernel services during
+ * \li POST_KERNEL_SMP: Used for units that require kernel services during
* configuration after SMP initialization.
* \n
* \li APPLICATION: Used for application components (i.e. non-kernel components)
- * that need automatic configuration. These devices can use all services
+ * that need automatic configuration. These units can use all services
* provided by the kernel during configuration.
*
+ * Units are the objects that Zephyr knows how to manage. They represent system
+ * resources that can be initialised and executed based on the level and
+ * priority defined for each unit. Units in some ways are similar to services
+ * or jobs in other init systems and additionally include device drivers.
+ *
* @param prio The initialization priority of the device, relative to
* other devices of the same initialization level. Specified as an integer
* value in the range 0 to 99; lower values indicate earlier initialization.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
We have system services via SYS_INIT() which get invoked from PRE_KERNEL phases, and I fail to see how removing this improves the kernel in a significant way.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@anas I did change the doc already, could you check? I did it before you proposal, basically I used "initialization objects" instead of "units".
ca41a6e
to
9bab271
Compare
@carlescufi I guess that's ready to be merged any time you want. (I'll rebase if new commits makes it non-mergable" |
@tbursztyka @carlescufi The merge of #17631 requires an update to this. https://github.com/pabigot/zephyr/commits/nordic/pr/23407 has the necessary fixup patch, plus a second DNM patch that has the coccinelle script that will fix other cases if more things get merged before this gets merged. |
Thanks @pabigot. I believe @tbursztyka is off on holiday today, so would it be possible to get this PR merged and then merge the PR (I think you listed the wrong one since you point at this very one) that has the required fixes? |
@carlescufi Yes it's off here, but I had to login, so I can do it |
@tbursztyka Three more patches are necessary due to problems with I can apply them and similar patches resulting from further delays if you authorize me to push to your branch---I don't do that without clear prior assent. |
eacf14b
to
891dc84
Compare
include/syscall_handler.h
Outdated
@@ -453,15 +452,15 @@ static inline int z_obj_validation_check(struct z_object *ko, | |||
* | |||
* @param _device Untrusted device pointer | |||
* @param _dtype Expected kernel object type for the provided device pointer | |||
* @param _init_fn Expected init function memory address | |||
* @param _api Expected driver API structure memory address | |||
* @return 0 on success, nonzero on failure | |||
*/ | |||
#define Z_SYSCALL_SPECIFIC_DRIVER(_device, _dtype, _init_fn) \ |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Missed the rename of _init_fn
to _api
to match use in the macro body.
@pabigot can you re-check? |
@tbursztyka Yes, this one seems to have everything: maxim test of syscall driver works, no additional changes snuck in. |
The whole file is perfectly indented everywhere else. Signed-off-by: Tomasz Bursztyka <[email protected]>
The whole file is perfectly indented everywhere else. Signed-off-by: Tomasz Bursztyka <[email protected]>
When the device driver model got introduced, there were no concept of SYS_INIT() which can be seen as software service. These were introduced afterwards and reusing the device infrastructure for simplicity. However, it meant to allocate a bit too much for something that only required an initialization function to be called at right time. Thus refactoring the devices structures relevantly: - introducing struct init_entry which is a generic init end-point - struct deviceconfig is removed and struct device owns everything now. - SYS_INIT() generates only a struct init_entry via calling INIT_ENTRY_DEFINE() - DEVICE_AND_API_INIT() generates a struct device and calls INIT_ENTRY_DEFINE() - init objects sections are in ROM - device objects sections are in RAM (but will end up in ROM once they will be 'constified') It also generate a tiny memory gain on both ROM and RAM, which is nice. Perhaps kernel/device.c could be renamed to something more relevant. Signed-off-by: Tomasz Bursztyka <[email protected]>
Since struct devconfig was merged earlier into struct device, let's fix accessing config_info, name, ... attributes everywhere via: grep -rlZ 'dev->config->' | xargs -0 sed -i 's/dev->config->/dev->/g' Signed-off-by: Tomasz Bursztyka <[email protected]>
device_api attribute is not at offset 4 but 8 now as name and config_info has been directly imported into struct device. Signed-off-by: Tomasz Bursztyka <[email protected]>
…ring init_fn is not anymore part of struct device, so let's test instead the driver's API structure pointer which is also unique per device driver. Signed-off-by: Tomasz Bursztyka <[email protected]>
s/init.h/device.h Signed-off-by: Tomasz Bursztyka <[email protected]>
The '_' is not necessary, plus it makes the sys init object name aligning with all others. Signed-off-by: Tomasz Bursztyka <[email protected]>
Part of #22941
Original struct device was only meant for actual devices. But its infrastructure has been then used also for non-hardware based boot-time critical piece of software. Though this was a simple solution, it brought the device concept to non-device systems.
So refactoring all of this in order to get rid of struct device from these systems, as well as clarifying the struct device as well.
This leads to some bytes saved from both ROM and RAM.