device: Provide de-init device function only if requested
This feature, fixing a specific corner case, is unilateraly growing all struct device with a pointer that 99% of the time is not used. Thus uselessly utilizing ROM. Making the feature Kconfig controlled. Signed-off-by: Tomasz Bursztyka <tobu@bang-olufsen.dk>
This commit is contained in:
parent
2edb6d2517
commit
c14ee16463
3 changed files with 39 additions and 2 deletions
|
@ -144,6 +144,8 @@ typedef int16_t device_handle_t;
|
|||
* device from a devicetree node, use DEVICE_DT_DEINIT_DEFINE() or
|
||||
* DEVICE_DT_INST_DEINIT_DEFINE() instead.
|
||||
*
|
||||
* Note: deinit_fn will only be used if CONFIG_DEVICE_DEINIT_SUPPORT is enabled.
|
||||
*
|
||||
* @param dev_id A unique token which is used in the name of the global device
|
||||
* structure as a C identifier.
|
||||
* @param name A string name for the device, which will be stored in
|
||||
|
@ -214,6 +216,8 @@ typedef int16_t device_handle_t;
|
|||
* @kconfig{CONFIG_LLEXT_EXPORT_DEVICES} is enabled). Before using the
|
||||
* pointer, the referenced object should be checked using device_is_ready().
|
||||
*
|
||||
* Note: deinit_fn will only be used if CONFIG_DEVICE_DEINIT_SUPPORT is enabled.
|
||||
*
|
||||
* @param node_id The devicetree node identifier.
|
||||
* @param init_fn Pointer to the device's initialization function, which will be
|
||||
* run by the kernel during system initialization. Can be `NULL`.
|
||||
|
@ -494,8 +498,10 @@ typedef uint8_t device_flags_t;
|
|||
struct device_ops {
|
||||
/** Initialization function */
|
||||
int (*init)(const struct device *dev);
|
||||
#ifdef CONFIG_DEVICE_DEINIT_SUPPORT
|
||||
/** De-initialization function */
|
||||
int (*deinit)(const struct device *dev);
|
||||
#endif /* CONFIG_DEVICE_DEINIT_SUPPORT */
|
||||
};
|
||||
|
||||
/**
|
||||
|
@ -881,6 +887,8 @@ __syscall int device_init(const struct device *dev);
|
|||
* acquired (e.g. pins, memory, clocks, DMA channels, etc.) and its status will
|
||||
* be left as in its reset state.
|
||||
*
|
||||
* Note: this will be available if CONFIG_DEVICE_DEINIT_SUPPORT is enabled.
|
||||
*
|
||||
* @warning It is the responsibility of the caller to ensure that the device is
|
||||
* ready to be de-initialized.
|
||||
*
|
||||
|
@ -888,7 +896,8 @@ __syscall int device_init(const struct device *dev);
|
|||
*
|
||||
* @retval 0 If successful
|
||||
* @retval -EPERM If device has not been initialized.
|
||||
* @retval -ENOTSUP If device does not support de-initialization.
|
||||
* @retval -ENOTSUP If device does not support de-initialization, or if the
|
||||
* feature is not enabled (see CONFIG_DEVICE_DEINIT_SUPPORT)
|
||||
* @retval -errno For any other errors.
|
||||
*/
|
||||
__syscall int device_deinit(const struct device *dev);
|
||||
|
@ -1132,6 +1141,19 @@ device_get_dt_nodelabels(const struct device *dev)
|
|||
BUILD_ASSERT(sizeof(Z_STRINGIFY(name)) <= Z_DEVICE_MAX_NAME_LEN, \
|
||||
Z_STRINGIFY(name) " too long")
|
||||
|
||||
/**
|
||||
* @brief Fill in the struct device_ops
|
||||
*
|
||||
* @param init_fn_ Initialization function
|
||||
* @param deinit_fn_ De-initialization function
|
||||
*/
|
||||
#define Z_DEVICE_OPS(init_fn_, deinit_fn_) \
|
||||
{ \
|
||||
.init = (init_fn_), \
|
||||
IF_ENABLED(CONFIG_DEVICE_DEINIT_SUPPORT, \
|
||||
(.deinit = (deinit_fn_),)) \
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Initializer for @ref device.
|
||||
*
|
||||
|
@ -1156,7 +1178,7 @@ device_get_dt_nodelabels(const struct device *dev)
|
|||
.api = (api_), \
|
||||
.state = (state_), \
|
||||
.data = (data_), \
|
||||
.ops = { .init = (init_fn_), .deinit = (deinit_fn_) }, \
|
||||
.ops = Z_DEVICE_OPS(init_fn_, deinit_fn_), \
|
||||
.flags = (flags_), \
|
||||
IF_ENABLED(CONFIG_DEVICE_DEPS, (.deps = (deps_),)) /**/ \
|
||||
IF_ENABLED(CONFIG_PM_DEVICE, Z_DEVICE_INIT_PM_BASE(pm_)) /**/ \
|
||||
|
|
|
@ -33,6 +33,16 @@ config DEVICE_DT_METADATA
|
|||
each device. This allows you to use device_get_by_dt_nodelabel(),
|
||||
device_get_dt_metadata(), etc.
|
||||
|
||||
config DEVICE_DEINIT_SUPPORT
|
||||
bool "Support device de-initialization"
|
||||
default y
|
||||
help
|
||||
In very specific case, it might be necessary to de-initialize
|
||||
a device at runtime. This is possible by providing a function
|
||||
to do so. Note, that this will grow every struct device by a
|
||||
function pointer. All device drivers that use the relevant
|
||||
macros and provide such function should select this option.
|
||||
|
||||
endmenu
|
||||
|
||||
menu "Initialization Priorities"
|
||||
|
|
|
@ -145,6 +145,7 @@ bool z_impl_device_is_ready(const struct device *dev)
|
|||
|
||||
int z_impl_device_deinit(const struct device *dev)
|
||||
{
|
||||
#ifdef CONFIG_DEVICE_DEINIT_SUPPORT
|
||||
int ret;
|
||||
|
||||
if (!dev->state->initialized) {
|
||||
|
@ -163,6 +164,10 @@ int z_impl_device_deinit(const struct device *dev)
|
|||
dev->state->initialized = false;
|
||||
|
||||
return 0;
|
||||
#else
|
||||
ARG_UNUSED(dev);
|
||||
return -ENOTSUP;
|
||||
#endif /* CONFIG_DEVICE_DEINIT_SUPPORT */
|
||||
}
|
||||
|
||||
#ifdef CONFIG_USERSPACE
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue