[U-Boot] [PATCH v3 4/5] devres: make Devres optional with CONFIG_DEVRES

Masahiro Yamada yamada.masahiro at socionext.com
Thu Jul 23 08:17:07 CEST 2015


Currently, Devres requires additional 16 byte for each allocation,
which is not so insignificant in some cases.

Add CONFIG_DEVRES to make this framework optional.
If the option is disabled, devres functions fall back to
non-managed variants.  For example, devres_alloc() to kzalloc(),
devm_kmalloc() to kmalloc(), etc.

Because devres_head is also surrounded by the ifdef conditional,
there is no memory overhead when CONFIG_DEVRES is disabled.

Signed-off-by: Masahiro Yamada <yamada.masahiro at socionext.com>
Suggested-by: Simon Glass <sjg at chromium.org>
---

Changes in v3:
  - Introduce CONFIG_DEVRES
  - Surround devres_head member with ifdef CONFIG_DEVRES

Changes in v2: None

 drivers/core/Kconfig         | 14 +++++++-
 drivers/core/Makefile        |  3 +-
 drivers/core/device.c        |  2 ++
 include/dm/device-internal.h | 13 +++++++
 include/dm/device.h          | 86 ++++++++++++++++++++++++++++++++++++++++++++
 5 files changed, 116 insertions(+), 2 deletions(-)

diff --git a/drivers/core/Kconfig b/drivers/core/Kconfig
index 6889025..e1d8a6a 100644
--- a/drivers/core/Kconfig
+++ b/drivers/core/Kconfig
@@ -60,9 +60,21 @@ config DM_SEQ_ALIAS
 	  numbered devices (e.g. serial0 = &serial0). This feature can be
 	  disabled if it is not required, to save code space in SPL.
 
+config DEVRES
+	bool "Managed device resources"
+	depends on DM
+	help
+	  This option enables the Managed device resources core support.
+	  Device resources managed by Devres are automatically released
+	  whether initialization fails half-way or the device gets detached.
+
+	  If this option is disabled, devres functions fall back to
+	  non-managed variants.  For example, devres_alloc() to kzalloc(),
+	  devm_kmalloc() to kmalloc(), etc.
+
 config DEBUG_DEVRES
 	bool "Managed device resources verbose debug messages"
-	depends on DM
+	depends on DEVRES
 	help
 	  If this option is enabled, devres debug messages are printed.
 	  Select this if you are having a problem with devres or want to
diff --git a/drivers/core/Makefile b/drivers/core/Makefile
index d2cf2ea..d3cd968 100644
--- a/drivers/core/Makefile
+++ b/drivers/core/Makefile
@@ -4,7 +4,8 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
-obj-y	+= device.o lists.o root.o uclass.o util.o devres.o
+obj-y	+= device.o lists.o root.o uclass.o util.o
+obj-$(CONFIG_DEVRES) += devres.o
 ifndef CONFIG_SPL_BUILD
 obj-$(CONFIG_OF_CONTROL) += simple-bus.o
 endif
diff --git a/drivers/core/device.c b/drivers/core/device.c
index a2e384c..b479be7 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -47,7 +47,9 @@ int device_bind(struct udevice *parent, const struct driver *drv,
 	INIT_LIST_HEAD(&dev->sibling_node);
 	INIT_LIST_HEAD(&dev->child_head);
 	INIT_LIST_HEAD(&dev->uclass_node);
+#ifdef CONFIG_DEVRES
 	INIT_LIST_HEAD(&dev->devres_head);
+#endif
 	dev->platdata = platdata;
 	dev->name = name;
 	dev->of_offset = of_offset;
diff --git a/include/dm/device-internal.h b/include/dm/device-internal.h
index ee3b00d..7da4216 100644
--- a/include/dm/device-internal.h
+++ b/include/dm/device-internal.h
@@ -144,6 +144,8 @@ static inline void device_free(struct udevice *dev) {}
 #define DM_UCLASS_ROOT_NON_CONST	(((gd_t *)gd)->uclass_root)
 
 /* device resource management */
+#ifdef CONFIG_DEVRES
+
 /**
  * devres_release_probe - Release managed resources allocated after probing
  * @dev: Device to release resources for
@@ -162,4 +164,15 @@ void devres_release_probe(struct udevice *dev);
  */
 void devres_release_all(struct udevice *dev);
 
+#else /* ! CONFIG_DEVRES */
+
+static inline void devres_release_probe(struct udevice *dev)
+{
+}
+
+static inline void devres_release_all(struct udevice *dev)
+{
+}
+
+#endif /* ! CONFIG_DEVRES */
 #endif
diff --git a/include/dm/device.h b/include/dm/device.h
index 7fddacd..5fbfe4f 100644
--- a/include/dm/device.h
+++ b/include/dm/device.h
@@ -98,7 +98,9 @@ struct udevice {
 	uint32_t flags;
 	int req_seq;
 	int seq;
+#ifdef CONFIG_DEVRES
 	struct list_head devres_head;
+#endif
 };
 
 /* Maximum sequence number supported */
@@ -470,6 +472,8 @@ bool device_is_last_sibling(struct udevice *dev);
 typedef void (*dr_release_t)(struct udevice *dev, void *res);
 typedef int (*dr_match_t)(struct udevice *dev, void *res, void *match_data);
 
+#ifdef CONFIG_DEVRES
+
 #ifdef CONFIG_DEBUG_DEVRES
 void *__devres_alloc(dr_release_t release, size_t size, gfp_t gfp,
 		     const char *name);
@@ -646,5 +650,87 @@ static inline void *devm_kcalloc(struct udevice *dev,
  */
 void devm_kfree(struct udevice *dev, void *p);
 
+#else /* ! CONFIG_DEVRES */
+
+/*
+ * If CONFIG_DM_DEVICE_REMOVE is not defined, we need not manage resources.
+ * The devres functions fall back to normal allocators.
+ */
+static inline void *devres_alloc(dr_release_t release, size_t size, gfp_t gfp)
+{
+	return kzalloc(size, gfp);
+}
+
+static inline void devres_free(void *res)
+{
+	kfree(res);
+}
+
+static inline void devres_add(struct udevice *dev, void *res)
+{
+}
+
+static inline void *devres_find(struct udevice *dev, dr_release_t release,
+				dr_match_t match, void *match_data)
+{
+	return NULL;
+}
+
+static inline void *devres_get(struct udevice *dev, void *new_res,
+			       dr_match_t match, void *match_data)
+{
+	return NULL;
+}
+
+static inline void *devres_remove(struct udevice *dev, dr_release_t release,
+				  dr_match_t match, void *match_data)
+{
+	return NULL;
+}
+
+static inline int devres_destroy(struct udevice *dev, dr_release_t release,
+				 dr_match_t match, void *match_data)
+{
+	return 0;
+}
+
+static inline int devres_release(struct udevice *dev, dr_release_t release,
+				 dr_match_t match, void *match_data)
+{
+	return 0;
+}
+
+static inline void *devm_kmalloc(struct udevice *dev, size_t size, gfp_t gfp)
+{
+	return kmalloc(size, gfp);
+}
+
+static inline void *devm_kzalloc(struct udevice *dev, size_t size, gfp_t gfp)
+{
+	return kzalloc(size, gfp);
+}
+
+static inline void *devm_kmaloc_array(struct udevice *dev,
+				      size_t n, size_t size, gfp_t flags)
+{
+	/* TODO: add kmalloc_array() to linux/compat.h */
+	if (size != 0 && n > SIZE_MAX / size)
+		return NULL;
+	return kmalloc(n * size, flags);
+}
+
+static inline void *devm_kcalloc(struct udevice *dev,
+				 size_t n, size_t size, gfp_t flags)
+{
+	/* TODO: add kcalloc() to linux/compat.h */
+	return kmalloc(n * size, flags | __GFP_ZERO);
+}
+
+static inline void devm_kfree(struct udevice *dev, void *p)
+{
+	kfree(p);
+}
+
+#endif /* ! CONFIG_DEVRES */
 
 #endif
-- 
1.9.1



More information about the U-Boot mailing list