device: Refactor device structures

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 <tomasz.bursztyka@linux.intel.com>
This commit is contained in:
Tomasz Bursztyka 2020-03-09 11:02:20 +01:00 committed by Carles Cufí
commit 8d7bb8ffd8
11 changed files with 304 additions and 250 deletions

View file

@ -45,7 +45,7 @@
*/
#ifdef CONFIG_DEVICE_POWER_MANAGEMENT
#define DEVICE_COUNT \
((__device_init_end - __device_init_start) / _DEVICE_STRUCT_SIZEOF)
((__device_end - __device_start) / _DEVICE_STRUCT_SIZEOF)
#define DEV_BUSY_SZ (((DEVICE_COUNT + 31) / 32) * 4)
#define DEVICE_BUSY_BITFIELD() \
FILL(0x00) ; \
@ -57,37 +57,53 @@
#endif
/*
* generate a symbol to mark the start of the device initialization objects for
* the specified level, then link all of those objects (sorted by priority);
* ensure the objects aren't discarded if there is no direct reference to them
* generate a symbol to mark the start of the objects array for
* the specified object and level, then link all of those objects
* (sorted by priority). Ensure the objects aren't discarded if there is
* no direct reference to them
*/
#define DEVICE_INIT_LEVEL(level) \
__device_##level##_start = .; \
KEEP(*(SORT(.init_##level[0-9]))); \
KEEP(*(SORT(.init_##level[1-9][0-9]))); \
#define CREATE_OBJ_LEVEL(object, level) \
__##object##_##level##_start = .; \
KEEP(*(SORT(.##object##_##level[0-9]))); \
KEEP(*(SORT(.##object##_##level[1-9][0-9]))); \
/*
* link in device initialization objects for all devices that are automatically
* link in initialization objects for all objects that are automatically
* initialized by the kernel; the objects are sorted in the order they will be
* initialized (i.e. ordered by level, sorted by priority within a level)
*/
#define DEVICE_INIT_SECTIONS() \
__device_init_start = .; \
DEVICE_INIT_LEVEL(PRE_KERNEL_1) \
DEVICE_INIT_LEVEL(PRE_KERNEL_2) \
DEVICE_INIT_LEVEL(POST_KERNEL) \
DEVICE_INIT_LEVEL(APPLICATION) \
DEVICE_INIT_LEVEL(SMP) \
__device_init_end = .; \
DEVICE_BUSY_BITFIELD() \
#define INIT_SECTIONS() \
__init_start = .; \
CREATE_OBJ_LEVEL(init, PRE_KERNEL_1) \
CREATE_OBJ_LEVEL(init, PRE_KERNEL_2) \
CREATE_OBJ_LEVEL(init, POST_KERNEL) \
CREATE_OBJ_LEVEL(init, APPLICATION) \
CREATE_OBJ_LEVEL(init, SMP) \
__init_end = .; \
/* define a section for undefined device initialization levels */
#define DEVICE_INIT_UNDEFINED_SECTION() \
#define INIT_UNDEFINED_SECTION() \
KEEP(*(SORT(.init_[_A-Z0-9]*))) \
/*
* link in devices objects, which are tied to the init ones;
* the objects are thus sorted the same way as their init object parent
* see include/device.h
*/
#define DEVICE_SECTIONS() \
__device_start = .; \
CREATE_OBJ_LEVEL(device, PRE_KERNEL_1) \
CREATE_OBJ_LEVEL(device, PRE_KERNEL_2) \
CREATE_OBJ_LEVEL(device, POST_KERNEL) \
CREATE_OBJ_LEVEL(device, APPLICATION) \
CREATE_OBJ_LEVEL(device, SMP) \
__device_end = .; \
DEVICE_BUSY_BITFIELD() \
/*
* link in shell initialization objects for all modules that use shell and
* their shell commands are automatically initialized by the kernel.