All of lore.kernel.org
 help / color / mirror / Atom feed
* [U-Boot] [PATCH v4 0/5] Devres (Managed Device Resource) for U-Boot
@ 2015-07-25 12:52 Masahiro Yamada
  2015-07-25 12:52 ` [U-Boot] [PATCH v4 1/5] dm: add DM_FLAG_BOUND flag Masahiro Yamada
                   ` (4 more replies)
  0 siblings, 5 replies; 13+ messages in thread
From: Masahiro Yamada @ 2015-07-25 12:52 UTC (permalink / raw)
  To: u-boot

This is version 4 of Devres series.

Simon, Albert and I discussed whether we need (want) to
get this framework in.

Looks like our agreement is that we can add Devres, but
keeping it optional.  The DM core part still sticks to the
manual malloc() and free().

With CONFIG_DEVRES disabled, devres APIs fall back to
normal memory allocators, so there is no overhead.



Masahiro Yamada (5):
  dm: add DM_FLAG_BOUND flag
  devres: introduce Devres (Managed Device Resource) framework
  devres: add devm_kmalloc() and friends (managed memory allocators)
  devres: make Devres optional with CONFIG_DEVRES
  devres: add debug command to dump device resources

 drivers/core/Kconfig         |  24 ++++
 drivers/core/Makefile        |   1 +
 drivers/core/device-remove.c |   8 ++
 drivers/core/device.c        |   7 ++
 drivers/core/devres.c        | 259 +++++++++++++++++++++++++++++++++++++++++
 include/dm/device-internal.h |  32 +++++
 include/dm/device.h          | 269 +++++++++++++++++++++++++++++++++++++++++++
 include/dm/util.h            |   9 ++
 test/dm/cmd_dm.c             |  12 +-
 9 files changed, 620 insertions(+), 1 deletion(-)
 create mode 100644 drivers/core/devres.c

-- 
1.9.1

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [U-Boot] [PATCH v4 1/5] dm: add DM_FLAG_BOUND flag
  2015-07-25 12:52 [U-Boot] [PATCH v4 0/5] Devres (Managed Device Resource) for U-Boot Masahiro Yamada
@ 2015-07-25 12:52 ` Masahiro Yamada
  2015-07-29  3:29   ` Simon Glass
  2015-07-25 12:52 ` [U-Boot] [PATCH v4 2/5] devres: introduce Devres (Managed Device Resource) framework Masahiro Yamada
                   ` (3 subsequent siblings)
  4 siblings, 1 reply; 13+ messages in thread
From: Masahiro Yamada @ 2015-07-25 12:52 UTC (permalink / raw)
  To: u-boot

Currently, we only have DM_FLAG_ACTIVATED to indicate the device
status, but we still cannot know in which stage is in progress,
binding or probing.

This commit introduces a new flag, DM_FLAG_BOUND, which is set when
the device is really bound, and cleared when it is unbound.

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

Changes in v4: None
Changes in v3: None
Changes in v2: None

 drivers/core/device-remove.c | 3 +++
 drivers/core/device.c        | 2 ++
 include/dm/device.h          | 3 +++
 3 files changed, 8 insertions(+)

diff --git a/drivers/core/device-remove.c b/drivers/core/device-remove.c
index 6b87f86..45d6543 100644
--- a/drivers/core/device-remove.c
+++ b/drivers/core/device-remove.c
@@ -61,6 +61,9 @@ int device_unbind(struct udevice *dev)
 	if (dev->flags & DM_FLAG_ACTIVATED)
 		return -EINVAL;
 
+	if (!(dev->flags & DM_FLAG_BOUND))
+		return -EINVAL;
+
 	drv = dev->driver;
 	assert(drv);
 
diff --git a/drivers/core/device.c b/drivers/core/device.c
index 51b1b44..0333889 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -132,6 +132,8 @@ int device_bind(struct udevice *parent, const struct driver *drv,
 		dm_dbg("Bound device %s to %s\n", dev->name, parent->name);
 	*devp = dev;
 
+	dev->flags |= DM_FLAG_BOUND;
+
 	return 0;
 
 fail_child_post_bind:
diff --git a/include/dm/device.h b/include/dm/device.h
index 9fa0048..43004ac 100644
--- a/include/dm/device.h
+++ b/include/dm/device.h
@@ -36,6 +36,9 @@ struct driver_info;
 /* Allocate driver private data on a DMA boundary */
 #define DM_FLAG_ALLOC_PRIV_DMA	(1 << 5)
 
+/* Device is bound */
+#define DM_FLAG_BOUND	(1 << 6)
+
 /**
  * struct udevice - An instance of a driver
  *
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [U-Boot] [PATCH v4 2/5] devres: introduce Devres (Managed Device Resource) framework
  2015-07-25 12:52 [U-Boot] [PATCH v4 0/5] Devres (Managed Device Resource) for U-Boot Masahiro Yamada
  2015-07-25 12:52 ` [U-Boot] [PATCH v4 1/5] dm: add DM_FLAG_BOUND flag Masahiro Yamada
@ 2015-07-25 12:52 ` Masahiro Yamada
  2015-07-28 18:07   ` Simon Glass
  2015-07-25 12:52 ` [U-Boot] [PATCH v4 3/5] devres: add devm_kmalloc() and friends (managed memory allocators) Masahiro Yamada
                   ` (2 subsequent siblings)
  4 siblings, 1 reply; 13+ messages in thread
From: Masahiro Yamada @ 2015-07-25 12:52 UTC (permalink / raw)
  To: u-boot

In U-Boot's driver model, memory is basically allocated and freed
in the core framework.  So, low level drivers generally only have
to specify the size of needed memory with .priv_auto_alloc_size,
.platdata_auto_alloc_size, etc.  Nevertheless, some drivers still
need to allocate/free memory on their own in case they cannot
statically know the necessary memory size.  So, I believe it is
reasonable enough to port Devres into U-boot.

Devres, which originates in Linux, manages device resources for each
device and automatically releases them on driver detach.  With devres,
device resources are guaranteed to be freed whether initialization
fails half-way or the device gets detached.

The basic idea is totally the same to that of Linux, but I tweaked
it a bit so that it fits in U-Boot's driver model.

In U-Boot, drivers are activated in two steps: binding and probing.
Binding puts a driver and a device together.  It is just data
manipulation on the system memory, so nothing has happened on the
hardware device at this moment.  When the device is really used, it
is probed.  Probing initializes the real hardware device to make it
really ready for use.

So, the resources acquired during the probing process must be freed
when the device is removed.  Likewise, what has been allocated in
binding should be released when the device is unbound.  The struct
devres has a member "probe" to remember when the resource was
allocated.

CONFIG_DEBUG_DEVRES is also supported for easier debugging.
If enabled, debug messages are printed each time a resource is
allocated/freed.

Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
---

Changes in v4:
  - Comment struct devres

Changes in v3:
  - Update git-description.  Do not mention about the DM core part.

Changes in v2:
  - Add more APIs: _free, _find, _get, _remove, _destroy, _release
  - Move devres_release_probe() and devres_release_all() decrlarations
    to dm/device-internal.h
  - Move comments to headers

 drivers/core/Kconfig         |  10 +++
 drivers/core/Makefile        |   2 +-
 drivers/core/device-remove.c |   5 ++
 drivers/core/device.c        |   3 +
 drivers/core/devres.c        | 196 +++++++++++++++++++++++++++++++++++++++++++
 include/dm/device-internal.h |  19 +++++
 include/dm/device.h          | 140 +++++++++++++++++++++++++++++++
 7 files changed, 374 insertions(+), 1 deletion(-)
 create mode 100644 drivers/core/devres.c

diff --git a/drivers/core/Kconfig b/drivers/core/Kconfig
index e40372d..6889025 100644
--- a/drivers/core/Kconfig
+++ b/drivers/core/Kconfig
@@ -59,3 +59,13 @@ config DM_SEQ_ALIAS
 	  Most boards will have a '/aliases' node containing the path to
 	  numbered devices (e.g. serial0 = &serial0). This feature can be
 	  disabled if it is not required, to save code space in SPL.
+
+config DEBUG_DEVRES
+	bool "Managed device resources verbose debug messages"
+	depends on DM
+	help
+	  If this option is enabled, devres debug messages are printed.
+	  Select this if you are having a problem with devres or want to
+	  debug resource management for a managed device.
+
+	  If you are unsure about this, Say N here.
diff --git a/drivers/core/Makefile b/drivers/core/Makefile
index 5c2ead8..d2cf2ea 100644
--- a/drivers/core/Makefile
+++ b/drivers/core/Makefile
@@ -4,7 +4,7 @@
 # SPDX-License-Identifier:	GPL-2.0+
 #
 
-obj-y	+= device.o lists.o root.o uclass.o util.o
+obj-y	+= device.o lists.o root.o uclass.o util.o devres.o
 ifndef CONFIG_SPL_BUILD
 obj-$(CONFIG_OF_CONTROL) += simple-bus.o
 endif
diff --git a/drivers/core/device-remove.c b/drivers/core/device-remove.c
index 45d6543..bd6d406 100644
--- a/drivers/core/device-remove.c
+++ b/drivers/core/device-remove.c
@@ -95,6 +95,9 @@ int device_unbind(struct udevice *dev)
 
 	if (dev->parent)
 		list_del(&dev->sibling_node);
+
+	devres_release_all(dev);
+
 	free(dev);
 
 	return 0;
@@ -128,6 +131,8 @@ void device_free(struct udevice *dev)
 			dev->parent_priv = NULL;
 		}
 	}
+
+	devres_release_probe(dev);
 }
 
 int device_remove(struct udevice *dev)
diff --git a/drivers/core/device.c b/drivers/core/device.c
index 0333889..a2e384c 100644
--- a/drivers/core/device.c
+++ b/drivers/core/device.c
@@ -47,6 +47,7 @@ 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);
+	INIT_LIST_HEAD(&dev->devres_head);
 	dev->platdata = platdata;
 	dev->name = name;
 	dev->of_offset = of_offset;
@@ -170,6 +171,8 @@ fail_alloc2:
 		dev->platdata = NULL;
 	}
 fail_alloc1:
+	devres_release_all(dev);
+
 	free(dev);
 
 	return ret;
diff --git a/drivers/core/devres.c b/drivers/core/devres.c
new file mode 100644
index 0000000..49c270c
--- /dev/null
+++ b/drivers/core/devres.c
@@ -0,0 +1,196 @@
+/*
+ * Copyright (C) 2015 Masahiro Yamada <yamada.masahiro@socionext.com>
+ *
+ * Based on the original work in Linux by
+ * Copyright (c) 2006  SUSE Linux Products GmbH
+ * Copyright (c) 2006  Tejun Heo <teheo@suse.de>
+ *
+ * SPDX-License-Identifier:	GPL-2.0+
+ */
+
+#include <common.h>
+#include <linux/compat.h>
+#include <linux/kernel.h>
+#include <linux/list.h>
+#include <dm/device.h>
+
+/**
+ * struct devres - Bookkeeping info for managed device resource
+ * @entry: List to associate this structure with a device
+ * @release: Callback invoked when this resource is released
+ * @probe: Flag to show when this resource was allocated
+	   (true = probe, false = bind)
+ * @name: Name of release function
+ * @size: Size of resource data
+ * @data: Resource data
+ */
+struct devres {
+	struct list_head		entry;
+	dr_release_t			release;
+	bool				probe;
+#ifdef CONFIG_DEBUG_DEVRES
+	const char			*name;
+	size_t				size;
+#endif
+	unsigned long long		data[];
+};
+
+#ifdef CONFIG_DEBUG_DEVRES
+static void set_node_dbginfo(struct devres *dr, const char *name, size_t size)
+{
+	dr->name = name;
+	dr->size = size;
+}
+
+static void devres_log(struct udevice *dev, struct devres *dr,
+		       const char *op)
+{
+	printf("%s: DEVRES %3s %p %s (%lu bytes)\n",
+	       dev->name, op, dr, dr->name, (unsigned long)dr->size);
+}
+#else /* CONFIG_DEBUG_DEVRES */
+#define set_node_dbginfo(dr, n, s)	do {} while (0)
+#define devres_log(dev, dr, op)		do {} while (0)
+#endif
+
+#if CONFIG_DEBUG_DEVRES
+void *__devres_alloc(dr_release_t release, size_t size, gfp_t gfp,
+		     const char *name)
+#else
+void *_devres_alloc(dr_release_t release, size_t size, gfp_t gfp)
+#endif
+{
+	size_t tot_size = sizeof(struct devres) + size;
+	struct devres *dr;
+
+	dr = kmalloc(tot_size, gfp);
+	if (unlikely(!dr))
+		return NULL;
+
+	INIT_LIST_HEAD(&dr->entry);
+	dr->release = release;
+	set_node_dbginfo(dr, name, size);
+
+	return dr->data;
+}
+
+void devres_free(void *res)
+{
+	if (res) {
+		struct devres *dr = container_of(res, struct devres, data);
+
+		BUG_ON(!list_empty(&dr->entry));
+		kfree(dr);
+	}
+}
+
+void devres_add(struct udevice *dev, void *res)
+{
+	struct devres *dr = container_of(res, struct devres, data);
+
+	devres_log(dev, dr, "ADD");
+	BUG_ON(!list_empty(&dr->entry));
+	dr->probe = dev->flags & DM_FLAG_BOUND ? true : false;
+	list_add_tail(&dr->entry, &dev->devres_head);
+}
+
+void *devres_find(struct udevice *dev, dr_release_t release,
+		  dr_match_t match, void *match_data)
+{
+	struct devres *dr;
+
+	list_for_each_entry_reverse(dr, &dev->devres_head, entry) {
+		if (dr->release != release)
+			continue;
+		if (match && !match(dev, dr->data, match_data))
+			continue;
+		return dr->data;
+	}
+
+	return NULL;
+}
+
+void *devres_get(struct udevice *dev, void *new_res,
+		 dr_match_t match, void *match_data)
+{
+	struct devres *new_dr = container_of(new_res, struct devres, data);
+	void *res;
+
+	res = devres_find(dev, new_dr->release, match, match_data);
+	if (!res) {
+		devres_add(dev, new_res);
+		res = new_res;
+		new_res = NULL;
+	}
+	devres_free(new_res);
+
+	return res;
+}
+
+void *devres_remove(struct udevice *dev, dr_release_t release,
+		    dr_match_t match, void *match_data)
+{
+	void *res;
+
+	res = devres_find(dev, release, match, match_data);
+	if (res) {
+		struct devres *dr = container_of(res, struct devres, data);
+
+		list_del_init(&dr->entry);
+		devres_log(dev, dr, "REM");
+	}
+
+	return res;
+}
+
+int devres_destroy(struct udevice *dev, dr_release_t release,
+		   dr_match_t match, void *match_data)
+{
+	void *res;
+
+	res = devres_remove(dev, release, match, match_data);
+	if (unlikely(!res))
+		return -ENOENT;
+
+	devres_free(res);
+	return 0;
+}
+
+int devres_release(struct udevice *dev, dr_release_t release,
+		   dr_match_t match, void *match_data)
+{
+	void *res;
+
+	res = devres_remove(dev, release, match, match_data);
+	if (unlikely(!res))
+		return -ENOENT;
+
+	(*release)(dev, res);
+	devres_free(res);
+	return 0;
+}
+
+static void release_nodes(struct udevice *dev, struct list_head *head,
+			  bool probe_only)
+{
+	struct devres *dr, *tmp;
+
+	list_for_each_entry_safe_reverse(dr, tmp, head, entry)  {
+		if (probe_only && !dr->probe)
+			break;
+		devres_log(dev, dr, "REL");
+		dr->release(dev, dr->data);
+		list_del(&dr->entry);
+		kfree(dr);
+	}
+}
+
+void devres_release_probe(struct udevice *dev)
+{
+	release_nodes(dev, &dev->devres_head, true);
+}
+
+void devres_release_all(struct udevice *dev)
+{
+	release_nodes(dev, &dev->devres_head, false);
+}
diff --git a/include/dm/device-internal.h b/include/dm/device-internal.h
index 402304f..ee3b00d 100644
--- a/include/dm/device-internal.h
+++ b/include/dm/device-internal.h
@@ -143,4 +143,23 @@ static inline void device_free(struct udevice *dev) {}
 #define DM_ROOT_NON_CONST		(((gd_t *)gd)->dm_root)
 #define DM_UCLASS_ROOT_NON_CONST	(((gd_t *)gd)->uclass_root)
 
+/* device resource management */
+/**
+ * devres_release_probe - Release managed resources allocated after probing
+ * @dev: Device to release resources for
+ *
+ * Release all resources allocated for @dev when it was probed or later.
+ * This function is called on driver removal.
+ */
+void devres_release_probe(struct udevice *dev);
+
+/**
+ * devres_release_all - Release all managed resources
+ * @dev: Device to release resources for
+ *
+ * Release all resources associated with @dev.  This function is
+ * called on driver unbinding.
+ */
+void devres_release_all(struct udevice *dev);
+
 #endif
diff --git a/include/dm/device.h b/include/dm/device.h
index 43004ac..b909b9a 100644
--- a/include/dm/device.h
+++ b/include/dm/device.h
@@ -96,6 +96,7 @@ struct udevice {
 	uint32_t flags;
 	int req_seq;
 	int seq;
+	struct list_head devres_head;
 };
 
 /* Maximum sequence number supported */
@@ -463,4 +464,143 @@ bool device_has_active_children(struct udevice *dev);
  */
 bool device_is_last_sibling(struct udevice *dev);
 
+/* device resource management */
+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_DEBUG_DEVRES
+void *__devres_alloc(dr_release_t release, size_t size, gfp_t gfp,
+		     const char *name);
+#define _devres_alloc(release, size, gfp) \
+	__devres_alloc(release, size, gfp, #release)
+#else
+void *_devres_alloc(dr_release_t release, size_t size, gfp_t gfp);
+#endif
+
+/**
+ * devres_alloc - Allocate device resource data
+ * @release: Release function devres will be associated with
+ * @size: Allocation size
+ * @gfp: Allocation flags
+ *
+ * Allocate devres of @size bytes.  The allocated area is associated
+ * with @release.  The returned pointer can be passed to
+ * other devres_*() functions.
+ *
+ * RETURNS:
+ * Pointer to allocated devres on success, NULL on failure.
+ */
+#define devres_alloc(release, size, gfp) \
+	_devres_alloc(release, size, gfp | __GFP_ZERO)
+
+/**
+ * devres_free - Free device resource data
+ * @res: Pointer to devres data to free
+ *
+ * Free devres created with devres_alloc().
+ */
+void devres_free(void *res);
+
+/**
+ * devres_add - Register device resource
+ * @dev: Device to add resource to
+ * @res: Resource to register
+ *
+ * Register devres @res to @dev.  @res should have been allocated
+ * using devres_alloc().  On driver detach, the associated release
+ * function will be invoked and devres will be freed automatically.
+ */
+void devres_add(struct udevice *dev, void *res);
+
+/**
+ * devres_find - Find device resource
+ * @dev: Device to lookup resource from
+ * @release: Look for resources associated with this release function
+ * @match: Match function (optional)
+ * @match_data: Data for the match function
+ *
+ * Find the latest devres of @dev which is associated with @release
+ * and for which @match returns 1.  If @match is NULL, it's considered
+ * to match all.
+ *
+ * RETURNS:
+ * Pointer to found devres, NULL if not found.
+ */
+void *devres_find(struct udevice *dev, dr_release_t release,
+		  dr_match_t match, void *match_data);
+
+/**
+ * devres_get - Find devres, if non-existent, add one atomically
+ * @dev: Device to lookup or add devres for
+ * @new_res: Pointer to new initialized devres to add if not found
+ * @match: Match function (optional)
+ * @match_data: Data for the match function
+ *
+ * Find the latest devres of @dev which has the same release function
+ * as @new_res and for which @match return 1.  If found, @new_res is
+ * freed; otherwise, @new_res is added atomically.
+ *
+ * RETURNS:
+ * Pointer to found or added devres.
+ */
+void *devres_get(struct udevice *dev, void *new_res,
+		 dr_match_t match, void *match_data);
+
+/**
+ * devres_remove - Find a device resource and remove it
+ * @dev: Device to find resource from
+ * @release: Look for resources associated with this release function
+ * @match: Match function (optional)
+ * @match_data: Data for the match function
+ *
+ * Find the latest devres of @dev associated with @release and for
+ * which @match returns 1.  If @match is NULL, it's considered to
+ * match all.  If found, the resource is removed atomically and
+ * returned.
+ *
+ * RETURNS:
+ * Pointer to removed devres on success, NULL if not found.
+ */
+void *devres_remove(struct udevice *dev, dr_release_t release,
+		    dr_match_t match, void *match_data);
+
+/**
+ * devres_destroy - Find a device resource and destroy it
+ * @dev: Device to find resource from
+ * @release: Look for resources associated with this release function
+ * @match: Match function (optional)
+ * @match_data: Data for the match function
+ *
+ * Find the latest devres of @dev associated with @release and for
+ * which @match returns 1.  If @match is NULL, it's considered to
+ * match all.  If found, the resource is removed atomically and freed.
+ *
+ * Note that the release function for the resource will not be called,
+ * only the devres-allocated data will be freed.  The caller becomes
+ * responsible for freeing any other data.
+ *
+ * RETURNS:
+ * 0 if devres is found and freed, -ENOENT if not found.
+ */
+int devres_destroy(struct udevice *dev, dr_release_t release,
+		   dr_match_t match, void *match_data);
+
+/**
+ * devres_release - Find a device resource and destroy it, calling release
+ * @dev: Device to find resource from
+ * @release: Look for resources associated with this release function
+ * @match: Match function (optional)
+ * @match_data: Data for the match function
+ *
+ * Find the latest devres of @dev associated with @release and for
+ * which @match returns 1.  If @match is NULL, it's considered to
+ * match all.  If found, the resource is removed atomically, the
+ * release function called and the resource freed.
+ *
+ * RETURNS:
+ * 0 if devres is found and freed, -ENOENT if not found.
+ */
+int devres_release(struct udevice *dev, dr_release_t release,
+		   dr_match_t match, void *match_data);
+
 #endif
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [U-Boot] [PATCH v4 3/5] devres: add devm_kmalloc() and friends (managed memory allocators)
  2015-07-25 12:52 [U-Boot] [PATCH v4 0/5] Devres (Managed Device Resource) for U-Boot Masahiro Yamada
  2015-07-25 12:52 ` [U-Boot] [PATCH v4 1/5] dm: add DM_FLAG_BOUND flag Masahiro Yamada
  2015-07-25 12:52 ` [U-Boot] [PATCH v4 2/5] devres: introduce Devres (Managed Device Resource) framework Masahiro Yamada
@ 2015-07-25 12:52 ` Masahiro Yamada
  2015-07-29  3:30   ` Simon Glass
  2015-07-25 12:52 ` [U-Boot] [PATCH v4 4/5] devres: make Devres optional with CONFIG_DEVRES Masahiro Yamada
  2015-07-25 12:52 ` [U-Boot] [PATCH v4 5/5] devres: add debug command to dump device resources Masahiro Yamada
  4 siblings, 1 reply; 13+ messages in thread
From: Masahiro Yamada @ 2015-07-25 12:52 UTC (permalink / raw)
  To: u-boot

devm_kmalloc() is identical to kmalloc() except that the memory
allocated with it is managed and will be automatically released
when the device is removed/unbound.

Likewise for the other variants.

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

Changes in v4: None
Changes in v3: None
Changes in v2:
  - Rip off "extern" from the func declarations
  - Add comments in headers
  - Add devm_kfree()
  - Do not force devm_kmalloc() zero-filling

 drivers/core/devres.c | 34 ++++++++++++++++++++++++++++++++++
 include/dm/device.h   | 44 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 78 insertions(+)

diff --git a/drivers/core/devres.c b/drivers/core/devres.c
index 49c270c..f235c1b 100644
--- a/drivers/core/devres.c
+++ b/drivers/core/devres.c
@@ -194,3 +194,37 @@ void devres_release_all(struct udevice *dev)
 {
 	release_nodes(dev, &dev->devres_head, false);
 }
+
+/*
+ * Managed kmalloc/kfree
+ */
+static void devm_kmalloc_release(struct udevice *dev, void *res)
+{
+	/* noop */
+}
+
+static int devm_kmalloc_match(struct udevice *dev, void *res, void *data)
+{
+	return res == data;
+}
+
+void *devm_kmalloc(struct udevice *dev, size_t size, gfp_t gfp)
+{
+	void *data;
+
+	data = _devres_alloc(devm_kmalloc_release, size, gfp);
+	if (unlikely(!data))
+		return NULL;
+
+	devres_add(dev, data);
+
+	return data;
+}
+
+void devm_kfree(struct udevice *dev, void *p)
+{
+	int rc;
+
+	rc = devres_destroy(dev, devm_kmalloc_release, devm_kmalloc_match, p);
+	WARN_ON(rc);
+}
diff --git a/include/dm/device.h b/include/dm/device.h
index b909b9a..7fddacd 100644
--- a/include/dm/device.h
+++ b/include/dm/device.h
@@ -14,6 +14,8 @@
 #include <dm/uclass-id.h>
 #include <fdtdec.h>
 #include <linker_lists.h>
+#include <linux/compat.h>
+#include <linux/kernel.h>
 #include <linux/list.h>
 
 struct driver_info;
@@ -603,4 +605,46 @@ int devres_destroy(struct udevice *dev, dr_release_t release,
 int devres_release(struct udevice *dev, dr_release_t release,
 		   dr_match_t match, void *match_data);
 
+/* managed devm_k.alloc/kfree for device drivers */
+/**
+ * devm_kmalloc - Resource-managed kmalloc
+ * @dev: Device to allocate memory for
+ * @size: Allocation size
+ * @gfp: Allocation gfp flags
+ *
+ * Managed kmalloc.  Memory allocated with this function is
+ * automatically freed on driver detach.  Like all other devres
+ * resources, guaranteed alignment is unsigned long long.
+ *
+ * RETURNS:
+ * Pointer to allocated memory on success, NULL on failure.
+ */
+void *devm_kmalloc(struct udevice *dev, size_t size, gfp_t gfp);
+static inline void *devm_kzalloc(struct udevice *dev, size_t size, gfp_t gfp)
+{
+	return devm_kmalloc(dev, size, gfp | __GFP_ZERO);
+}
+static inline void *devm_kmalloc_array(struct udevice *dev,
+				       size_t n, size_t size, gfp_t flags)
+{
+	if (size != 0 && n > SIZE_MAX / size)
+		return NULL;
+	return devm_kmalloc(dev, n * size, flags);
+}
+static inline void *devm_kcalloc(struct udevice *dev,
+				 size_t n, size_t size, gfp_t flags)
+{
+	return devm_kmalloc_array(dev, n, size, flags | __GFP_ZERO);
+}
+
+/**
+ * devm_kfree - Resource-managed kfree
+ * @dev: Device this memory belongs to
+ * @p: Memory to free
+ *
+ * Free memory allocated with devm_kmalloc().
+ */
+void devm_kfree(struct udevice *dev, void *p);
+
+
 #endif
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [U-Boot] [PATCH v4 4/5] devres: make Devres optional with CONFIG_DEVRES
  2015-07-25 12:52 [U-Boot] [PATCH v4 0/5] Devres (Managed Device Resource) for U-Boot Masahiro Yamada
                   ` (2 preceding siblings ...)
  2015-07-25 12:52 ` [U-Boot] [PATCH v4 3/5] devres: add devm_kmalloc() and friends (managed memory allocators) Masahiro Yamada
@ 2015-07-25 12:52 ` Masahiro Yamada
  2015-07-29  3:30   ` Simon Glass
  2015-07-25 12:52 ` [U-Boot] [PATCH v4 5/5] devres: add debug command to dump device resources Masahiro Yamada
  4 siblings, 1 reply; 13+ messages in thread
From: Masahiro Yamada @ 2015-07-25 12:52 UTC (permalink / raw)
  To: u-boot

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>
---

Changes in v4:
  - drop a comment that does not make sense

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

Changes in v2: None

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

diff --git a/drivers/core/Kconfig b/drivers/core/Kconfig
index 6889025..db2ec1c 100644
--- a/drivers/core/Kconfig
+++ b/drivers/core/Kconfig
@@ -60,9 +60,22 @@ 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 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
 	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..38e23f8 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,83 @@ static inline void *devm_kcalloc(struct udevice *dev,
  */
 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
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [U-Boot] [PATCH v4 5/5] devres: add debug command to dump device resources
  2015-07-25 12:52 [U-Boot] [PATCH v4 0/5] Devres (Managed Device Resource) for U-Boot Masahiro Yamada
                   ` (3 preceding siblings ...)
  2015-07-25 12:52 ` [U-Boot] [PATCH v4 4/5] devres: make Devres optional with CONFIG_DEVRES Masahiro Yamada
@ 2015-07-25 12:52 ` Masahiro Yamada
  2015-07-28 18:07   ` Simon Glass
  4 siblings, 1 reply; 13+ messages in thread
From: Masahiro Yamada @ 2015-07-25 12:52 UTC (permalink / raw)
  To: u-boot

This new command can dump all device resources associated to
each device.  The fields in every line shows:
  - The address of the resource
  - The size of the resource
  - The name of the release function
  - The stage in which the resource has been acquired (BIND/PROBE)

Currently, there is no driver using devres, but if such drivers are
implemented, the output of this command should look like this:

=> dm devres
- root_driver
- soc
- extbus
- serial at 54006800
    bfb541e8 (8 byte) devm_kmalloc_release  BIND
    bfb54440 (4 byte) devm_kmalloc_release  PROBE
    bfb54460 (4 byte) devm_kmalloc_release  PROBE
- serial at 54006900
    bfb54270 (8 byte) devm_kmalloc_release  BIND
- gpio at 55000000
- i2c at 58780000
    bfb5bce8 (12 byte) devm_kmalloc_release  PROBE
    bfb5bd10 (4 byte) devm_kmalloc_release  PROBE
- eeprom
    bfb54418 (12 byte) devm_kmalloc_release  BIND

Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
---

Changes in v4:
  - Drop "0x" from the devres address in the dump commend
  - Change the command name "devres" to "dm devres"
  - Update git-description.

Changes in v3: None
Changes in v2:
  - add static to dump_resources()

 drivers/core/Kconfig  |  3 ++-
 drivers/core/devres.c | 29 +++++++++++++++++++++++++++++
 include/dm/util.h     |  9 +++++++++
 test/dm/cmd_dm.c      | 12 +++++++++++-
 4 files changed, 51 insertions(+), 2 deletions(-)

diff --git a/drivers/core/Kconfig b/drivers/core/Kconfig
index db2ec1c..c153b3f 100644
--- a/drivers/core/Kconfig
+++ b/drivers/core/Kconfig
@@ -74,10 +74,11 @@ config DEVRES
 	  devm_kmalloc() to kmalloc(), etc.
 
 config DEBUG_DEVRES
-	bool "Managed device resources verbose debug messages"
+	bool "Managed device resources debugging functions"
 	depends on DEVRES
 	help
 	  If this option is enabled, devres debug messages are printed.
+	  Also, a function is available to dump a list of device resources.
 	  Select this if you are having a problem with devres or want to
 	  debug resource management for a managed device.
 
diff --git a/drivers/core/devres.c b/drivers/core/devres.c
index f235c1b..605295b 100644
--- a/drivers/core/devres.c
+++ b/drivers/core/devres.c
@@ -13,6 +13,8 @@
 #include <linux/kernel.h>
 #include <linux/list.h>
 #include <dm/device.h>
+#include <dm/root.h>
+#include <dm/util.h>
 
 /**
  * struct devres - Bookkeeping info for managed device resource
@@ -195,6 +197,33 @@ void devres_release_all(struct udevice *dev)
 	release_nodes(dev, &dev->devres_head, false);
 }
 
+#ifdef CONFIG_DEBUG_DEVRES
+static void dump_resources(struct udevice *dev, int depth)
+{
+	struct devres *dr;
+	struct udevice *child;
+
+	printf("- %s\n", dev->name);
+
+	list_for_each_entry(dr, &dev->devres_head, entry)
+		printf("    %p (%lu byte) %s  %s\n", dr,
+		       (unsigned long)dr->size, dr->name,
+		       dr->probe ? "PROBE" : "BIND");
+
+	list_for_each_entry(child, &dev->child_head, sibling_node)
+		dump_resources(child, depth + 1);
+}
+
+void dm_dump_devres(void)
+{
+	struct udevice *root;
+
+	root = dm_root();
+	if (root)
+		dump_resources(root, 0);
+}
+#endif
+
 /*
  * Managed kmalloc/kfree
  */
diff --git a/include/dm/util.h b/include/dm/util.h
index 7dbed67..15daa3d 100644
--- a/include/dm/util.h
+++ b/include/dm/util.h
@@ -39,4 +39,13 @@ void dm_dump_all(void);
 /* Dump out a list of uclasses and their devices */
 void dm_dump_uclass(void);
 
+#ifdef CONFIG_DEBUG_DEVRES
+/* Dump out a list of device resources */
+void dm_dump_devres(void);
+#else
+static inline void dm_dump_devres(void)
+{
+}
+#endif
+
 #endif
diff --git a/test/dm/cmd_dm.c b/test/dm/cmd_dm.c
index 5c501ec..caff49a 100644
--- a/test/dm/cmd_dm.c
+++ b/test/dm/cmd_dm.c
@@ -32,9 +32,18 @@ static int do_dm_dump_uclass(cmd_tbl_t *cmdtp, int flag, int argc,
 	return 0;
 }
 
+static int do_dm_dump_devres(cmd_tbl_t *cmdtp, int flag, int argc,
+			     char * const argv[])
+{
+	dm_dump_devres();
+
+	return 0;
+}
+
 static cmd_tbl_t test_commands[] = {
 	U_BOOT_CMD_MKENT(tree, 0, 1, do_dm_dump_all, "", ""),
 	U_BOOT_CMD_MKENT(uclass, 1, 1, do_dm_dump_uclass, "", ""),
+	U_BOOT_CMD_MKENT(devres, 1, 1, do_dm_dump_devres, "", ""),
 };
 
 static int do_dm(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
@@ -60,5 +69,6 @@ U_BOOT_CMD(
 	dm,	3,	1,	do_dm,
 	"Driver model low level access",
 	"tree         Dump driver model tree ('*' = activated)\n"
-	"dm uclass        Dump list of instances for each uclass"
+	"dm uclass        Dump list of instances for each uclass\n"
+	"dm devres        Dump list of device resources for each device"
 );
-- 
1.9.1

^ permalink raw reply related	[flat|nested] 13+ messages in thread

* [U-Boot] [PATCH v4 2/5] devres: introduce Devres (Managed Device Resource) framework
  2015-07-25 12:52 ` [U-Boot] [PATCH v4 2/5] devres: introduce Devres (Managed Device Resource) framework Masahiro Yamada
@ 2015-07-28 18:07   ` Simon Glass
  2015-07-29  3:30     ` Simon Glass
  0 siblings, 1 reply; 13+ messages in thread
From: Simon Glass @ 2015-07-28 18:07 UTC (permalink / raw)
  To: u-boot

On 25 July 2015 at 06:52, Masahiro Yamada <yamada.masahiro@socionext.com> wrote:
> In U-Boot's driver model, memory is basically allocated and freed
> in the core framework.  So, low level drivers generally only have
> to specify the size of needed memory with .priv_auto_alloc_size,
> .platdata_auto_alloc_size, etc.  Nevertheless, some drivers still
> need to allocate/free memory on their own in case they cannot
> statically know the necessary memory size.  So, I believe it is
> reasonable enough to port Devres into U-boot.
>
> Devres, which originates in Linux, manages device resources for each
> device and automatically releases them on driver detach.  With devres,
> device resources are guaranteed to be freed whether initialization
> fails half-way or the device gets detached.
>
> The basic idea is totally the same to that of Linux, but I tweaked
> it a bit so that it fits in U-Boot's driver model.
>
> In U-Boot, drivers are activated in two steps: binding and probing.
> Binding puts a driver and a device together.  It is just data
> manipulation on the system memory, so nothing has happened on the
> hardware device at this moment.  When the device is really used, it
> is probed.  Probing initializes the real hardware device to make it
> really ready for use.
>
> So, the resources acquired during the probing process must be freed
> when the device is removed.  Likewise, what has been allocated in
> binding should be released when the device is unbound.  The struct
> devres has a member "probe" to remember when the resource was
> allocated.
>
> CONFIG_DEBUG_DEVRES is also supported for easier debugging.
> If enabled, debug messages are printed each time a resource is
> allocated/freed.
>
> Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
> ---
>
> Changes in v4:
>   - Comment struct devres
>
> Changes in v3:
>   - Update git-description.  Do not mention about the DM core part.
>
> Changes in v2:
>   - Add more APIs: _free, _find, _get, _remove, _destroy, _release
>   - Move devres_release_probe() and devres_release_all() decrlarations
>     to dm/device-internal.h
>   - Move comments to headers
>
>  drivers/core/Kconfig         |  10 +++
>  drivers/core/Makefile        |   2 +-
>  drivers/core/device-remove.c |   5 ++
>  drivers/core/device.c        |   3 +
>  drivers/core/devres.c        | 196 +++++++++++++++++++++++++++++++++++++++++++
>  include/dm/device-internal.h |  19 +++++
>  include/dm/device.h          | 140 +++++++++++++++++++++++++++++++
>  7 files changed, 374 insertions(+), 1 deletion(-)

Acked-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [U-Boot] [PATCH v4 5/5] devres: add debug command to dump device resources
  2015-07-25 12:52 ` [U-Boot] [PATCH v4 5/5] devres: add debug command to dump device resources Masahiro Yamada
@ 2015-07-28 18:07   ` Simon Glass
  2015-07-29  3:30     ` Simon Glass
  0 siblings, 1 reply; 13+ messages in thread
From: Simon Glass @ 2015-07-28 18:07 UTC (permalink / raw)
  To: u-boot

On 25 July 2015 at 06:52, Masahiro Yamada <yamada.masahiro@socionext.com> wrote:
> This new command can dump all device resources associated to
> each device.  The fields in every line shows:
>   - The address of the resource
>   - The size of the resource
>   - The name of the release function
>   - The stage in which the resource has been acquired (BIND/PROBE)
>
> Currently, there is no driver using devres, but if such drivers are
> implemented, the output of this command should look like this:
>
> => dm devres
> - root_driver
> - soc
> - extbus
> - serial at 54006800
>     bfb541e8 (8 byte) devm_kmalloc_release  BIND
>     bfb54440 (4 byte) devm_kmalloc_release  PROBE
>     bfb54460 (4 byte) devm_kmalloc_release  PROBE
> - serial at 54006900
>     bfb54270 (8 byte) devm_kmalloc_release  BIND
> - gpio at 55000000
> - i2c at 58780000
>     bfb5bce8 (12 byte) devm_kmalloc_release  PROBE
>     bfb5bd10 (4 byte) devm_kmalloc_release  PROBE
> - eeprom
>     bfb54418 (12 byte) devm_kmalloc_release  BIND
>
> Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
> ---
>
> Changes in v4:
>   - Drop "0x" from the devres address in the dump commend
>   - Change the command name "devres" to "dm devres"
>   - Update git-description.
>
> Changes in v3: None
> Changes in v2:
>   - add static to dump_resources()
>
>  drivers/core/Kconfig  |  3 ++-
>  drivers/core/devres.c | 29 +++++++++++++++++++++++++++++
>  include/dm/util.h     |  9 +++++++++
>  test/dm/cmd_dm.c      | 12 +++++++++++-
>  4 files changed, 51 insertions(+), 2 deletions(-)

Acked-by: Simon Glass <sjg@chromium.org>

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [U-Boot] [PATCH v4 1/5] dm: add DM_FLAG_BOUND flag
  2015-07-25 12:52 ` [U-Boot] [PATCH v4 1/5] dm: add DM_FLAG_BOUND flag Masahiro Yamada
@ 2015-07-29  3:29   ` Simon Glass
  0 siblings, 0 replies; 13+ messages in thread
From: Simon Glass @ 2015-07-29  3:29 UTC (permalink / raw)
  To: u-boot

On 25 July 2015 at 06:52, Masahiro Yamada <yamada.masahiro@socionext.com> wrote:
> Currently, we only have DM_FLAG_ACTIVATED to indicate the device
> status, but we still cannot know in which stage is in progress,
> binding or probing.
>
> This commit introduces a new flag, DM_FLAG_BOUND, which is set when
> the device is really bound, and cleared when it is unbound.
>
> Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
> Acked-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v4: None
> Changes in v3: None
> Changes in v2: None
>
>  drivers/core/device-remove.c | 3 +++
>  drivers/core/device.c        | 2 ++
>  include/dm/device.h          | 3 +++
>  3 files changed, 8 insertions(+)

Applied to u-boot-dm, thanks!

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [U-Boot] [PATCH v4 2/5] devres: introduce Devres (Managed Device Resource) framework
  2015-07-28 18:07   ` Simon Glass
@ 2015-07-29  3:30     ` Simon Glass
  0 siblings, 0 replies; 13+ messages in thread
From: Simon Glass @ 2015-07-29  3:30 UTC (permalink / raw)
  To: u-boot

On 28 July 2015 at 12:07, Simon Glass <sjg@chromium.org> wrote:
> On 25 July 2015 at 06:52, Masahiro Yamada <yamada.masahiro@socionext.com> wrote:
>> In U-Boot's driver model, memory is basically allocated and freed
>> in the core framework.  So, low level drivers generally only have
>> to specify the size of needed memory with .priv_auto_alloc_size,
>> .platdata_auto_alloc_size, etc.  Nevertheless, some drivers still
>> need to allocate/free memory on their own in case they cannot
>> statically know the necessary memory size.  So, I believe it is
>> reasonable enough to port Devres into U-boot.
>>
>> Devres, which originates in Linux, manages device resources for each
>> device and automatically releases them on driver detach.  With devres,
>> device resources are guaranteed to be freed whether initialization
>> fails half-way or the device gets detached.
>>
>> The basic idea is totally the same to that of Linux, but I tweaked
>> it a bit so that it fits in U-Boot's driver model.
>>
>> In U-Boot, drivers are activated in two steps: binding and probing.
>> Binding puts a driver and a device together.  It is just data
>> manipulation on the system memory, so nothing has happened on the
>> hardware device at this moment.  When the device is really used, it
>> is probed.  Probing initializes the real hardware device to make it
>> really ready for use.
>>
>> So, the resources acquired during the probing process must be freed
>> when the device is removed.  Likewise, what has been allocated in
>> binding should be released when the device is unbound.  The struct
>> devres has a member "probe" to remember when the resource was
>> allocated.
>>
>> CONFIG_DEBUG_DEVRES is also supported for easier debugging.
>> If enabled, debug messages are printed each time a resource is
>> allocated/freed.
>>
>> Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
>> ---
>>
>> Changes in v4:
>>   - Comment struct devres
>>
>> Changes in v3:
>>   - Update git-description.  Do not mention about the DM core part.
>>
>> Changes in v2:
>>   - Add more APIs: _free, _find, _get, _remove, _destroy, _release
>>   - Move devres_release_probe() and devres_release_all() decrlarations
>>     to dm/device-internal.h
>>   - Move comments to headers
>>
>>  drivers/core/Kconfig         |  10 +++
>>  drivers/core/Makefile        |   2 +-
>>  drivers/core/device-remove.c |   5 ++
>>  drivers/core/device.c        |   3 +
>>  drivers/core/devres.c        | 196 +++++++++++++++++++++++++++++++++++++++++++
>>  include/dm/device-internal.h |  19 +++++
>>  include/dm/device.h          | 140 +++++++++++++++++++++++++++++++
>>  7 files changed, 374 insertions(+), 1 deletion(-)
>
> Acked-by: Simon Glass <sjg@chromium.org>

Applied to u-boot-dm, thanks!

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [U-Boot] [PATCH v4 3/5] devres: add devm_kmalloc() and friends (managed memory allocators)
  2015-07-25 12:52 ` [U-Boot] [PATCH v4 3/5] devres: add devm_kmalloc() and friends (managed memory allocators) Masahiro Yamada
@ 2015-07-29  3:30   ` Simon Glass
  0 siblings, 0 replies; 13+ messages in thread
From: Simon Glass @ 2015-07-29  3:30 UTC (permalink / raw)
  To: u-boot

On 25 July 2015 at 06:52, Masahiro Yamada <yamada.masahiro@socionext.com> wrote:
> devm_kmalloc() is identical to kmalloc() except that the memory
> allocated with it is managed and will be automatically released
> when the device is removed/unbound.
>
> Likewise for the other variants.
>
> Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
> Acked-by: Simon Glass <sjg@chromium.org>
> ---
>
> Changes in v4: None
> Changes in v3: None
> Changes in v2:
>   - Rip off "extern" from the func declarations
>   - Add comments in headers
>   - Add devm_kfree()
>   - Do not force devm_kmalloc() zero-filling
>
>  drivers/core/devres.c | 34 ++++++++++++++++++++++++++++++++++
>  include/dm/device.h   | 44 ++++++++++++++++++++++++++++++++++++++++++++
>  2 files changed, 78 insertions(+)

Applied to u-boot-dm, thanks!

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [U-Boot] [PATCH v4 4/5] devres: make Devres optional with CONFIG_DEVRES
  2015-07-25 12:52 ` [U-Boot] [PATCH v4 4/5] devres: make Devres optional with CONFIG_DEVRES Masahiro Yamada
@ 2015-07-29  3:30   ` Simon Glass
  0 siblings, 0 replies; 13+ messages in thread
From: Simon Glass @ 2015-07-29  3:30 UTC (permalink / raw)
  To: u-boot

On 25 July 2015 at 06:52, Masahiro Yamada <yamada.masahiro@socionext.com> wrote:
> 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>
> ---
>
> Changes in v4:
>   - drop a comment that does not make sense
>
> Changes in v3:
>   - Introduce CONFIG_DEVRES
>   - Surround devres_head member with ifdef CONFIG_DEVRES
>
> Changes in v2: None
>
>  drivers/core/Kconfig         | 15 +++++++-
>  drivers/core/Makefile        |  3 +-
>  drivers/core/device.c        |  2 ++
>  include/dm/device-internal.h | 13 +++++++
>  include/dm/device.h          | 82 ++++++++++++++++++++++++++++++++++++++++++++
>  5 files changed, 113 insertions(+), 2 deletions(-)

Applied to u-boot-dm, thanks!

^ permalink raw reply	[flat|nested] 13+ messages in thread

* [U-Boot] [PATCH v4 5/5] devres: add debug command to dump device resources
  2015-07-28 18:07   ` Simon Glass
@ 2015-07-29  3:30     ` Simon Glass
  0 siblings, 0 replies; 13+ messages in thread
From: Simon Glass @ 2015-07-29  3:30 UTC (permalink / raw)
  To: u-boot

On 28 July 2015 at 12:07, Simon Glass <sjg@chromium.org> wrote:
> On 25 July 2015 at 06:52, Masahiro Yamada <yamada.masahiro@socionext.com> wrote:
>> This new command can dump all device resources associated to
>> each device.  The fields in every line shows:
>>   - The address of the resource
>>   - The size of the resource
>>   - The name of the release function
>>   - The stage in which the resource has been acquired (BIND/PROBE)
>>
>> Currently, there is no driver using devres, but if such drivers are
>> implemented, the output of this command should look like this:
>>
>> => dm devres
>> - root_driver
>> - soc
>> - extbus
>> - serial at 54006800
>>     bfb541e8 (8 byte) devm_kmalloc_release  BIND
>>     bfb54440 (4 byte) devm_kmalloc_release  PROBE
>>     bfb54460 (4 byte) devm_kmalloc_release  PROBE
>> - serial at 54006900
>>     bfb54270 (8 byte) devm_kmalloc_release  BIND
>> - gpio at 55000000
>> - i2c at 58780000
>>     bfb5bce8 (12 byte) devm_kmalloc_release  PROBE
>>     bfb5bd10 (4 byte) devm_kmalloc_release  PROBE
>> - eeprom
>>     bfb54418 (12 byte) devm_kmalloc_release  BIND
>>
>> Signed-off-by: Masahiro Yamada <yamada.masahiro@socionext.com>
>> ---
>>
>> Changes in v4:
>>   - Drop "0x" from the devres address in the dump commend
>>   - Change the command name "devres" to "dm devres"
>>   - Update git-description.
>>
>> Changes in v3: None
>> Changes in v2:
>>   - add static to dump_resources()
>>
>>  drivers/core/Kconfig  |  3 ++-
>>  drivers/core/devres.c | 29 +++++++++++++++++++++++++++++
>>  include/dm/util.h     |  9 +++++++++
>>  test/dm/cmd_dm.c      | 12 +++++++++++-
>>  4 files changed, 51 insertions(+), 2 deletions(-)
>
> Acked-by: Simon Glass <sjg@chromium.org>

Applied to u-boot-dm, thanks!

^ permalink raw reply	[flat|nested] 13+ messages in thread

end of thread, other threads:[~2015-07-29  3:30 UTC | newest]

Thread overview: 13+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2015-07-25 12:52 [U-Boot] [PATCH v4 0/5] Devres (Managed Device Resource) for U-Boot Masahiro Yamada
2015-07-25 12:52 ` [U-Boot] [PATCH v4 1/5] dm: add DM_FLAG_BOUND flag Masahiro Yamada
2015-07-29  3:29   ` Simon Glass
2015-07-25 12:52 ` [U-Boot] [PATCH v4 2/5] devres: introduce Devres (Managed Device Resource) framework Masahiro Yamada
2015-07-28 18:07   ` Simon Glass
2015-07-29  3:30     ` Simon Glass
2015-07-25 12:52 ` [U-Boot] [PATCH v4 3/5] devres: add devm_kmalloc() and friends (managed memory allocators) Masahiro Yamada
2015-07-29  3:30   ` Simon Glass
2015-07-25 12:52 ` [U-Boot] [PATCH v4 4/5] devres: make Devres optional with CONFIG_DEVRES Masahiro Yamada
2015-07-29  3:30   ` Simon Glass
2015-07-25 12:52 ` [U-Boot] [PATCH v4 5/5] devres: add debug command to dump device resources Masahiro Yamada
2015-07-28 18:07   ` Simon Glass
2015-07-29  3:30     ` Simon Glass

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.