Browse Source

devres: make Devres optional with CONFIG_DEVRES

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 an ifdef conditional,
there is no memory overhead when CONFIG_DEVRES is disabled.

Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
Suggested-by: Simon Glass <sjg@chromium.org>
Acked-by: Simon Glass <sjg@chromium.org>
Masahiro Yamada 10 years ago
parent
commit
e2282d7076
5 changed files with 113 additions and 2 deletions
  1. 14 1
      drivers/core/Kconfig
  2. 2 1
      drivers/core/Makefile
  3. 2 0
      drivers/core/device.c
  4. 13 0
      include/dm/device-internal.h
  5. 82 0
      include/dm/device.h

+ 14 - 1
drivers/core/Kconfig

@@ -79,9 +79,22 @@ config SYSCON
 	  by this uclass, including accessing registers via regmap and
 	  by this uclass, including accessing registers via regmap and
 	  assigning a unique number to each.
 	  assigning a unique number to each.
 
 
+config DEVRES
+	bool "Managed device resources"
+	depends on DM
+	help
+	  This option enables the Managed device resources core support.
+	  Device resources managed by the devres framework 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
 config DEBUG_DEVRES
 	bool "Managed device resources verbose debug messages"
 	bool "Managed device resources verbose debug messages"
-	depends on DM
+	depends on DEVRES
 	help
 	help
 	  If this option is enabled, devres debug messages are printed.
 	  If this option is enabled, devres debug messages are printed.
 	  Select this if you are having a problem with devres or want to
 	  Select this if you are having a problem with devres or want to

+ 2 - 1
drivers/core/Makefile

@@ -4,7 +4,8 @@
 # SPDX-License-Identifier:	GPL-2.0+
 # 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
 ifndef CONFIG_SPL_BUILD
 obj-$(CONFIG_OF_CONTROL) += simple-bus.o
 obj-$(CONFIG_OF_CONTROL) += simple-bus.o
 endif
 endif

+ 2 - 0
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->sibling_node);
 	INIT_LIST_HEAD(&dev->child_head);
 	INIT_LIST_HEAD(&dev->child_head);
 	INIT_LIST_HEAD(&dev->uclass_node);
 	INIT_LIST_HEAD(&dev->uclass_node);
+#ifdef CONFIG_DEVRES
 	INIT_LIST_HEAD(&dev->devres_head);
 	INIT_LIST_HEAD(&dev->devres_head);
+#endif
 	dev->platdata = platdata;
 	dev->platdata = platdata;
 	dev->name = name;
 	dev->name = name;
 	dev->of_offset = of_offset;
 	dev->of_offset = of_offset;

+ 13 - 0
include/dm/device-internal.h

@@ -156,6 +156,8 @@ fdt_addr_t simple_bus_translate(struct udevice *dev, fdt_addr_t addr);
 #define DM_UCLASS_ROOT_NON_CONST	(((gd_t *)gd)->uclass_root)
 #define DM_UCLASS_ROOT_NON_CONST	(((gd_t *)gd)->uclass_root)
 
 
 /* device resource management */
 /* device resource management */
+#ifdef CONFIG_DEVRES
+
 /**
 /**
  * devres_release_probe - Release managed resources allocated after probing
  * devres_release_probe - Release managed resources allocated after probing
  * @dev: Device to release resources for
  * @dev: Device to release resources for
@@ -174,4 +176,15 @@ void devres_release_probe(struct udevice *dev);
  */
  */
 void devres_release_all(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
 #endif

+ 82 - 0
include/dm/device.h

@@ -98,7 +98,9 @@ struct udevice {
 	uint32_t flags;
 	uint32_t flags;
 	int req_seq;
 	int req_seq;
 	int seq;
 	int seq;
+#ifdef CONFIG_DEVRES
 	struct list_head devres_head;
 	struct list_head devres_head;
+#endif
 };
 };
 
 
 /* Maximum sequence number supported */
 /* Maximum sequence number supported */
@@ -472,6 +474,8 @@ bool device_is_last_sibling(struct udevice *dev);
 typedef void (*dr_release_t)(struct udevice *dev, void *res);
 typedef void (*dr_release_t)(struct udevice *dev, void *res);
 typedef int (*dr_match_t)(struct udevice *dev, void *res, void *match_data);
 typedef int (*dr_match_t)(struct udevice *dev, void *res, void *match_data);
 
 
+#ifdef CONFIG_DEVRES
+
 #ifdef CONFIG_DEBUG_DEVRES
 #ifdef CONFIG_DEBUG_DEVRES
 void *__devres_alloc(dr_release_t release, size_t size, gfp_t gfp,
 void *__devres_alloc(dr_release_t release, size_t size, gfp_t gfp,
 		     const char *name);
 		     const char *name);
@@ -648,5 +652,83 @@ static inline void *devm_kcalloc(struct udevice *dev,
  */
  */
 void devm_kfree(struct udevice *dev, void *p);
 void devm_kfree(struct udevice *dev, void *p);
 
 
+#else /* ! CONFIG_DEVRES */
+
+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
 #endif