Skip to content

Commit c14ee16

Browse files
tbursztykakartben
authored andcommitted
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 <[email protected]>
1 parent 2edb6d2 commit c14ee16

File tree

3 files changed

+39
-2
lines changed

3 files changed

+39
-2
lines changed

include/zephyr/device.h

Lines changed: 24 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -144,6 +144,8 @@ typedef int16_t device_handle_t;
144144
* device from a devicetree node, use DEVICE_DT_DEINIT_DEFINE() or
145145
* DEVICE_DT_INST_DEINIT_DEFINE() instead.
146146
*
147+
* Note: deinit_fn will only be used if CONFIG_DEVICE_DEINIT_SUPPORT is enabled.
148+
*
147149
* @param dev_id A unique token which is used in the name of the global device
148150
* structure as a C identifier.
149151
* @param name A string name for the device, which will be stored in
@@ -214,6 +216,8 @@ typedef int16_t device_handle_t;
214216
* @kconfig{CONFIG_LLEXT_EXPORT_DEVICES} is enabled). Before using the
215217
* pointer, the referenced object should be checked using device_is_ready().
216218
*
219+
* Note: deinit_fn will only be used if CONFIG_DEVICE_DEINIT_SUPPORT is enabled.
220+
*
217221
* @param node_id The devicetree node identifier.
218222
* @param init_fn Pointer to the device's initialization function, which will be
219223
* run by the kernel during system initialization. Can be `NULL`.
@@ -494,8 +498,10 @@ typedef uint8_t device_flags_t;
494498
struct device_ops {
495499
/** Initialization function */
496500
int (*init)(const struct device *dev);
501+
#ifdef CONFIG_DEVICE_DEINIT_SUPPORT
497502
/** De-initialization function */
498503
int (*deinit)(const struct device *dev);
504+
#endif /* CONFIG_DEVICE_DEINIT_SUPPORT */
499505
};
500506

501507
/**
@@ -881,14 +887,17 @@ __syscall int device_init(const struct device *dev);
881887
* acquired (e.g. pins, memory, clocks, DMA channels, etc.) and its status will
882888
* be left as in its reset state.
883889
*
890+
* Note: this will be available if CONFIG_DEVICE_DEINIT_SUPPORT is enabled.
891+
*
884892
* @warning It is the responsibility of the caller to ensure that the device is
885893
* ready to be de-initialized.
886894
*
887895
* @param dev device to be de-initialized.
888896
*
889897
* @retval 0 If successful
890898
* @retval -EPERM If device has not been initialized.
891-
* @retval -ENOTSUP If device does not support de-initialization.
899+
* @retval -ENOTSUP If device does not support de-initialization, or if the
900+
* feature is not enabled (see CONFIG_DEVICE_DEINIT_SUPPORT)
892901
* @retval -errno For any other errors.
893902
*/
894903
__syscall int device_deinit(const struct device *dev);
@@ -1132,6 +1141,19 @@ device_get_dt_nodelabels(const struct device *dev)
11321141
BUILD_ASSERT(sizeof(Z_STRINGIFY(name)) <= Z_DEVICE_MAX_NAME_LEN, \
11331142
Z_STRINGIFY(name) " too long")
11341143

1144+
/**
1145+
* @brief Fill in the struct device_ops
1146+
*
1147+
* @param init_fn_ Initialization function
1148+
* @param deinit_fn_ De-initialization function
1149+
*/
1150+
#define Z_DEVICE_OPS(init_fn_, deinit_fn_) \
1151+
{ \
1152+
.init = (init_fn_), \
1153+
IF_ENABLED(CONFIG_DEVICE_DEINIT_SUPPORT, \
1154+
(.deinit = (deinit_fn_),)) \
1155+
}
1156+
11351157
/**
11361158
* @brief Initializer for @ref device.
11371159
*
@@ -1156,7 +1178,7 @@ device_get_dt_nodelabels(const struct device *dev)
11561178
.api = (api_), \
11571179
.state = (state_), \
11581180
.data = (data_), \
1159-
.ops = { .init = (init_fn_), .deinit = (deinit_fn_) }, \
1181+
.ops = Z_DEVICE_OPS(init_fn_, deinit_fn_), \
11601182
.flags = (flags_), \
11611183
IF_ENABLED(CONFIG_DEVICE_DEPS, (.deps = (deps_),)) /**/ \
11621184
IF_ENABLED(CONFIG_PM_DEVICE, Z_DEVICE_INIT_PM_BASE(pm_)) /**/ \

kernel/Kconfig.device

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,16 @@ config DEVICE_DT_METADATA
3333
each device. This allows you to use device_get_by_dt_nodelabel(),
3434
device_get_dt_metadata(), etc.
3535

36+
config DEVICE_DEINIT_SUPPORT
37+
bool "Support device de-initialization"
38+
default y
39+
help
40+
In very specific case, it might be necessary to de-initialize
41+
a device at runtime. This is possible by providing a function
42+
to do so. Note, that this will grow every struct device by a
43+
function pointer. All device drivers that use the relevant
44+
macros and provide such function should select this option.
45+
3646
endmenu
3747

3848
menu "Initialization Priorities"

kernel/device.c

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -145,6 +145,7 @@ bool z_impl_device_is_ready(const struct device *dev)
145145

146146
int z_impl_device_deinit(const struct device *dev)
147147
{
148+
#ifdef CONFIG_DEVICE_DEINIT_SUPPORT
148149
int ret;
149150

150151
if (!dev->state->initialized) {
@@ -163,6 +164,10 @@ int z_impl_device_deinit(const struct device *dev)
163164
dev->state->initialized = false;
164165

165166
return 0;
167+
#else
168+
ARG_UNUSED(dev);
169+
return -ENOTSUP;
170+
#endif /* CONFIG_DEVICE_DEINIT_SUPPORT */
166171
}
167172

168173
#ifdef CONFIG_USERSPACE

0 commit comments

Comments
 (0)