All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/6] OF: Fixes preparing transactions/overlays
@ 2014-06-22  9:40 Pantelis Antoniou
  2014-06-22  9:40 ` [PATCH 1/6] of: Do not free memory at of_node_release Pantelis Antoniou
                   ` (5 more replies)
  0 siblings, 6 replies; 63+ messages in thread
From: Pantelis Antoniou @ 2014-06-22  9:40 UTC (permalink / raw)
  To: Grant Likely
  Cc: Rob Herring, Stephen Warren, Matt Porter, Koen Kooi,
	Greg Kroah-Hartman, Alison Chaiken, Dinh Nguyen, Jan Lubbe,
	Alexander Sverdlin, Michael Stickel, Guenter Roeck, Dirk Behme,
	Alan Tull, Sascha Hauer, Michael Bohan, Ionut Nicu, Michal Simek,
	Matt Ranostay, Joel Becker, devicetree, Wolfram Sang, linux-i2c,
	Mark Brown, linux-spi, linux-kernel, Pete Popov, Dan Malek,
	Georgi Vlaev, Pantelis Antoniou, Pantelis Antoniou

This patchset series fixes general issues that have to do
with preparing for the introduction of transactions and overlays.

Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>

Pantelis Antoniou (6):
  of: Do not free memory at of_node_release
  OF: Add [__]of_find_node_by_full_name
  of: platform: Fix and export of_platform_device_destroy
  OF: Export a number of __of_* methods
  OF: Utility helper functions for dynamic nodes
  of: Introduce tree change __foo_post methods.

 drivers/of/Makefile         |   2 +-
 drivers/of/base.c           | 363 +++++++++++++++++++++++++++++---------------
 drivers/of/platform.c       |  11 +-
 drivers/of/util.c           | 141 +++++++++++++++++
 include/linux/of.h          |  87 +++++++++++
 include/linux/of_platform.h |   2 +
 6 files changed, 485 insertions(+), 121 deletions(-)
 create mode 100644 drivers/of/util.c

-- 
1.7.12

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

* [PATCH 1/6] of: Do not free memory at of_node_release
  2014-06-22  9:40 [PATCH 0/6] OF: Fixes preparing transactions/overlays Pantelis Antoniou
@ 2014-06-22  9:40 ` Pantelis Antoniou
  2014-06-24 14:10   ` Grant Likely
  2014-06-22  9:40 ` [PATCH 2/6] OF: Add [__]of_find_node_by_full_name Pantelis Antoniou
                   ` (4 subsequent siblings)
  5 siblings, 1 reply; 63+ messages in thread
From: Pantelis Antoniou @ 2014-06-22  9:40 UTC (permalink / raw)
  To: Grant Likely
  Cc: Rob Herring, Stephen Warren, Matt Porter, Koen Kooi,
	Greg Kroah-Hartman, Alison Chaiken, Dinh Nguyen, Jan Lubbe,
	Alexander Sverdlin, Michael Stickel, Guenter Roeck, Dirk Behme,
	Alan Tull, Sascha Hauer, Michael Bohan, Ionut Nicu, Michal Simek,
	Matt Ranostay, Joel Becker, devicetree, Wolfram Sang, linux-i2c,
	Mark Brown, linux-spi, linux-kernel, Pete Popov, Dan Malek,
	Georgi Vlaev, Pantelis Antoniou, Pantelis Antoniou

The life-cycle of nodes and properties does not allow us to release
the memory taken by a device_node. Pointer to properties and nodes
might still be in use in drivers, so any memory free'ing is dangerous.

Simply move all the properties to the deadprops list, and the node
itself to of_alldeadnodes until the life-cycles issues are resolved.

Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
---
 drivers/of/base.c | 43 ++++++++++++++++++++++++++++---------------
 1 file changed, 28 insertions(+), 15 deletions(-)

diff --git a/drivers/of/base.c b/drivers/of/base.c
index b986480..d3493e1 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -110,17 +110,27 @@ static inline struct device_node *kobj_to_device_node(struct kobject *kobj)
 	return container_of(kobj, struct device_node, kobj);
 }
 
+static struct device_node *of_alldeadnodes;
+static DEFINE_RAW_SPINLOCK(deadtree_lock);
+
 /**
  *	of_node_release - release a dynamically allocated node
  *	@kref:  kref element of the node to be released
  *
  *	In of_node_put() this function is passed to kref_put()
  *	as the destructor.
+ *
+ *	Note that due to the way that node and property life-cycles
+ *	are not completely managed, we can't free the memory of
+ *	a node at will. Instead we move the node to the dead nodes
+ *	list where it will remain until the life-cycle issues are
+ *	resolved.
  */
 static void of_node_release(struct kobject *kobj)
 {
 	struct device_node *node = kobj_to_device_node(kobj);
-	struct property *prop = node->properties;
+	struct property *prop;
+	unsigned long flags;
 
 	/* We should never be releasing nodes that haven't been detached. */
 	if (!of_node_check_flag(node, OF_DETACHED)) {
@@ -129,24 +139,27 @@ static void of_node_release(struct kobject *kobj)
 		return;
 	}
 
-	if (!of_node_check_flag(node, OF_DYNAMIC))
+	pr_info("%s: dead node \"%s\"\n", __func__, node->full_name);
+
+	/* we should not be trying to release the root */
+	if (WARN_ON(node == of_allnodes))
 		return;
 
-	while (prop) {
-		struct property *next = prop->next;
-		kfree(prop->name);
-		kfree(prop->value);
-		kfree(prop);
-		prop = next;
+	/* can't use devtree lock; at of_node_put caller might be holding it */
+	raw_spin_lock_irqsave(&deadtree_lock, flags);
 
-		if (!prop) {
-			prop = node->deadprops;
-			node->deadprops = NULL;
-		}
+	/* move all properties to dead properties */
+	while ((prop = node->properties) != NULL) {
+		node->properties = prop->next;
+		prop->next = node->deadprops;
+		node->deadprops = prop;
 	}
-	kfree(node->full_name);
-	kfree(node->data);
-	kfree(node);
+
+	/* move node to alldeadnodes */
+	node->allnext = of_alldeadnodes;
+	of_alldeadnodes = node;
+
+	raw_spin_unlock_irqrestore(&deadtree_lock, flags);
 }
 
 /**
-- 
1.7.12

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

* [PATCH 2/6] OF: Add [__]of_find_node_by_full_name
  2014-06-22  9:40 [PATCH 0/6] OF: Fixes preparing transactions/overlays Pantelis Antoniou
  2014-06-22  9:40 ` [PATCH 1/6] of: Do not free memory at of_node_release Pantelis Antoniou
@ 2014-06-22  9:40 ` Pantelis Antoniou
  2014-06-23 17:58   ` Guenter Roeck
  2014-06-24 14:12   ` Grant Likely
  2014-06-22  9:40 ` [PATCH 3/6] of: platform: Fix and export of_platform_device_destroy Pantelis Antoniou
                   ` (3 subsequent siblings)
  5 siblings, 2 replies; 63+ messages in thread
From: Pantelis Antoniou @ 2014-06-22  9:40 UTC (permalink / raw)
  To: Grant Likely
  Cc: Rob Herring, Stephen Warren, Matt Porter, Koen Kooi,
	Greg Kroah-Hartman, Alison Chaiken, Dinh Nguyen, Jan Lubbe,
	Alexander Sverdlin, Michael Stickel, Guenter Roeck, Dirk Behme,
	Alan Tull, Sascha Hauer, Michael Bohan, Ionut Nicu, Michal Simek,
	Matt Ranostay, Joel Becker, devicetree, Wolfram Sang, linux-i2c,
	Mark Brown, linux-spi, linux-kernel, Pete Popov, Dan Malek,
	Georgi Vlaev, Pantelis Antoniou, Pantelis Antoniou

__of_find_node_by_full_name recursively searches for a matching node
with the given full name without taking any locks.

of_find_node_by_full_name takes locks and takes a reference on the
matching node.

Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
---
 drivers/of/base.c  | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/of.h |  4 ++++
 2 files changed, 62 insertions(+)

diff --git a/drivers/of/base.c b/drivers/of/base.c
index d3493e1..80fef33 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -1201,6 +1201,64 @@ static void *of_find_property_value_of_size(const struct device_node *np,
 }
 
 /**
+ * __of_find_node_by_full_name - Find a node with the full name recursively
+ * @node:	Root of the tree to perform the search
+ * @full_name:	Full name of the node to find.
+ *
+ * Find a node with the give full name by recursively following any of
+ * the child node links.
+ * Returns the matching node, or NULL if not found.
+ * Note that the devtree lock is not taken, so this function is only
+ * safe to call on either detached trees, or when devtree lock is already
+ * taken.
+ */
+struct device_node *__of_find_node_by_full_name(struct device_node *node,
+		const char *full_name)
+{
+	struct device_node *child, *found;
+
+	if (node == NULL)
+		return NULL;
+
+	/* check */
+	if (of_node_cmp(node->full_name, full_name) == 0)
+		return node;
+
+	__for_each_child_of_node(node, child) {
+		found = __of_find_node_by_full_name(child, full_name);
+		if (found != NULL)
+			return found;
+	}
+
+	return NULL;
+}
+EXPORT_SYMBOL(__of_find_node_by_full_name);
+
+/**
+ * of_find_node_by_full_name - Find a node with the full name recursively
+ * @node:	Root of the tree to perform the search
+ * @full_name:	Full name of the node to find.
+ *
+ * Find a node with the give full name by recursively following any of
+ * the child node links.
+ * Returns the matching node (with a ref taken), or NULL if not found.
+ */
+struct device_node *of_find_node_by_full_name(struct device_node *node,
+		const char *full_name)
+{
+	unsigned long flags;
+	struct device_node *np;
+
+	raw_spin_lock_irqsave(&devtree_lock, flags);
+	np = of_find_node_by_full_name(node, full_name);
+	of_node_get(np);
+	raw_spin_unlock_irqrestore(&devtree_lock, flags);
+
+	return np;
+}
+EXPORT_SYMBOL(of_find_node_by_full_name);
+
+/**
  * of_property_read_u32_index - Find and read a u32 from a multi-value property.
  *
  * @np:		device node from which the property value is to be read.
diff --git a/include/linux/of.h b/include/linux/of.h
index 196b34c..f7392c0 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -230,6 +230,10 @@ extern struct device_node *of_find_matching_node_and_match(
 
 extern struct device_node *of_find_node_by_path(const char *path);
 extern struct device_node *of_find_node_by_phandle(phandle handle);
+struct device_node *__of_find_node_by_full_name(struct device_node *node,
+						const char *full_name);
+struct device_node *of_find_node_by_full_name(struct device_node *node,
+						const char *full_name);
 extern struct device_node *of_get_parent(const struct device_node *node);
 extern struct device_node *of_get_next_parent(struct device_node *node);
 extern struct device_node *of_get_next_child(const struct device_node *node,
-- 
1.7.12

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

* [PATCH 3/6] of: platform: Fix and export of_platform_device_destroy
  2014-06-22  9:40 [PATCH 0/6] OF: Fixes preparing transactions/overlays Pantelis Antoniou
  2014-06-22  9:40 ` [PATCH 1/6] of: Do not free memory at of_node_release Pantelis Antoniou
  2014-06-22  9:40 ` [PATCH 2/6] OF: Add [__]of_find_node_by_full_name Pantelis Antoniou
@ 2014-06-22  9:40 ` Pantelis Antoniou
  2014-06-24 14:23   ` Grant Likely
  2014-06-24 15:13   ` Grant Likely
  2014-06-22  9:40 ` [PATCH 4/6] OF: Export a number of __of_* methods Pantelis Antoniou
                   ` (2 subsequent siblings)
  5 siblings, 2 replies; 63+ messages in thread
From: Pantelis Antoniou @ 2014-06-22  9:40 UTC (permalink / raw)
  To: Grant Likely
  Cc: Rob Herring, Stephen Warren, Matt Porter, Koen Kooi,
	Greg Kroah-Hartman, Alison Chaiken, Dinh Nguyen, Jan Lubbe,
	Alexander Sverdlin, Michael Stickel, Guenter Roeck, Dirk Behme,
	Alan Tull, Sascha Hauer, Michael Bohan, Ionut Nicu, Michal Simek,
	Matt Ranostay, Joel Becker, devicetree, Wolfram Sang, linux-i2c,
	Mark Brown, linux-spi, linux-kernel, Pete Popov, Dan Malek,
	Georgi Vlaev, Pantelis Antoniou, Pantelis Antoniou

of_platform_destroy did not work properly, since the tree
population test was iterating on all devices having a parent
a given platform device.

The check was intended to check whether any other *platform*
devices were still populated, but instead checked for every
kind of device. This is wrong, since platform devices typically
create a subsystem regular device and set themselves as parents.

Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
---
 drivers/of/platform.c       | 11 ++++++++++-
 include/linux/of_platform.h |  2 ++
 2 files changed, 12 insertions(+), 1 deletion(-)

diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index 500436f..4f60060 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -506,10 +506,18 @@ int of_platform_populate(struct device_node *root,
 }
 EXPORT_SYMBOL_GPL(of_platform_populate);
 
-static int of_platform_device_destroy(struct device *dev, void *data)
+int of_platform_device_destroy(struct device *dev, void *data)
 {
 	bool *children_left = data;
 
+	/* if the device is not a platform device, do nothing */
+	if (dev->bus != &platform_bus_type
+#ifdef CONFIG_ARM_AMBA
+		&& dev->bus != &amba_bustype
+#endif
+	   )
+		return 0;
+
 	/* Do not touch devices not populated from the device tree */
 	if (!dev->of_node || !of_node_check_flag(dev->of_node, OF_POPULATED)) {
 		*children_left = true;
@@ -537,6 +545,7 @@ static int of_platform_device_destroy(struct device *dev, void *data)
 
 	return 0;
 }
+EXPORT_SYMBOL_GPL(of_platform_device_destroy);
 
 /**
  * of_platform_depopulate() - Remove devices populated from device tree
diff --git a/include/linux/of_platform.h b/include/linux/of_platform.h
index d96e1ba..61c7e8c 100644
--- a/include/linux/of_platform.h
+++ b/include/linux/of_platform.h
@@ -64,6 +64,8 @@ extern struct platform_device *of_platform_device_create(struct device_node *np,
 						   const char *bus_id,
 						   struct device *parent);
 
+extern int of_platform_device_destroy(struct device *dev, void *data);
+
 extern int of_platform_bus_probe(struct device_node *root,
 				 const struct of_device_id *matches,
 				 struct device *parent);
-- 
1.7.12

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

* [PATCH 4/6] OF: Export a number of __of_* methods
  2014-06-22  9:40 [PATCH 0/6] OF: Fixes preparing transactions/overlays Pantelis Antoniou
                   ` (2 preceding siblings ...)
  2014-06-22  9:40 ` [PATCH 3/6] of: platform: Fix and export of_platform_device_destroy Pantelis Antoniou
@ 2014-06-22  9:40 ` Pantelis Antoniou
  2014-06-24 19:27   ` Grant Likely
  2014-06-22  9:40 ` [PATCH 5/6] OF: Utility helper functions for dynamic nodes Pantelis Antoniou
  2014-06-22  9:40 ` [PATCH 6/6] of: Introduce tree change __foo_post methods Pantelis Antoniou
  5 siblings, 1 reply; 63+ messages in thread
From: Pantelis Antoniou @ 2014-06-22  9:40 UTC (permalink / raw)
  To: Grant Likely
  Cc: Rob Herring, Stephen Warren, Matt Porter, Koen Kooi,
	Greg Kroah-Hartman, Alison Chaiken, Dinh Nguyen, Jan Lubbe,
	Alexander Sverdlin, Michael Stickel, Guenter Roeck, Dirk Behme,
	Alan Tull, Sascha Hauer, Michael Bohan, Ionut Nicu, Michal Simek,
	Matt Ranostay, Joel Becker, devicetree, Wolfram Sang, linux-i2c,
	Mark Brown, linux-spi, linux-kernel, Pete Popov, Dan Malek,
	Georgi Vlaev, Pantelis Antoniou, Pantelis Antoniou

As part of moving to transactional DT, a number of methods are
reworked and exported.

The methods exported are:

__of_get_next_child, __for_each_child_of_node, __of_add_property,
__of_remove_property, __of_update_property, __of_attach_node,
__of_detach_node, __of_device_is_compatible, __of_device_is_available,
__of_get_property.

__of_update_property has been reworked to be more efficient
(double walk of the property list eliminated)
of_get_property was reworked to use __of_get_property internally.

Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
---
 drivers/of/base.c  | 192 +++++++++++++++++++++++++++++------------------------
 include/linux/of.h |  34 ++++++++++
 2 files changed, 139 insertions(+), 87 deletions(-)

diff --git a/drivers/of/base.c b/drivers/of/base.c
index 80fef33..42c735d 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -382,7 +382,7 @@ EXPORT_SYMBOL(of_find_all_nodes);
  * Find a property with a given name for a given node
  * and return the value.
  */
-static const void *__of_get_property(const struct device_node *np,
+const void *__of_get_property(const struct device_node *np,
 				     const char *name, int *lenp)
 {
 	struct property *pp = __of_find_property(np, name, lenp);
@@ -397,9 +397,13 @@ static const void *__of_get_property(const struct device_node *np,
 const void *of_get_property(const struct device_node *np, const char *name,
 			    int *lenp)
 {
-	struct property *pp = of_find_property(np, name, lenp);
+	unsigned long flags;
+	const void *value;
 
-	return pp ? pp->value : NULL;
+	raw_spin_lock_irqsave(&devtree_lock, flags);
+	value = __of_get_property(np, name, lenp);
+	raw_spin_unlock_irqrestore(&devtree_lock, flags);
+	return value;
 }
 EXPORT_SYMBOL(of_get_property);
 
@@ -536,7 +540,7 @@ EXPORT_SYMBOL(of_get_cpu_node);
  * 10. type
  * 11. name
  */
-static int __of_device_is_compatible(const struct device_node *device,
+int __of_device_is_compatible(const struct device_node *device,
 				     const char *compat, const char *type, const char *name)
 {
 	struct property *prop;
@@ -619,7 +623,7 @@ EXPORT_SYMBOL(of_machine_is_compatible);
  *  Returns 1 if the status property is absent or set to "okay" or "ok",
  *  0 otherwise
  */
-static int __of_device_is_available(const struct device_node *device)
+int __of_device_is_available(const struct device_node *device)
 {
 	const char *status;
 	int statlen;
@@ -709,7 +713,7 @@ struct device_node *of_get_next_parent(struct device_node *node)
 }
 EXPORT_SYMBOL(of_get_next_parent);
 
-static struct device_node *__of_get_next_child(const struct device_node *node,
+struct device_node *__of_get_next_child(const struct device_node *node,
 						struct device_node *prev)
 {
 	struct device_node *next;
@@ -724,9 +728,7 @@ static struct device_node *__of_get_next_child(const struct device_node *node,
 	of_node_put(prev);
 	return next;
 }
-#define __for_each_child_of_node(parent, child) \
-	for (child = __of_get_next_child(parent, NULL); child != NULL; \
-	     child = __of_get_next_child(parent, child))
+EXPORT_SYMBOL(__of_get_next_child);
 
 /**
  *	of_get_next_child - Iterate a node childs
@@ -1820,7 +1822,7 @@ int of_count_phandle_with_args(const struct device_node *np, const char *list_na
 EXPORT_SYMBOL(of_count_phandle_with_args);
 
 #if defined(CONFIG_OF_DYNAMIC)
-static int of_property_notify(int action, struct device_node *np,
+int of_property_notify(int action, struct device_node *np,
 			      struct property *prop)
 {
 	struct of_prop_reconfig pr;
@@ -1833,18 +1835,12 @@ static int of_property_notify(int action, struct device_node *np,
 	pr.prop = prop;
 	return of_reconfig_notify(action, &pr);
 }
-#else
-static int of_property_notify(int action, struct device_node *np,
-			      struct property *prop)
-{
-	return 0;
-}
 #endif
 
 /**
  * __of_add_property - Add a property to a node without lock operations
  */
-static int __of_add_property(struct device_node *np, struct property *prop)
+int __of_add_property(struct device_node *np, struct property *prop)
 {
 	struct property **next;
 
@@ -1886,6 +1882,25 @@ int of_add_property(struct device_node *np, struct property *prop)
 	return rc;
 }
 
+int __of_remove_property(struct device_node *np, struct property *prop)
+{
+	struct property **next;
+
+	for (next = &np->properties; *next; next = &(*next)->next) {
+		if (*next == prop)
+			break;
+	}
+	if (*next == NULL)
+		return -ENODEV;
+
+	/* found the node */
+	*next = prop->next;
+	prop->next = np->deadprops;
+	np->deadprops = prop;
+
+	return 0;
+}
+
 /**
  * of_remove_property - Remove a property from a node.
  *
@@ -1896,9 +1911,7 @@ int of_add_property(struct device_node *np, struct property *prop)
  */
 int of_remove_property(struct device_node *np, struct property *prop)
 {
-	struct property **next;
 	unsigned long flags;
-	int found = 0;
 	int rc;
 
 	rc = of_property_notify(OF_RECONFIG_REMOVE_PROPERTY, np, prop);
@@ -1906,22 +1919,11 @@ int of_remove_property(struct device_node *np, struct property *prop)
 		return rc;
 
 	raw_spin_lock_irqsave(&devtree_lock, flags);
-	next = &np->properties;
-	while (*next) {
-		if (*next == prop) {
-			/* found the node */
-			*next = prop->next;
-			prop->next = np->deadprops;
-			np->deadprops = prop;
-			found = 1;
-			break;
-		}
-		next = &(*next)->next;
-	}
+	rc = __of_remove_property(np, prop);
 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
 
-	if (!found)
-		return -ENODEV;
+	if (rc)
+		return rc;
 
 	/* at early boot, bail hear and defer setup to of_init() */
 	if (!of_kset)
@@ -1932,6 +1934,32 @@ int of_remove_property(struct device_node *np, struct property *prop)
 	return 0;
 }
 
+int __of_update_property(struct device_node *np, struct property *newprop,
+		struct property **oldpropp)
+{
+	struct property **next, *oldprop;
+
+	for (next = &np->properties; *next; next = &(*next)->next) {
+		if (of_prop_cmp((*next)->name, newprop->name) == 0)
+			break;
+	}
+	*oldpropp = oldprop = *next;
+
+	if (oldprop) {
+		/* replace the node */
+		newprop->next = oldprop->next;
+		*next = newprop;
+		oldprop->next = np->deadprops;
+		np->deadprops = oldprop;
+	} else {
+		/* new node */
+		newprop->next = NULL;
+		*next = newprop;
+	}
+
+	return 0;
+}
+
 /*
  * of_update_property - Update a property in a node, if the property does
  * not exist, add it.
@@ -1941,36 +1969,21 @@ int of_remove_property(struct device_node *np, struct property *prop)
  * Instead we just move the property to the "dead properties" list,
  * and add the new property to the property list
  */
-int of_update_property(struct device_node *np, struct property *newprop)
+int of_update_property(struct device_node *np, struct property *prop)
 {
-	struct property **next, *oldprop;
+	struct property *oldprop;
 	unsigned long flags;
 	int rc;
 
-	rc = of_property_notify(OF_RECONFIG_UPDATE_PROPERTY, np, newprop);
+	if (!prop->name)
+		return -EINVAL;
+
+	rc = of_property_notify(OF_RECONFIG_UPDATE_PROPERTY, np, prop);
 	if (rc)
 		return rc;
 
-	if (!newprop->name)
-		return -EINVAL;
-
 	raw_spin_lock_irqsave(&devtree_lock, flags);
-	next = &np->properties;
-	oldprop = __of_find_property(np, newprop->name, NULL);
-	if (!oldprop) {
-		/* add the new node */
-		rc = __of_add_property(np, newprop);
-	} else while (*next) {
-		/* replace the node */
-		if (*next == oldprop) {
-			newprop->next = oldprop->next;
-			*next = newprop;
-			oldprop->next = np->deadprops;
-			np->deadprops = oldprop;
-			break;
-		}
-		next = &(*next)->next;
-	}
+	rc = __of_update_property(np, prop, &oldprop);
 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
 	if (rc)
 		return rc;
@@ -1982,7 +1995,7 @@ int of_update_property(struct device_node *np, struct property *newprop)
 	/* Update the sysfs attribute */
 	if (oldprop)
 		sysfs_remove_bin_file(&np->kobj, &oldprop->attr);
-	__of_add_property_sysfs(np, newprop);
+	__of_add_property_sysfs(np, prop);
 
 	return 0;
 }
@@ -2018,6 +2031,15 @@ int of_reconfig_notify(unsigned long action, void *p)
 	return notifier_to_errno(rc);
 }
 
+void __of_attach_node(struct device_node *np)
+{
+	np->sibling = np->parent->child;
+	np->allnext = np->parent->allnext;
+	np->parent->allnext = np;
+	np->parent->child = np;
+	of_node_clear_flag(np, OF_DETACHED);
+}
+
 /**
  * of_attach_node - Plug a device node into the tree and global list.
  */
@@ -2031,51 +2053,29 @@ int of_attach_node(struct device_node *np)
 		return rc;
 
 	raw_spin_lock_irqsave(&devtree_lock, flags);
-	np->sibling = np->parent->child;
-	np->allnext = np->parent->allnext;
-	np->parent->allnext = np;
-	np->parent->child = np;
-	of_node_clear_flag(np, OF_DETACHED);
+	__of_attach_node(np);
 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
 
 	of_node_add(np);
 	return 0;
 }
 
-/**
- * of_detach_node - "Unplug" a node from the device tree.
- *
- * The caller must hold a reference to the node.  The memory associated with
- * the node is not freed until its refcount goes to zero.
- */
-int of_detach_node(struct device_node *np)
+void __of_detach_node(struct device_node *np)
 {
 	struct device_node *parent;
-	unsigned long flags;
-	int rc = 0;
-
-	rc = of_reconfig_notify(OF_RECONFIG_DETACH_NODE, np);
-	if (rc)
-		return rc;
+	struct device_node *prev;
+	struct device_node *prevsib;
 
-	raw_spin_lock_irqsave(&devtree_lock, flags);
-
-	if (of_node_check_flag(np, OF_DETACHED)) {
-		/* someone already detached it */
-		raw_spin_unlock_irqrestore(&devtree_lock, flags);
-		return rc;
-	}
+	if (WARN_ON(of_node_check_flag(np, OF_DETACHED)))
+		return;
 
 	parent = np->parent;
-	if (!parent) {
-		raw_spin_unlock_irqrestore(&devtree_lock, flags);
-		return rc;
-	}
+	if (WARN_ON(!parent))
+		return;
 
 	if (of_allnodes == np)
 		of_allnodes = np->allnext;
 	else {
-		struct device_node *prev;
 		for (prev = of_allnodes;
 		     prev->allnext != np;
 		     prev = prev->allnext)
@@ -2086,7 +2086,6 @@ int of_detach_node(struct device_node *np)
 	if (parent->child == np)
 		parent->child = np->sibling;
 	else {
-		struct device_node *prevsib;
 		for (prevsib = np->parent->child;
 		     prevsib->sibling != np;
 		     prevsib = prevsib->sibling)
@@ -2095,6 +2094,25 @@ int of_detach_node(struct device_node *np)
 	}
 
 	of_node_set_flag(np, OF_DETACHED);
+}
+
+/**
+ * of_detach_node - "Unplug" a node from the device tree.
+ *
+ * The caller must hold a reference to the node.  The memory associated with
+ * the node is not freed until its refcount goes to zero.
+ */
+int of_detach_node(struct device_node *np)
+{
+	unsigned long flags;
+	int rc = 0;
+
+	rc = of_reconfig_notify(OF_RECONFIG_DETACH_NODE, np);
+	if (rc)
+		return rc;
+
+	raw_spin_lock_irqsave(&devtree_lock, flags);
+	__of_detach_node(np);
 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
 
 	of_node_remove(np);
diff --git a/include/linux/of.h b/include/linux/of.h
index f7392c0..5e4e1b3 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -98,6 +98,8 @@ static inline int of_node_is_attached(struct device_node *node)
 #ifdef CONFIG_OF_DYNAMIC
 extern struct device_node *of_node_get(struct device_node *node);
 extern void of_node_put(struct device_node *node);
+extern int of_property_notify(int action, struct device_node *np,
+			      struct property *prop);
 #else /* CONFIG_OF_DYNAMIC */
 /* Dummy ref counting routines - to be implemented later */
 static inline struct device_node *of_node_get(struct device_node *node)
@@ -105,6 +107,11 @@ static inline struct device_node *of_node_get(struct device_node *node)
 	return node;
 }
 static inline void of_node_put(struct device_node *node) { }
+static inline int of_property_notify(int action, struct device_node *np,
+			      struct property *prop)
+{
+	return 0;
+}
 #endif /* !CONFIG_OF_DYNAMIC */
 
 #ifdef CONFIG_OF
@@ -238,6 +245,8 @@ extern struct device_node *of_get_parent(const struct device_node *node);
 extern struct device_node *of_get_next_parent(struct device_node *node);
 extern struct device_node *of_get_next_child(const struct device_node *node,
 					     struct device_node *prev);
+struct device_node *__of_get_next_child(const struct device_node *node,
+						struct device_node *prev);
 extern struct device_node *of_get_next_available_child(
 	const struct device_node *node, struct device_node *prev);
 
@@ -279,9 +288,17 @@ extern int of_property_match_string(struct device_node *np,
 				    const char *string);
 extern int of_property_count_strings(struct device_node *np,
 				     const char *propname);
+int __of_device_is_compatible(const struct device_node *device,
+				     const char *compat, const char *type,
+				     const char *name);
 extern int of_device_is_compatible(const struct device_node *device,
 				   const char *);
+extern int __of_device_is_available(const struct device_node *device);
 extern int of_device_is_available(const struct device_node *device);
+
+extern const void *__of_get_property(const struct device_node *node,
+				const char *name,
+				int *lenp);
 extern const void *of_get_property(const struct device_node *node,
 				const char *name,
 				int *lenp);
@@ -312,6 +329,11 @@ extern int of_alias_get_id(struct device_node *np, const char *stem);
 
 extern int of_machine_is_compatible(const char *compat);
 
+int __of_add_property(struct device_node *np, struct property *prop);
+int __of_remove_property(struct device_node *np, struct property *prop);
+int __of_update_property(struct device_node *np, struct property *newprop,
+		struct property **oldprop);
+
 extern int of_add_property(struct device_node *np, struct property *prop);
 extern int of_remove_property(struct device_node *np, struct property *prop);
 extern int of_update_property(struct device_node *np, struct property *newprop);
@@ -332,6 +354,9 @@ extern int of_reconfig_notifier_register(struct notifier_block *);
 extern int of_reconfig_notifier_unregister(struct notifier_block *);
 extern int of_reconfig_notify(unsigned long, void *);
 
+void __of_attach_node(struct device_node *np);
+void __of_detach_node(struct device_node *np);
+
 extern int of_attach_node(struct device_node *);
 extern int of_detach_node(struct device_node *);
 
@@ -401,6 +426,12 @@ static inline struct device_node *of_get_next_child(
 	return NULL;
 }
 
+static inline struct device_node *__of_get_next_child(
+	const struct device_node *node, struct device_node *prev)
+{
+	return NULL;
+}
+
 static inline struct device_node *of_get_next_available_child(
 	const struct device_node *node, struct device_node *prev)
 {
@@ -738,6 +769,9 @@ static inline int of_property_read_u32(const struct device_node *np,
 #define for_each_child_of_node(parent, child) \
 	for (child = of_get_next_child(parent, NULL); child != NULL; \
 	     child = of_get_next_child(parent, child))
+#define __for_each_child_of_node(parent, child) \
+	for (child = __of_get_next_child(parent, NULL); child != NULL; \
+	     child = __of_get_next_child(parent, child))
 #define for_each_available_child_of_node(parent, child) \
 	for (child = of_get_next_available_child(parent, NULL); child != NULL; \
 	     child = of_get_next_available_child(parent, child))
-- 
1.7.12

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

* [PATCH 5/6] OF: Utility helper functions for dynamic nodes
  2014-06-22  9:40 [PATCH 0/6] OF: Fixes preparing transactions/overlays Pantelis Antoniou
                   ` (3 preceding siblings ...)
  2014-06-22  9:40 ` [PATCH 4/6] OF: Export a number of __of_* methods Pantelis Antoniou
@ 2014-06-22  9:40 ` Pantelis Antoniou
  2014-06-23 16:26     ` Alexander Sverdlin
  2014-06-25 11:14   ` Grant Likely
  2014-06-22  9:40 ` [PATCH 6/6] of: Introduce tree change __foo_post methods Pantelis Antoniou
  5 siblings, 2 replies; 63+ messages in thread
From: Pantelis Antoniou @ 2014-06-22  9:40 UTC (permalink / raw)
  To: Grant Likely
  Cc: Rob Herring, Stephen Warren, Matt Porter, Koen Kooi,
	Greg Kroah-Hartman, Alison Chaiken, Dinh Nguyen, Jan Lubbe,
	Alexander Sverdlin, Michael Stickel, Guenter Roeck, Dirk Behme,
	Alan Tull, Sascha Hauer, Michael Bohan, Ionut Nicu, Michal Simek,
	Matt Ranostay, Joel Becker, devicetree, Wolfram Sang, linux-i2c,
	Mark Brown, linux-spi, linux-kernel, Pete Popov, Dan Malek,
	Georgi Vlaev, Pantelis Antoniou, Pantelis Antoniou

Introduce helper functions for working with the live DT tree,
all of them related to dynamically adding/removing nodes and
properties.

__of_copy_property() copies a property dynamically
__of_create_empty_node() creates an empty node

Bug fix about prop->len == 0 by Ionut Nicu <ioan.nicu.ext@nsn.com>

Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
---
 drivers/of/Makefile |   2 +-
 drivers/of/util.c   | 141 ++++++++++++++++++++++++++++++++++++++++++++++++++++
 include/linux/of.h  |  42 ++++++++++++++++
 3 files changed, 184 insertions(+), 1 deletion(-)
 create mode 100644 drivers/of/util.c

diff --git a/drivers/of/Makefile b/drivers/of/Makefile
index 099b1fb..734d3e2 100644
--- a/drivers/of/Makefile
+++ b/drivers/of/Makefile
@@ -1,4 +1,4 @@
-obj-y = base.o device.o platform.o
+obj-y = base.o device.o platform.o util.o
 obj-$(CONFIG_OF_FLATTREE) += fdt.o
 obj-$(CONFIG_OF_EARLY_FLATTREE) += fdt_address.o
 obj-$(CONFIG_OF_PROMTREE) += pdt.o
diff --git a/drivers/of/util.c b/drivers/of/util.c
new file mode 100644
index 0000000..f4211f8
--- /dev/null
+++ b/drivers/of/util.c
@@ -0,0 +1,141 @@
+/*
+ * Utility functions for working with device tree(s)
+ *
+ * Copyright (C) 2012 Pantelis Antoniou <panto@antoniou-consulting.com>
+ * Copyright (C) 2012 Texas Instruments Inc.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * version 2 as published by the Free Software Foundation.
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/of.h>
+#include <linux/of_device.h>
+#include <linux/string.h>
+#include <linux/ctype.h>
+#include <linux/errno.h>
+#include <linux/string.h>
+#include <linux/slab.h>
+#include <linux/err.h>
+
+/**
+ * __of_copy_property - Copy a property dynamically.
+ * @prop:	Property to copy
+ * @allocflags:	Allocation flags (typically pass GFP_KERNEL)
+ * @propflags:	Property flags
+ *
+ * Copy a property by dynamically allocating the memory of both the
+ * property stucture and the property name & contents. The property's
+ * flags have the OF_DYNAMIC bit set so that we can differentiate between
+ * dynamically allocated properties and not.
+ * Returns the newly allocated property or NULL on out of memory error.
+ */
+struct property *__of_copy_property(const struct property *prop,
+		gfp_t allocflags, unsigned long propflags)
+{
+	struct property *propn;
+
+	propn = kzalloc(sizeof(*prop), allocflags);
+	if (propn == NULL)
+		return NULL;
+
+	propn->_flags = propflags;
+
+	if (of_property_check_flag(propn, OF_ALLOCNAME)) {
+		propn->name = kstrdup(prop->name, allocflags);
+		if (propn->name == NULL)
+			goto err_fail_name;
+	} else
+		propn->name = prop->name;
+
+	if (prop->length > 0) {
+		if (of_property_check_flag(propn, OF_ALLOCVALUE)) {
+			propn->value = kmalloc(prop->length, allocflags);
+			if (propn->value == NULL)
+				goto err_fail_value;
+			memcpy(propn->value, prop->value, prop->length);
+		} else
+			propn->value = prop->value;
+
+		propn->length = prop->length;
+	}
+
+	/* mark the property as dynamic */
+	of_property_set_flag(propn, OF_DYNAMIC);
+
+	return propn;
+
+err_fail_value:
+	if (of_property_check_flag(propn, OF_ALLOCNAME))
+		kfree(propn->name);
+err_fail_name:
+	kfree(propn);
+	return NULL;
+}
+
+/**
+ * __of_create_empty_node - Create an empty device node dynamically.
+ * @name:	Name of the new device node
+ * @type:	Type of the new device node
+ * @full_name:	Full name of the new device node
+ * @phandle:	Phandle of the new device node
+ * @allocflags:	Allocation flags (typically pass GFP_KERNEL)
+ * @nodeflags:	Node flags
+ *
+ * Create an empty device tree node, suitable for further modification.
+ * The node data are dynamically allocated and all the node flags
+ * have the OF_DYNAMIC & OF_DETACHED bits set.
+ * Returns the newly allocated node or NULL on out of memory error.
+ */
+struct device_node *__of_create_empty_node(
+		const char *name, const char *type, const char *full_name,
+		phandle phandle, gfp_t allocflags, unsigned long nodeflags)
+{
+	struct device_node *node;
+
+	node = kzalloc(sizeof(*node), allocflags);
+	if (node == NULL)
+		return NULL;
+
+	node->_flags = nodeflags;
+
+	if (of_node_check_flag(node, OF_ALLOCNAME)) {
+		node->name = kstrdup(name, allocflags);
+		if (node->name == NULL)
+			goto err_free_node;
+	} else
+		node->name = name;
+
+	if (of_node_check_flag(node, OF_ALLOCTYPE)) {
+		node->type = kstrdup(type, allocflags);
+		if (node->type == NULL)
+			goto err_free_name;
+	} else
+		node->type = type;
+
+	if (of_node_check_flag(node, OF_ALLOCFULL)) {
+		node->full_name = kstrdup(full_name, allocflags);
+		if (node->full_name == NULL)
+			goto err_free_type;
+	} else
+		node->full_name = full_name;
+
+	node->phandle = phandle;
+	of_node_set_flag(node, OF_DYNAMIC);
+	of_node_set_flag(node, OF_DETACHED);
+
+	of_node_init(node);
+
+	return node;
+err_free_type:
+	if (of_node_check_flag(node, OF_ALLOCTYPE))
+		kfree(node->type);
+err_free_name:
+	if (of_node_check_flag(node, OF_ALLOCNAME))
+		kfree(node->name);
+err_free_node:
+	kfree(node);
+	return NULL;
+}
diff --git a/include/linux/of.h b/include/linux/of.h
index 5e4e1b3..d381eb5 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -211,6 +211,15 @@ static inline unsigned long of_read_ulong(const __be32 *cell, int size)
 #define OF_DYNAMIC	1 /* node and properties were allocated via kmalloc */
 #define OF_DETACHED	2 /* node has been detached from the device tree */
 #define OF_POPULATED	3 /* device already created for the node */
+#define OF_ALLOCNAME	4 /* name was kmalloc-ed */
+#define OF_ALLOCTYPE	5 /* type was kmalloc-ed */
+#define OF_ALLOCFULL	6 /* full_name was kmalloc-ed */
+#define OF_ALLOCVALUE	7 /* value was kmalloc-ed */
+
+#define OF_NODE_ALLOCALL \
+	((1 << OF_ALLOCNAME) | (1 << OF_ALLOCTYPE) | (1 << OF_ALLOCFULL))
+#define OF_PROP_ALLOCALL \
+	((1 << OF_ALLOCNAME) | (1 << OF_ALLOCVALUE))
 
 #define OF_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags)
 #define OF_MARK_DYNAMIC(x) set_bit(OF_DYNAMIC, &x->_flags)
@@ -824,4 +833,37 @@ typedef void (*of_init_fn_1)(struct device_node *);
 #define OF_DECLARE_2(table, name, compat, fn) \
 		_OF_DECLARE(table, name, compat, fn, of_init_fn_2)
 
+/**
+ * General utilities for working with live trees.
+ *
+ * All functions with two leading underscores operate
+ * without taking node references, so you either have to
+ * own the devtree lock or work on detached trees only.
+ */
+
+#ifdef CONFIG_OF
+
+struct property *__of_copy_property(const struct property *prop,
+		gfp_t allocflags, unsigned long propflags);
+struct device_node *__of_create_empty_node(const char *name,
+		const char *type, const char *full_name,
+		phandle phandle, gfp_t allocflags, unsigned long nodeflags);
+
+#else /* !CONFIG_OF */
+
+static inline struct property *__of_copy_property(const struct property *prop,
+		gfp_t allocflags, unsigned long propflags)
+{
+	return NULL;
+}
+
+static inline struct device_node *__of_create_empty_node(const char *name,
+		const char *type, const char *full_name,
+		phandle phandle, gfp_t allocflags, unsigned long nodeflags)
+{
+	return NULL;
+}
+
+#endif	/* !CONFIG_OF */
+
 #endif /* _LINUX_OF_H */
-- 
1.7.12

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

* [PATCH 6/6] of: Introduce tree change __foo_post methods.
  2014-06-22  9:40 [PATCH 0/6] OF: Fixes preparing transactions/overlays Pantelis Antoniou
                   ` (4 preceding siblings ...)
  2014-06-22  9:40 ` [PATCH 5/6] OF: Utility helper functions for dynamic nodes Pantelis Antoniou
@ 2014-06-22  9:40 ` Pantelis Antoniou
  5 siblings, 0 replies; 63+ messages in thread
From: Pantelis Antoniou @ 2014-06-22  9:40 UTC (permalink / raw)
  To: Grant Likely
  Cc: Rob Herring, Stephen Warren, Matt Porter, Koen Kooi,
	Greg Kroah-Hartman, Alison Chaiken, Dinh Nguyen, Jan Lubbe,
	Alexander Sverdlin, Michael Stickel, Guenter Roeck, Dirk Behme,
	Alan Tull, Sascha Hauer, Michael Bohan, Ionut Nicu, Michal Simek,
	Matt Ranostay, Joel Becker, devicetree, Wolfram Sang, linux-i2c,
	Mark Brown, linux-spi, linux-kernel, Pete Popov, Dan Malek,
	Georgi Vlaev, Pantelis Antoniou, Pantelis Antoniou

As part of transactional DT support there needs to be a clearer
definition of how each dynamic tree change method works.

Let's take for example the of_add_property method. There are
discrete steps taken in sequence.

1. The OF_RECONFIG_ADD_PROPERTY notifier will be fired.
2. The devtree lock will be taken.
3. Insertion of the property in the live tree.
4. The devtree lock will be released.
5. The property will be inserted in the sysfs tree.

For each of the of_attach_node, of_detach_node, of_add_property,
of_remove_property and of_update_property methods we export (and
introduce if not available), their counterparts of
__of_attach_node, __of_attach_node_post, __of_detach_node,
__of_detach_node_post, __of_add_property, __of_add_property_post,
__of_remove_property, __of_remove_property_post, __of_update_property
and __of_update_property post.

So each of the tree modification methods is following the same
pattern, i.e. for method foo we have:

Firing of the notifer, lock, __foo, unlock, __foo_post

This breakdown is required when we introduce transaction.

Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
---
 drivers/of/base.c  | 74 ++++++++++++++++++++++++++++++++++++++++--------------
 include/linux/of.h |  7 ++++++
 2 files changed, 62 insertions(+), 19 deletions(-)

diff --git a/drivers/of/base.c b/drivers/of/base.c
index 42c735d..b5d854d 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -213,13 +213,24 @@ static const char *safe_name(struct kobject *kobj, const char *orig_name)
 	return name;
 }
 
-static int __of_add_property_sysfs(struct device_node *np, struct property *pp)
+static int __of_add_property_sysfs(struct device_node *np, struct property *pp,
+		int ignore_dup_name)
 {
 	int rc;
 
 	/* Important: Don't leak passwords */
 	bool secure = strncmp(pp->name, "security-", 9) == 0;
 
+	/* ignore duplicate name (transaction case) */
+	if (ignore_dup_name) {
+		struct kernfs_node *kn = sysfs_get_dirent(np->kobj.sd,
+				pp->name);
+		if (kn) {
+			sysfs_put(kn);
+			return 0;
+		}
+	}
+
 	sysfs_bin_attr_init(&pp->attr);
 	pp->attr.attr.name = safe_name(&np->kobj, pp->name);
 	pp->attr.attr.mode = secure ? S_IRUSR : S_IRUGO;
@@ -253,7 +264,7 @@ static int __of_node_add(struct device_node *np)
 		return rc;
 
 	for_each_property_of_node(np, pp)
-		__of_add_property_sysfs(np, pp);
+		__of_add_property_sysfs(np, pp, 1);
 
 	return 0;
 }
@@ -1858,6 +1869,13 @@ int __of_add_property(struct device_node *np, struct property *prop)
 	return 0;
 }
 
+void __of_add_property_post(struct device_node *np, struct property *prop,
+		int ignore_dup_name)
+{
+	if (of_node_is_attached(np))
+		__of_add_property_sysfs(np, prop, ignore_dup_name);
+}
+
 /**
  * of_add_property - Add a property to a node
  */
@@ -1876,8 +1894,7 @@ int of_add_property(struct device_node *np, struct property *prop)
 	if (rc)
 		return rc;
 
-	if (of_node_is_attached(np))
-		__of_add_property_sysfs(np, prop);
+	__of_add_property_post(np, prop, 0);
 
 	return rc;
 }
@@ -1901,6 +1918,13 @@ int __of_remove_property(struct device_node *np, struct property *prop)
 	return 0;
 }
 
+void __of_remove_property_post(struct device_node *np, struct property *prop)
+{
+	/* at early boot, bail here and defer setup to of_init() */
+	if (of_kset)
+		sysfs_remove_bin_file(&np->kobj, &prop->attr);
+}
+
 /**
  * of_remove_property - Remove a property from a node.
  *
@@ -1925,11 +1949,7 @@ int of_remove_property(struct device_node *np, struct property *prop)
 	if (rc)
 		return rc;
 
-	/* at early boot, bail hear and defer setup to of_init() */
-	if (!of_kset)
-		return 0;
-
-	sysfs_remove_bin_file(&np->kobj, &prop->attr);
+	__of_remove_property_post(np, prop);
 
 	return 0;
 }
@@ -1960,6 +1980,19 @@ int __of_update_property(struct device_node *np, struct property *newprop,
 	return 0;
 }
 
+void __of_update_property_post(struct device_node *np, struct property *newprop,
+		struct property *oldprop)
+{
+	/* At early boot, bail out and defer setup to of_init() */
+	if (!of_kset)
+		return;
+
+	/* Update the sysfs attribute */
+	if (oldprop)
+		sysfs_remove_bin_file(&np->kobj, &oldprop->attr);
+	__of_add_property_sysfs(np, newprop, 0);
+}
+
 /*
  * of_update_property - Update a property in a node, if the property does
  * not exist, add it.
@@ -1988,14 +2021,7 @@ int of_update_property(struct device_node *np, struct property *prop)
 	if (rc)
 		return rc;
 
-	/* At early boot, bail out and defer setup to of_init() */
-	if (!of_kset)
-		return 0;
-
-	/* Update the sysfs attribute */
-	if (oldprop)
-		sysfs_remove_bin_file(&np->kobj, &oldprop->attr);
-	__of_add_property_sysfs(np, prop);
+	__of_update_property_post(np, prop, oldprop);
 
 	return 0;
 }
@@ -2040,6 +2066,11 @@ void __of_attach_node(struct device_node *np)
 	of_node_clear_flag(np, OF_DETACHED);
 }
 
+void __of_attach_node_post(struct device_node *np)
+{
+	of_node_add(np);
+}
+
 /**
  * of_attach_node - Plug a device node into the tree and global list.
  */
@@ -2056,7 +2087,7 @@ int of_attach_node(struct device_node *np)
 	__of_attach_node(np);
 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
 
-	of_node_add(np);
+	__of_attach_node_post(np);
 	return 0;
 }
 
@@ -2096,6 +2127,11 @@ void __of_detach_node(struct device_node *np)
 	of_node_set_flag(np, OF_DETACHED);
 }
 
+void __of_detach_node_post(struct device_node *np)
+{
+	of_node_remove(np);
+}
+
 /**
  * of_detach_node - "Unplug" a node from the device tree.
  *
@@ -2115,7 +2151,7 @@ int of_detach_node(struct device_node *np)
 	__of_detach_node(np);
 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
 
-	of_node_remove(np);
+	__of_detach_node_post(np);
 	return rc;
 }
 #endif /* defined(CONFIG_OF_DYNAMIC) */
diff --git a/include/linux/of.h b/include/linux/of.h
index d381eb5..60e9f3b 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -339,9 +339,14 @@ extern int of_alias_get_id(struct device_node *np, const char *stem);
 extern int of_machine_is_compatible(const char *compat);
 
 int __of_add_property(struct device_node *np, struct property *prop);
+void __of_add_property_post(struct device_node *np, struct property *prop,
+		int ignore_dup_name);
 int __of_remove_property(struct device_node *np, struct property *prop);
+void __of_remove_property_post(struct device_node *np, struct property *prop);
 int __of_update_property(struct device_node *np, struct property *newprop,
 		struct property **oldprop);
+void __of_update_property_post(struct device_node *np, struct property *newprop,
+		struct property *oldprop);
 
 extern int of_add_property(struct device_node *np, struct property *prop);
 extern int of_remove_property(struct device_node *np, struct property *prop);
@@ -364,7 +369,9 @@ extern int of_reconfig_notifier_unregister(struct notifier_block *);
 extern int of_reconfig_notify(unsigned long, void *);
 
 void __of_attach_node(struct device_node *np);
+void __of_attach_node_post(struct device_node *np);
 void __of_detach_node(struct device_node *np);
+void __of_detach_node_post(struct device_node *np);
 
 extern int of_attach_node(struct device_node *);
 extern int of_detach_node(struct device_node *);
-- 
1.7.12

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

* Re: [PATCH 5/6] OF: Utility helper functions for dynamic nodes
@ 2014-06-23 16:26     ` Alexander Sverdlin
  0 siblings, 0 replies; 63+ messages in thread
From: Alexander Sverdlin @ 2014-06-23 16:26 UTC (permalink / raw)
  To: ext Pantelis Antoniou, Grant Likely, Ionut Nicu
  Cc: Rob Herring, Stephen Warren, Matt Porter, Koen Kooi,
	Greg Kroah-Hartman, Alison Chaiken, Dinh Nguyen, Jan Lubbe,
	Michael Stickel, Guenter Roeck, Dirk Behme, Alan Tull,
	Sascha Hauer, Michael Bohan, Michal Simek, Matt Ranostay,
	Joel Becker, devicetree, Wolfram Sang, linux-i2c, Mark Brown,
	linux-spi, linux-kernel, Pete Popov, Dan Malek, Georgi Vlaev,
	Pantelis Antoniou

Hello Pantelis!

On 22/06/14 11:40, ext Pantelis Antoniou wrote:
> Introduce helper functions for working with the live DT tree,
> all of them related to dynamically adding/removing nodes and
> properties.
> 
> __of_copy_property() copies a property dynamically
> __of_create_empty_node() creates an empty node
> 
> Bug fix about prop->len == 0 by Ionut Nicu <ioan.nicu.ext@nsn.com>

Are you sure about this? (see below...)
 
> Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
> ---
>  drivers/of/Makefile |   2 +-
>  drivers/of/util.c   | 141 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/of.h  |  42 ++++++++++++++++
>  3 files changed, 184 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/of/util.c
> 
> diff --git a/drivers/of/Makefile b/drivers/of/Makefile
> index 099b1fb..734d3e2 100644
> --- a/drivers/of/Makefile
> +++ b/drivers/of/Makefile
> @@ -1,4 +1,4 @@
> -obj-y = base.o device.o platform.o
> +obj-y = base.o device.o platform.o util.o
>  obj-$(CONFIG_OF_FLATTREE) += fdt.o
>  obj-$(CONFIG_OF_EARLY_FLATTREE) += fdt_address.o
>  obj-$(CONFIG_OF_PROMTREE) += pdt.o
> diff --git a/drivers/of/util.c b/drivers/of/util.c
> new file mode 100644
> index 0000000..f4211f8
> --- /dev/null
> +++ b/drivers/of/util.c
> @@ -0,0 +1,141 @@
> +/*
> + * Utility functions for working with device tree(s)
> + *
> + * Copyright (C) 2012 Pantelis Antoniou <panto@antoniou-consulting.com>
> + * Copyright (C) 2012 Texas Instruments Inc.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * version 2 as published by the Free Software Foundation.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/string.h>
> +#include <linux/ctype.h>
> +#include <linux/errno.h>
> +#include <linux/string.h>
> +#include <linux/slab.h>
> +#include <linux/err.h>
> +
> +/**
> + * __of_copy_property - Copy a property dynamically.
> + * @prop:	Property to copy
> + * @allocflags:	Allocation flags (typically pass GFP_KERNEL)
> + * @propflags:	Property flags
> + *
> + * Copy a property by dynamically allocating the memory of both the
> + * property stucture and the property name & contents. The property's
> + * flags have the OF_DYNAMIC bit set so that we can differentiate between
> + * dynamically allocated properties and not.
> + * Returns the newly allocated property or NULL on out of memory error.
> + */
> +struct property *__of_copy_property(const struct property *prop,
> +		gfp_t allocflags, unsigned long propflags)
> +{
> +	struct property *propn;
> +
> +	propn = kzalloc(sizeof(*prop), allocflags);
> +	if (propn == NULL)
> +		return NULL;
> +
> +	propn->_flags = propflags;
> +
> +	if (of_property_check_flag(propn, OF_ALLOCNAME)) {
> +		propn->name = kstrdup(prop->name, allocflags);
> +		if (propn->name == NULL)
> +			goto err_fail_name;
> +	} else
> +		propn->name = prop->name;
> +
> +	if (prop->length > 0) {
        ^^^^^^^^^^^^^^^^^^^^^
Seems, that length==0 case will still produce value==NULL results,
which will brake some checks in the kernel... Or am I missing something in
the new version?


> +		if (of_property_check_flag(propn, OF_ALLOCVALUE)) {
> +			propn->value = kmalloc(prop->length, allocflags);
> +			if (propn->value == NULL)
> +				goto err_fail_value;
> +			memcpy(propn->value, prop->value, prop->length);
> +		} else
> +			propn->value = prop->value;
> +
> +		propn->length = prop->length;
> +	}
> +
> +	/* mark the property as dynamic */
> +	of_property_set_flag(propn, OF_DYNAMIC);
> +
> +	return propn;
> +
> +err_fail_value:
> +	if (of_property_check_flag(propn, OF_ALLOCNAME))
> +		kfree(propn->name);
> +err_fail_name:
> +	kfree(propn);
> +	return NULL;
> +}
> +
> +/**
> + * __of_create_empty_node - Create an empty device node dynamically.
> + * @name:	Name of the new device node
> + * @type:	Type of the new device node
> + * @full_name:	Full name of the new device node
> + * @phandle:	Phandle of the new device node
> + * @allocflags:	Allocation flags (typically pass GFP_KERNEL)
> + * @nodeflags:	Node flags
> + *
> + * Create an empty device tree node, suitable for further modification.
> + * The node data are dynamically allocated and all the node flags
> + * have the OF_DYNAMIC & OF_DETACHED bits set.
> + * Returns the newly allocated node or NULL on out of memory error.
> + */
> +struct device_node *__of_create_empty_node(
> +		const char *name, const char *type, const char *full_name,
> +		phandle phandle, gfp_t allocflags, unsigned long nodeflags)
> +{
> +	struct device_node *node;
> +
> +	node = kzalloc(sizeof(*node), allocflags);
> +	if (node == NULL)
> +		return NULL;
> +
> +	node->_flags = nodeflags;
> +
> +	if (of_node_check_flag(node, OF_ALLOCNAME)) {
> +		node->name = kstrdup(name, allocflags);
> +		if (node->name == NULL)
> +			goto err_free_node;
> +	} else
> +		node->name = name;
> +
> +	if (of_node_check_flag(node, OF_ALLOCTYPE)) {
> +		node->type = kstrdup(type, allocflags);
> +		if (node->type == NULL)
> +			goto err_free_name;
> +	} else
> +		node->type = type;
> +
> +	if (of_node_check_flag(node, OF_ALLOCFULL)) {
> +		node->full_name = kstrdup(full_name, allocflags);
> +		if (node->full_name == NULL)
> +			goto err_free_type;
> +	} else
> +		node->full_name = full_name;
> +
> +	node->phandle = phandle;
> +	of_node_set_flag(node, OF_DYNAMIC);
> +	of_node_set_flag(node, OF_DETACHED);
> +
> +	of_node_init(node);
> +
> +	return node;
> +err_free_type:
> +	if (of_node_check_flag(node, OF_ALLOCTYPE))
> +		kfree(node->type);
> +err_free_name:
> +	if (of_node_check_flag(node, OF_ALLOCNAME))
> +		kfree(node->name);
> +err_free_node:
> +	kfree(node);
> +	return NULL;
> +}
> diff --git a/include/linux/of.h b/include/linux/of.h
> index 5e4e1b3..d381eb5 100644
> --- a/include/linux/of.h
> +++ b/include/linux/of.h
> @@ -211,6 +211,15 @@ static inline unsigned long of_read_ulong(const __be32 *cell, int size)
>  #define OF_DYNAMIC	1 /* node and properties were allocated via kmalloc */
>  #define OF_DETACHED	2 /* node has been detached from the device tree */
>  #define OF_POPULATED	3 /* device already created for the node */
> +#define OF_ALLOCNAME	4 /* name was kmalloc-ed */
> +#define OF_ALLOCTYPE	5 /* type was kmalloc-ed */
> +#define OF_ALLOCFULL	6 /* full_name was kmalloc-ed */
> +#define OF_ALLOCVALUE	7 /* value was kmalloc-ed */
> +
> +#define OF_NODE_ALLOCALL \
> +	((1 << OF_ALLOCNAME) | (1 << OF_ALLOCTYPE) | (1 << OF_ALLOCFULL))
> +#define OF_PROP_ALLOCALL \
> +	((1 << OF_ALLOCNAME) | (1 << OF_ALLOCVALUE))
>  
>  #define OF_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags)
>  #define OF_MARK_DYNAMIC(x) set_bit(OF_DYNAMIC, &x->_flags)
> @@ -824,4 +833,37 @@ typedef void (*of_init_fn_1)(struct device_node *);
>  #define OF_DECLARE_2(table, name, compat, fn) \
>  		_OF_DECLARE(table, name, compat, fn, of_init_fn_2)
>  
> +/**
> + * General utilities for working with live trees.
> + *
> + * All functions with two leading underscores operate
> + * without taking node references, so you either have to
> + * own the devtree lock or work on detached trees only.
> + */
> +
> +#ifdef CONFIG_OF
> +
> +struct property *__of_copy_property(const struct property *prop,
> +		gfp_t allocflags, unsigned long propflags);
> +struct device_node *__of_create_empty_node(const char *name,
> +		const char *type, const char *full_name,
> +		phandle phandle, gfp_t allocflags, unsigned long nodeflags);
> +
> +#else /* !CONFIG_OF */
> +
> +static inline struct property *__of_copy_property(const struct property *prop,
> +		gfp_t allocflags, unsigned long propflags)
> +{
> +	return NULL;
> +}
> +
> +static inline struct device_node *__of_create_empty_node(const char *name,
> +		const char *type, const char *full_name,
> +		phandle phandle, gfp_t allocflags, unsigned long nodeflags)
> +{
> +	return NULL;
> +}
> +
> +#endif	/* !CONFIG_OF */
> +
>  #endif /* _LINUX_OF_H */
> 

-- 
Best regards,
Alexander Sverdlin.

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

* Re: [PATCH 5/6] OF: Utility helper functions for dynamic nodes
@ 2014-06-23 16:26     ` Alexander Sverdlin
  0 siblings, 0 replies; 63+ messages in thread
From: Alexander Sverdlin @ 2014-06-23 16:26 UTC (permalink / raw)
  To: ext Pantelis Antoniou, Grant Likely, Ionut Nicu
  Cc: Rob Herring, Stephen Warren, Matt Porter, Koen Kooi,
	Greg Kroah-Hartman, Alison Chaiken, Dinh Nguyen, Jan Lubbe,
	Michael Stickel, Guenter Roeck, Dirk Behme, Alan Tull,
	Sascha Hauer, Michael Bohan, Michal Simek, Matt Ranostay,
	Joel Becker, devicetree-u79uwXL29TY76Z2rM5mHXA, Wolfram Sang,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA, Mark Brown,
	linux-spi-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Pete Popov, Dan Malek

Hello Pantelis!

On 22/06/14 11:40, ext Pantelis Antoniou wrote:
> Introduce helper functions for working with the live DT tree,
> all of them related to dynamically adding/removing nodes and
> properties.
> 
> __of_copy_property() copies a property dynamically
> __of_create_empty_node() creates an empty node
> 
> Bug fix about prop->len == 0 by Ionut Nicu <ioan.nicu.ext-OYasijW0DpE@public.gmane.org>

Are you sure about this? (see below...)
 
> Signed-off-by: Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
> ---
>  drivers/of/Makefile |   2 +-
>  drivers/of/util.c   | 141 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/of.h  |  42 ++++++++++++++++
>  3 files changed, 184 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/of/util.c
> 
> diff --git a/drivers/of/Makefile b/drivers/of/Makefile
> index 099b1fb..734d3e2 100644
> --- a/drivers/of/Makefile
> +++ b/drivers/of/Makefile
> @@ -1,4 +1,4 @@
> -obj-y = base.o device.o platform.o
> +obj-y = base.o device.o platform.o util.o
>  obj-$(CONFIG_OF_FLATTREE) += fdt.o
>  obj-$(CONFIG_OF_EARLY_FLATTREE) += fdt_address.o
>  obj-$(CONFIG_OF_PROMTREE) += pdt.o
> diff --git a/drivers/of/util.c b/drivers/of/util.c
> new file mode 100644
> index 0000000..f4211f8
> --- /dev/null
> +++ b/drivers/of/util.c
> @@ -0,0 +1,141 @@
> +/*
> + * Utility functions for working with device tree(s)
> + *
> + * Copyright (C) 2012 Pantelis Antoniou <panto-wVdstyuyKrO8r51toPun2/C9HSW9iNxf@public.gmane.org>
> + * Copyright (C) 2012 Texas Instruments Inc.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * version 2 as published by the Free Software Foundation.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/string.h>
> +#include <linux/ctype.h>
> +#include <linux/errno.h>
> +#include <linux/string.h>
> +#include <linux/slab.h>
> +#include <linux/err.h>
> +
> +/**
> + * __of_copy_property - Copy a property dynamically.
> + * @prop:	Property to copy
> + * @allocflags:	Allocation flags (typically pass GFP_KERNEL)
> + * @propflags:	Property flags
> + *
> + * Copy a property by dynamically allocating the memory of both the
> + * property stucture and the property name & contents. The property's
> + * flags have the OF_DYNAMIC bit set so that we can differentiate between
> + * dynamically allocated properties and not.
> + * Returns the newly allocated property or NULL on out of memory error.
> + */
> +struct property *__of_copy_property(const struct property *prop,
> +		gfp_t allocflags, unsigned long propflags)
> +{
> +	struct property *propn;
> +
> +	propn = kzalloc(sizeof(*prop), allocflags);
> +	if (propn == NULL)
> +		return NULL;
> +
> +	propn->_flags = propflags;
> +
> +	if (of_property_check_flag(propn, OF_ALLOCNAME)) {
> +		propn->name = kstrdup(prop->name, allocflags);
> +		if (propn->name == NULL)
> +			goto err_fail_name;
> +	} else
> +		propn->name = prop->name;
> +
> +	if (prop->length > 0) {
        ^^^^^^^^^^^^^^^^^^^^^
Seems, that length==0 case will still produce value==NULL results,
which will brake some checks in the kernel... Or am I missing something in
the new version?


> +		if (of_property_check_flag(propn, OF_ALLOCVALUE)) {
> +			propn->value = kmalloc(prop->length, allocflags);
> +			if (propn->value == NULL)
> +				goto err_fail_value;
> +			memcpy(propn->value, prop->value, prop->length);
> +		} else
> +			propn->value = prop->value;
> +
> +		propn->length = prop->length;
> +	}
> +
> +	/* mark the property as dynamic */
> +	of_property_set_flag(propn, OF_DYNAMIC);
> +
> +	return propn;
> +
> +err_fail_value:
> +	if (of_property_check_flag(propn, OF_ALLOCNAME))
> +		kfree(propn->name);
> +err_fail_name:
> +	kfree(propn);
> +	return NULL;
> +}
> +
> +/**
> + * __of_create_empty_node - Create an empty device node dynamically.
> + * @name:	Name of the new device node
> + * @type:	Type of the new device node
> + * @full_name:	Full name of the new device node
> + * @phandle:	Phandle of the new device node
> + * @allocflags:	Allocation flags (typically pass GFP_KERNEL)
> + * @nodeflags:	Node flags
> + *
> + * Create an empty device tree node, suitable for further modification.
> + * The node data are dynamically allocated and all the node flags
> + * have the OF_DYNAMIC & OF_DETACHED bits set.
> + * Returns the newly allocated node or NULL on out of memory error.
> + */
> +struct device_node *__of_create_empty_node(
> +		const char *name, const char *type, const char *full_name,
> +		phandle phandle, gfp_t allocflags, unsigned long nodeflags)
> +{
> +	struct device_node *node;
> +
> +	node = kzalloc(sizeof(*node), allocflags);
> +	if (node == NULL)
> +		return NULL;
> +
> +	node->_flags = nodeflags;
> +
> +	if (of_node_check_flag(node, OF_ALLOCNAME)) {
> +		node->name = kstrdup(name, allocflags);
> +		if (node->name == NULL)
> +			goto err_free_node;
> +	} else
> +		node->name = name;
> +
> +	if (of_node_check_flag(node, OF_ALLOCTYPE)) {
> +		node->type = kstrdup(type, allocflags);
> +		if (node->type == NULL)
> +			goto err_free_name;
> +	} else
> +		node->type = type;
> +
> +	if (of_node_check_flag(node, OF_ALLOCFULL)) {
> +		node->full_name = kstrdup(full_name, allocflags);
> +		if (node->full_name == NULL)
> +			goto err_free_type;
> +	} else
> +		node->full_name = full_name;
> +
> +	node->phandle = phandle;
> +	of_node_set_flag(node, OF_DYNAMIC);
> +	of_node_set_flag(node, OF_DETACHED);
> +
> +	of_node_init(node);
> +
> +	return node;
> +err_free_type:
> +	if (of_node_check_flag(node, OF_ALLOCTYPE))
> +		kfree(node->type);
> +err_free_name:
> +	if (of_node_check_flag(node, OF_ALLOCNAME))
> +		kfree(node->name);
> +err_free_node:
> +	kfree(node);
> +	return NULL;
> +}
> diff --git a/include/linux/of.h b/include/linux/of.h
> index 5e4e1b3..d381eb5 100644
> --- a/include/linux/of.h
> +++ b/include/linux/of.h
> @@ -211,6 +211,15 @@ static inline unsigned long of_read_ulong(const __be32 *cell, int size)
>  #define OF_DYNAMIC	1 /* node and properties were allocated via kmalloc */
>  #define OF_DETACHED	2 /* node has been detached from the device tree */
>  #define OF_POPULATED	3 /* device already created for the node */
> +#define OF_ALLOCNAME	4 /* name was kmalloc-ed */
> +#define OF_ALLOCTYPE	5 /* type was kmalloc-ed */
> +#define OF_ALLOCFULL	6 /* full_name was kmalloc-ed */
> +#define OF_ALLOCVALUE	7 /* value was kmalloc-ed */
> +
> +#define OF_NODE_ALLOCALL \
> +	((1 << OF_ALLOCNAME) | (1 << OF_ALLOCTYPE) | (1 << OF_ALLOCFULL))
> +#define OF_PROP_ALLOCALL \
> +	((1 << OF_ALLOCNAME) | (1 << OF_ALLOCVALUE))
>  
>  #define OF_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags)
>  #define OF_MARK_DYNAMIC(x) set_bit(OF_DYNAMIC, &x->_flags)
> @@ -824,4 +833,37 @@ typedef void (*of_init_fn_1)(struct device_node *);
>  #define OF_DECLARE_2(table, name, compat, fn) \
>  		_OF_DECLARE(table, name, compat, fn, of_init_fn_2)
>  
> +/**
> + * General utilities for working with live trees.
> + *
> + * All functions with two leading underscores operate
> + * without taking node references, so you either have to
> + * own the devtree lock or work on detached trees only.
> + */
> +
> +#ifdef CONFIG_OF
> +
> +struct property *__of_copy_property(const struct property *prop,
> +		gfp_t allocflags, unsigned long propflags);
> +struct device_node *__of_create_empty_node(const char *name,
> +		const char *type, const char *full_name,
> +		phandle phandle, gfp_t allocflags, unsigned long nodeflags);
> +
> +#else /* !CONFIG_OF */
> +
> +static inline struct property *__of_copy_property(const struct property *prop,
> +		gfp_t allocflags, unsigned long propflags)
> +{
> +	return NULL;
> +}
> +
> +static inline struct device_node *__of_create_empty_node(const char *name,
> +		const char *type, const char *full_name,
> +		phandle phandle, gfp_t allocflags, unsigned long nodeflags)
> +{
> +	return NULL;
> +}
> +
> +#endif	/* !CONFIG_OF */
> +
>  #endif /* _LINUX_OF_H */
> 

-- 
Best regards,
Alexander Sverdlin.
--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH 5/6] OF: Utility helper functions for dynamic nodes
@ 2014-06-23 16:26     ` Alexander Sverdlin
  0 siblings, 0 replies; 63+ messages in thread
From: Alexander Sverdlin @ 2014-06-23 16:26 UTC (permalink / raw)
  To: ext Pantelis Antoniou, Grant Likely, Ionut Nicu
  Cc: Rob Herring, Stephen Warren, Matt Porter, Koen Kooi,
	Greg Kroah-Hartman, Alison Chaiken, Dinh Nguyen, Jan Lubbe,
	Michael Stickel, Guenter Roeck, Dirk Behme, Alan Tull,
	Sascha Hauer, Michael Bohan, Michal Simek, Matt Ranostay,
	Joel Becker, devicetree-u79uwXL29TY76Z2rM5mHXA, Wolfram Sang,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA, Mark Brown,
	linux-spi-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Pete Popov, Dan Malek

Hello Pantelis!

On 22/06/14 11:40, ext Pantelis Antoniou wrote:
> Introduce helper functions for working with the live DT tree,
> all of them related to dynamically adding/removing nodes and
> properties.
> 
> __of_copy_property() copies a property dynamically
> __of_create_empty_node() creates an empty node
> 
> Bug fix about prop->len == 0 by Ionut Nicu <ioan.nicu.ext-OYasijW0DpE@public.gmane.org>

Are you sure about this? (see below...)
 
> Signed-off-by: Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
> ---
>  drivers/of/Makefile |   2 +-
>  drivers/of/util.c   | 141 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/of.h  |  42 ++++++++++++++++
>  3 files changed, 184 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/of/util.c
> 
> diff --git a/drivers/of/Makefile b/drivers/of/Makefile
> index 099b1fb..734d3e2 100644
> --- a/drivers/of/Makefile
> +++ b/drivers/of/Makefile
> @@ -1,4 +1,4 @@
> -obj-y = base.o device.o platform.o
> +obj-y = base.o device.o platform.o util.o
>  obj-$(CONFIG_OF_FLATTREE) += fdt.o
>  obj-$(CONFIG_OF_EARLY_FLATTREE) += fdt_address.o
>  obj-$(CONFIG_OF_PROMTREE) += pdt.o
> diff --git a/drivers/of/util.c b/drivers/of/util.c
> new file mode 100644
> index 0000000..f4211f8
> --- /dev/null
> +++ b/drivers/of/util.c
> @@ -0,0 +1,141 @@
> +/*
> + * Utility functions for working with device tree(s)
> + *
> + * Copyright (C) 2012 Pantelis Antoniou <panto-wVdstyuyKrO8r51toPun2/C9HSW9iNxf@public.gmane.org>
> + * Copyright (C) 2012 Texas Instruments Inc.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * version 2 as published by the Free Software Foundation.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/string.h>
> +#include <linux/ctype.h>
> +#include <linux/errno.h>
> +#include <linux/string.h>
> +#include <linux/slab.h>
> +#include <linux/err.h>
> +
> +/**
> + * __of_copy_property - Copy a property dynamically.
> + * @prop:	Property to copy
> + * @allocflags:	Allocation flags (typically pass GFP_KERNEL)
> + * @propflags:	Property flags
> + *
> + * Copy a property by dynamically allocating the memory of both the
> + * property stucture and the property name & contents. The property's
> + * flags have the OF_DYNAMIC bit set so that we can differentiate between
> + * dynamically allocated properties and not.
> + * Returns the newly allocated property or NULL on out of memory error.
> + */
> +struct property *__of_copy_property(const struct property *prop,
> +		gfp_t allocflags, unsigned long propflags)
> +{
> +	struct property *propn;
> +
> +	propn = kzalloc(sizeof(*prop), allocflags);
> +	if (propn == NULL)
> +		return NULL;
> +
> +	propn->_flags = propflags;
> +
> +	if (of_property_check_flag(propn, OF_ALLOCNAME)) {
> +		propn->name = kstrdup(prop->name, allocflags);
> +		if (propn->name == NULL)
> +			goto err_fail_name;
> +	} else
> +		propn->name = prop->name;
> +
> +	if (prop->length > 0) {
        ^^^^^^^^^^^^^^^^^^^^^
Seems, that length==0 case will still produce value==NULL results,
which will brake some checks in the kernel... Or am I missing something in
the new version?


> +		if (of_property_check_flag(propn, OF_ALLOCVALUE)) {
> +			propn->value = kmalloc(prop->length, allocflags);
> +			if (propn->value == NULL)
> +				goto err_fail_value;
> +			memcpy(propn->value, prop->value, prop->length);
> +		} else
> +			propn->value = prop->value;
> +
> +		propn->length = prop->length;
> +	}
> +
> +	/* mark the property as dynamic */
> +	of_property_set_flag(propn, OF_DYNAMIC);
> +
> +	return propn;
> +
> +err_fail_value:
> +	if (of_property_check_flag(propn, OF_ALLOCNAME))
> +		kfree(propn->name);
> +err_fail_name:
> +	kfree(propn);
> +	return NULL;
> +}
> +
> +/**
> + * __of_create_empty_node - Create an empty device node dynamically.
> + * @name:	Name of the new device node
> + * @type:	Type of the new device node
> + * @full_name:	Full name of the new device node
> + * @phandle:	Phandle of the new device node
> + * @allocflags:	Allocation flags (typically pass GFP_KERNEL)
> + * @nodeflags:	Node flags
> + *
> + * Create an empty device tree node, suitable for further modification.
> + * The node data are dynamically allocated and all the node flags
> + * have the OF_DYNAMIC & OF_DETACHED bits set.
> + * Returns the newly allocated node or NULL on out of memory error.
> + */
> +struct device_node *__of_create_empty_node(
> +		const char *name, const char *type, const char *full_name,
> +		phandle phandle, gfp_t allocflags, unsigned long nodeflags)
> +{
> +	struct device_node *node;
> +
> +	node = kzalloc(sizeof(*node), allocflags);
> +	if (node == NULL)
> +		return NULL;
> +
> +	node->_flags = nodeflags;
> +
> +	if (of_node_check_flag(node, OF_ALLOCNAME)) {
> +		node->name = kstrdup(name, allocflags);
> +		if (node->name == NULL)
> +			goto err_free_node;
> +	} else
> +		node->name = name;
> +
> +	if (of_node_check_flag(node, OF_ALLOCTYPE)) {
> +		node->type = kstrdup(type, allocflags);
> +		if (node->type == NULL)
> +			goto err_free_name;
> +	} else
> +		node->type = type;
> +
> +	if (of_node_check_flag(node, OF_ALLOCFULL)) {
> +		node->full_name = kstrdup(full_name, allocflags);
> +		if (node->full_name == NULL)
> +			goto err_free_type;
> +	} else
> +		node->full_name = full_name;
> +
> +	node->phandle = phandle;
> +	of_node_set_flag(node, OF_DYNAMIC);
> +	of_node_set_flag(node, OF_DETACHED);
> +
> +	of_node_init(node);
> +
> +	return node;
> +err_free_type:
> +	if (of_node_check_flag(node, OF_ALLOCTYPE))
> +		kfree(node->type);
> +err_free_name:
> +	if (of_node_check_flag(node, OF_ALLOCNAME))
> +		kfree(node->name);
> +err_free_node:
> +	kfree(node);
> +	return NULL;
> +}
> diff --git a/include/linux/of.h b/include/linux/of.h
> index 5e4e1b3..d381eb5 100644
> --- a/include/linux/of.h
> +++ b/include/linux/of.h
> @@ -211,6 +211,15 @@ static inline unsigned long of_read_ulong(const __be32 *cell, int size)
>  #define OF_DYNAMIC	1 /* node and properties were allocated via kmalloc */
>  #define OF_DETACHED	2 /* node has been detached from the device tree */
>  #define OF_POPULATED	3 /* device already created for the node */
> +#define OF_ALLOCNAME	4 /* name was kmalloc-ed */
> +#define OF_ALLOCTYPE	5 /* type was kmalloc-ed */
> +#define OF_ALLOCFULL	6 /* full_name was kmalloc-ed */
> +#define OF_ALLOCVALUE	7 /* value was kmalloc-ed */
> +
> +#define OF_NODE_ALLOCALL \
> +	((1 << OF_ALLOCNAME) | (1 << OF_ALLOCTYPE) | (1 << OF_ALLOCFULL))
> +#define OF_PROP_ALLOCALL \
> +	((1 << OF_ALLOCNAME) | (1 << OF_ALLOCVALUE))
>  
>  #define OF_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags)
>  #define OF_MARK_DYNAMIC(x) set_bit(OF_DYNAMIC, &x->_flags)
> @@ -824,4 +833,37 @@ typedef void (*of_init_fn_1)(struct device_node *);
>  #define OF_DECLARE_2(table, name, compat, fn) \
>  		_OF_DECLARE(table, name, compat, fn, of_init_fn_2)
>  
> +/**
> + * General utilities for working with live trees.
> + *
> + * All functions with two leading underscores operate
> + * without taking node references, so you either have to
> + * own the devtree lock or work on detached trees only.
> + */
> +
> +#ifdef CONFIG_OF
> +
> +struct property *__of_copy_property(const struct property *prop,
> +		gfp_t allocflags, unsigned long propflags);
> +struct device_node *__of_create_empty_node(const char *name,
> +		const char *type, const char *full_name,
> +		phandle phandle, gfp_t allocflags, unsigned long nodeflags);
> +
> +#else /* !CONFIG_OF */
> +
> +static inline struct property *__of_copy_property(const struct property *prop,
> +		gfp_t allocflags, unsigned long propflags)
> +{
> +	return NULL;
> +}
> +
> +static inline struct device_node *__of_create_empty_node(const char *name,
> +		const char *type, const char *full_name,
> +		phandle phandle, gfp_t allocflags, unsigned long nodeflags)
> +{
> +	return NULL;
> +}
> +
> +#endif	/* !CONFIG_OF */
> +
>  #endif /* _LINUX_OF_H */
> 

-- 
Best regards,
Alexander Sverdlin.
--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH 5/6] OF: Utility helper functions for dynamic nodes
  2014-06-23 16:26     ` Alexander Sverdlin
  (?)
  (?)
@ 2014-06-23 16:57     ` Pantelis Antoniou
  2014-06-23 18:33       ` Ioan Nicu
  -1 siblings, 1 reply; 63+ messages in thread
From: Pantelis Antoniou @ 2014-06-23 16:57 UTC (permalink / raw)
  To: Alexander Sverdlin
  Cc: Grant Likely, Ionut Nicu, Rob Herring, Stephen Warren,
	Matt Porter, Koen Kooi, Greg Kroah-Hartman, Alison Chaiken,
	Dinh Nguyen, Jan Lubbe, Michael Stickel, Guenter Roeck,
	Dirk Behme, Alan Tull, Sascha Hauer, Michael Bohan, Michal Simek,
	Matt Ranostay, Joel Becker, devicetree, Wolfram Sang, linux-i2c,
	Mark Brown, linux-spi, linux-kernel, Pete Popov, Dan Malek,
	Georgi Vlaev

Hi Alexander,

On Jun 23, 2014, at 7:26 PM, Alexander Sverdlin wrote:

> Hello Pantelis!
> 
> On 22/06/14 11:40, ext Pantelis Antoniou wrote:
>> Introduce helper functions for working with the live DT tree,
>> all of them related to dynamically adding/removing nodes and
>> properties.
>> 
>> __of_copy_property() copies a property dynamically
>> __of_create_empty_node() creates an empty node
>> 
>> Bug fix about prop->len == 0 by Ionut Nicu <ioan.nicu.ext@nsn.com>
> 
> Are you sure about this? (see below...)
> 
>> Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
>> ---

[snip]
>> +
>> +	if (prop->length > 0) {
>        ^^^^^^^^^^^^^^^^^^^^^
> Seems, that length==0 case will still produce value==NULL results,
> which will brake some checks in the kernel... Or am I missing something in
> the new version?
> 

prop->value will be set to NULL, and length will be set to zero (kzalloc).
This is a normal zero length property.

I don't know of any place in the kernel accessing the value if prop->length==0


> 
>> +		if (of_property_check_flag(propn, OF_ALLOCVALUE)) {
>> +			propn->value = kmalloc(prop->length, allocflags);
>> +			if (propn->value == NULL)
>> +				goto err_fail_value;
>> +	

[snip]

>> +
>> #endif /* _LINUX_OF_H */
>> 
> 
> -- 
> Best regards,
> Alexander Sverdlin.

Regards

-- Pantelis

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

* Re: [PATCH 2/6] OF: Add [__]of_find_node_by_full_name
  2014-06-22  9:40 ` [PATCH 2/6] OF: Add [__]of_find_node_by_full_name Pantelis Antoniou
@ 2014-06-23 17:58   ` Guenter Roeck
  2014-06-23 18:00     ` Pantelis Antoniou
  2014-06-24 14:12   ` Grant Likely
  1 sibling, 1 reply; 63+ messages in thread
From: Guenter Roeck @ 2014-06-23 17:58 UTC (permalink / raw)
  To: Pantelis Antoniou, Grant Likely
  Cc: Rob Herring, Stephen Warren, Matt Porter, Koen Kooi,
	Greg Kroah-Hartman, Alison Chaiken, Dinh Nguyen, Jan Lubbe,
	Alexander Sverdlin, Michael Stickel, Dirk Behme, Alan Tull,
	Sascha Hauer, Michael Bohan, Ionut Nicu, Michal Simek,
	Matt Ranostay, Joel Becker, devicetree, Wolfram Sang, linux-i2c,
	Mark Brown, linux-spi, linux-kernel, Pete Popov, Dan Malek,
	Georgi Vlaev, Pantelis Antoniou

On 06/22/2014 02:40 AM, Pantelis Antoniou wrote:
> __of_find_node_by_full_name recursively searches for a matching node
> with the given full name without taking any locks.
>
> of_find_node_by_full_name takes locks and takes a reference on the
> matching node.
>
> Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
> ---
>   drivers/of/base.c  | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>   include/linux/of.h |  4 ++++
>   2 files changed, 62 insertions(+)
>
> diff --git a/drivers/of/base.c b/drivers/of/base.c
> index d3493e1..80fef33 100644
> --- a/drivers/of/base.c
> +++ b/drivers/of/base.c
> @@ -1201,6 +1201,64 @@ static void *of_find_property_value_of_size(const struct device_node *np,
>   }
>
>   /**
> + * __of_find_node_by_full_name - Find a node with the full name recursively
> + * @node:	Root of the tree to perform the search
> + * @full_name:	Full name of the node to find.
> + *
> + * Find a node with the give full name by recursively following any of
> + * the child node links.
> + * Returns the matching node, or NULL if not found.
> + * Note that the devtree lock is not taken, so this function is only
> + * safe to call on either detached trees, or when devtree lock is already
> + * taken.
> + */
> +struct device_node *__of_find_node_by_full_name(struct device_node *node,
> +		const char *full_name)
> +{
> +	struct device_node *child, *found;
> +
> +	if (node == NULL)
> +		return NULL;
> +
> +	/* check */
> +	if (of_node_cmp(node->full_name, full_name) == 0)
> +		return node;
> +
> +	__for_each_child_of_node(node, child) {
> +		found = __of_find_node_by_full_name(child, full_name);
> +		if (found != NULL)
> +			return found;
> +	}
> +
> +	return NULL;
> +}
> +EXPORT_SYMBOL(__of_find_node_by_full_name);
> +
> +/**
> + * of_find_node_by_full_name - Find a node with the full name recursively
> + * @node:	Root of the tree to perform the search
> + * @full_name:	Full name of the node to find.
> + *
> + * Find a node with the give full name by recursively following any of
> + * the child node links.
> + * Returns the matching node (with a ref taken), or NULL if not found.
> + */
> +struct device_node *of_find_node_by_full_name(struct device_node *node,
> +		const char *full_name)
> +{
> +	unsigned long flags;
> +	struct device_node *np;
> +
> +	raw_spin_lock_irqsave(&devtree_lock, flags);
> +	np = of_find_node_by_full_name(node, full_name);

Should this be __of_find_node_by_full_name, or am I missing something ?

Guenter

> +	of_node_get(np);
> +	raw_spin_unlock_irqrestore(&devtree_lock, flags);
> +
> +	return np;
> +}
> +EXPORT_SYMBOL(of_find_node_by_full_name);
> +
> +/**
>    * of_property_read_u32_index - Find and read a u32 from a multi-value property.
>    *
>    * @np:		device node from which the property value is to be read.
> diff --git a/include/linux/of.h b/include/linux/of.h
> index 196b34c..f7392c0 100644
> --- a/include/linux/of.h
> +++ b/include/linux/of.h
> @@ -230,6 +230,10 @@ extern struct device_node *of_find_matching_node_and_match(
>
>   extern struct device_node *of_find_node_by_path(const char *path);
>   extern struct device_node *of_find_node_by_phandle(phandle handle);
> +struct device_node *__of_find_node_by_full_name(struct device_node *node,
> +						const char *full_name);
> +struct device_node *of_find_node_by_full_name(struct device_node *node,
> +						const char *full_name);
>   extern struct device_node *of_get_parent(const struct device_node *node);
>   extern struct device_node *of_get_next_parent(struct device_node *node);
>   extern struct device_node *of_get_next_child(const struct device_node *node,
>

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

* Re: [PATCH 2/6] OF: Add [__]of_find_node_by_full_name
  2014-06-23 17:58   ` Guenter Roeck
@ 2014-06-23 18:00     ` Pantelis Antoniou
  2014-06-24 13:55         ` Grant Likely
  0 siblings, 1 reply; 63+ messages in thread
From: Pantelis Antoniou @ 2014-06-23 18:00 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Grant Likely, Rob Herring, Stephen Warren, Matt Porter,
	Koen Kooi, Greg Kroah-Hartman, Alison Chaiken, Dinh Nguyen,
	Jan Lubbe, Alexander Sverdlin, Michael Stickel, Dirk Behme,
	Alan Tull, Sascha Hauer, Michael Bohan, Ionut Nicu, Michal Simek,
	Matt Ranostay, Joel Becker, devicetree, Wolfram Sang, linux-i2c,
	Mark Brown, linux-spi, linux-kernel, Pete Popov, Dan Malek,
	Georgi Vlaev

Hi Guenter,

On Jun 23, 2014, at 8:58 PM, Guenter Roeck wrote:

> On 06/22/2014 02:40 AM, Pantelis Antoniou wrote:
>> __of_find_node_by_full_name recursively searches for a matching node
>> with the given full name without taking any locks.
>> 
>> of_find_node_by_full_name takes locks and takes a reference on the
>> matching node.
>> 
>> Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
>> ---
>>  drivers/of/base.c  | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>>  include/linux/of.h |  4 ++++
>>  2 files changed, 62 insertions(+)
>> 
>> diff --git a/drivers/of/base.c b/drivers/of/base.c
>> index d3493e1..80fef33 100644
>> --- a/drivers/of/base.c
>> +++ b/drivers/of/base.c
>> @@ -1201,6 +1201,64 @@ static void *of_find_property_value_of_size(const struct device_node *np,
>>  }
>> 
>>  /**
>> + * __of_find_node_by_full_name - Find a node with the full name recursively
>> + * @node:	Root of the tree to perform the search
>> + * @full_name:	Full name of the node to find.
>> + *
>> + * Find a node with the give full name by recursively following any of
>> + * the child node links.
>> + * Returns the matching node, or NULL if not found.
>> + * Note that the devtree lock is not taken, so this function is only
>> + * safe to call on either detached trees, or when devtree lock is already
>> + * taken.
>> + */
>> +struct device_node *__of_find_node_by_full_name(struct device_node *node,
>> +		const char *full_name)
>> +{
>> +	struct device_node *child, *found;
>> +
>> +	if (node == NULL)
>> +		return NULL;
>> +
>> +	/* check */
>> +	if (of_node_cmp(node->full_name, full_name) == 0)
>> +		return node;
>> +
>> +	__for_each_child_of_node(node, child) {
>> +		found = __of_find_node_by_full_name(child, full_name);
>> +		if (found != NULL)
>> +			return found;
>> +	}
>> +
>> +	return NULL;
>> +}
>> +EXPORT_SYMBOL(__of_find_node_by_full_name);
>> +
>> +/**
>> + * of_find_node_by_full_name - Find a node with the full name recursively
>> + * @node:	Root of the tree to perform the search
>> + * @full_name:	Full name of the node to find.
>> + *
>> + * Find a node with the give full name by recursively following any of
>> + * the child node links.
>> + * Returns the matching node (with a ref taken), or NULL if not found.
>> + */
>> +struct device_node *of_find_node_by_full_name(struct device_node *node,
>> +		const char *full_name)
>> +{
>> +	unsigned long flags;
>> +	struct device_node *np;
>> +
>> +	raw_spin_lock_irqsave(&devtree_lock, flags);
>> +	np = of_find_node_by_full_name(node, full_name);
> 
> Should this be __of_find_node_by_full_name, or am I missing something ?
> 

Ugh, you're not missing something. This slipped through since this is not 
used in the current code

Thanks!

> Guenter
> 

Regards

-- Pantelis

>> +	of_node_get(np);
>> +	raw_spin_unlock_irqrestore(&devtree_lock, flags);
>> +
>> +	return np;
>> +}
>> +EXPORT_SYMBOL(of_find_node_by_full_name);
>> +
>> +/**
>>   * of_property_read_u32_index - Find and read a u32 from a multi-value property.
>>   *
>>   * @np:		device node from which the property value is to be read.
>> diff --git a/include/linux/of.h b/include/linux/of.h
>> index 196b34c..f7392c0 100644
>> --- a/include/linux/of.h
>> +++ b/include/linux/of.h
>> @@ -230,6 +230,10 @@ extern struct device_node *of_find_matching_node_and_match(
>> 
>>  extern struct device_node *of_find_node_by_path(const char *path);
>>  extern struct device_node *of_find_node_by_phandle(phandle handle);
>> +struct device_node *__of_find_node_by_full_name(struct device_node *node,
>> +						const char *full_name);
>> +struct device_node *of_find_node_by_full_name(struct device_node *node,
>> +						const char *full_name);
>>  extern struct device_node *of_get_parent(const struct device_node *node);
>>  extern struct device_node *of_get_next_parent(struct device_node *node);
>>  extern struct device_node *of_get_next_child(const struct device_node *node,
>> 
> 

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

* Re: [PATCH 5/6] OF: Utility helper functions for dynamic nodes
  2014-06-23 16:57     ` Pantelis Antoniou
@ 2014-06-23 18:33       ` Ioan Nicu
  2014-06-23 19:13         ` Pantelis Antoniou
  2014-06-24  8:10           ` Alexander Sverdlin
  0 siblings, 2 replies; 63+ messages in thread
From: Ioan Nicu @ 2014-06-23 18:33 UTC (permalink / raw)
  To: ext Pantelis Antoniou
  Cc: Alexander Sverdlin, Grant Likely, Rob Herring, Stephen Warren,
	Matt Porter, Koen Kooi, Greg Kroah-Hartman, Alison Chaiken,
	Dinh Nguyen, Jan Lubbe, Michael Stickel, Guenter Roeck,
	Dirk Behme, Alan Tull, Sascha Hauer, Michael Bohan, Michal Simek,
	Matt Ranostay, Joel Becker, devicetree, Wolfram Sang, linux-i2c,
	Mark Brown, linux-spi, linux-kernel, Pete Popov, Dan Malek,
	Georgi Vlaev

Hi Pantelis,

On Mon, Jun 23, 2014 at 07:57:24PM +0300, ext Pantelis Antoniou wrote:
> Hi Alexander,
> 
> On Jun 23, 2014, at 7:26 PM, Alexander Sverdlin wrote:
> 
> > Hello Pantelis!
> > 
> > On 22/06/14 11:40, ext Pantelis Antoniou wrote:
> >> Introduce helper functions for working with the live DT tree,
> >> all of them related to dynamically adding/removing nodes and
> >> properties.
> >> 
> >> __of_copy_property() copies a property dynamically
> >> __of_create_empty_node() creates an empty node
> >> 
> >> Bug fix about prop->len == 0 by Ionut Nicu <ioan.nicu.ext@nsn.com>
> > 
> > Are you sure about this? (see below...)
> > 

Alexander is right, my fix was lost even though it's mentioned in this patch.

> >> Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
> >> ---
> 
> [snip]
> >> +
> >> +	if (prop->length > 0) {
> >        ^^^^^^^^^^^^^^^^^^^^^
> > Seems, that length==0 case will still produce value==NULL results,
> > which will brake some checks in the kernel... Or am I missing something in
> > the new version?
> > 
> 
> prop->value will be set to NULL, and length will be set to zero (kzalloc).
> This is a normal zero length property.
> 
> I don't know of any place in the kernel accessing the value if prop->length==0
> 

We have a simple use case. We have an overlay which adds an interrupt controller.
If you look in drivers/of/irq.c, in of_irq_parse_raw():

[...]
	/* Now start the actual "proper" walk of the interrupt tree */
	while (ipar != NULL) {
		/* Now check if cursor is an interrupt-controller and if it is
		 * then we are done
		 */
		if (of_get_property(ipar, "interrupt-controller", NULL) !=
				NULL) {
			pr_debug(" -> got it !\n");
			return 0;
		}
[...]

A node is identified as an interrupt controller if it has a zero-length property
called "interrupt-controller" but with a non-NULL value.

My proposed fix for this was to remove the if () condition. propn->value will be
allocated with kmalloc(0) which returns ZERO_SIZE_PTR which is != NULL.


> 
> [snip]
> 
> >> +
> >> #endif /* _LINUX_OF_H */
> >> 
> > 
> > -- 
> > Best regards,
> > Alexander Sverdlin.
> 
> Regards
> 
> -- Pantelis
> 

Regards,
Ionut Nicu

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

* Re: [PATCH 5/6] OF: Utility helper functions for dynamic nodes
  2014-06-23 18:33       ` Ioan Nicu
@ 2014-06-23 19:13         ` Pantelis Antoniou
  2014-06-23 19:48             ` Guenter Roeck
  2014-06-24  8:12             ` Alexander Sverdlin
  2014-06-24  8:10           ` Alexander Sverdlin
  1 sibling, 2 replies; 63+ messages in thread
From: Pantelis Antoniou @ 2014-06-23 19:13 UTC (permalink / raw)
  To: Ioan Nicu
  Cc: Alexander Sverdlin, Grant Likely, Rob Herring, Stephen Warren,
	Matt Porter, Koen Kooi, Greg Kroah-Hartman, Alison Chaiken,
	Dinh Nguyen, Jan Lubbe, Michael Stickel, Guenter Roeck,
	Dirk Behme, Alan Tull, Sascha Hauer, Michael Bohan, Michal Simek,
	Matt Ranostay, Joel Becker, devicetree, Wolfram Sang, linux-i2c,
	Mark Brown, linux-spi, linux-kernel, Pete Popov, Dan Malek,
	Georgi Vlaev

Hi Ioan,

I'm going to let Grant answer that but the code in question doesn't look right.

On Jun 23, 2014, at 9:33 PM, Ioan Nicu wrote:

> Hi Pantelis,
> 
> On Mon, Jun 23, 2014 at 07:57:24PM +0300, ext Pantelis Antoniou wrote:
>> Hi Alexander,
>> 
>> On Jun 23, 2014, at 7:26 PM, Alexander Sverdlin wrote:
>> 
>>> Hello Pantelis!
>>> 
>>> On 22/06/14 11:40, ext Pantelis Antoniou wrote:
>>>> Introduce helper functions for working with the live DT tree,
>>>> all of them related to dynamically adding/removing nodes and
>>>> properties.
>>>> 
>>>> __of_copy_property() copies a property dynamically
>>>> __of_create_empty_node() creates an empty node
>>>> 
>>>> Bug fix about prop->len == 0 by Ionut Nicu <ioan.nicu.ext@nsn.com>
>>> 
>>> Are you sure about this? (see below...)
>>> 
> 
> Alexander is right, my fix was lost even though it's mentioned in this patch.
> 

I'm sorry, I didn't understand that the intention of the fix was to address
the issue below.

>>>> Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
>>>> ---
>> 
>> [snip]
>>>> +
>>>> +	if (prop->length > 0) {
>>>       ^^^^^^^^^^^^^^^^^^^^^
>>> Seems, that length==0 case will still produce value==NULL results,
>>> which will brake some checks in the kernel... Or am I missing something in
>>> the new version?
>>> 
>> 
>> prop->value will be set to NULL, and length will be set to zero (kzalloc).
>> This is a normal zero length property.
>> 
>> I don't know of any place in the kernel accessing the value if prop->length==0
>> 
> 
> We have a simple use case. We have an overlay which adds an interrupt controller.
> If you look in drivers/of/irq.c, in of_irq_parse_raw():
> 
> [...]
> 	/* Now start the actual "proper" walk of the interrupt tree */
> 	while (ipar != NULL) {
> 		/* Now check if cursor is an interrupt-controller and if it is
> 		 * then we are done
> 		 */
> 		if (of_get_property(ipar, "interrupt-controller", NULL) !=
> 				NULL) {
> 			pr_debug(" -> got it !\n");
> 			return 0;
> 		}
> [...]
> 
> A node is identified as an interrupt controller if it has a zero-length property
> called "interrupt-controller" but with a non-NULL value.
> 
> My proposed fix for this was to remove the if () condition. propn->value will be
> allocated with kmalloc(0) which returns ZERO_SIZE_PTR which is != NULL.
> 

If that's the case, the code in irq.c is wrong.

interrupt-controller is a bool property; the correct call to use is of_property_read_bool()
which returns true or false when the value is defined.

The use of of_get_property is a bug here. It is perfectly valid for a property to have a
NULL value when length = 0.

Regards

-- Pantelis

> 
>> 
>> [snip]
>> 
>>>> +
>>>> #endif /* _LINUX_OF_H */
>>>> 
>>> 
>>> -- 
>>> Best regards,
>>> Alexander Sverdlin.
>> 
>> Regards
>> 
>> -- Pantelis
>> 
> 
> Regards,
> Ionut Nicu

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

* Re: [PATCH 5/6] OF: Utility helper functions for dynamic nodes
@ 2014-06-23 19:48             ` Guenter Roeck
  0 siblings, 0 replies; 63+ messages in thread
From: Guenter Roeck @ 2014-06-23 19:48 UTC (permalink / raw)
  To: Pantelis Antoniou, Ioan Nicu
  Cc: Alexander Sverdlin, Grant Likely, Rob Herring, Stephen Warren,
	Matt Porter, Koen Kooi, Greg Kroah-Hartman, Alison Chaiken,
	Dinh Nguyen, Jan Lubbe, Michael Stickel, Dirk Behme, Alan Tull,
	Sascha Hauer, Michael Bohan, Michal Simek, Matt Ranostay,
	Joel Becker, devicetree, Wolfram Sang, linux-i2c, Mark Brown,
	linux-spi, linux-kernel, Pete Popov, Dan Malek, Georgi Vlaev

On 06/23/2014 12:13 PM, Pantelis Antoniou wrote:
> Hi Ioan,
>
> I'm going to let Grant answer that but the code in question doesn't look right.
>
> On Jun 23, 2014, at 9:33 PM, Ioan Nicu wrote:
>
>> Hi Pantelis,
>>
>> On Mon, Jun 23, 2014 at 07:57:24PM +0300, ext Pantelis Antoniou wrote:
>>> Hi Alexander,
>>>
>>> On Jun 23, 2014, at 7:26 PM, Alexander Sverdlin wrote:
>>>
>>>> Hello Pantelis!
>>>>
>>>> On 22/06/14 11:40, ext Pantelis Antoniou wrote:
>>>>> Introduce helper functions for working with the live DT tree,
>>>>> all of them related to dynamically adding/removing nodes and
>>>>> properties.
>>>>>
>>>>> __of_copy_property() copies a property dynamically
>>>>> __of_create_empty_node() creates an empty node
>>>>>
>>>>> Bug fix about prop->len == 0 by Ionut Nicu <ioan.nicu.ext@nsn.com>
>>>>
>>>> Are you sure about this? (see below...)
>>>>
>>
>> Alexander is right, my fix was lost even though it's mentioned in this patch.
>>
>
> I'm sorry, I didn't understand that the intention of the fix was to address
> the issue below.
>
>>>>> Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
>>>>> ---
>>>
>>> [snip]
>>>>> +
>>>>> +	if (prop->length > 0) {
>>>>        ^^^^^^^^^^^^^^^^^^^^^
>>>> Seems, that length==0 case will still produce value==NULL results,
>>>> which will brake some checks in the kernel... Or am I missing something in
>>>> the new version?
>>>>
>>>
>>> prop->value will be set to NULL, and length will be set to zero (kzalloc).
>>> This is a normal zero length property.
>>>
>>> I don't know of any place in the kernel accessing the value if prop->length==0
>>>
>>
>> We have a simple use case. We have an overlay which adds an interrupt controller.
>> If you look in drivers/of/irq.c, in of_irq_parse_raw():
>>
>> [...]
>> 	/* Now start the actual "proper" walk of the interrupt tree */
>> 	while (ipar != NULL) {
>> 		/* Now check if cursor is an interrupt-controller and if it is
>> 		 * then we are done
>> 		 */
>> 		if (of_get_property(ipar, "interrupt-controller", NULL) !=
>> 				NULL) {
>> 			pr_debug(" -> got it !\n");
>> 			return 0;
>> 		}
>> [...]
>>
>> A node is identified as an interrupt controller if it has a zero-length property
>> called "interrupt-controller" but with a non-NULL value.
>>
>> My proposed fix for this was to remove the if () condition. propn->value will be
>> allocated with kmalloc(0) which returns ZERO_SIZE_PTR which is != NULL.
>>
>
> If that's the case, the code in irq.c is wrong.
>
> interrupt-controller is a bool property; the correct call to use is of_property_read_bool()
> which returns true or false when the value is defined.
>
> The use of of_get_property is a bug here. It is perfectly valid for a property to have a
> NULL value when length = 0.
>

That usage is spread throughout the code though. There are three or four similar checks
for interrupt-controller in the code, and many others using of_get_property() to check
for booleans.

Some examples:
	s5m8767,pmic-buck2-ramp-enable
	s5m8767,pmic-buck3-ramp-enable
	s5m8767,pmic-buck4-ramp-enable
	d7s-flipped?
	atmel,use-dma-rx
	linux,rs485-enabled-at-boot-time
	marvell,enable-port1 (and many others)
	linux,bootx-noscreen
	linux,opened

and many many others.

Maybe people meant to use of_find_property() ?

Either case, if the new code depends on proper use of of_get_property(), we may have
a problem unless all those bad use cases are fixed.

Guenter


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

* Re: [PATCH 5/6] OF: Utility helper functions for dynamic nodes
@ 2014-06-23 19:48             ` Guenter Roeck
  0 siblings, 0 replies; 63+ messages in thread
From: Guenter Roeck @ 2014-06-23 19:48 UTC (permalink / raw)
  To: Pantelis Antoniou, Ioan Nicu
  Cc: Alexander Sverdlin, Grant Likely, Rob Herring, Stephen Warren,
	Matt Porter, Koen Kooi, Greg Kroah-Hartman, Alison Chaiken,
	Dinh Nguyen, Jan Lubbe, Michael Stickel, Dirk Behme, Alan Tull,
	Sascha Hauer, Michael Bohan, Michal Simek, Matt Ranostay,
	Joel Becker, devicetree-u79uwXL29TY76Z2rM5mHXA, Wolfram Sang,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA, Mark Brown,
	linux-spi-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA

On 06/23/2014 12:13 PM, Pantelis Antoniou wrote:
> Hi Ioan,
>
> I'm going to let Grant answer that but the code in question doesn't look right.
>
> On Jun 23, 2014, at 9:33 PM, Ioan Nicu wrote:
>
>> Hi Pantelis,
>>
>> On Mon, Jun 23, 2014 at 07:57:24PM +0300, ext Pantelis Antoniou wrote:
>>> Hi Alexander,
>>>
>>> On Jun 23, 2014, at 7:26 PM, Alexander Sverdlin wrote:
>>>
>>>> Hello Pantelis!
>>>>
>>>> On 22/06/14 11:40, ext Pantelis Antoniou wrote:
>>>>> Introduce helper functions for working with the live DT tree,
>>>>> all of them related to dynamically adding/removing nodes and
>>>>> properties.
>>>>>
>>>>> __of_copy_property() copies a property dynamically
>>>>> __of_create_empty_node() creates an empty node
>>>>>
>>>>> Bug fix about prop->len == 0 by Ionut Nicu <ioan.nicu.ext-OYasijW0DpE@public.gmane.org>
>>>>
>>>> Are you sure about this? (see below...)
>>>>
>>
>> Alexander is right, my fix was lost even though it's mentioned in this patch.
>>
>
> I'm sorry, I didn't understand that the intention of the fix was to address
> the issue below.
>
>>>>> Signed-off-by: Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
>>>>> ---
>>>
>>> [snip]
>>>>> +
>>>>> +	if (prop->length > 0) {
>>>>        ^^^^^^^^^^^^^^^^^^^^^
>>>> Seems, that length==0 case will still produce value==NULL results,
>>>> which will brake some checks in the kernel... Or am I missing something in
>>>> the new version?
>>>>
>>>
>>> prop->value will be set to NULL, and length will be set to zero (kzalloc).
>>> This is a normal zero length property.
>>>
>>> I don't know of any place in the kernel accessing the value if prop->length==0
>>>
>>
>> We have a simple use case. We have an overlay which adds an interrupt controller.
>> If you look in drivers/of/irq.c, in of_irq_parse_raw():
>>
>> [...]
>> 	/* Now start the actual "proper" walk of the interrupt tree */
>> 	while (ipar != NULL) {
>> 		/* Now check if cursor is an interrupt-controller and if it is
>> 		 * then we are done
>> 		 */
>> 		if (of_get_property(ipar, "interrupt-controller", NULL) !=
>> 				NULL) {
>> 			pr_debug(" -> got it !\n");
>> 			return 0;
>> 		}
>> [...]
>>
>> A node is identified as an interrupt controller if it has a zero-length property
>> called "interrupt-controller" but with a non-NULL value.
>>
>> My proposed fix for this was to remove the if () condition. propn->value will be
>> allocated with kmalloc(0) which returns ZERO_SIZE_PTR which is != NULL.
>>
>
> If that's the case, the code in irq.c is wrong.
>
> interrupt-controller is a bool property; the correct call to use is of_property_read_bool()
> which returns true or false when the value is defined.
>
> The use of of_get_property is a bug here. It is perfectly valid for a property to have a
> NULL value when length = 0.
>

That usage is spread throughout the code though. There are three or four similar checks
for interrupt-controller in the code, and many others using of_get_property() to check
for booleans.

Some examples:
	s5m8767,pmic-buck2-ramp-enable
	s5m8767,pmic-buck3-ramp-enable
	s5m8767,pmic-buck4-ramp-enable
	d7s-flipped?
	atmel,use-dma-rx
	linux,rs485-enabled-at-boot-time
	marvell,enable-port1 (and many others)
	linux,bootx-noscreen
	linux,opened

and many many others.

Maybe people meant to use of_find_property() ?

Either case, if the new code depends on proper use of of_get_property(), we may have
a problem unless all those bad use cases are fixed.

Guenter

--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH 5/6] OF: Utility helper functions for dynamic nodes
@ 2014-06-23 19:48             ` Guenter Roeck
  0 siblings, 0 replies; 63+ messages in thread
From: Guenter Roeck @ 2014-06-23 19:48 UTC (permalink / raw)
  To: Pantelis Antoniou, Ioan Nicu
  Cc: Alexander Sverdlin, Grant Likely, Rob Herring, Stephen Warren,
	Matt Porter, Koen Kooi, Greg Kroah-Hartman, Alison Chaiken,
	Dinh Nguyen, Jan Lubbe, Michael Stickel, Dirk Behme, Alan Tull,
	Sascha Hauer, Michael Bohan, Michal Simek, Matt Ranostay,
	Joel Becker, devicetree-u79uwXL29TY76Z2rM5mHXA, Wolfram Sang,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA, Mark Brown,
	linux-spi-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Pe

On 06/23/2014 12:13 PM, Pantelis Antoniou wrote:
> Hi Ioan,
>
> I'm going to let Grant answer that but the code in question doesn't look right.
>
> On Jun 23, 2014, at 9:33 PM, Ioan Nicu wrote:
>
>> Hi Pantelis,
>>
>> On Mon, Jun 23, 2014 at 07:57:24PM +0300, ext Pantelis Antoniou wrote:
>>> Hi Alexander,
>>>
>>> On Jun 23, 2014, at 7:26 PM, Alexander Sverdlin wrote:
>>>
>>>> Hello Pantelis!
>>>>
>>>> On 22/06/14 11:40, ext Pantelis Antoniou wrote:
>>>>> Introduce helper functions for working with the live DT tree,
>>>>> all of them related to dynamically adding/removing nodes and
>>>>> properties.
>>>>>
>>>>> __of_copy_property() copies a property dynamically
>>>>> __of_create_empty_node() creates an empty node
>>>>>
>>>>> Bug fix about prop->len == 0 by Ionut Nicu <ioan.nicu.ext-OYasijW0DpE@public.gmane.org>
>>>>
>>>> Are you sure about this? (see below...)
>>>>
>>
>> Alexander is right, my fix was lost even though it's mentioned in this patch.
>>
>
> I'm sorry, I didn't understand that the intention of the fix was to address
> the issue below.
>
>>>>> Signed-off-by: Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
>>>>> ---
>>>
>>> [snip]
>>>>> +
>>>>> +	if (prop->length > 0) {
>>>>        ^^^^^^^^^^^^^^^^^^^^^
>>>> Seems, that length==0 case will still produce value==NULL results,
>>>> which will brake some checks in the kernel... Or am I missing something in
>>>> the new version?
>>>>
>>>
>>> prop->value will be set to NULL, and length will be set to zero (kzalloc).
>>> This is a normal zero length property.
>>>
>>> I don't know of any place in the kernel accessing the value if prop->length==0
>>>
>>
>> We have a simple use case. We have an overlay which adds an interrupt controller.
>> If you look in drivers/of/irq.c, in of_irq_parse_raw():
>>
>> [...]
>> 	/* Now start the actual "proper" walk of the interrupt tree */
>> 	while (ipar != NULL) {
>> 		/* Now check if cursor is an interrupt-controller and if it is
>> 		 * then we are done
>> 		 */
>> 		if (of_get_property(ipar, "interrupt-controller", NULL) !=
>> 				NULL) {
>> 			pr_debug(" -> got it !\n");
>> 			return 0;
>> 		}
>> [...]
>>
>> A node is identified as an interrupt controller if it has a zero-length property
>> called "interrupt-controller" but with a non-NULL value.
>>
>> My proposed fix for this was to remove the if () condition. propn->value will be
>> allocated with kmalloc(0) which returns ZERO_SIZE_PTR which is != NULL.
>>
>
> If that's the case, the code in irq.c is wrong.
>
> interrupt-controller is a bool property; the correct call to use is of_property_read_bool()
> which returns true or false when the value is defined.
>
> The use of of_get_property is a bug here. It is perfectly valid for a property to have a
> NULL value when length = 0.
>

That usage is spread throughout the code though. There are three or four similar checks
for interrupt-controller in the code, and many others using of_get_property() to check
for booleans.

Some examples:
	s5m8767,pmic-buck2-ramp-enable
	s5m8767,pmic-buck3-ramp-enable
	s5m8767,pmic-buck4-ramp-enable
	d7s-flipped?
	atmel,use-dma-rx
	linux,rs485-enabled-at-boot-time
	marvell,enable-port1 (and many others)
	linux,bootx-noscreen
	linux,opened

and many many others.

Maybe people meant to use of_find_property() ?

Either case, if the new code depends on proper use of of_get_property(), we may have
a problem unless all those bad use cases are fixed.

Guenter

--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH 5/6] OF: Utility helper functions for dynamic nodes
  2014-06-23 19:48             ` Guenter Roeck
  (?)
  (?)
@ 2014-06-23 20:39             ` Ioan Nicu
  -1 siblings, 0 replies; 63+ messages in thread
From: Ioan Nicu @ 2014-06-23 20:39 UTC (permalink / raw)
  To: ext Guenter Roeck
  Cc: Pantelis Antoniou, Alexander Sverdlin, Grant Likely, Rob Herring,
	Stephen Warren, Matt Porter, Koen Kooi, Greg Kroah-Hartman,
	Alison Chaiken, Dinh Nguyen, Jan Lubbe, Michael Stickel,
	Dirk Behme, Alan Tull, Sascha Hauer, Michael Bohan, Michal Simek,
	Matt Ranostay, Joel Becker, devicetree, Wolfram Sang, linux-i2c,
	Mark Brown, linux-spi, linux-kernel, Pete Popov, Dan Malek,
	Georgi Vlaev

Hi,

On Mon, Jun 23, 2014 at 12:48:26PM -0700, ext Guenter Roeck wrote:
> On 06/23/2014 12:13 PM, Pantelis Antoniou wrote:
> >Hi Ioan,
> >
> >I'm going to let Grant answer that but the code in question doesn't look right.
> >
> >On Jun 23, 2014, at 9:33 PM, Ioan Nicu wrote:
> >
> >>Hi Pantelis,
> >>
> >>On Mon, Jun 23, 2014 at 07:57:24PM +0300, ext Pantelis Antoniou wrote:
> >>>Hi Alexander,
> >>>
> >>>On Jun 23, 2014, at 7:26 PM, Alexander Sverdlin wrote:
> >>>
> >>>>Hello Pantelis!
> >>>>
> >>>>On 22/06/14 11:40, ext Pantelis Antoniou wrote:
> >>>>>Introduce helper functions for working with the live DT tree,
> >>>>>all of them related to dynamically adding/removing nodes and
> >>>>>properties.
> >>>>>
> >>>>>__of_copy_property() copies a property dynamically
> >>>>>__of_create_empty_node() creates an empty node
> >>>>>
> >>>>>Bug fix about prop->len == 0 by Ionut Nicu <ioan.nicu.ext@nsn.com>
> >>>>
> >>>>Are you sure about this? (see below...)
> >>>>
> >>
> >>Alexander is right, my fix was lost even though it's mentioned in this patch.
> >>
> >
> >I'm sorry, I didn't understand that the intention of the fix was to address
> >the issue below.
> >
> >>>>>Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
> >>>>>---
> >>>
> >>>[snip]
> >>>>>+
> >>>>>+	if (prop->length > 0) {
> >>>>       ^^^^^^^^^^^^^^^^^^^^^
> >>>>Seems, that length==0 case will still produce value==NULL results,
> >>>>which will brake some checks in the kernel... Or am I missing something in
> >>>>the new version?
> >>>>
> >>>
> >>>prop->value will be set to NULL, and length will be set to zero (kzalloc).
> >>>This is a normal zero length property.
> >>>
> >>>I don't know of any place in the kernel accessing the value if prop->length==0
> >>>
> >>
> >>We have a simple use case. We have an overlay which adds an interrupt controller.
> >>If you look in drivers/of/irq.c, in of_irq_parse_raw():
> >>
> >>[...]
> >>	/* Now start the actual "proper" walk of the interrupt tree */
> >>	while (ipar != NULL) {
> >>		/* Now check if cursor is an interrupt-controller and if it is
> >>		 * then we are done
> >>		 */
> >>		if (of_get_property(ipar, "interrupt-controller", NULL) !=
> >>				NULL) {
> >>			pr_debug(" -> got it !\n");
> >>			return 0;
> >>		}
> >>[...]
> >>
> >>A node is identified as an interrupt controller if it has a zero-length property
> >>called "interrupt-controller" but with a non-NULL value.
> >>
> >>My proposed fix for this was to remove the if () condition. propn->value will be
> >>allocated with kmalloc(0) which returns ZERO_SIZE_PTR which is != NULL.
> >>
> >
> >If that's the case, the code in irq.c is wrong.
> >
> >interrupt-controller is a bool property; the correct call to use is of_property_read_bool()
> >which returns true or false when the value is defined.
> >
> >The use of of_get_property is a bug here. It is perfectly valid for a property to have a
> >NULL value when length = 0.
> >
> 
> That usage is spread throughout the code though. There are three or four similar checks
> for interrupt-controller in the code, and many others using of_get_property() to check
> for booleans.
> 
> Some examples:
> 	s5m8767,pmic-buck2-ramp-enable
> 	s5m8767,pmic-buck3-ramp-enable
> 	s5m8767,pmic-buck4-ramp-enable
> 	d7s-flipped?
> 	atmel,use-dma-rx
> 	linux,rs485-enabled-at-boot-time
> 	marvell,enable-port1 (and many others)
> 	linux,bootx-noscreen
> 	linux,opened
> 
> and many many others.
> 
> Maybe people meant to use of_find_property() ?
> 
> Either case, if the new code depends on proper use of of_get_property(), we may have
> a problem unless all those bad use cases are fixed.
> 

That's the real problem. If you look at unflatten_device_tree()/unflatten_dt_node(), you will
see that those boolean properties which have prop->length == 0 will be initialized with a
prop->value != NULL.

Even if it's not conceptually correct, there are some places in the kernel where people call
of_get_property() instead of of_find_property() for those properties, and rely on the fact that
the value is not NULL.

I would also like to hear Grant's opinion for this. Based on that we could either use my simple
fix for your patch, or try to fix all existing use cases in the kernel for this zero length
properties.

Ionut

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

* Re: [PATCH 5/6] OF: Utility helper functions for dynamic nodes
  2014-06-23 18:33       ` Ioan Nicu
  2014-06-23 19:13         ` Pantelis Antoniou
@ 2014-06-24  8:10           ` Alexander Sverdlin
  1 sibling, 0 replies; 63+ messages in thread
From: Alexander Sverdlin @ 2014-06-24  8:10 UTC (permalink / raw)
  To: Ioan Nicu, ext Pantelis Antoniou, Grant Likely
  Cc: Rob Herring, Stephen Warren, Matt Porter, Koen Kooi,
	Greg Kroah-Hartman, Alison Chaiken, Dinh Nguyen, Jan Lubbe,
	Michael Stickel, Guenter Roeck, Dirk Behme, Alan Tull,
	Sascha Hauer, Michael Bohan, Michal Simek, Matt Ranostay,
	Joel Becker, devicetree, Wolfram Sang, linux-i2c, Mark Brown,
	linux-spi, linux-kernel, Pete Popov, Dan Malek, Georgi Vlaev

Hi Pantelis, Grant,

On 23/06/14 20:33, Ioan Nicu wrote:
>>> On 22/06/14 11:40, ext Pantelis Antoniou wrote:
>>>> Introduce helper functions for working with the live DT tree,
>>>> all of them related to dynamically adding/removing nodes and
>>>> properties.
>>>>
>>>> __of_copy_property() copies a property dynamically
>>>> __of_create_empty_node() creates an empty node
>>>>
>>>> Bug fix about prop->len == 0 by Ionut Nicu <ioan.nicu.ext@nsn.com>
>>>
>>> Are you sure about this? (see below...)
>>>
> 
> Alexander is right, my fix was lost even though it's mentioned in this patch.
> 
>>>> Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
>>>> ---
>>
>> [snip]
>>>> +
>>>> +	if (prop->length > 0) {
>>>        ^^^^^^^^^^^^^^^^^^^^^
>>> Seems, that length==0 case will still produce value==NULL results,
>>> which will brake some checks in the kernel... Or am I missing something in
>>> the new version?
>>>
>>
>> prop->value will be set to NULL, and length will be set to zero (kzalloc).
>> This is a normal zero length property.
>>
>> I don't know of any place in the kernel accessing the value if prop->length==0
>>
> 
> We have a simple use case. We have an overlay which adds an interrupt controller.
> If you look in drivers/of/irq.c, in of_irq_parse_raw():
> 
> [...]
> 	/* Now start the actual "proper" walk of the interrupt tree */
> 	while (ipar != NULL) {
> 		/* Now check if cursor is an interrupt-controller and if it is
> 		 * then we are done
> 		 */
> 		if (of_get_property(ipar, "interrupt-controller", NULL) !=

We have to define, if it's allowed for an empty property to have NULL value.
Several places in the kernel use of_get_property() to check for property existence.
We either have to make a tree-wide patch and replace of_get_property() with of_find_property() in those cases,
or ensure value != NULL in this copy function...

Grant, what do you think?

> 				NULL) {
> 			pr_debug(" -> got it !\n");
> 			return 0;
> 		}
> [...]
> 
> A node is identified as an interrupt controller if it has a zero-length property
> called "interrupt-controller" but with a non-NULL value.
> 
> My proposed fix for this was to remove the if () condition. propn->value will be
> allocated with kmalloc(0) which returns ZERO_SIZE_PTR which is != NULL.
> 
> 
>>
>> [snip]
>>
>>>> +
>>>> #endif /* _LINUX_OF_H */
>>>>
>>>
>>> -- 
>>> Best regards,
>>> Alexander Sverdlin.
>>
>> Regards
>>
>> -- Pantelis
>>
> 
> Regards,
> Ionut Nicu
> 

-- 
Best regards,
Alexander Sverdlin.

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

* Re: [PATCH 5/6] OF: Utility helper functions for dynamic nodes
@ 2014-06-24  8:10           ` Alexander Sverdlin
  0 siblings, 0 replies; 63+ messages in thread
From: Alexander Sverdlin @ 2014-06-24  8:10 UTC (permalink / raw)
  To: Ioan Nicu, ext Pantelis Antoniou, Grant Likely
  Cc: Rob Herring, Stephen Warren, Matt Porter, Koen Kooi,
	Greg Kroah-Hartman, Alison Chaiken, Dinh Nguyen, Jan Lubbe,
	Michael Stickel, Guenter Roeck, Dirk Behme, Alan Tull,
	Sascha Hauer, Michael Bohan, Michal Simek, Matt Ranostay,
	Joel Becker, devicetree-u79uwXL29TY76Z2rM5mHXA, Wolfram Sang,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA, Mark Brown,
	linux-spi-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Pete Popov, Dan Malek

Hi Pantelis, Grant,

On 23/06/14 20:33, Ioan Nicu wrote:
>>> On 22/06/14 11:40, ext Pantelis Antoniou wrote:
>>>> Introduce helper functions for working with the live DT tree,
>>>> all of them related to dynamically adding/removing nodes and
>>>> properties.
>>>>
>>>> __of_copy_property() copies a property dynamically
>>>> __of_create_empty_node() creates an empty node
>>>>
>>>> Bug fix about prop->len == 0 by Ionut Nicu <ioan.nicu.ext-OYasijW0DpE@public.gmane.org>
>>>
>>> Are you sure about this? (see below...)
>>>
> 
> Alexander is right, my fix was lost even though it's mentioned in this patch.
> 
>>>> Signed-off-by: Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
>>>> ---
>>
>> [snip]
>>>> +
>>>> +	if (prop->length > 0) {
>>>        ^^^^^^^^^^^^^^^^^^^^^
>>> Seems, that length==0 case will still produce value==NULL results,
>>> which will brake some checks in the kernel... Or am I missing something in
>>> the new version?
>>>
>>
>> prop->value will be set to NULL, and length will be set to zero (kzalloc).
>> This is a normal zero length property.
>>
>> I don't know of any place in the kernel accessing the value if prop->length==0
>>
> 
> We have a simple use case. We have an overlay which adds an interrupt controller.
> If you look in drivers/of/irq.c, in of_irq_parse_raw():
> 
> [...]
> 	/* Now start the actual "proper" walk of the interrupt tree */
> 	while (ipar != NULL) {
> 		/* Now check if cursor is an interrupt-controller and if it is
> 		 * then we are done
> 		 */
> 		if (of_get_property(ipar, "interrupt-controller", NULL) !=

We have to define, if it's allowed for an empty property to have NULL value.
Several places in the kernel use of_get_property() to check for property existence.
We either have to make a tree-wide patch and replace of_get_property() with of_find_property() in those cases,
or ensure value != NULL in this copy function...

Grant, what do you think?

> 				NULL) {
> 			pr_debug(" -> got it !\n");
> 			return 0;
> 		}
> [...]
> 
> A node is identified as an interrupt controller if it has a zero-length property
> called "interrupt-controller" but with a non-NULL value.
> 
> My proposed fix for this was to remove the if () condition. propn->value will be
> allocated with kmalloc(0) which returns ZERO_SIZE_PTR which is != NULL.
> 
> 
>>
>> [snip]
>>
>>>> +
>>>> #endif /* _LINUX_OF_H */
>>>>
>>>
>>> -- 
>>> Best regards,
>>> Alexander Sverdlin.
>>
>> Regards
>>
>> -- Pantelis
>>
> 
> Regards,
> Ionut Nicu
> 

-- 
Best regards,
Alexander Sverdlin.

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

* Re: [PATCH 5/6] OF: Utility helper functions for dynamic nodes
@ 2014-06-24  8:10           ` Alexander Sverdlin
  0 siblings, 0 replies; 63+ messages in thread
From: Alexander Sverdlin @ 2014-06-24  8:10 UTC (permalink / raw)
  To: Ioan Nicu, ext Pantelis Antoniou, Grant Likely
  Cc: Rob Herring, Stephen Warren, Matt Porter, Koen Kooi,
	Greg Kroah-Hartman, Alison Chaiken, Dinh Nguyen, Jan Lubbe,
	Michael Stickel, Guenter Roeck, Dirk Behme, Alan Tull,
	Sascha Hauer, Michael Bohan, Michal Simek, Matt Ranostay,
	Joel Becker, devicetree-u79uwXL29TY76Z2rM5mHXA, Wolfram Sang,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA, Mark Brown,
	linux-spi-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Pete Popov, Dan Malek

Hi Pantelis, Grant,

On 23/06/14 20:33, Ioan Nicu wrote:
>>> On 22/06/14 11:40, ext Pantelis Antoniou wrote:
>>>> Introduce helper functions for working with the live DT tree,
>>>> all of them related to dynamically adding/removing nodes and
>>>> properties.
>>>>
>>>> __of_copy_property() copies a property dynamically
>>>> __of_create_empty_node() creates an empty node
>>>>
>>>> Bug fix about prop->len == 0 by Ionut Nicu <ioan.nicu.ext-OYasijW0DpE@public.gmane.org>
>>>
>>> Are you sure about this? (see below...)
>>>
> 
> Alexander is right, my fix was lost even though it's mentioned in this patch.
> 
>>>> Signed-off-by: Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
>>>> ---
>>
>> [snip]
>>>> +
>>>> +	if (prop->length > 0) {
>>>        ^^^^^^^^^^^^^^^^^^^^^
>>> Seems, that length==0 case will still produce value==NULL results,
>>> which will brake some checks in the kernel... Or am I missing something in
>>> the new version?
>>>
>>
>> prop->value will be set to NULL, and length will be set to zero (kzalloc).
>> This is a normal zero length property.
>>
>> I don't know of any place in the kernel accessing the value if prop->length==0
>>
> 
> We have a simple use case. We have an overlay which adds an interrupt controller.
> If you look in drivers/of/irq.c, in of_irq_parse_raw():
> 
> [...]
> 	/* Now start the actual "proper" walk of the interrupt tree */
> 	while (ipar != NULL) {
> 		/* Now check if cursor is an interrupt-controller and if it is
> 		 * then we are done
> 		 */
> 		if (of_get_property(ipar, "interrupt-controller", NULL) !=

We have to define, if it's allowed for an empty property to have NULL value.
Several places in the kernel use of_get_property() to check for property existence.
We either have to make a tree-wide patch and replace of_get_property() with of_find_property() in those cases,
or ensure value != NULL in this copy function...

Grant, what do you think?

> 				NULL) {
> 			pr_debug(" -> got it !\n");
> 			return 0;
> 		}
> [...]
> 
> A node is identified as an interrupt controller if it has a zero-length property
> called "interrupt-controller" but with a non-NULL value.
> 
> My proposed fix for this was to remove the if () condition. propn->value will be
> allocated with kmalloc(0) which returns ZERO_SIZE_PTR which is != NULL.
> 
> 
>>
>> [snip]
>>
>>>> +
>>>> #endif /* _LINUX_OF_H */
>>>>
>>>
>>> -- 
>>> Best regards,
>>> Alexander Sverdlin.
>>
>> Regards
>>
>> -- Pantelis
>>
> 
> Regards,
> Ionut Nicu
> 

-- 
Best regards,
Alexander Sverdlin.

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

* Re: [PATCH 5/6] OF: Utility helper functions for dynamic nodes
@ 2014-06-24  8:12             ` Alexander Sverdlin
  0 siblings, 0 replies; 63+ messages in thread
From: Alexander Sverdlin @ 2014-06-24  8:12 UTC (permalink / raw)
  To: ext Pantelis Antoniou, Ioan Nicu
  Cc: Grant Likely, Rob Herring, Stephen Warren, Matt Porter,
	Koen Kooi, Greg Kroah-Hartman, Alison Chaiken, Dinh Nguyen,
	Jan Lubbe, Michael Stickel, Guenter Roeck, Dirk Behme, Alan Tull,
	Sascha Hauer, Michael Bohan, Michal Simek, Matt Ranostay,
	Joel Becker, devicetree, Wolfram Sang, linux-i2c, Mark Brown,
	linux-spi, linux-kernel, Pete Popov, Dan Malek, Georgi Vlaev

Hi!

On 23/06/14 21:13, ext Pantelis Antoniou wrote:

[...]

>>> I don't know of any place in the kernel accessing the value if prop->length==0
>>>
>>
>> We have a simple use case. We have an overlay which adds an interrupt controller.
>> If you look in drivers/of/irq.c, in of_irq_parse_raw():
>>
>> [...]
>> 	/* Now start the actual "proper" walk of the interrupt tree */
>> 	while (ipar != NULL) {
>> 		/* Now check if cursor is an interrupt-controller and if it is
>> 		 * then we are done
>> 		 */
>> 		if (of_get_property(ipar, "interrupt-controller", NULL) !=
>> 				NULL) {
>> 			pr_debug(" -> got it !\n");
>> 			return 0;
>> 		}
>> [...]
>>
>> A node is identified as an interrupt controller if it has a zero-length property
>> called "interrupt-controller" but with a non-NULL value.
>>
>> My proposed fix for this was to remove the if () condition. propn->value will be
>> allocated with kmalloc(0) which returns ZERO_SIZE_PTR which is != NULL.
>>
> 
> If that's the case, the code in irq.c is wrong.
> 
> interrupt-controller is a bool property; the correct call to use is of_property_read_bool()
> which returns true or false when the value is defined.

No, it's not bool... It's an existence of a void property. 

> The use of of_get_property is a bug here. It is perfectly valid for a property to have a
> NULL value when length = 0.

of_find_property() would be really correct in this particular case...

-- 
Best regards,
Alexander Sverdlin.

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

* Re: [PATCH 5/6] OF: Utility helper functions for dynamic nodes
@ 2014-06-24  8:12             ` Alexander Sverdlin
  0 siblings, 0 replies; 63+ messages in thread
From: Alexander Sverdlin @ 2014-06-24  8:12 UTC (permalink / raw)
  To: ext Pantelis Antoniou, Ioan Nicu
  Cc: Grant Likely, Rob Herring, Stephen Warren, Matt Porter,
	Koen Kooi, Greg Kroah-Hartman, Alison Chaiken, Dinh Nguyen,
	Jan Lubbe, Michael Stickel, Guenter Roeck, Dirk Behme, Alan Tull,
	Sascha Hauer, Michael Bohan, Michal Simek, Matt Ranostay,
	Joel Becker, devicetree-u79uwXL29TY76Z2rM5mHXA, Wolfram Sang,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA, Mark Brown,
	linux-spi-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Pete Popov

Hi!

On 23/06/14 21:13, ext Pantelis Antoniou wrote:

[...]

>>> I don't know of any place in the kernel accessing the value if prop->length==0
>>>
>>
>> We have a simple use case. We have an overlay which adds an interrupt controller.
>> If you look in drivers/of/irq.c, in of_irq_parse_raw():
>>
>> [...]
>> 	/* Now start the actual "proper" walk of the interrupt tree */
>> 	while (ipar != NULL) {
>> 		/* Now check if cursor is an interrupt-controller and if it is
>> 		 * then we are done
>> 		 */
>> 		if (of_get_property(ipar, "interrupt-controller", NULL) !=
>> 				NULL) {
>> 			pr_debug(" -> got it !\n");
>> 			return 0;
>> 		}
>> [...]
>>
>> A node is identified as an interrupt controller if it has a zero-length property
>> called "interrupt-controller" but with a non-NULL value.
>>
>> My proposed fix for this was to remove the if () condition. propn->value will be
>> allocated with kmalloc(0) which returns ZERO_SIZE_PTR which is != NULL.
>>
> 
> If that's the case, the code in irq.c is wrong.
> 
> interrupt-controller is a bool property; the correct call to use is of_property_read_bool()
> which returns true or false when the value is defined.

No, it's not bool... It's an existence of a void property. 

> The use of of_get_property is a bug here. It is perfectly valid for a property to have a
> NULL value when length = 0.

of_find_property() would be really correct in this particular case...

-- 
Best regards,
Alexander Sverdlin.
--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH 5/6] OF: Utility helper functions for dynamic nodes
@ 2014-06-24  8:12             ` Alexander Sverdlin
  0 siblings, 0 replies; 63+ messages in thread
From: Alexander Sverdlin @ 2014-06-24  8:12 UTC (permalink / raw)
  To: ext Pantelis Antoniou, Ioan Nicu
  Cc: Grant Likely, Rob Herring, Stephen Warren, Matt Porter,
	Koen Kooi, Greg Kroah-Hartman, Alison Chaiken, Dinh Nguyen,
	Jan Lubbe, Michael Stickel, Guenter Roeck, Dirk Behme, Alan Tull,
	Sascha Hauer, Michael Bohan, Michal Simek, Matt Ranostay,
	Joel Becker, devicetree-u79uwXL29TY76Z2rM5mHXA, Wolfram Sang,
	linux-i2c-u79uwXL29TY76Z2rM5mHXA, Mark Brown,
	linux-spi-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Pete Popov

Hi!

On 23/06/14 21:13, ext Pantelis Antoniou wrote:

[...]

>>> I don't know of any place in the kernel accessing the value if prop->length==0
>>>
>>
>> We have a simple use case. We have an overlay which adds an interrupt controller.
>> If you look in drivers/of/irq.c, in of_irq_parse_raw():
>>
>> [...]
>> 	/* Now start the actual "proper" walk of the interrupt tree */
>> 	while (ipar != NULL) {
>> 		/* Now check if cursor is an interrupt-controller and if it is
>> 		 * then we are done
>> 		 */
>> 		if (of_get_property(ipar, "interrupt-controller", NULL) !=
>> 				NULL) {
>> 			pr_debug(" -> got it !\n");
>> 			return 0;
>> 		}
>> [...]
>>
>> A node is identified as an interrupt controller if it has a zero-length property
>> called "interrupt-controller" but with a non-NULL value.
>>
>> My proposed fix for this was to remove the if () condition. propn->value will be
>> allocated with kmalloc(0) which returns ZERO_SIZE_PTR which is != NULL.
>>
> 
> If that's the case, the code in irq.c is wrong.
> 
> interrupt-controller is a bool property; the correct call to use is of_property_read_bool()
> which returns true or false when the value is defined.

No, it's not bool... It's an existence of a void property. 

> The use of of_get_property is a bug here. It is perfectly valid for a property to have a
> NULL value when length = 0.

of_find_property() would be really correct in this particular case...

-- 
Best regards,
Alexander Sverdlin.
--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH 5/6] OF: Utility helper functions for dynamic nodes
  2014-06-24  8:12             ` Alexander Sverdlin
  (?)
  (?)
@ 2014-06-24  8:19             ` Pantelis Antoniou
  2014-06-24  8:38               ` Alexander Sverdlin
  -1 siblings, 1 reply; 63+ messages in thread
From: Pantelis Antoniou @ 2014-06-24  8:19 UTC (permalink / raw)
  To: Alexander Sverdlin
  Cc: Ioan Nicu, Grant Likely, Rob Herring, Stephen Warren,
	Matt Porter, Koen Kooi, Greg Kroah-Hartman, Alison Chaiken,
	Dinh Nguyen, Jan Lubbe, Michael Stickel, Guenter Roeck,
	Dirk Behme, Alan Tull, Sascha Hauer, Michael Bohan, Michal Simek,
	Matt Ranostay, Joel Becker, devicetree, Wolfram Sang, linux-i2c,
	Mark Brown, linux-spi, linux-kernel, Pete Popov, Dan Malek,
	Georgi Vlaev

Hi Alexander,

On Jun 24, 2014, at 11:12 AM, Alexander Sverdlin wrote:

> Hi!
> 
> On 23/06/14 21:13, ext Pantelis Antoniou wrote:
> 
> [...]
> 
>>>> I don't know of any place in the kernel accessing the value if prop->length==0
>>>> 
>>> 
>>> We have a simple use case. We have an overlay which adds an interrupt controller.
>>> If you look in drivers/of/irq.c, in of_irq_parse_raw():
>>> 
>>> [...]
>>> 	/* Now start the actual "proper" walk of the interrupt tree */
>>> 	while (ipar != NULL) {
>>> 		/* Now check if cursor is an interrupt-controller and if it is
>>> 		 * then we are done
>>> 		 */
>>> 		if (of_get_property(ipar, "interrupt-controller", NULL) !=
>>> 				NULL) {
>>> 			pr_debug(" -> got it !\n");
>>> 			return 0;
>>> 		}
>>> [...]
>>> 
>>> A node is identified as an interrupt controller if it has a zero-length property
>>> called "interrupt-controller" but with a non-NULL value.
>>> 
>>> My proposed fix for this was to remove the if () condition. propn->value will be
>>> allocated with kmalloc(0) which returns ZERO_SIZE_PTR which is != NULL.
>>> 
>> 
>> If that's the case, the code in irq.c is wrong.
>> 
>> interrupt-controller is a bool property; the correct call to use is of_property_read_bool()
>> which returns true or false when the value is defined.
> 
> No, it's not bool... It's an existence of a void property. 
> 

The is no such thing as a void property. A property without contents is defined as a bool. 

From Documentation/devicetree/bindings/interrupts.txt

"A device is marked as an interrupt controller with the "interrupt-controller"
property. This is a empty, boolean property."

>> The use of of_get_property is a bug here. It is perfectly valid for a property to have a
>> NULL value when length = 0.
> 
> of_find_property() would be really correct in this particular case...
> 
> -- 
> Best regards,
> Alexander Sverdlin.

Regards

-- Pantelis

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

* Re: [PATCH 5/6] OF: Utility helper functions for dynamic nodes
  2014-06-24  8:19             ` Pantelis Antoniou
@ 2014-06-24  8:38               ` Alexander Sverdlin
  2014-06-24  8:54                 ` Pantelis Antoniou
  0 siblings, 1 reply; 63+ messages in thread
From: Alexander Sverdlin @ 2014-06-24  8:38 UTC (permalink / raw)
  To: ext Pantelis Antoniou
  Cc: Ioan Nicu, Grant Likely, Rob Herring, Stephen Warren,
	Matt Porter, Koen Kooi, Greg Kroah-Hartman, Alison Chaiken,
	Dinh Nguyen, Jan Lubbe, Michael Stickel, Guenter Roeck,
	Dirk Behme, Alan Tull, Sascha Hauer, Michael Bohan, Michal Simek,
	Matt Ranostay, Joel Becker, devicetree, Wolfram Sang, linux-i2c,
	Mark Brown, linux-spi, linux-kernel, Pete Popov, Dan Malek,
	Georgi Vlaev

Hi!

On 24/06/14 10:19, ext Pantelis Antoniou wrote:

[...]

>> No, it's not bool... It's an existence of a void property. 
>>
> 
> The is no such thing as a void property. A property without contents is defined as a bool. 
> 
>>>From Documentation/devicetree/bindings/interrupts.txt
> 
> "A device is marked as an interrupt controller with the "interrupt-controller"
> property. This is a empty, boolean property."

Maybe, the comment here should be also corrected :)

If we refer back to ePAPR, there are several use-cases of "<empty>" properties, for example:

2.3.8 ranges
Property: ranges
Value type: <empty> or <prop-encoded-array> encoded as arbitrary number of triplets of (child-bus-
address, parent-bus-address, length).
Description:
The ranges property provides a means of defining a mapping or translation between the
address space of the bus (the child address space) and the address space of the bus node's
parent (the parent address space).
...
If the property is defined with an <empty> value, it specifies that the parent and child address
space is identical, and no address translation is required.

=> by no means, should <empty> here be considered a "boolean".

2.4.2.2 Interrupt-controller
Property: interrupt-controller
Value type: <empty>
Description:
The presence of an interrupt-controller property defines a node as an interrupt controller node.

Also, ePAPR has no single occurrence of "bool", so this is something out of specification scope of the
device-tree :)

>>> The use of of_get_property is a bug here. It is perfectly valid for a property to have a
>>> NULL value when length = 0.
>>
>> of_find_property() would be really correct in this particular case...

-- 
Best regards,
Alexander Sverdlin.

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

* Re: [PATCH 5/6] OF: Utility helper functions for dynamic nodes
  2014-06-24  8:38               ` Alexander Sverdlin
@ 2014-06-24  8:54                 ` Pantelis Antoniou
  2014-06-24  9:00                   ` Alexander Sverdlin
  0 siblings, 1 reply; 63+ messages in thread
From: Pantelis Antoniou @ 2014-06-24  8:54 UTC (permalink / raw)
  To: Alexander Sverdlin
  Cc: Ioan Nicu, Grant Likely, Rob Herring, Stephen Warren,
	Matt Porter, Koen Kooi, Greg Kroah-Hartman, Alison Chaiken,
	Dinh Nguyen, Jan Lubbe, Michael Stickel, Guenter Roeck,
	Dirk Behme, Alan Tull, Sascha Hauer, Michael Bohan, Michal Simek,
	Matt Ranostay, Joel Becker, devicetree, Wolfram Sang, linux-i2c,
	Mark Brown, linux-spi, linux-kernel, Pete Popov, Dan Malek,
	Georgi Vlaev

Hi Alexander,

On Jun 24, 2014, at 11:38 AM, Alexander Sverdlin wrote:

> Hi!
> 
> On 24/06/14 10:19, ext Pantelis Antoniou wrote:
> 
> [...]
> 
>>> No, it's not bool... It's an existence of a void property. 
>>> 
>> 
>> The is no such thing as a void property. A property without contents is defined as a bool. 
>> 
>>> From Documentation/devicetree/bindings/interrupts.txt
>> 
>> "A device is marked as an interrupt controller with the "interrupt-controller"
>> property. This is a empty, boolean property."
> 
> Maybe, the comment here should be also corrected :)
> 
> If we refer back to ePAPR, there are several use-cases of "<empty>" properties, for example:
> 
> 2.3.8 ranges
> Property: ranges
> Value type: <empty> or <prop-encoded-array> encoded as arbitrary number of triplets of (child-bus-
> address, parent-bus-address, length).
> Description:
> The ranges property provides a means of defining a mapping or translation between the
> address space of the bus (the child address space) and the address space of the bus node's
> parent (the parent address space).
> ...
> If the property is defined with an <empty> value, it specifies that the parent and child address
> space is identical, and no address translation is required.
> 

> => by no means, should <empty> here be considered a "boolean".
> 
> 2.4.2.2 Interrupt-controller
> Property: interrupt-controller
> Value type: <empty>
> Description:
> The presence of an interrupt-controller property defines a node as an interrupt controller node.
> 

> Also, ePAPR has no single occurrence of "bool", so this is something out of specification scope of the
> device-tree :)
> 

Let's just say that ePAPR hasn't been updated for quite a while.

The fact of the matter is that use of of_get_property() where the intended use is to check
for the existence of a property (that might be empty) is incorrect IMO. of_find_property might
work, as well as the more correct form, where we know the property is a boolean, of_property_read_bool().

The pointer returned from of_get_property() is not usable in any form. Whether it does 
contains a NULL or not value is immaterial. That it works at all is a side-effect of how the
flattening code assigns value pointers.

My vote is to just fix all the call sites using this questionable idiom.

>>>> The use of of_get_property is a bug here. It is perfectly valid for a property to have a
>>>> NULL value when length = 0.
>>> 
>>> of_find_property() would be really correct in this particular case...
> 
> -- 
> Best regards,
> Alexander Sverdlin.

Regards

-- Pantelis

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

* Re: [PATCH 5/6] OF: Utility helper functions for dynamic nodes
  2014-06-24  8:54                 ` Pantelis Antoniou
@ 2014-06-24  9:00                   ` Alexander Sverdlin
  2014-06-24  9:09                     ` Pantelis Antoniou
  0 siblings, 1 reply; 63+ messages in thread
From: Alexander Sverdlin @ 2014-06-24  9:00 UTC (permalink / raw)
  To: ext Pantelis Antoniou
  Cc: Ioan Nicu, Grant Likely, Rob Herring, Stephen Warren,
	Matt Porter, Koen Kooi, Greg Kroah-Hartman, Alison Chaiken,
	Dinh Nguyen, Jan Lubbe, Michael Stickel, Guenter Roeck,
	Dirk Behme, Alan Tull, Sascha Hauer, Michael Bohan, Michal Simek,
	Matt Ranostay, Joel Becker, devicetree, Wolfram Sang, linux-i2c,
	Mark Brown, linux-spi, linux-kernel, Pete Popov, Dan Malek,
	Georgi Vlaev

Hi!

On 24/06/14 10:54, ext Pantelis Antoniou wrote:
> The fact of the matter is that use of of_get_property() where the intended use is to check
> for the existence of a property (that might be empty) is incorrect IMO. of_find_property might
> work, as well as the more correct form, where we know the property is a boolean, of_property_read_bool().
> 
> The pointer returned from of_get_property() is not usable in any form. Whether it does 
> contains a NULL or not value is immaterial. That it works at all is a side-effect of how the
> flattening code assigns value pointers.
> 
> My vote is to just fix all the call sites using this questionable idiom.

I fully agree with you here, this assumption that value!=NULL is simply not obvious.
Let's wait, what Grant says, I can prepare a tree-wide patch, I think...

-- 
Best regards,
Alexander Sverdlin.

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

* Re: [PATCH 5/6] OF: Utility helper functions for dynamic nodes
  2014-06-23 19:48             ` Guenter Roeck
                               ` (2 preceding siblings ...)
  (?)
@ 2014-06-24  9:08             ` Pantelis Antoniou
  2014-06-24 13:46               ` Rob Herring
  -1 siblings, 1 reply; 63+ messages in thread
From: Pantelis Antoniou @ 2014-06-24  9:08 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Ioan Nicu, Alexander Sverdlin, Grant Likely, Rob Herring,
	Stephen Warren, Matt Porter, Koen Kooi, Greg Kroah-Hartman,
	Alison Chaiken, Dinh Nguyen, Jan Lubbe, Michael Stickel,
	Dirk Behme, Alan Tull, Sascha Hauer, Michael Bohan, Michal Simek,
	Matt Ranostay, Joel Becker, devicetree, Wolfram Sang, linux-i2c,
	Mark Brown, linux-spi, linux-kernel, Pete Popov, Dan Malek,
	Georgi Vlaev

Hi Guenter,

On Jun 23, 2014, at 10:48 PM, Guenter Roeck wrote:

> On 06/23/2014 12:13 PM, Pantelis Antoniou wrote:
>> Hi Ioan,
>> 
>> I'm going to let Grant answer that but the code in question doesn't look right.
>> 
>> On Jun 23, 2014, at 9:33 PM, Ioan Nicu wrote:
>> 
>>> Hi Pantelis,
>>> 
>>> On Mon, Jun 23, 2014 at 07:57:24PM +0300, ext Pantelis Antoniou wrote:
>>>> Hi Alexander,
>>>> 
>>>> On Jun 23, 2014, at 7:26 PM, Alexander Sverdlin wrote:
>>>> 
>>>>> Hello Pantelis!
>>>>> 
>>>>> On 22/06/14 11:40, ext Pantelis Antoniou wrote:
>>>>>> Introduce helper functions for working with the live DT tree,
>>>>>> all of them related to dynamically adding/removing nodes and
>>>>>> properties.
>>>>>> 
>>>>>> __of_copy_property() copies a property dynamically
>>>>>> __of_create_empty_node() creates an empty node
>>>>>> 
>>>>>> Bug fix about prop->len == 0 by Ionut Nicu <ioan.nicu.ext@nsn.com>
>>>>> 
>>>>> Are you sure about this? (see below...)
>>>>> 
>>> 
>>> Alexander is right, my fix was lost even though it's mentioned in this patch.
>>> 
>> 
>> I'm sorry, I didn't understand that the intention of the fix was to address
>> the issue below.
>> 
>>>>>> Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
>>>>>> ---
>>>> 
>>>> [snip]
>>>>>> +
>>>>>> +	if (prop->length > 0) {
>>>>>       ^^^^^^^^^^^^^^^^^^^^^
>>>>> Seems, that length==0 case will still produce value==NULL results,
>>>>> which will brake some checks in the kernel... Or am I missing something in
>>>>> the new version?
>>>>> 
>>>> 
>>>> prop->value will be set to NULL, and length will be set to zero (kzalloc).
>>>> This is a normal zero length property.
>>>> 
>>>> I don't know of any place in the kernel accessing the value if prop->length==0
>>>> 
>>> 
>>> We have a simple use case. We have an overlay which adds an interrupt controller.
>>> If you look in drivers/of/irq.c, in of_irq_parse_raw():
>>> 
>>> [...]
>>> 	/* Now start the actual "proper" walk of the interrupt tree */
>>> 	while (ipar != NULL) {
>>> 		/* Now check if cursor is an interrupt-controller and if it is
>>> 		 * then we are done
>>> 		 */
>>> 		if (of_get_property(ipar, "interrupt-controller", NULL) !=
>>> 				NULL) {
>>> 			pr_debug(" -> got it !\n");
>>> 			return 0;
>>> 		}
>>> [...]
>>> 
>>> A node is identified as an interrupt controller if it has a zero-length property
>>> called "interrupt-controller" but with a non-NULL value.
>>> 
>>> My proposed fix for this was to remove the if () condition. propn->value will be
>>> allocated with kmalloc(0) which returns ZERO_SIZE_PTR which is != NULL.
>>> 
>> 
>> If that's the case, the code in irq.c is wrong.
>> 
>> interrupt-controller is a bool property; the correct call to use is of_property_read_bool()
>> which returns true or false when the value is defined.
>> 
>> The use of of_get_property is a bug here. It is perfectly valid for a property to have a
>> NULL value when length = 0.
>> 
> 
> That usage is spread throughout the code though. There are three or four similar checks
> for interrupt-controller in the code, and many others using of_get_property() to check
> for booleans.
> 
> Some examples:
> 	s5m8767,pmic-buck2-ramp-enable
> 	s5m8767,pmic-buck3-ramp-enable
> 	s5m8767,pmic-buck4-ramp-enable
> 	d7s-flipped?
> 	atmel,use-dma-rx
> 	linux,rs485-enabled-at-boot-time
> 	marvell,enable-port1 (and many others)
> 	linux,bootx-noscreen
> 	linux,opened
> 
> and many many others.
> 
> Maybe people meant to use of_find_property() ?
> 

I bet... I see a lot of users doing if (of_get_property()).

Which is no good.


> Either case, if the new code depends on proper use of of_get_property(), we may have
> a problem unless all those bad use cases are fixed.
> 

I have prepared a patch that fixes the caller problem, and issues a warning, so that we
know what we have to fix.

> Guenter

Regards

-- Pantelis

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

* Re: [PATCH 5/6] OF: Utility helper functions for dynamic nodes
  2014-06-24  9:00                   ` Alexander Sverdlin
@ 2014-06-24  9:09                     ` Pantelis Antoniou
  0 siblings, 0 replies; 63+ messages in thread
From: Pantelis Antoniou @ 2014-06-24  9:09 UTC (permalink / raw)
  To: Alexander Sverdlin
  Cc: Ioan Nicu, Grant Likely, Rob Herring, Stephen Warren,
	Matt Porter, Koen Kooi, Greg Kroah-Hartman, Alison Chaiken,
	Dinh Nguyen, Jan Lubbe, Michael Stickel, Guenter Roeck,
	Dirk Behme, Alan Tull, Sascha Hauer, Michael Bohan, Michal Simek,
	Matt Ranostay, Joel Becker, devicetree, Wolfram Sang, linux-i2c,
	Mark Brown, linux-spi, linux-kernel, Pete Popov, Dan Malek,
	Georgi Vlaev

Hi Alexander,

On Jun 24, 2014, at 12:00 PM, Alexander Sverdlin wrote:

> Hi!
> 
> On 24/06/14 10:54, ext Pantelis Antoniou wrote:
>> The fact of the matter is that use of of_get_property() where the intended use is to check
>> for the existence of a property (that might be empty) is incorrect IMO. of_find_property might
>> work, as well as the more correct form, where we know the property is a boolean, of_property_read_bool().
>> 
>> The pointer returned from of_get_property() is not usable in any form. Whether it does 
>> contains a NULL or not value is immaterial. That it works at all is a side-effect of how the
>> flattening code assigns value pointers.
>> 
>> My vote is to just fix all the call sites using this questionable idiom.
> 
> I fully agree with you here, this assumption that value!=NULL is simply not obvious.
> Let's wait, what Grant says, I can prepare a tree-wide patch, I think...
> 

There's a simpler fix, the included patch, and here's a bootlog of it's trigger.
Let's just wait for Grant to show up... Grant?

> -- 
> Best regards,
> Alexander Sverdlin.

Regards

-- Pantelis

> diff --git a/drivers/of/base.c b/drivers/of/base.c
> index 6dc6d63..fc965487 100644
> --- a/drivers/of/base.c
> +++ b/drivers/of/base.c
> @@ -400,7 +400,17 @@ const void *__of_get_property(const struct device_node *np,
>  {
>         struct property *pp = __of_find_property(np, name, lenp);
>  
> -       return pp ? pp->value : NULL;
> +       if (!pp)
> +               return NULL;
> +
> +       if (pp->length > 0)
> +               return pp->value;
> +
> +       pr_warn("__of_get_property() on boolean property %s/%s\n",
> +                       np->full_name, name);
> +
> +       /* return a pointer to an empty string */
> +       return "";
>  }
>  
>  /*
> 


> [    0.000000] __of_get_property() on boolean property /ocp/ranges
> [    0.000000] __of_get_property() on boolean property /ocp/ranges
> [    0.000000] __of_get_property() on boolean property /ocp/ranges
> [    0.000000] __of_get_property() on boolean property /ocp/timer@44e31000/ti,timer-alwon
> [    0.000000] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.000000] __of_get_property() on boolean property /ocp/ranges
> [    0.000000] __of_get_property() on boolean property /ocp/ranges
> [    0.000000] __of_get_property() on boolean property /ocp/timer@44e31000/ti,timer-alwon
> [    0.000000] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.000000] __of_get_property() on boolean property /ocp/ranges
> [    0.000000] __of_get_property() on boolean property /ocp/ranges
> [    0.079665] __of_get_property() on boolean property /ocp/ranges
> [    0.079903] __of_get_property() on boolean property /ocp/ranges
> [    0.080072] __of_get_property() on boolean property /ocp/ranges
> [    0.080222] __of_get_property() on boolean property /ocp/ranges
> [    0.080676] __of_get_property() on boolean property /ocp/ranges
> [    0.081180] __of_get_property() on boolean property /ocp/ranges
> [    0.081335] __of_get_property() on boolean property /ocp/ranges
> [    0.081491] __of_get_property() on boolean property /ocp/ranges
> [    0.081673] __of_get_property() on boolean property /ocp/ranges
> [    0.081853] __of_get_property() on boolean property /ocp/ranges
> [    0.083405] __of_get_property() on boolean property /ocp/ranges
> [    0.083620] __of_get_property() on boolean property /ocp/ranges
> [    0.083827] __of_get_property() on boolean property /ocp/ranges
> [    0.084036] __of_get_property() on boolean property /ocp/ranges
> [    0.084245] __of_get_property() on boolean property /ocp/ranges
> [    0.084526] __of_get_property() on boolean property /ocp/ranges
> [    0.084684] __of_get_property() on boolean property /ocp/ranges
> [    0.084843] __of_get_property() on boolean property /ocp/ranges
> [    0.085006] __of_get_property() on boolean property /ocp/ranges
> [    0.085169] __of_get_property() on boolean property /ocp/ranges
> [    0.085357] __of_get_property() on boolean property /ocp/ranges
> [    0.089088] __of_get_property() on boolean property /ocp/ranges
> [    0.089307] __of_get_property() on boolean property /ocp/ranges
> [    0.090186] __of_get_property() on boolean property /ocp/ranges
> [    0.090445] __of_get_property() on boolean property /ocp/ranges
> [    0.091570] __of_get_property() on boolean property /ocp/ranges
> [    0.206661] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.206696] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.208971] __of_get_property() on boolean property /ocp/ranges
> [    0.209000] __of_get_property() on boolean property /ocp/ranges
> [    0.209014] __of_get_property() on boolean property /ocp/ranges
> [    0.209475] __of_get_property() on boolean property /ocp/ranges
> [    0.209499] __of_get_property() on boolean property /ocp/ranges
> [    0.209512] __of_get_property() on boolean property /ocp/ranges
> [    0.209946] __of_get_property() on boolean property /ocp/ranges
> [    0.209969] __of_get_property() on boolean property /ocp/ranges
> [    0.209982] __of_get_property() on boolean property /ocp/ranges
> [    0.210415] __of_get_property() on boolean property /ocp/ranges
> [    0.210432] __of_get_property() on boolean property /ocp/ranges
> [    0.210475] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.210498] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.210518] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.210543] __of_get_property() on boolean property /ocp/ranges
> [    0.210557] __of_get_property() on boolean property /ocp/ranges
> [    0.210578] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.210603] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.210624] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.210639] __of_get_property() on boolean property /ocp/ranges
> [    0.211240] __of_get_property() on boolean property /ocp/ranges
> [    0.211275] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.211300] __of_get_property() on boolean property /ocp/ranges
> [    0.211321] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.211338] __of_get_property() on boolean property /ocp/ranges
> [    0.213540] __of_get_property() on boolean property /ocp/ranges
> [    0.213602] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.213629] __of_get_property() on boolean property /ocp/ranges
> [    0.213650] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.213671] __of_get_property() on boolean property /ocp/ranges
> [    0.215593] __of_get_property() on boolean property /ocp/ranges
> [    0.215643] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.215669] __of_get_property() on boolean property /ocp/ranges
> [    0.215691] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.215710] __of_get_property() on boolean property /ocp/ranges
> [    0.217330] __of_get_property() on boolean property /ocp/ranges
> [    0.217373] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.217398] __of_get_property() on boolean property /ocp/ranges
> [    0.217419] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.217437] __of_get_property() on boolean property /ocp/ranges
> [    0.219099] __of_get_property() on boolean property /ocp/ranges
> [    0.219137] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.219163] __of_get_property() on boolean property /ocp/ranges
> [    0.219183] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.219202] __of_get_property() on boolean property /ocp/ranges
> [    0.220051] __of_get_property() on boolean property /ocp/ranges
> [    0.220095] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.220122] __of_get_property() on boolean property /ocp/ranges
> [    0.220143] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.220162] __of_get_property() on boolean property /ocp/ranges
> [    0.220703] __of_get_property() on boolean property /ocp/ranges
> [    0.220733] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.220757] __of_get_property() on boolean property /ocp/ranges
> [    0.220775] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.220792] __of_get_property() on boolean property /ocp/ranges
> [    0.221276] __of_get_property() on boolean property /ocp/ranges
> [    0.221305] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.221328] __of_get_property() on boolean property /ocp/ranges
> [    0.221345] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.221362] __of_get_property() on boolean property /ocp/ranges
> [    0.221865] __of_get_property() on boolean property /ocp/ranges
> [    0.221890] __of_get_property() on boolean property /ocp/ranges
> [    0.221903] __of_get_property() on boolean property /ocp/ranges
> [    0.222366] __of_get_property() on boolean property /ocp/ranges
> [    0.222398] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.222423] __of_get_property() on boolean property /ocp/ranges
> [    0.222443] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.222460] __of_get_property() on boolean property /ocp/ranges
> [    0.223004] __of_get_property() on boolean property /ocp/ranges
> [    0.223035] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.223060] __of_get_property() on boolean property /ocp/ranges
> [    0.223079] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.223096] __of_get_property() on boolean property /ocp/ranges
> [    0.223652] __of_get_property() on boolean property /ocp/ranges
> [    0.223684] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.223710] __of_get_property() on boolean property /ocp/ranges
> [    0.223731] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.223747] __of_get_property() on boolean property /ocp/ranges
> [    0.224210] __of_get_property() on boolean property /ocp/ranges
> [    0.224238] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.224263] __of_get_property() on boolean property /ocp/ranges
> [    0.224283] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.224299] __of_get_property() on boolean property /ocp/ranges
> [    0.224757] __of_get_property() on boolean property /ocp/ranges
> [    0.224787] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.224811] __of_get_property() on boolean property /ocp/ranges
> [    0.224831] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.224847] __of_get_property() on boolean property /ocp/ranges
> [    0.225341] __of_get_property() on boolean property /ocp/ranges
> [    0.225370] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.225394] __of_get_property() on boolean property /ocp/ranges
> [    0.225414] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.225431] __of_get_property() on boolean property /ocp/ranges
> [    0.225896] __of_get_property() on boolean property /ocp/ranges
> [    0.225926] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.225945] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.225969] __of_get_property() on boolean property /ocp/ranges
> [    0.225988] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.226011] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.226026] __of_get_property() on boolean property /ocp/ranges
> [    0.226501] __of_get_property() on boolean property /ocp/ranges
> [    0.226524] __of_get_property() on boolean property /ocp/ranges
> [    0.226537] __of_get_property() on boolean property /ocp/ranges
> [    0.227069] __of_get_property() on boolean property /ocp/ranges
> [    0.227089] __of_get_property() on boolean property /ocp/ranges
> [    0.227117] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.227135] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.227153] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.227169] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.227193] __of_get_property() on boolean property /ocp/ranges
> [    0.227209] __of_get_property() on boolean property /ocp/ranges
> [    0.227227] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.227251] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.227271] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.227290] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.227306] __of_get_property() on boolean property /ocp/ranges
> [    0.227867] __of_get_property() on boolean property /ocp/ranges
> [    0.227891] __of_get_property() on boolean property /ocp/ranges
> [    0.227904] __of_get_property() on boolean property /ocp/ranges
> [    0.228373] __of_get_property() on boolean property /ocp/ranges
> [    0.228391] __of_get_property() on boolean property /ocp/ranges
> [    0.228412] __of_get_property() on boolean property /ocp/ranges
> [    0.228426] __of_get_property() on boolean property /ocp/ranges
> [    0.228439] __of_get_property() on boolean property /ocp/ranges
> [    0.228909] __of_get_property() on boolean property /ocp/ranges
> [    0.228945] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.228968] __of_get_property() on boolean property /ocp/ranges
> [    0.228985] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.229003] __of_get_property() on boolean property /ocp/ranges
> [    0.229531] __of_get_property() on boolean property /ocp/ranges
> [    0.229562] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.229588] __of_get_property() on boolean property /ocp/ranges
> [    0.229608] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.229624] __of_get_property() on boolean property /ocp/ranges
> [    0.230099] __of_get_property() on boolean property /ocp/ranges
> [    0.230129] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.230154] __of_get_property() on boolean property /ocp/ranges
> [    0.230174] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.230191] __of_get_property() on boolean property /ocp/ranges
> [    0.230686] __of_get_property() on boolean property /ocp/ranges
> [    0.230715] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.230739] __of_get_property() on boolean property /ocp/ranges
> [    0.230759] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.230776] __of_get_property() on boolean property /ocp/ranges
> [    0.233422] __of_get_property() on boolean property /ocp/ranges
> [    0.233951] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.233979] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    0.399973] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    2.711911] __of_get_property() on boolean property /ocp/usb@47400000/ranges
> [    2.719306] __of_get_property() on boolean property /ocp/ranges
> [    2.725511] __of_get_property() on boolean property /ocp/usb@47400000/ranges
> [    2.732881] __of_get_property() on boolean property /ocp/ranges
> [    2.739088] __of_get_property() on boolean property /ocp/usb@47400000/ranges
> [    2.746458] __of_get_property() on boolean property /ocp/ranges
> [    2.752655] __of_get_property() on boolean property /ocp/usb@47400000/ranges
> [    2.760024] __of_get_property() on boolean property /ocp/ranges
> [    2.766218] __of_get_property() on boolean property /ocp/usb@47400000/ranges
> [    2.773587] __of_get_property() on boolean property /ocp/ranges
> [    2.780534] __of_get_property() on boolean property /ocp/usb@47400000/ranges
> [    2.787938] __of_get_property() on boolean property /ocp/ranges
> [    2.794149] __of_get_property() on boolean property /ocp/usb@47400000/ranges
> [    2.801525] __of_get_property() on boolean property /ocp/ranges
> [    2.807720] __of_get_property() on boolean property /ocp/usb@47400000/ranges
> [    2.815090] __of_get_property() on boolean property /ocp/ranges
> [    2.840043] __of_get_property() on boolean property /ocp/usb@47400000/ranges
> [    2.847441] __of_get_property() on boolean property /ocp/ranges
> [    2.853642] __of_get_property() on boolean property /ocp/usb@47400000/ranges
> [    2.861013] __of_get_property() on boolean property /ocp/ranges
> [    2.867241] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    2.877447] __of_get_property() on boolean property /ocp/usb@47400000/ranges
> [    2.884820] __of_get_property() on boolean property /ocp/ranges
> [    2.891017] __of_get_property() on boolean property /ocp/usb@47400000/ranges
> [    2.898387] __of_get_property() on boolean property /ocp/ranges
> [    2.904592] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    2.914786] __of_get_property() on boolean property /ocp/usb@47400000/ranges
> [    2.922157] __of_get_property() on boolean property /ocp/ranges
> [    2.930055] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    2.964001] __of_get_property() on boolean property /ocp/usb@47400000/ranges
> [    2.971392] __of_get_property() on boolean property /ocp/ranges
> [    2.977604] __of_get_property() on boolean property /ocp/usb@47400000/ranges
> [    2.984978] __of_get_property() on boolean property /ocp/ranges
> [    2.991177] __of_get_property() on boolean property /ocp/usb@47400000/ranges
> [    2.998548] __of_get_property() on boolean property /ocp/ranges
> [    3.023524] __of_get_property() on boolean property /ocp/usb@47400000/ranges
> [    3.030924] __of_get_property() on boolean property /ocp/ranges
> [    3.037127] __of_get_property() on boolean property /ocp/usb@47400000/ranges
> [    3.044504] __of_get_property() on boolean property /ocp/ranges
> [    3.050732] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    3.060943] __of_get_property() on boolean property /ocp/usb@47400000/ranges
> [    3.068320] __of_get_property() on boolean property /ocp/ranges
> [    3.074519] __of_get_property() on boolean property /ocp/usb@47400000/ranges
> [    3.081891] __of_get_property() on boolean property /ocp/ranges
> [    3.088098] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    3.098295] __of_get_property() on boolean property /ocp/usb@47400000/ranges
> [    3.105669] __of_get_property() on boolean property /ocp/ranges
> [    3.113250] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    3.147107] __of_get_property() on boolean property /ocp/usb@47400000/ranges
> [    3.154497] __of_get_property() on boolean property /ocp/ranges
> [    3.160699] __of_get_property() on boolean property /ocp/usb@47400000/ranges
> [    3.168072] __of_get_property() on boolean property /ocp/ranges
> [    3.174270] __of_get_property() on boolean property /ocp/usb@47400000/ranges
> [    3.181641] __of_get_property() on boolean property /ocp/ranges
> [    3.187840] __of_get_property() on boolean property /ocp/usb@47400000/ranges
> [    3.195210] __of_get_property() on boolean property /ocp/ranges
> [    3.201432] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    3.211640] __of_get_property() on boolean property /ocp/usb@47400000/ranges
> [    3.219014] __of_get_property() on boolean property /ocp/ranges
> [    3.225214] __of_get_property() on boolean property /ocp/usb@47400000/ranges
> [    3.232585] __of_get_property() on boolean property /ocp/ranges
> [    3.238783] __of_get_property() on boolean property /ocp/usb@47400000/ranges
> [    3.246155] __of_get_property() on boolean property /ocp/ranges
> [    3.252354] __of_get_property() on boolean property /ocp/usb@47400000/ranges
> [    3.259725] __of_get_property() on boolean property /ocp/ranges
> [    3.265930] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    3.276127] __of_get_property() on boolean property /ocp/usb@47400000/ranges
> [    3.283500] __of_get_property() on boolean property /ocp/ranges
> [    3.290315] __of_get_property() on boolean property /ocp/usb@47400000/ranges
> [    3.297707] __of_get_property() on boolean property /ocp/ranges
> [    3.303925] __of_get_property() on boolean property /ocp/usb@47400000/ranges
> [    3.311300] __of_get_property() on boolean property /ocp/ranges
> [    3.317508] __of_get_property() on boolean property /ocp/usb@47400000/ranges
> [    3.324881] __of_get_property() on boolean property /ocp/ranges
> [    3.331088] __of_get_property() on boolean property /ocp/usb@47400000/ranges
> [    3.338461] __of_get_property() on boolean property /ocp/ranges
> [    3.344933] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    3.398609] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    3.408921] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    3.473733] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    3.538616] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    3.665475] __of_get_property() on boolean property /ocp/ranges
> [    3.682774] __of_get_property() on boolean property /ocp/ranges
> [    3.689099] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    3.835081] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    3.933734] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    4.035694] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    4.273629] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    4.348412] __of_get_property() on boolean property /ocp/ethernet@4a100000/ranges
> [    4.356291] __of_get_property() on boolean property /ocp/ranges
> [    4.362547] __of_get_property() on boolean property /ocp/ethernet@4a100000/ranges
> [    4.370376] __of_get_property() on boolean property /ocp/ranges
> [    4.376574] __of_get_property() on boolean property /ocp/ethernet@4a100000/ranges
> [    4.384397] __of_get_property() on boolean property /ocp/ranges
> [    4.468262] __of_get_property() on boolean property /ocp/ethernet@4a100000/ranges
> [    4.476121] __of_get_property() on boolean property /ocp/ranges
> [    4.482366] __of_get_property() on boolean property /ocp/ethernet@4a100000/ranges
> [    4.490348] __of_get_property() on boolean property /ocp/ranges
> [    4.496553] __of_get_property() on boolean property /ocp/ethernet@4a100000/ranges
> [    4.504377] __of_get_property() on boolean property /ocp/ranges
> [    4.518562] __of_get_property() on boolean property /ocp/interrupt-controller@48200000/interrupt-controller
> [    4.605843] __of_get_property() on boolean property /testcase-data/interrupts/intc0/interrupt-controller
> [    4.615764] __of_get_property() on boolean property /testcase-data/interrupts/intc0/interrupt-controller
> [    4.625684] __of_get_property() on boolean property /testcase-data/interrupts/intc0/interrupt-controller
> [    4.635600] __of_get_property() on boolean property /testcase-data/interrupts/intc0/interrupt-controller
> [    4.645538] __of_get_property() on boolean property /testcase-data/interrupts/intc0/interrupt-controller
> [    4.655467] __of_get_property() on boolean property /testcase-data/interrupts/intc1/interrupt-controller
> [    4.665396] __of_get_property() on boolean property /testcase-data/interrupts/intc2/interrupt-controller
> [    4.675327] __of_get_property() on boolean property /testcase-data/interrupts/intc2/interrupt-controller
> [    4.685256] __of_get_property() on boolean property /testcase-data/interrupts/intc0/interrupt-controller
> [    4.695176] __of_get_property() on boolean property /testcase-data/interrupts/intc1/interrupt-controller
> [    4.705099] __of_get_property() on boolean property /testcase-data/interrupts/intc2/interrupt-controller
> [    4.715062] __of_get_property() on boolean property /testcase-data/interrupts/intc0/interrupt-controller
> [    4.725004] __of_get_property() on boolean property /testcase-data/interrupts/intc1/interrupt-controller
> [    4.734945] __of_get_property() on boolean property /testcase-data/interrupts/intc2/interrupt-controller
> [    4.744882] __of_get_property() on boolean property /testcase-data/interrupts/intc0/interrupt-controller
> [    4.755108] __of_get_property() on boolean property /testcase-data/interrupts/intc0/interrupt-controller
> [    4.765056] __of_get_property() on boolean property /testcase-data/interrupts/intc0/interrupt-controller
> [    4.783748] __of_get_property() on boolean property /testcase-data/interrupts/intc0/interrupt-controller
> 

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

* Re: [PATCH 5/6] OF: Utility helper functions for dynamic nodes
  2014-06-24  9:08             ` Pantelis Antoniou
@ 2014-06-24 13:46               ` Rob Herring
  2014-06-24 13:53                 ` Alexander Sverdlin
  0 siblings, 1 reply; 63+ messages in thread
From: Rob Herring @ 2014-06-24 13:46 UTC (permalink / raw)
  To: Pantelis Antoniou
  Cc: Guenter Roeck, Ioan Nicu, Alexander Sverdlin, Grant Likely,
	Stephen Warren, Matt Porter, Koen Kooi, Greg Kroah-Hartman,
	Alison Chaiken, Dinh Nguyen, Jan Lubbe, Michael Stickel,
	Dirk Behme, Alan Tull, Sascha Hauer, Michael Bohan, Michal Simek,
	Matt Ranostay, Joel Becker, devicetree, Wolfram Sang, linux-i2c,
	Mark Brown, linux-spi, linux-kernel, Pete Popov, Dan Malek,
	Georgi Vlaev

On Tue, Jun 24, 2014 at 4:08 AM, Pantelis Antoniou
<pantelis.antoniou@konsulko.com> wrote:
> Hi Guenter,
>
> On Jun 23, 2014, at 10:48 PM, Guenter Roeck wrote:
>
>> On 06/23/2014 12:13 PM, Pantelis Antoniou wrote:
>>> Hi Ioan,
>>>
>>> I'm going to let Grant answer that but the code in question doesn't look right.
>>>
>>> On Jun 23, 2014, at 9:33 PM, Ioan Nicu wrote:
>>>
>>>> Hi Pantelis,
>>>>
>>>> On Mon, Jun 23, 2014 at 07:57:24PM +0300, ext Pantelis Antoniou wrote:
>>>>> Hi Alexander,
>>>>>
>>>>> On Jun 23, 2014, at 7:26 PM, Alexander Sverdlin wrote:
>>>>>
>>>>>> Hello Pantelis!
>>>>>>
>>>>>> On 22/06/14 11:40, ext Pantelis Antoniou wrote:
>>>>>>> Introduce helper functions for working with the live DT tree,
>>>>>>> all of them related to dynamically adding/removing nodes and
>>>>>>> properties.
>>>>>>>
>>>>>>> __of_copy_property() copies a property dynamically
>>>>>>> __of_create_empty_node() creates an empty node
>>>>>>>
>>>>>>> Bug fix about prop->len == 0 by Ionut Nicu <ioan.nicu.ext@nsn.com>
>>>>>>
>>>>>> Are you sure about this? (see below...)
>>>>>>
>>>>
>>>> Alexander is right, my fix was lost even though it's mentioned in this patch.
>>>>
>>>
>>> I'm sorry, I didn't understand that the intention of the fix was to address
>>> the issue below.
>>>
>>>>>>> Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
>>>>>>> ---
>>>>>
>>>>> [snip]
>>>>>>> +
>>>>>>> +        if (prop->length > 0) {
>>>>>>       ^^^^^^^^^^^^^^^^^^^^^
>>>>>> Seems, that length==0 case will still produce value==NULL results,
>>>>>> which will brake some checks in the kernel... Or am I missing something in
>>>>>> the new version?
>>>>>>
>>>>>
>>>>> prop->value will be set to NULL, and length will be set to zero (kzalloc).
>>>>> This is a normal zero length property.
>>>>>
>>>>> I don't know of any place in the kernel accessing the value if prop->length==0
>>>>>
>>>>
>>>> We have a simple use case. We have an overlay which adds an interrupt controller.
>>>> If you look in drivers/of/irq.c, in of_irq_parse_raw():
>>>>
>>>> [...]
>>>>     /* Now start the actual "proper" walk of the interrupt tree */
>>>>     while (ipar != NULL) {
>>>>             /* Now check if cursor is an interrupt-controller and if it is
>>>>              * then we are done
>>>>              */
>>>>             if (of_get_property(ipar, "interrupt-controller", NULL) !=
>>>>                             NULL) {
>>>>                     pr_debug(" -> got it !\n");
>>>>                     return 0;
>>>>             }
>>>> [...]
>>>>
>>>> A node is identified as an interrupt controller if it has a zero-length property
>>>> called "interrupt-controller" but with a non-NULL value.
>>>>
>>>> My proposed fix for this was to remove the if () condition. propn->value will be
>>>> allocated with kmalloc(0) which returns ZERO_SIZE_PTR which is != NULL.
>>>>
>>>
>>> If that's the case, the code in irq.c is wrong.
>>>
>>> interrupt-controller is a bool property; the correct call to use is of_property_read_bool()
>>> which returns true or false when the value is defined.
>>>
>>> The use of of_get_property is a bug here. It is perfectly valid for a property to have a
>>> NULL value when length = 0.
>>>
>>
>> That usage is spread throughout the code though. There are three or four similar checks
>> for interrupt-controller in the code, and many others using of_get_property() to check
>> for booleans.
>>
>> Some examples:
>>       s5m8767,pmic-buck2-ramp-enable
>>       s5m8767,pmic-buck3-ramp-enable
>>       s5m8767,pmic-buck4-ramp-enable
>>       d7s-flipped?
>>       atmel,use-dma-rx
>>       linux,rs485-enabled-at-boot-time
>>       marvell,enable-port1 (and many others)
>>       linux,bootx-noscreen
>>       linux,opened
>>
>> and many many others.
>>
>> Maybe people meant to use of_find_property() ?
>>
>
> I bet... I see a lot of users doing if (of_get_property()).
>
> Which is no good.

I don't see what the issue is. The irq.c code is correct. The code is
checking for existence of a property or not and of_get_property
adequately does that. of_find_property is equivalent in this case. Now
we could make the code stricter that properties defined to be empty
are in fact empty. My opinion is that it is not the kernel's job to
validate DTs. This can and should be done at dtb build time.

Boolean and empty properties are not the same. Booleans can have a
value of true or false in addition to being absent (false) or present
with no value (true). of_get_property predates of_property_read_bool
and other helpers by many years, so no doubt there are many callers of
of_get_property which could be converted. Patches welcome. :)

Rob

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

* Re: [PATCH 5/6] OF: Utility helper functions for dynamic nodes
  2014-06-24 13:46               ` Rob Herring
@ 2014-06-24 13:53                 ` Alexander Sverdlin
  2014-06-24 14:49                   ` Rob Herring
  0 siblings, 1 reply; 63+ messages in thread
From: Alexander Sverdlin @ 2014-06-24 13:53 UTC (permalink / raw)
  To: ext Rob Herring, Pantelis Antoniou
  Cc: Guenter Roeck, Ioan Nicu, Grant Likely, Stephen Warren,
	Matt Porter, Koen Kooi, Greg Kroah-Hartman, Alison Chaiken,
	Dinh Nguyen, Jan Lubbe, Michael Stickel, Dirk Behme, Alan Tull,
	Sascha Hauer, Michael Bohan, Michal Simek, Matt Ranostay,
	Joel Becker, devicetree, Wolfram Sang, linux-i2c, Mark Brown,
	linux-spi, linux-kernel, Pete Popov, Dan Malek, Georgi Vlaev

Hi!

On 24/06/14 15:46, ext Rob Herring wrote:
[...]

>>>> If that's the case, the code in irq.c is wrong.
>>>>
>>>> interrupt-controller is a bool property; the correct call to use is of_property_read_bool()
>>>> which returns true or false when the value is defined.
>>>>
>>>> The use of of_get_property is a bug here. It is perfectly valid for a property to have a
>>>> NULL value when length = 0.
>>>>
>>>
>>> That usage is spread throughout the code though. There are three or four similar checks
>>> for interrupt-controller in the code, and many others using of_get_property() to check
>>> for booleans.
>>>
>>> Some examples:
>>>       s5m8767,pmic-buck2-ramp-enable
>>>       s5m8767,pmic-buck3-ramp-enable
>>>       s5m8767,pmic-buck4-ramp-enable
>>>       d7s-flipped?
>>>       atmel,use-dma-rx
>>>       linux,rs485-enabled-at-boot-time
>>>       marvell,enable-port1 (and many others)
>>>       linux,bootx-noscreen
>>>       linux,opened
>>>
>>> and many many others.
>>>
>>> Maybe people meant to use of_find_property() ?
>>>
>>
>> I bet... I see a lot of users doing if (of_get_property()).
>>
>> Which is no good.
> 
> I don't see what the issue is. The irq.c code is correct. The code is
> checking for existence of a property or not and of_get_property
> adequately does that. of_find_property is equivalent in this case. Now

The code is correct and the functions are equal as long as we declare that
void property has value != NULL. Which must not be actually and the patch
from Pantelis actually creates this situation first time.

So let's first agree, how should the empty property look like.
length should be 0, it's clear. But what about the value?

> we could make the code stricter that properties defined to be empty
> are in fact empty. My opinion is that it is not the kernel's job to
> validate DTs. This can and should be done at dtb build time.
> 
> Boolean and empty properties are not the same. Booleans can have a
> value of true or false in addition to being absent (false) or present
> with no value (true). of_get_property predates of_property_read_bool
> and other helpers by many years, so no doubt there are many callers of
> of_get_property which could be converted. Patches welcome. :)

-- 
Best regards,
Alexander Sverdlin.

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

* Re: [PATCH 2/6] OF: Add [__]of_find_node_by_full_name
@ 2014-06-24 13:55         ` Grant Likely
  0 siblings, 0 replies; 63+ messages in thread
From: Grant Likely @ 2014-06-24 13:55 UTC (permalink / raw)
  To: Pantelis Antoniou, Guenter Roeck
  Cc: Rob Herring, Stephen Warren, Matt Porter, Koen Kooi,
	Greg Kroah-Hartman, Alison Chaiken, Dinh Nguyen, Jan Lubbe,
	Alexander Sverdlin, Michael Stickel, Dirk Behme, Alan Tull,
	Sascha Hauer, Michael Bohan, Ionut Nicu, Michal Simek,
	Matt Ranostay, Joel Becker, devicetree, Wolfram Sang, linux-i2c,
	Mark Brown, linux-spi, linux-kernel, Pete Popov, Dan Malek,
	Georgi Vlaev

On Mon, 23 Jun 2014 21:00:39 +0300, Pantelis Antoniou <pantelis.antoniou@konsulko.com> wrote:
> Hi Guenter,
> 
> On Jun 23, 2014, at 8:58 PM, Guenter Roeck wrote:
> 
> > On 06/22/2014 02:40 AM, Pantelis Antoniou wrote:
> >> __of_find_node_by_full_name recursively searches for a matching node
> >> with the given full name without taking any locks.
> >> 
> >> of_find_node_by_full_name takes locks and takes a reference on the
> >> matching node.
> >> 
> >> Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
> >> ---
> >>  drivers/of/base.c  | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >>  include/linux/of.h |  4 ++++
> >>  2 files changed, 62 insertions(+)
> >> 
> >> diff --git a/drivers/of/base.c b/drivers/of/base.c
> >> index d3493e1..80fef33 100644
> >> --- a/drivers/of/base.c
> >> +++ b/drivers/of/base.c
> >> @@ -1201,6 +1201,64 @@ static void *of_find_property_value_of_size(const struct device_node *np,
> >>  }
> >> 
> >>  /**
> >> + * __of_find_node_by_full_name - Find a node with the full name recursively
> >> + * @node:	Root of the tree to perform the search
> >> + * @full_name:	Full name of the node to find.
> >> + *
> >> + * Find a node with the give full name by recursively following any of
> >> + * the child node links.
> >> + * Returns the matching node, or NULL if not found.
> >> + * Note that the devtree lock is not taken, so this function is only
> >> + * safe to call on either detached trees, or when devtree lock is already
> >> + * taken.
> >> + */
> >> +struct device_node *__of_find_node_by_full_name(struct device_node *node,
> >> +		const char *full_name)
> >> +{
> >> +	struct device_node *child, *found;
> >> +
> >> +	if (node == NULL)
> >> +		return NULL;
> >> +
> >> +	/* check */
> >> +	if (of_node_cmp(node->full_name, full_name) == 0)
> >> +		return node;
> >> +
> >> +	__for_each_child_of_node(node, child) {
> >> +		found = __of_find_node_by_full_name(child, full_name);
> >> +		if (found != NULL)
> >> +			return found;
> >> +	}
> >> +
> >> +	return NULL;
> >> +}
> >> +EXPORT_SYMBOL(__of_find_node_by_full_name);
> >> +
> >> +/**
> >> + * of_find_node_by_full_name - Find a node with the full name recursively
> >> + * @node:	Root of the tree to perform the search
> >> + * @full_name:	Full name of the node to find.
> >> + *
> >> + * Find a node with the give full name by recursively following any of
> >> + * the child node links.
> >> + * Returns the matching node (with a ref taken), or NULL if not found.
> >> + */
> >> +struct device_node *of_find_node_by_full_name(struct device_node *node,
> >> +		const char *full_name)
> >> +{
> >> +	unsigned long flags;
> >> +	struct device_node *np;
> >> +
> >> +	raw_spin_lock_irqsave(&devtree_lock, flags);
> >> +	np = of_find_node_by_full_name(node, full_name);
> > 
> > Should this be __of_find_node_by_full_name, or am I missing something ?
> > 
> 
> Ugh, you're not missing something. This slipped through since this is not 
> used in the current code

Then perhaps the function shouldn't exist at all.

g.


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

* Re: [PATCH 2/6] OF: Add [__]of_find_node_by_full_name
@ 2014-06-24 13:55         ` Grant Likely
  0 siblings, 0 replies; 63+ messages in thread
From: Grant Likely @ 2014-06-24 13:55 UTC (permalink / raw)
  To: Pantelis Antoniou, Guenter Roeck
  Cc: Rob Herring, Stephen Warren, Matt Porter, Koen Kooi,
	Greg Kroah-Hartman, Alison Chaiken, Dinh Nguyen, Jan Lubbe,
	Alexander Sverdlin, Michael Stickel, Dirk Behme, Alan Tull,
	Sascha Hauer, Michael Bohan, Ionut Nicu, Michal Simek,
	Matt Ranostay, Joel Becker, devicetree-u79uwXL29TY76Z2rM5mHXA,
	Wolfram Sang, linux-i2c-u79uwXL29TY76Z2rM5mHXA, Mark Brown,
	linux-spi-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Pete

On Mon, 23 Jun 2014 21:00:39 +0300, Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org> wrote:
> Hi Guenter,
> 
> On Jun 23, 2014, at 8:58 PM, Guenter Roeck wrote:
> 
> > On 06/22/2014 02:40 AM, Pantelis Antoniou wrote:
> >> __of_find_node_by_full_name recursively searches for a matching node
> >> with the given full name without taking any locks.
> >> 
> >> of_find_node_by_full_name takes locks and takes a reference on the
> >> matching node.
> >> 
> >> Signed-off-by: Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
> >> ---
> >>  drivers/of/base.c  | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >>  include/linux/of.h |  4 ++++
> >>  2 files changed, 62 insertions(+)
> >> 
> >> diff --git a/drivers/of/base.c b/drivers/of/base.c
> >> index d3493e1..80fef33 100644
> >> --- a/drivers/of/base.c
> >> +++ b/drivers/of/base.c
> >> @@ -1201,6 +1201,64 @@ static void *of_find_property_value_of_size(const struct device_node *np,
> >>  }
> >> 
> >>  /**
> >> + * __of_find_node_by_full_name - Find a node with the full name recursively
> >> + * @node:	Root of the tree to perform the search
> >> + * @full_name:	Full name of the node to find.
> >> + *
> >> + * Find a node with the give full name by recursively following any of
> >> + * the child node links.
> >> + * Returns the matching node, or NULL if not found.
> >> + * Note that the devtree lock is not taken, so this function is only
> >> + * safe to call on either detached trees, or when devtree lock is already
> >> + * taken.
> >> + */
> >> +struct device_node *__of_find_node_by_full_name(struct device_node *node,
> >> +		const char *full_name)
> >> +{
> >> +	struct device_node *child, *found;
> >> +
> >> +	if (node == NULL)
> >> +		return NULL;
> >> +
> >> +	/* check */
> >> +	if (of_node_cmp(node->full_name, full_name) == 0)
> >> +		return node;
> >> +
> >> +	__for_each_child_of_node(node, child) {
> >> +		found = __of_find_node_by_full_name(child, full_name);
> >> +		if (found != NULL)
> >> +			return found;
> >> +	}
> >> +
> >> +	return NULL;
> >> +}
> >> +EXPORT_SYMBOL(__of_find_node_by_full_name);
> >> +
> >> +/**
> >> + * of_find_node_by_full_name - Find a node with the full name recursively
> >> + * @node:	Root of the tree to perform the search
> >> + * @full_name:	Full name of the node to find.
> >> + *
> >> + * Find a node with the give full name by recursively following any of
> >> + * the child node links.
> >> + * Returns the matching node (with a ref taken), or NULL if not found.
> >> + */
> >> +struct device_node *of_find_node_by_full_name(struct device_node *node,
> >> +		const char *full_name)
> >> +{
> >> +	unsigned long flags;
> >> +	struct device_node *np;
> >> +
> >> +	raw_spin_lock_irqsave(&devtree_lock, flags);
> >> +	np = of_find_node_by_full_name(node, full_name);
> > 
> > Should this be __of_find_node_by_full_name, or am I missing something ?
> > 
> 
> Ugh, you're not missing something. This slipped through since this is not 
> used in the current code

Then perhaps the function shouldn't exist at all.

g.

--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH 2/6] OF: Add [__]of_find_node_by_full_name
@ 2014-06-24 13:55         ` Grant Likely
  0 siblings, 0 replies; 63+ messages in thread
From: Grant Likely @ 2014-06-24 13:55 UTC (permalink / raw)
  To: Pantelis Antoniou, Guenter Roeck
  Cc: Rob Herring, Stephen Warren, Matt Porter, Koen Kooi,
	Greg Kroah-Hartman, Alison Chaiken, Dinh Nguyen, Jan Lubbe,
	Alexander Sverdlin, Michael Stickel, Dirk Behme, Alan Tull,
	Sascha Hauer, Michael Bohan, Ionut Nicu, Michal Simek,
	Matt Ranostay, Joel Becker, devicetree-u79uwXL29TY76Z2rM5mHXA,
	Wolfram Sang, linux-i2c-u79uwXL29TY76Z2rM5mHXA, Mark Brown,
	linux-spi-u79uwXL29TY76Z2rM5mHXA,
	linux-kernel-u79uwXL29TY76Z2rM5mHXA, Pete

On Mon, 23 Jun 2014 21:00:39 +0300, Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org> wrote:
> Hi Guenter,
> 
> On Jun 23, 2014, at 8:58 PM, Guenter Roeck wrote:
> 
> > On 06/22/2014 02:40 AM, Pantelis Antoniou wrote:
> >> __of_find_node_by_full_name recursively searches for a matching node
> >> with the given full name without taking any locks.
> >> 
> >> of_find_node_by_full_name takes locks and takes a reference on the
> >> matching node.
> >> 
> >> Signed-off-by: Pantelis Antoniou <pantelis.antoniou-OWPKS81ov/FWk0Htik3J/w@public.gmane.org>
> >> ---
> >>  drivers/of/base.c  | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
> >>  include/linux/of.h |  4 ++++
> >>  2 files changed, 62 insertions(+)
> >> 
> >> diff --git a/drivers/of/base.c b/drivers/of/base.c
> >> index d3493e1..80fef33 100644
> >> --- a/drivers/of/base.c
> >> +++ b/drivers/of/base.c
> >> @@ -1201,6 +1201,64 @@ static void *of_find_property_value_of_size(const struct device_node *np,
> >>  }
> >> 
> >>  /**
> >> + * __of_find_node_by_full_name - Find a node with the full name recursively
> >> + * @node:	Root of the tree to perform the search
> >> + * @full_name:	Full name of the node to find.
> >> + *
> >> + * Find a node with the give full name by recursively following any of
> >> + * the child node links.
> >> + * Returns the matching node, or NULL if not found.
> >> + * Note that the devtree lock is not taken, so this function is only
> >> + * safe to call on either detached trees, or when devtree lock is already
> >> + * taken.
> >> + */
> >> +struct device_node *__of_find_node_by_full_name(struct device_node *node,
> >> +		const char *full_name)
> >> +{
> >> +	struct device_node *child, *found;
> >> +
> >> +	if (node == NULL)
> >> +		return NULL;
> >> +
> >> +	/* check */
> >> +	if (of_node_cmp(node->full_name, full_name) == 0)
> >> +		return node;
> >> +
> >> +	__for_each_child_of_node(node, child) {
> >> +		found = __of_find_node_by_full_name(child, full_name);
> >> +		if (found != NULL)
> >> +			return found;
> >> +	}
> >> +
> >> +	return NULL;
> >> +}
> >> +EXPORT_SYMBOL(__of_find_node_by_full_name);
> >> +
> >> +/**
> >> + * of_find_node_by_full_name - Find a node with the full name recursively
> >> + * @node:	Root of the tree to perform the search
> >> + * @full_name:	Full name of the node to find.
> >> + *
> >> + * Find a node with the give full name by recursively following any of
> >> + * the child node links.
> >> + * Returns the matching node (with a ref taken), or NULL if not found.
> >> + */
> >> +struct device_node *of_find_node_by_full_name(struct device_node *node,
> >> +		const char *full_name)
> >> +{
> >> +	unsigned long flags;
> >> +	struct device_node *np;
> >> +
> >> +	raw_spin_lock_irqsave(&devtree_lock, flags);
> >> +	np = of_find_node_by_full_name(node, full_name);
> > 
> > Should this be __of_find_node_by_full_name, or am I missing something ?
> > 
> 
> Ugh, you're not missing something. This slipped through since this is not 
> used in the current code

Then perhaps the function shouldn't exist at all.

g.

--
To unsubscribe from this list: send the line "unsubscribe linux-spi" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

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

* Re: [PATCH 1/6] of: Do not free memory at of_node_release
  2014-06-22  9:40 ` [PATCH 1/6] of: Do not free memory at of_node_release Pantelis Antoniou
@ 2014-06-24 14:10   ` Grant Likely
  2014-06-24 14:23     ` Pantelis Antoniou
  2014-06-24 14:53     ` Guenter Roeck
  0 siblings, 2 replies; 63+ messages in thread
From: Grant Likely @ 2014-06-24 14:10 UTC (permalink / raw)
  To: Pantelis Antoniou
  Cc: Rob Herring, Stephen Warren, Matt Porter, Koen Kooi,
	Greg Kroah-Hartman, Alison Chaiken, Dinh Nguyen, Jan Lubbe,
	Alexander Sverdlin, Michael Stickel, Guenter Roeck, Dirk Behme,
	Alan Tull, Sascha Hauer, Michael Bohan, Ionut Nicu, Michal Simek,
	Matt Ranostay, Joel Becker, devicetree, Wolfram Sang, linux-i2c,
	Mark Brown, linux-spi, linux-kernel, Pete Popov, Dan Malek,
	Georgi Vlaev, Pantelis Antoniou

On Sun, 22 Jun 2014 12:40:34 +0300, Pantelis Antoniou <pantelis.antoniou@konsulko.com> wrote:
> The life-cycle of nodes and properties does not allow us to release
> the memory taken by a device_node. Pointer to properties and nodes
> might still be in use in drivers, so any memory free'ing is dangerous.
> 
> Simply move all the properties to the deadprops list, and the node
> itself to of_alldeadnodes until the life-cycles issues are resolved.

Ummm. this looks wrong. The release function is supposed to be the place
to do the freeing, and with our discussion the other day about moving to
rcu, but keeping of_node_get/put() for anything that needs to hold a
long term reference, that means the lifecycle issues are pretty much
resolved. I don't think this patch is necessary.

g.

> 
> Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
> ---
>  drivers/of/base.c | 43 ++++++++++++++++++++++++++++---------------
>  1 file changed, 28 insertions(+), 15 deletions(-)
> 
> diff --git a/drivers/of/base.c b/drivers/of/base.c
> index b986480..d3493e1 100644
> --- a/drivers/of/base.c
> +++ b/drivers/of/base.c
> @@ -110,17 +110,27 @@ static inline struct device_node *kobj_to_device_node(struct kobject *kobj)
>  	return container_of(kobj, struct device_node, kobj);
>  }
>  
> +static struct device_node *of_alldeadnodes;
> +static DEFINE_RAW_SPINLOCK(deadtree_lock);
> +
>  /**
>   *	of_node_release - release a dynamically allocated node
>   *	@kref:  kref element of the node to be released
>   *
>   *	In of_node_put() this function is passed to kref_put()
>   *	as the destructor.
> + *
> + *	Note that due to the way that node and property life-cycles
> + *	are not completely managed, we can't free the memory of
> + *	a node at will. Instead we move the node to the dead nodes
> + *	list where it will remain until the life-cycle issues are
> + *	resolved.
>   */
>  static void of_node_release(struct kobject *kobj)
>  {
>  	struct device_node *node = kobj_to_device_node(kobj);
> -	struct property *prop = node->properties;
> +	struct property *prop;
> +	unsigned long flags;
>  
>  	/* We should never be releasing nodes that haven't been detached. */
>  	if (!of_node_check_flag(node, OF_DETACHED)) {
> @@ -129,24 +139,27 @@ static void of_node_release(struct kobject *kobj)
>  		return;
>  	}
>  
> -	if (!of_node_check_flag(node, OF_DYNAMIC))
> +	pr_info("%s: dead node \"%s\"\n", __func__, node->full_name);
> +
> +	/* we should not be trying to release the root */
> +	if (WARN_ON(node == of_allnodes))
>  		return;
>  
> -	while (prop) {
> -		struct property *next = prop->next;
> -		kfree(prop->name);
> -		kfree(prop->value);
> -		kfree(prop);
> -		prop = next;
> +	/* can't use devtree lock; at of_node_put caller might be holding it */
> +	raw_spin_lock_irqsave(&deadtree_lock, flags);
>  
> -		if (!prop) {
> -			prop = node->deadprops;
> -			node->deadprops = NULL;
> -		}
> +	/* move all properties to dead properties */
> +	while ((prop = node->properties) != NULL) {
> +		node->properties = prop->next;
> +		prop->next = node->deadprops;
> +		node->deadprops = prop;
>  	}
> -	kfree(node->full_name);
> -	kfree(node->data);
> -	kfree(node);
> +
> +	/* move node to alldeadnodes */
> +	node->allnext = of_alldeadnodes;
> +	of_alldeadnodes = node;
> +
> +	raw_spin_unlock_irqrestore(&deadtree_lock, flags);
>  }
>  
>  /**
> -- 
> 1.7.12
> 

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

* Re: [PATCH 2/6] OF: Add [__]of_find_node_by_full_name
  2014-06-22  9:40 ` [PATCH 2/6] OF: Add [__]of_find_node_by_full_name Pantelis Antoniou
  2014-06-23 17:58   ` Guenter Roeck
@ 2014-06-24 14:12   ` Grant Likely
  2014-06-24 14:23     ` Pantelis Antoniou
  1 sibling, 1 reply; 63+ messages in thread
From: Grant Likely @ 2014-06-24 14:12 UTC (permalink / raw)
  To: Pantelis Antoniou
  Cc: Rob Herring, Stephen Warren, Matt Porter, Koen Kooi,
	Greg Kroah-Hartman, Alison Chaiken, Dinh Nguyen, Jan Lubbe,
	Alexander Sverdlin, Michael Stickel, Guenter Roeck, Dirk Behme,
	Alan Tull, Sascha Hauer, Michael Bohan, Ionut Nicu, Michal Simek,
	Matt Ranostay, Joel Becker, devicetree, Wolfram Sang, linux-i2c,
	Mark Brown, linux-spi, linux-kernel, Pete Popov, Dan Malek,
	Georgi Vlaev, Pantelis Antoniou

On Sun, 22 Jun 2014 12:40:35 +0300, Pantelis Antoniou <pantelis.antoniou@konsulko.com> wrote:
> __of_find_node_by_full_name recursively searches for a matching node
> with the given full name without taking any locks.
> 
> of_find_node_by_full_name takes locks and takes a reference on the
> matching node.
> 
> Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>

The only user of this turns out to be the resolver. No need to export it
or advertise it in include/linux/of.h. I don't want drive-by users. Move
it to the resolver.c file.

g.

> ---
>  drivers/of/base.c  | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/of.h |  4 ++++
>  2 files changed, 62 insertions(+)
> 
> diff --git a/drivers/of/base.c b/drivers/of/base.c
> index d3493e1..80fef33 100644
> --- a/drivers/of/base.c
> +++ b/drivers/of/base.c
> @@ -1201,6 +1201,64 @@ static void *of_find_property_value_of_size(const struct device_node *np,
>  }
>  
>  /**
> + * __of_find_node_by_full_name - Find a node with the full name recursively
> + * @node:	Root of the tree to perform the search
> + * @full_name:	Full name of the node to find.
> + *
> + * Find a node with the give full name by recursively following any of
> + * the child node links.
> + * Returns the matching node, or NULL if not found.
> + * Note that the devtree lock is not taken, so this function is only
> + * safe to call on either detached trees, or when devtree lock is already
> + * taken.
> + */
> +struct device_node *__of_find_node_by_full_name(struct device_node *node,
> +		const char *full_name)
> +{
> +	struct device_node *child, *found;
> +
> +	if (node == NULL)
> +		return NULL;
> +
> +	/* check */
> +	if (of_node_cmp(node->full_name, full_name) == 0)
> +		return node;
> +
> +	__for_each_child_of_node(node, child) {
> +		found = __of_find_node_by_full_name(child, full_name);
> +		if (found != NULL)
> +			return found;
> +	}
> +
> +	return NULL;
> +}
> +EXPORT_SYMBOL(__of_find_node_by_full_name);
> +
> +/**
> + * of_find_node_by_full_name - Find a node with the full name recursively
> + * @node:	Root of the tree to perform the search
> + * @full_name:	Full name of the node to find.
> + *
> + * Find a node with the give full name by recursively following any of
> + * the child node links.
> + * Returns the matching node (with a ref taken), or NULL if not found.
> + */
> +struct device_node *of_find_node_by_full_name(struct device_node *node,
> +		const char *full_name)
> +{
> +	unsigned long flags;
> +	struct device_node *np;
> +
> +	raw_spin_lock_irqsave(&devtree_lock, flags);
> +	np = of_find_node_by_full_name(node, full_name);
> +	of_node_get(np);
> +	raw_spin_unlock_irqrestore(&devtree_lock, flags);
> +
> +	return np;
> +}
> +EXPORT_SYMBOL(of_find_node_by_full_name);
> +
> +/**
>   * of_property_read_u32_index - Find and read a u32 from a multi-value property.
>   *
>   * @np:		device node from which the property value is to be read.
> diff --git a/include/linux/of.h b/include/linux/of.h
> index 196b34c..f7392c0 100644
> --- a/include/linux/of.h
> +++ b/include/linux/of.h
> @@ -230,6 +230,10 @@ extern struct device_node *of_find_matching_node_and_match(
>  
>  extern struct device_node *of_find_node_by_path(const char *path);
>  extern struct device_node *of_find_node_by_phandle(phandle handle);
> +struct device_node *__of_find_node_by_full_name(struct device_node *node,
> +						const char *full_name);
> +struct device_node *of_find_node_by_full_name(struct device_node *node,
> +						const char *full_name);
>  extern struct device_node *of_get_parent(const struct device_node *node);
>  extern struct device_node *of_get_next_parent(struct device_node *node);
>  extern struct device_node *of_get_next_child(const struct device_node *node,
> -- 
> 1.7.12
> 

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

* Re: [PATCH 3/6] of: platform: Fix and export of_platform_device_destroy
  2014-06-22  9:40 ` [PATCH 3/6] of: platform: Fix and export of_platform_device_destroy Pantelis Antoniou
@ 2014-06-24 14:23   ` Grant Likely
  2014-06-24 15:13   ` Grant Likely
  1 sibling, 0 replies; 63+ messages in thread
From: Grant Likely @ 2014-06-24 14:23 UTC (permalink / raw)
  To: Pantelis Antoniou
  Cc: Rob Herring, Stephen Warren, Matt Porter, Koen Kooi,
	Greg Kroah-Hartman, Alison Chaiken, Dinh Nguyen, Jan Lubbe,
	Alexander Sverdlin, Michael Stickel, Guenter Roeck, Dirk Behme,
	Alan Tull, Sascha Hauer, Michael Bohan, Ionut Nicu, Michal Simek,
	Matt Ranostay, Joel Becker, devicetree, Wolfram Sang, linux-i2c,
	Mark Brown, linux-spi, linux-kernel, Pete Popov, Dan Malek,
	Georgi Vlaev, Pantelis Antoniou

On Sun, 22 Jun 2014 12:40:36 +0300, Pantelis Antoniou <pantelis.antoniou@konsulko.com> wrote:
> of_platform_destroy did not work properly, since the tree
> population test was iterating on all devices having a parent
> a given platform device.
> 
> The check was intended to check whether any other *platform*
> devices were still populated, but instead checked for every
> kind of device. This is wrong, since platform devices typically
> create a subsystem regular device and set themselves as parents.
> 
> Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>

The commit text says nothing about why it is being exported. Regardless,
the notifier code needs to be moved into drivers/of/platform.c, which
removes the need for the export.

> ---
>  drivers/of/platform.c       | 11 ++++++++++-
>  include/linux/of_platform.h |  2 ++
>  2 files changed, 12 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/of/platform.c b/drivers/of/platform.c
> index 500436f..4f60060 100644
> --- a/drivers/of/platform.c
> +++ b/drivers/of/platform.c
> @@ -506,10 +506,18 @@ int of_platform_populate(struct device_node *root,
>  }
>  EXPORT_SYMBOL_GPL(of_platform_populate);
>  
> -static int of_platform_device_destroy(struct device *dev, void *data)
> +int of_platform_device_destroy(struct device *dev, void *data)
>  {
>  	bool *children_left = data;
>  
> +	/* if the device is not a platform device, do nothing */
> +	if (dev->bus != &platform_bus_type
> +#ifdef CONFIG_ARM_AMBA
> +		&& dev->bus != &amba_bustype
> +#endif
> +	   )
> +		return 0;
> +

Yes, this looks right. I'll pick up the patch as a fix and push it out
to Linus (without the export bit).

g.

>  	/* Do not touch devices not populated from the device tree */
>  	if (!dev->of_node || !of_node_check_flag(dev->of_node, OF_POPULATED)) {
>  		*children_left = true;
> @@ -537,6 +545,7 @@ static int of_platform_device_destroy(struct device *dev, void *data)
>  
>  	return 0;
>  }
> +EXPORT_SYMBOL_GPL(of_platform_device_destroy);
>  
>  /**
>   * of_platform_depopulate() - Remove devices populated from device tree
> diff --git a/include/linux/of_platform.h b/include/linux/of_platform.h
> index d96e1ba..61c7e8c 100644
> --- a/include/linux/of_platform.h
> +++ b/include/linux/of_platform.h
> @@ -64,6 +64,8 @@ extern struct platform_device *of_platform_device_create(struct device_node *np,
>  						   const char *bus_id,
>  						   struct device *parent);
>  
> +extern int of_platform_device_destroy(struct device *dev, void *data);
> +
>  extern int of_platform_bus_probe(struct device_node *root,
>  				 const struct of_device_id *matches,
>  				 struct device *parent);
> -- 
> 1.7.12
> 

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

* Re: [PATCH 1/6] of: Do not free memory at of_node_release
  2014-06-24 14:10   ` Grant Likely
@ 2014-06-24 14:23     ` Pantelis Antoniou
  2014-06-24 20:21       ` Grant Likely
  2014-06-24 14:53     ` Guenter Roeck
  1 sibling, 1 reply; 63+ messages in thread
From: Pantelis Antoniou @ 2014-06-24 14:23 UTC (permalink / raw)
  To: Grant Likely
  Cc: Rob Herring, Stephen Warren, Matt Porter, Koen Kooi,
	Greg Kroah-Hartman, Alison Chaiken, Dinh Nguyen, Jan Lubbe,
	Alexander Sverdlin, Michael Stickel, Guenter Roeck, Dirk Behme,
	Alan Tull, Sascha Hauer, Michael Bohan, Ionut Nicu, Michal Simek,
	Matt Ranostay, Joel Becker, devicetree, Wolfram Sang, linux-i2c,
	Mark Brown, linux-spi, linux-kernel, Pete Popov, Dan Malek,
	Georgi Vlaev

Hi Grant,

On Jun 24, 2014, at 5:10 PM, Grant Likely wrote:

> On Sun, 22 Jun 2014 12:40:34 +0300, Pantelis Antoniou <pantelis.antoniou@konsulko.com> wrote:
>> The life-cycle of nodes and properties does not allow us to release
>> the memory taken by a device_node. Pointer to properties and nodes
>> might still be in use in drivers, so any memory free'ing is dangerous.
>> 
>> Simply move all the properties to the deadprops list, and the node
>> itself to of_alldeadnodes until the life-cycles issues are resolved.
> 
> Ummm. this looks wrong. The release function is supposed to be the place
> to do the freeing, and with our discussion the other day about moving to
> rcu, but keeping of_node_get/put() for anything that needs to hold a
> long term reference, that means the lifecycle issues are pretty much
> resolved. I don't think this patch is necessary.
> 

Well, I thought about it too. This is the culmination of that process :)

The problem is not the node life-cycle, it's the properties. We can't
tell for sure who and where has a pointer to the properties of the node,
and when we free the node, the current code iterates over the properties
list and frees them. This works only because in my tests, of_node_release
only gets called when using overlays created nodes.

It is your call, but this patch makes me sleep easier at nights :)

> g.
> 

Regards

-- Pantelis

>> 
>> Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
>> ---
>> drivers/of/base.c | 43 ++++++++++++++++++++++++++++---------------
>> 1 file changed, 28 insertions(+), 15 deletions(-)
>> 
>> diff --git a/drivers/of/base.c b/drivers/of/base.c
>> index b986480..d3493e1 100644
>> --- a/drivers/of/base.c
>> +++ b/drivers/of/base.c
>> @@ -110,17 +110,27 @@ static inline struct device_node *kobj_to_device_node(struct kobject *kobj)
>> 	return container_of(kobj, struct device_node, kobj);
>> }
>> 
>> +static struct device_node *of_alldeadnodes;
>> +static DEFINE_RAW_SPINLOCK(deadtree_lock);
>> +
>> /**
>>  *	of_node_release - release a dynamically allocated node
>>  *	@kref:  kref element of the node to be released
>>  *
>>  *	In of_node_put() this function is passed to kref_put()
>>  *	as the destructor.
>> + *
>> + *	Note that due to the way that node and property life-cycles
>> + *	are not completely managed, we can't free the memory of
>> + *	a node at will. Instead we move the node to the dead nodes
>> + *	list where it will remain until the life-cycle issues are
>> + *	resolved.
>>  */
>> static void of_node_release(struct kobject *kobj)
>> {
>> 	struct device_node *node = kobj_to_device_node(kobj);
>> -	struct property *prop = node->properties;
>> +	struct property *prop;
>> +	unsigned long flags;
>> 
>> 	/* We should never be releasing nodes that haven't been detached. */
>> 	if (!of_node_check_flag(node, OF_DETACHED)) {
>> @@ -129,24 +139,27 @@ static void of_node_release(struct kobject *kobj)
>> 		return;
>> 	}
>> 
>> -	if (!of_node_check_flag(node, OF_DYNAMIC))
>> +	pr_info("%s: dead node \"%s\"\n", __func__, node->full_name);
>> +
>> +	/* we should not be trying to release the root */
>> +	if (WARN_ON(node == of_allnodes))
>> 		return;
>> 
>> -	while (prop) {
>> -		struct property *next = prop->next;
>> -		kfree(prop->name);
>> -		kfree(prop->value);
>> -		kfree(prop);
>> -		prop = next;
>> +	/* can't use devtree lock; at of_node_put caller might be holding it */
>> +	raw_spin_lock_irqsave(&deadtree_lock, flags);
>> 
>> -		if (!prop) {
>> -			prop = node->deadprops;
>> -			node->deadprops = NULL;
>> -		}
>> +	/* move all properties to dead properties */
>> +	while ((prop = node->properties) != NULL) {
>> +		node->properties = prop->next;
>> +		prop->next = node->deadprops;
>> +		node->deadprops = prop;
>> 	}
>> -	kfree(node->full_name);
>> -	kfree(node->data);
>> -	kfree(node);
>> +
>> +	/* move node to alldeadnodes */
>> +	node->allnext = of_alldeadnodes;
>> +	of_alldeadnodes = node;
>> +
>> +	raw_spin_unlock_irqrestore(&deadtree_lock, flags);
>> }
>> 
>> /**
>> -- 
>> 1.7.12
>> 
> 

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

* Re: [PATCH 2/6] OF: Add [__]of_find_node_by_full_name
  2014-06-24 14:12   ` Grant Likely
@ 2014-06-24 14:23     ` Pantelis Antoniou
  0 siblings, 0 replies; 63+ messages in thread
From: Pantelis Antoniou @ 2014-06-24 14:23 UTC (permalink / raw)
  To: Grant Likely
  Cc: Rob Herring, Stephen Warren, Matt Porter, Koen Kooi,
	Greg Kroah-Hartman, Alison Chaiken, Dinh Nguyen, Jan Lubbe,
	Alexander Sverdlin, Michael Stickel, Guenter Roeck, Dirk Behme,
	Alan Tull, Sascha Hauer, Michael Bohan, Ionut Nicu, Michal Simek,
	Matt Ranostay, Joel Becker, devicetree, Wolfram Sang, linux-i2c,
	Mark Brown, linux-spi, linux-kernel, Pete Popov, Dan Malek,
	Georgi Vlaev

Hi Grant,

On Jun 24, 2014, at 5:12 PM, Grant Likely wrote:

> On Sun, 22 Jun 2014 12:40:35 +0300, Pantelis Antoniou <pantelis.antoniou@konsulko.com> wrote:
>> __of_find_node_by_full_name recursively searches for a matching node
>> with the given full name without taking any locks.
>> 
>> of_find_node_by_full_name takes locks and takes a reference on the
>> matching node.
>> 
>> Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
> 
> The only user of this turns out to be the resolver. No need to export it
> or advertise it in include/linux/of.h. I don't want drive-by users. Move
> it to the resolver.c file.
> 

OK.

> g.
> 

Regards

-- Pantelis

>> ---
>> drivers/of/base.c  | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++
>> include/linux/of.h |  4 ++++
>> 2 files changed, 62 insertions(+)
>> 
>> diff --git a/drivers/of/base.c b/drivers/of/base.c
>> index d3493e1..80fef33 100644
>> --- a/drivers/of/base.c
>> +++ b/drivers/of/base.c
>> @@ -1201,6 +1201,64 @@ static void *of_find_property_value_of_size(const struct device_node *np,
>> }
>> 
>> /**
>> + * __of_find_node_by_full_name - Find a node with the full name recursively
>> + * @node:	Root of the tree to perform the search
>> + * @full_name:	Full name of the node to find.
>> + *
>> + * Find a node with the give full name by recursively following any of
>> + * the child node links.
>> + * Returns the matching node, or NULL if not found.
>> + * Note that the devtree lock is not taken, so this function is only
>> + * safe to call on either detached trees, or when devtree lock is already
>> + * taken.
>> + */
>> +struct device_node *__of_find_node_by_full_name(struct device_node *node,
>> +		const char *full_name)
>> +{
>> +	struct device_node *child, *found;
>> +
>> +	if (node == NULL)
>> +		return NULL;
>> +
>> +	/* check */
>> +	if (of_node_cmp(node->full_name, full_name) == 0)
>> +		return node;
>> +
>> +	__for_each_child_of_node(node, child) {
>> +		found = __of_find_node_by_full_name(child, full_name);
>> +		if (found != NULL)
>> +			return found;
>> +	}
>> +
>> +	return NULL;
>> +}
>> +EXPORT_SYMBOL(__of_find_node_by_full_name);
>> +
>> +/**
>> + * of_find_node_by_full_name - Find a node with the full name recursively
>> + * @node:	Root of the tree to perform the search
>> + * @full_name:	Full name of the node to find.
>> + *
>> + * Find a node with the give full name by recursively following any of
>> + * the child node links.
>> + * Returns the matching node (with a ref taken), or NULL if not found.
>> + */
>> +struct device_node *of_find_node_by_full_name(struct device_node *node,
>> +		const char *full_name)
>> +{
>> +	unsigned long flags;
>> +	struct device_node *np;
>> +
>> +	raw_spin_lock_irqsave(&devtree_lock, flags);
>> +	np = of_find_node_by_full_name(node, full_name);
>> +	of_node_get(np);
>> +	raw_spin_unlock_irqrestore(&devtree_lock, flags);
>> +
>> +	return np;
>> +}
>> +EXPORT_SYMBOL(of_find_node_by_full_name);
>> +
>> +/**
>>  * of_property_read_u32_index - Find and read a u32 from a multi-value property.
>>  *
>>  * @np:		device node from which the property value is to be read.
>> diff --git a/include/linux/of.h b/include/linux/of.h
>> index 196b34c..f7392c0 100644
>> --- a/include/linux/of.h
>> +++ b/include/linux/of.h
>> @@ -230,6 +230,10 @@ extern struct device_node *of_find_matching_node_and_match(
>> 
>> extern struct device_node *of_find_node_by_path(const char *path);
>> extern struct device_node *of_find_node_by_phandle(phandle handle);
>> +struct device_node *__of_find_node_by_full_name(struct device_node *node,
>> +						const char *full_name);
>> +struct device_node *of_find_node_by_full_name(struct device_node *node,
>> +						const char *full_name);
>> extern struct device_node *of_get_parent(const struct device_node *node);
>> extern struct device_node *of_get_next_parent(struct device_node *node);
>> extern struct device_node *of_get_next_child(const struct device_node *node,
>> -- 
>> 1.7.12
>> 
> 

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

* Re: [PATCH 5/6] OF: Utility helper functions for dynamic nodes
  2014-06-24 13:53                 ` Alexander Sverdlin
@ 2014-06-24 14:49                   ` Rob Herring
  2014-06-24 15:43                     ` Alexander Sverdlin
  0 siblings, 1 reply; 63+ messages in thread
From: Rob Herring @ 2014-06-24 14:49 UTC (permalink / raw)
  To: Alexander Sverdlin
  Cc: Pantelis Antoniou, Guenter Roeck, Ioan Nicu, Grant Likely,
	Stephen Warren, Matt Porter, Koen Kooi, Greg Kroah-Hartman,
	Alison Chaiken, Dinh Nguyen, Jan Lubbe, Michael Stickel,
	Dirk Behme, Alan Tull, Sascha Hauer, Michael Bohan, Michal Simek,
	Matt Ranostay, Joel Becker, devicetree, Wolfram Sang, linux-i2c,
	Mark Brown, linux-spi, linux-kernel, Pete Popov, Dan Malek,
	Georgi Vlaev

On Tue, Jun 24, 2014 at 8:53 AM, Alexander Sverdlin
<alexander.sverdlin@nsn.com> wrote:
> Hi!
>
> On 24/06/14 15:46, ext Rob Herring wrote:
> [...]
>
>>>>> If that's the case, the code in irq.c is wrong.
>>>>>
>>>>> interrupt-controller is a bool property; the correct call to use is of_property_read_bool()
>>>>> which returns true or false when the value is defined.
>>>>>
>>>>> The use of of_get_property is a bug here. It is perfectly valid for a property to have a
>>>>> NULL value when length = 0.
>>>>>
>>>>
>>>> That usage is spread throughout the code though. There are three or four similar checks
>>>> for interrupt-controller in the code, and many others using of_get_property() to check
>>>> for booleans.
>>>>
>>>> Some examples:
>>>>       s5m8767,pmic-buck2-ramp-enable
>>>>       s5m8767,pmic-buck3-ramp-enable
>>>>       s5m8767,pmic-buck4-ramp-enable
>>>>       d7s-flipped?
>>>>       atmel,use-dma-rx
>>>>       linux,rs485-enabled-at-boot-time
>>>>       marvell,enable-port1 (and many others)
>>>>       linux,bootx-noscreen
>>>>       linux,opened
>>>>
>>>> and many many others.
>>>>
>>>> Maybe people meant to use of_find_property() ?
>>>>
>>>
>>> I bet... I see a lot of users doing if (of_get_property()).
>>>
>>> Which is no good.
>>
>> I don't see what the issue is. The irq.c code is correct. The code is
>> checking for existence of a property or not and of_get_property
>> adequately does that. of_find_property is equivalent in this case. Now
>
> The code is correct and the functions are equal as long as we declare that
> void property has value != NULL. Which must not be actually and the patch
> from Pantelis actually creates this situation first time.
>
> So let's first agree, how should the empty property look like.
> length should be 0, it's clear. But what about the value?

Actually, it is really only about what of_get_property's behavior is,
and I'm saying it should remain as is. You could also make
of_get_property return an empty string if prop->value is NULL. That
could still possibly break some callers of of_find_property which
would need fixing. But there's ~300 callers vs. ~1300 for
of_get_property. In scanning thru of_find_property callers, it look
like in general they are okay if prop->value changed to NULL.

Unless there is some difficulty to support, the lower risk approach is
just ensure prop->value is not NULL.

Rob

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

* Re: [PATCH 1/6] of: Do not free memory at of_node_release
  2014-06-24 14:10   ` Grant Likely
  2014-06-24 14:23     ` Pantelis Antoniou
@ 2014-06-24 14:53     ` Guenter Roeck
  1 sibling, 0 replies; 63+ messages in thread
From: Guenter Roeck @ 2014-06-24 14:53 UTC (permalink / raw)
  To: Grant Likely, Pantelis Antoniou
  Cc: Rob Herring, Stephen Warren, Matt Porter, Koen Kooi,
	Greg Kroah-Hartman, Alison Chaiken, Dinh Nguyen, Jan Lubbe,
	Alexander Sverdlin, Michael Stickel, Dirk Behme, Alan Tull,
	Sascha Hauer, Michael Bohan, Ionut Nicu, Michal Simek,
	Matt Ranostay, Joel Becker, devicetree, Wolfram Sang, linux-i2c,
	Mark Brown, linux-spi, linux-kernel, Pete Popov, Dan Malek,
	Georgi Vlaev, Pantelis Antoniou

On 06/24/2014 07:10 AM, Grant Likely wrote:
> On Sun, 22 Jun 2014 12:40:34 +0300, Pantelis Antoniou <pantelis.antoniou@konsulko.com> wrote:
>> The life-cycle of nodes and properties does not allow us to release
>> the memory taken by a device_node. Pointer to properties and nodes
>> might still be in use in drivers, so any memory free'ing is dangerous.
>>
>> Simply move all the properties to the deadprops list, and the node
>> itself to of_alldeadnodes until the life-cycles issues are resolved.
>
> Ummm. this looks wrong. The release function is supposed to be the place
> to do the freeing, and with our discussion the other day about moving to
> rcu, but keeping of_node_get/put() for anything that needs to hold a
> long term reference, that means the lifecycle issues are pretty much
> resolved. I don't think this patch is necessary.
>
I am also a bit concerned about its implications. Does it mean that repeated
insertion/removal of an overlay will result in memory leaks ? I am sure
we'll find a bunch of memory leaks over time, but this looks like an
intentional one, which could be easy to create trouble if a system is
supposed to stay up for months or years.

Thanks,
Guenter

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

* Re: [PATCH 3/6] of: platform: Fix and export of_platform_device_destroy
  2014-06-22  9:40 ` [PATCH 3/6] of: platform: Fix and export of_platform_device_destroy Pantelis Antoniou
  2014-06-24 14:23   ` Grant Likely
@ 2014-06-24 15:13   ` Grant Likely
  1 sibling, 0 replies; 63+ messages in thread
From: Grant Likely @ 2014-06-24 15:13 UTC (permalink / raw)
  To: Pantelis Antoniou, Pawel Moll
  Cc: Rob Herring, Stephen Warren, Matt Porter, Koen Kooi,
	Greg Kroah-Hartman, Alison Chaiken, Dinh Nguyen, Jan Lubbe,
	Alexander Sverdlin, Michael Stickel, Guenter Roeck, Dirk Behme,
	Alan Tull, Sascha Hauer, Michael Bohan, Ionut Nicu, Michal Simek,
	Matt Ranostay, Joel Becker, devicetree, Wolfram Sang, linux-i2c,
	Mark Brown, linux-spi, linux-kernel, Pete Popov, Dan Malek,
	Georgi Vlaev, Pantelis Antoniou

On Sun, 22 Jun 2014 12:40:36 +0300, Pantelis Antoniou <pantelis.antoniou@konsulko.com> wrote:
> of_platform_destroy did not work properly, since the tree
> population test was iterating on all devices having a parent
> a given platform device.
> 
> The check was intended to check whether any other *platform*
> devices were still populated, but instead checked for every
> kind of device. This is wrong, since platform devices typically
> create a subsystem regular device and set themselves as parents.
> 
> Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
> ---
>  drivers/of/platform.c       | 11 ++++++++++-
>  include/linux/of_platform.h |  2 ++
>  2 files changed, 12 insertions(+), 1 deletion(-)
> 
> diff --git a/drivers/of/platform.c b/drivers/of/platform.c
> index 500436f..4f60060 100644
> --- a/drivers/of/platform.c
> +++ b/drivers/of/platform.c
> @@ -506,10 +506,18 @@ int of_platform_populate(struct device_node *root,
>  }
>  EXPORT_SYMBOL_GPL(of_platform_populate);
>  
> -static int of_platform_device_destroy(struct device *dev, void *data)
> +int of_platform_device_destroy(struct device *dev, void *data)
>  {
>  	bool *children_left = data;
>  
> +	/* if the device is not a platform device, do nothing */
> +	if (dev->bus != &platform_bus_type
> +#ifdef CONFIG_ARM_AMBA
> +		&& dev->bus != &amba_bustype
> +#endif
> +	   )
> +		return 0;
> +

[Adding Pawel who introduced of_platform_device_destroy()]

Actually, it occurs to me that the *children_left test is completly
wrong and should just be removed outright. If there are devices left,
then it is a great big driver bug because the driver failed to clean up
after itself on remove. We can let the driver core complain loudly when
things go wrong. In fact, we must do that because the device unregister
functions don't provide any return code anyway.

Pawel, does the following patch look correct to you?

g.

---
of/platform: Fix of_platform_device_destroy iteration of devices

of_platform_destroy does not work properly, since the tree
population test was iterating on all devices having as its parent
the given platform device.

The check was intended to check whether any other platform or amba
devices created by of_platform_populate were still populated, but
instead checked for every kind of device. This is wrong, since platform
devices typically create a subsystem regular device and set themselves
as parents.

Instead, go ahead and call the unregister functions for any devices
created with of_platform_populate. The driver core will take care of
unbinding drivers, and drivers are responsible for getting rid of any
child devices that weren't created by of_platform_populate.

Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
Signed-off-by: Grant Likely <grant.likely@linaro.org>
---
 drivers/of/platform.c       | 32 +++++++++-----------------------
 include/linux/of.h          |  1 +
 include/linux/of_platform.h |  7 ++-----
 3 files changed, 12 insertions(+), 28 deletions(-)

diff --git a/drivers/of/platform.c b/drivers/of/platform.c
index 6c48d73a7fd7..cb57e488779a 100644
--- a/drivers/of/platform.c
+++ b/drivers/of/platform.c
@@ -426,6 +426,7 @@ static int of_platform_bus_create(struct device_node *bus,
 			break;
 		}
 	}
+	of_node_set_flag(bus, OF_POPULATED_BUS);
 	return rc;
 }
 
@@ -512,19 +513,13 @@ EXPORT_SYMBOL_GPL(of_platform_populate);
 
 static int of_platform_device_destroy(struct device *dev, void *data)
 {
-	bool *children_left = data;
-
 	/* Do not touch devices not populated from the device tree */
-	if (!dev->of_node || !of_node_check_flag(dev->of_node, OF_POPULATED)) {
-		*children_left = true;
+	if (!dev->of_node || !of_node_check_flag(dev->of_node, OF_POPULATED))
 		return 0;
-	}
 
-	/* Recurse, but don't touch this device if it has any children left */
-	if (of_platform_depopulate(dev) != 0) {
-		*children_left = true;
-		return 0;
-	}
+	/* Recurse for any nodes that were treated as busses */
+	if (of_node_check_flag(dev->of_node, OF_POPULATED_BUS))
+		device_for_each_child(dev, NULL, of_platform_device_destroy);
 
 	if (dev->bus == &platform_bus_type)
 		platform_device_unregister(to_platform_device(dev));
@@ -532,19 +527,15 @@ static int of_platform_device_destroy(struct device *dev, void *data)
 	else if (dev->bus == &amba_bustype)
 		amba_device_unregister(to_amba_device(dev));
 #endif
-	else {
-		*children_left = true;
-		return 0;
-	}
 
 	of_node_clear_flag(dev->of_node, OF_POPULATED);
-
+	of_node_clear_flag(dev->of_node, OF_POPULATED_BUS);
 	return 0;
 }
 
 /**
  * of_platform_depopulate() - Remove devices populated from device tree
- * @parent: device which childred will be removed
+ * @parent: device which children will be removed
  *
  * Complementary to of_platform_populate(), this function removes children
  * of the given device (and, recurrently, their children) that have been
@@ -554,14 +545,9 @@ static int of_platform_device_destroy(struct device *dev, void *data)
  * Returns 0 when all children devices have been removed or
  * -EBUSY when some children remained.
  */
-int of_platform_depopulate(struct device *parent)
+void of_platform_depopulate(struct device *parent)
 {
-	bool children_left = false;
-
-	device_for_each_child(parent, &children_left,
-			      of_platform_device_destroy);
-
-	return children_left ? -EBUSY : 0;
+	device_for_each_child(parent, NULL, of_platform_device_destroy);
 }
 EXPORT_SYMBOL_GPL(of_platform_depopulate);
 
diff --git a/include/linux/of.h b/include/linux/of.h
index 196b34c1ef4e..abf829a1f150 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -204,6 +204,7 @@ static inline unsigned long of_read_ulong(const __be32 *cell, int size)
 #define OF_DYNAMIC	1 /* node and properties were allocated via kmalloc */
 #define OF_DETACHED	2 /* node has been detached from the device tree */
 #define OF_POPULATED	3 /* device already created for the node */
+#define OF_POPULATED_BUS	4 /* of_platform_populate recursed to children of this node */
 
 #define OF_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags)
 #define OF_MARK_DYNAMIC(x) set_bit(OF_DYNAMIC, &x->_flags)
diff --git a/include/linux/of_platform.h b/include/linux/of_platform.h
index d96e1badbee0..c2b0627a2317 100644
--- a/include/linux/of_platform.h
+++ b/include/linux/of_platform.h
@@ -72,7 +72,7 @@ extern int of_platform_populate(struct device_node *root,
 				const struct of_device_id *matches,
 				const struct of_dev_auxdata *lookup,
 				struct device *parent);
-extern int of_platform_depopulate(struct device *parent);
+extern void of_platform_depopulate(struct device *parent);
 #else
 static inline int of_platform_populate(struct device_node *root,
 					const struct of_device_id *matches,
@@ -81,10 +81,7 @@ static inline int of_platform_populate(struct device_node *root,
 {
 	return -ENODEV;
 }
-static inline int of_platform_depopulate(struct device *parent)
-{
-	return -ENODEV;
-}
+static inline void of_platform_depopulate(struct device *parent) { }
 #endif
 
 #endif	/* _LINUX_OF_PLATFORM_H */
-- 
1.9.1

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

* Re: [PATCH 5/6] OF: Utility helper functions for dynamic nodes
  2014-06-24 14:49                   ` Rob Herring
@ 2014-06-24 15:43                     ` Alexander Sverdlin
  2014-06-24 15:59                       ` Pantelis Antoniou
  0 siblings, 1 reply; 63+ messages in thread
From: Alexander Sverdlin @ 2014-06-24 15:43 UTC (permalink / raw)
  To: ext Rob Herring
  Cc: Pantelis Antoniou, Guenter Roeck, Ioan Nicu, Grant Likely,
	Stephen Warren, Matt Porter, Koen Kooi, Greg Kroah-Hartman,
	Alison Chaiken, Dinh Nguyen, Jan Lubbe, Michael Stickel,
	Dirk Behme, Alan Tull, Sascha Hauer, Michael Bohan, Michal Simek,
	Matt Ranostay, Joel Becker, devicetree, Wolfram Sang, linux-i2c,
	Mark Brown, linux-spi, linux-kernel, Pete Popov, Dan Malek,
	Georgi Vlaev

Hi Rob,

On 24/06/14 16:49, ext Rob Herring wrote:
>>>>>> If that's the case, the code in irq.c is wrong.
>>>>>>
>>>>>> interrupt-controller is a bool property; the correct call to use is of_property_read_bool()
>>>>>> which returns true or false when the value is defined.
>>>>>>
>>>>>> The use of of_get_property is a bug here. It is perfectly valid for a property to have a
>>>>>> NULL value when length = 0.
>>>>>>
>>>>>
>>>>> That usage is spread throughout the code though. There are three or four similar checks
>>>>> for interrupt-controller in the code, and many others using of_get_property() to check
>>>>> for booleans.
>>>>>
>>>>> Some examples:
>>>>>       s5m8767,pmic-buck2-ramp-enable
>>>>>       s5m8767,pmic-buck3-ramp-enable
>>>>>       s5m8767,pmic-buck4-ramp-enable
>>>>>       d7s-flipped?
>>>>>       atmel,use-dma-rx
>>>>>       linux,rs485-enabled-at-boot-time
>>>>>       marvell,enable-port1 (and many others)
>>>>>       linux,bootx-noscreen
>>>>>       linux,opened
>>>>>
>>>>> and many many others.
>>>>>
>>>>> Maybe people meant to use of_find_property() ?
>>>>>
>>>>
>>>> I bet... I see a lot of users doing if (of_get_property()).
>>>>
>>>> Which is no good.
>>>
>>> I don't see what the issue is. The irq.c code is correct. The code is
>>> checking for existence of a property or not and of_get_property
>>> adequately does that. of_find_property is equivalent in this case. Now
>>
>> The code is correct and the functions are equal as long as we declare that
>> void property has value != NULL. Which must not be actually and the patch
>> from Pantelis actually creates this situation first time.
>>
>> So let's first agree, how should the empty property look like.
>> length should be 0, it's clear. But what about the value?
> 
> Actually, it is really only about what of_get_property's behavior is,
> and I'm saying it should remain as is. You could also make
> of_get_property return an empty string if prop->value is NULL. That
> could still possibly break some callers of of_find_property which

This will not brake anything and especially of_find_property() users,
but it's even worse hack, than to ensure value!=NULL :)

> would need fixing. But there's ~300 callers vs. ~1300 for
> of_get_property. In scanning thru of_find_property callers, it look
> like in general they are okay if prop->value changed to NULL.

Most of the 1300 uses of of_get_property() are valid, because they want the
value directly. Only some of them, who actually only checks for the existence of
the property are wrong and must use of_find_property(). 

> Unless there is some difficulty to support, the lower risk approach is
> just ensure prop->value is not NULL.

-- 
Best regards,
Alexander Sverdlin.

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

* Re: [PATCH 5/6] OF: Utility helper functions for dynamic nodes
  2014-06-24 15:43                     ` Alexander Sverdlin
@ 2014-06-24 15:59                       ` Pantelis Antoniou
  2014-06-24 18:23                         ` Ioan Nicu
  0 siblings, 1 reply; 63+ messages in thread
From: Pantelis Antoniou @ 2014-06-24 15:59 UTC (permalink / raw)
  To: Alexander Sverdlin
  Cc: ext Rob Herring, Guenter Roeck, Ioan Nicu, Grant Likely,
	Stephen Warren, Matt Porter, Koen Kooi, Greg Kroah-Hartman,
	Alison Chaiken, Dinh Nguyen, Jan Lubbe, Michael Stickel,
	Dirk Behme, Alan Tull, Sascha Hauer, Michael Bohan, Michal Simek,
	Matt Ranostay, Joel Becker, devicetree, Wolfram Sang, linux-i2c,
	Mark Brown, linux-spi, linux-kernel, Pete Popov, Dan Malek,
	Georgi Vlaev

Hi Alexander,

On Jun 24, 2014, at 6:43 PM, Alexander Sverdlin wrote:

> Hi Rob,
> 
> On 24/06/14 16:49, ext Rob Herring wrote:
>>>>>>> If that's the case, the code in irq.c is wrong.
>>>>>>> 
>>>>>>> interrupt-controller is a bool property; the correct call to use is of_property_read_bool()
>>>>>>> which returns true or false when the value is defined.
>>>>>>> 
>>>>>>> The use of of_get_property is a bug here. It is perfectly valid for a property to have a
>>>>>>> NULL value when length = 0.
>>>>>>> 
>>>>>> 
>>>>>> That usage is spread throughout the code though. There are three or four similar checks
>>>>>> for interrupt-controller in the code, and many others using of_get_property() to check
>>>>>> for booleans.
>>>>>> 
>>>>>> Some examples:
>>>>>>      s5m8767,pmic-buck2-ramp-enable
>>>>>>      s5m8767,pmic-buck3-ramp-enable
>>>>>>      s5m8767,pmic-buck4-ramp-enable
>>>>>>      d7s-flipped?
>>>>>>      atmel,use-dma-rx
>>>>>>      linux,rs485-enabled-at-boot-time
>>>>>>      marvell,enable-port1 (and many others)
>>>>>>      linux,bootx-noscreen
>>>>>>      linux,opened
>>>>>> 
>>>>>> and many many others.
>>>>>> 
>>>>>> Maybe people meant to use of_find_property() ?
>>>>>> 
>>>>> 
>>>>> I bet... I see a lot of users doing if (of_get_property()).
>>>>> 
>>>>> Which is no good.
>>>> 
>>>> I don't see what the issue is. The irq.c code is correct. The code is
>>>> checking for existence of a property or not and of_get_property
>>>> adequately does that. of_find_property is equivalent in this case. Now
>>> 
>>> The code is correct and the functions are equal as long as we declare that
>>> void property has value != NULL. Which must not be actually and the patch
>>> from Pantelis actually creates this situation first time.
>>> 
>>> So let's first agree, how should the empty property look like.
>>> length should be 0, it's clear. But what about the value?
>> 
>> Actually, it is really only about what of_get_property's behavior is,
>> and I'm saying it should remain as is. You could also make
>> of_get_property return an empty string if prop->value is NULL. That
>> could still possibly break some callers of of_find_property which
> 
> This will not brake anything and especially of_find_property() users,
> but it's even worse hack, than to ensure value!=NULL :)
> 

The only users that break are the ones following the pattern:

if (of_get_property(np, "foo", NULL)) { .. }

The pointer returned by of_get_property is completely unusable, since
it's pointing to god knows where.

>> would need fixing. But there's ~300 callers vs. ~1300 for
>> of_get_property. In scanning thru of_find_property callers, it look
>> like in general they are okay if prop->value changed to NULL.
> 
> Most of the 1300 uses of of_get_property() are valid, because they want the
> value directly. Only some of them, who actually only checks for the existence of
> the property are wrong and must use of_find_property(). 
> 

For what is worth:

> $ grep 'if (of_get_property(' drivers/ -r | wc -l 
> 162
> 

Not all of them are accessing booleans per se.
The patch I posted earlier addresses the problem, and also generates a warning
to help us fix the callers pretty easily.


>> Unless there is some difficulty to support, the lower risk approach is
>> just ensure prop->value is not NULL.
> 
> -- 
> Best regards,
> Alexander Sverdlin.

Regards

-- Pantelis

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

* Re: [PATCH 5/6] OF: Utility helper functions for dynamic nodes
  2014-06-24 15:59                       ` Pantelis Antoniou
@ 2014-06-24 18:23                         ` Ioan Nicu
  2014-06-24 18:31                           ` Ioan Nicu
  2014-06-24 18:43                           ` Pantelis Antoniou
  0 siblings, 2 replies; 63+ messages in thread
From: Ioan Nicu @ 2014-06-24 18:23 UTC (permalink / raw)
  To: ext Pantelis Antoniou
  Cc: Alexander Sverdlin, ext Rob Herring, Guenter Roeck, Grant Likely,
	Stephen Warren, Matt Porter, Koen Kooi, Greg Kroah-Hartman,
	Alison Chaiken, Dinh Nguyen, Jan Lubbe, Michael Stickel,
	Dirk Behme, Alan Tull, Sascha Hauer, Michael Bohan, Michal Simek,
	Matt Ranostay, Joel Becker, devicetree, Wolfram Sang, linux-i2c,
	Mark Brown, linux-spi, linux-kernel, Pete Popov, Dan Malek,
	Georgi Vlaev

Hi Pantelis,

On Tue, Jun 24, 2014 at 06:59:41PM +0300, ext Pantelis Antoniou wrote:
> Hi Alexander,
> 
> On Jun 24, 2014, at 6:43 PM, Alexander Sverdlin wrote:
> 
> > Hi Rob,
> > 
> > On 24/06/14 16:49, ext Rob Herring wrote:
> >>>>>>> If that's the case, the code in irq.c is wrong.
> >>>>>>> 
> >>>>>>> interrupt-controller is a bool property; the correct call to use is of_property_read_bool()
> >>>>>>> which returns true or false when the value is defined.
> >>>>>>> 
> >>>>>>> The use of of_get_property is a bug here. It is perfectly valid for a property to have a
> >>>>>>> NULL value when length = 0.
> >>>>>>> 
> >>>>>> 
> >>>>>> That usage is spread throughout the code though. There are three or four similar checks
> >>>>>> for interrupt-controller in the code, and many others using of_get_property() to check
> >>>>>> for booleans.
> >>>>>> 
> >>>>>> Some examples:
> >>>>>>      s5m8767,pmic-buck2-ramp-enable
> >>>>>>      s5m8767,pmic-buck3-ramp-enable
> >>>>>>      s5m8767,pmic-buck4-ramp-enable
> >>>>>>      d7s-flipped?
> >>>>>>      atmel,use-dma-rx
> >>>>>>      linux,rs485-enabled-at-boot-time
> >>>>>>      marvell,enable-port1 (and many others)
> >>>>>>      linux,bootx-noscreen
> >>>>>>      linux,opened
> >>>>>> 
> >>>>>> and many many others.
> >>>>>> 
> >>>>>> Maybe people meant to use of_find_property() ?
> >>>>>> 
> >>>>> 
> >>>>> I bet... I see a lot of users doing if (of_get_property()).
> >>>>> 
> >>>>> Which is no good.
> >>>> 
> >>>> I don't see what the issue is. The irq.c code is correct. The code is
> >>>> checking for existence of a property or not and of_get_property
> >>>> adequately does that. of_find_property is equivalent in this case. Now
> >>> 
> >>> The code is correct and the functions are equal as long as we declare that
> >>> void property has value != NULL. Which must not be actually and the patch
> >>> from Pantelis actually creates this situation first time.
> >>> 
> >>> So let's first agree, how should the empty property look like.
> >>> length should be 0, it's clear. But what about the value?
> >> 
> >> Actually, it is really only about what of_get_property's behavior is,
> >> and I'm saying it should remain as is. You could also make
> >> of_get_property return an empty string if prop->value is NULL. That
> >> could still possibly break some callers of of_find_property which
> > 
> > This will not brake anything and especially of_find_property() users,
> > but it's even worse hack, than to ensure value!=NULL :)
> > 
> 
> The only users that break are the ones following the pattern:
> 
> if (of_get_property(np, "foo", NULL)) { .. }
> 
> The pointer returned by of_get_property is completely unusable, since
> it's pointing to god knows where.
> 

Those are not the only users, and drivers/ is not the only place to look
for them. For example in sound/ppc/tumbler.c:

[...]
        paddr = of_get_property(tas_node, "i2c-address", NULL);
        if (paddr == NULL)
                paddr = of_get_property(tas_node, "reg", NULL);
[...]

This code should also use of_find_property() IMHO.

So we may need more ellaborate grep patterns to identify them all.

> >> would need fixing. But there's ~300 callers vs. ~1300 for
> >> of_get_property. In scanning thru of_find_property callers, it look
> >> like in general they are okay if prop->value changed to NULL.
> > 
> > Most of the 1300 uses of of_get_property() are valid, because they want the
> > value directly. Only some of them, who actually only checks for the existence of
> > the property are wrong and must use of_find_property(). 
> > 
> 
> For what is worth:
> 
> > $ grep 'if (of_get_property(' drivers/ -r | wc -l 
> > 162
> > 
> 
> Not all of them are accessing booleans per se.
> The patch I posted earlier addresses the problem, and also generates a warning
> to help us fix the callers pretty easily.
> 

I actually like your patch. It provides backward compatibility for all these wrong uses
for of_get_property() on "boolean" properties and helps identifying them in the same time.

I'm not really convinced that they should be named boolean. See the code above which in
in principle should read as "if there's no i2c-address property then let's use the reg property".

Neither i2c-address, nor reg are boolean. This code checks if the property exists and it should
use of_find_property().

Regards,
Ionut

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

* Re: [PATCH 5/6] OF: Utility helper functions for dynamic nodes
  2014-06-24 18:23                         ` Ioan Nicu
@ 2014-06-24 18:31                           ` Ioan Nicu
  2014-06-24 18:43                           ` Pantelis Antoniou
  1 sibling, 0 replies; 63+ messages in thread
From: Ioan Nicu @ 2014-06-24 18:31 UTC (permalink / raw)
  To: ext Pantelis Antoniou
  Cc: Alexander Sverdlin, ext Rob Herring, Guenter Roeck, Grant Likely,
	Stephen Warren, Matt Porter, Koen Kooi, Greg Kroah-Hartman,
	Alison Chaiken, Dinh Nguyen, Jan Lubbe, Michael Stickel,
	Dirk Behme, Alan Tull, Sascha Hauer, Michael Bohan, Michal Simek,
	Matt Ranostay, Joel Becker, devicetree, Wolfram Sang, linux-i2c,
	Mark Brown, linux-spi, linux-kernel, Pete Popov, Dan Malek,
	Georgi Vlaev

Hi,

On Tue, Jun 24, 2014 at 08:23:08PM +0200, Ioan Nicu wrote:
> Hi Pantelis,
> 
> 
> Those are not the only users, and drivers/ is not the only place to look
> for them. For example in sound/ppc/tumbler.c:
> 
> [...]
>         paddr = of_get_property(tas_node, "i2c-address", NULL);
>         if (paddr == NULL)
>                 paddr = of_get_property(tas_node, "reg", NULL);
> [...]
> 
> This code should also use of_find_property() IMHO.
> 

One correction. This example is wrong for our discussion, so ignore it.
But I was showing it just to highlight that there may be other wrong uses
which don't fit the pattern you specified.

I guess that the only way to catch them all is using your patch which issues
a warning.

Regards,
Ioan.

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

* Re: [PATCH 5/6] OF: Utility helper functions for dynamic nodes
  2014-06-24 18:23                         ` Ioan Nicu
  2014-06-24 18:31                           ` Ioan Nicu
@ 2014-06-24 18:43                           ` Pantelis Antoniou
  1 sibling, 0 replies; 63+ messages in thread
From: Pantelis Antoniou @ 2014-06-24 18:43 UTC (permalink / raw)
  To: Ioan Nicu
  Cc: Alexander Sverdlin, ext Rob Herring, Guenter Roeck, Grant Likely,
	Stephen Warren, Matt Porter, Koen Kooi, Greg Kroah-Hartman,
	Alison Chaiken, Dinh Nguyen, Jan Lubbe, Michael Stickel,
	Dirk Behme, Alan Tull, Sascha Hauer, Michael Bohan, Michal Simek,
	Matt Ranostay, Joel Becker, devicetree, Wolfram Sang, linux-i2c,
	Mark Brown, linux-spi, linux-kernel, Pete Popov, Dan Malek,
	Georgi Vlaev

Hi Ioan,

On Jun 24, 2014, at 9:23 PM, Ioan Nicu wrote:

> Hi Pantelis,
> 
> On Tue, Jun 24, 2014 at 06:59:41PM +0300, ext Pantelis Antoniou wrote:
>> Hi Alexander,
>> 
>> On Jun 24, 2014, at 6:43 PM, Alexander Sverdlin wrote:
>> 
>>> Hi Rob,
>>> 
>>> On 24/06/14 16:49, ext Rob Herring wrote:
>>>>>>>>> If that's the case, the code in irq.c is wrong.
>>>>>>>>> 
>>>>>>>>> interrupt-controller is a bool property; the correct call to use is of_property_read_bool()
>>>>>>>>> which returns true or false when the value is defined.
>>>>>>>>> 
>>>>>>>>> The use of of_get_property is a bug here. It is perfectly valid for a property to have a
>>>>>>>>> NULL value when length = 0.
>>>>>>>>> 
>>>>>>>> 
>>>>>>>> That usage is spread throughout the code though. There are three or four similar checks
>>>>>>>> for interrupt-controller in the code, and many others using of_get_property() to check
>>>>>>>> for booleans.
>>>>>>>> 
>>>>>>>> Some examples:
>>>>>>>>     s5m8767,pmic-buck2-ramp-enable
>>>>>>>>     s5m8767,pmic-buck3-ramp-enable
>>>>>>>>     s5m8767,pmic-buck4-ramp-enable
>>>>>>>>     d7s-flipped?
>>>>>>>>     atmel,use-dma-rx
>>>>>>>>     linux,rs485-enabled-at-boot-time
>>>>>>>>     marvell,enable-port1 (and many others)
>>>>>>>>     linux,bootx-noscreen
>>>>>>>>     linux,opened
>>>>>>>> 
>>>>>>>> and many many others.
>>>>>>>> 
>>>>>>>> Maybe people meant to use of_find_property() ?
>>>>>>>> 
>>>>>>> 
>>>>>>> I bet... I see a lot of users doing if (of_get_property()).
>>>>>>> 
>>>>>>> Which is no good.
>>>>>> 
>>>>>> I don't see what the issue is. The irq.c code is correct. The code is
>>>>>> checking for existence of a property or not and of_get_property
>>>>>> adequately does that. of_find_property is equivalent in this case. Now
>>>>> 
>>>>> The code is correct and the functions are equal as long as we declare that
>>>>> void property has value != NULL. Which must not be actually and the patch
>>>>> from Pantelis actually creates this situation first time.
>>>>> 
>>>>> So let's first agree, how should the empty property look like.
>>>>> length should be 0, it's clear. But what about the value?
>>>> 
>>>> Actually, it is really only about what of_get_property's behavior is,
>>>> and I'm saying it should remain as is. You could also make
>>>> of_get_property return an empty string if prop->value is NULL. That
>>>> could still possibly break some callers of of_find_property which
>>> 
>>> This will not brake anything and especially of_find_property() users,
>>> but it's even worse hack, than to ensure value!=NULL :)
>>> 
>> 
>> The only users that break are the ones following the pattern:
>> 
>> if (of_get_property(np, "foo", NULL)) { .. }
>> 
>> The pointer returned by of_get_property is completely unusable, since
>> it's pointing to god knows where.
>> 
> 
> Those are not the only users, and drivers/ is not the only place to look
> for them. For example in sound/ppc/tumbler.c:
> 
> [...]
>        paddr = of_get_property(tas_node, "i2c-address", NULL);
>        if (paddr == NULL)
>                paddr = of_get_property(tas_node, "reg", NULL);
> [...]
> 

This is safe; the reg property is not a boolean so the pointer returned is valid.

> This code should also use of_find_property() IMHO.
> 
> So we may need more ellaborate grep patterns to identify them all.
> 
>>>> would need fixing. But there's ~300 callers vs. ~1300 for
>>>> of_get_property. In scanning thru of_find_property callers, it look
>>>> like in general they are okay if prop->value changed to NULL.
>>> 
>>> Most of the 1300 uses of of_get_property() are valid, because they want the
>>> value directly. Only some of them, who actually only checks for the existence of
>>> the property are wrong and must use of_find_property(). 
>>> 
>> 
>> For what is worth:
>> 
>>> $ grep 'if (of_get_property(' drivers/ -r | wc -l 
>>> 162
>>> 
>> 
>> Not all of them are accessing booleans per se.
>> The patch I posted earlier addresses the problem, and also generates a warning
>> to help us fix the callers pretty easily.
>> 
> 
> I actually like your patch. It provides backward compatibility for all these wrong uses
> for of_get_property() on "boolean" properties and helps identifying them in the same time.
> 
> I'm not really convinced that they should be named boolean. See the code above which in
> in principle should read as "if there's no i2c-address property then let's use the reg property".
> 
> Neither i2c-address, nor reg are boolean. This code checks if the property exists and it should
> use of_find_property().
> 

Those are not a problem :) The return of of_get_property is returning a 0-length pointer only
on bool properties, aka, with no property value.

> Regards,
> Ionut

Regards

-- Pantelis

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

* Re: [PATCH 4/6] OF: Export a number of __of_* methods
  2014-06-22  9:40 ` [PATCH 4/6] OF: Export a number of __of_* methods Pantelis Antoniou
@ 2014-06-24 19:27   ` Grant Likely
  2014-06-24 19:38     ` Pantelis Antoniou
  0 siblings, 1 reply; 63+ messages in thread
From: Grant Likely @ 2014-06-24 19:27 UTC (permalink / raw)
  To: Pantelis Antoniou
  Cc: Rob Herring, Stephen Warren, Matt Porter, Koen Kooi,
	Greg Kroah-Hartman, Alison Chaiken, Dinh Nguyen, Jan Lubbe,
	Alexander Sverdlin, Michael Stickel, Guenter Roeck, Dirk Behme,
	Alan Tull, Sascha Hauer, Michael Bohan, Ionut Nicu, Michal Simek,
	Matt Ranostay, Joel Becker, devicetree, Wolfram Sang, linux-i2c,
	Mark Brown, linux-spi, linux-kernel, Pete Popov, Dan Malek,
	Georgi Vlaev, Pantelis Antoniou

On Sun, 22 Jun 2014 12:40:37 +0300, Pantelis Antoniou <pantelis.antoniou@konsulko.com> wrote:
> As part of moving to transactional DT, a number of methods are
> reworked and exported.
> 
> The methods exported are:

The above is misleasing. The functions aren't exported, but the
prototypes are put into a header file.

> __of_get_next_child, __for_each_child_of_node, __of_add_property,
> __of_remove_property, __of_update_property, __of_attach_node,
> __of_detach_node, __of_device_is_compatible, __of_device_is_available,
> __of_get_property.
> 
> __of_update_property has been reworked to be more efficient
> (double walk of the property list eliminated)
> of_get_property was reworked to use __of_get_property internally.
> 
> Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>

For the next posting, please include this patch in the same series as
the patch that uses it. It isn't a bug fix, but rather a reorg required
by the transational patch.

> ---
>  drivers/of/base.c  | 192 +++++++++++++++++++++++++++++------------------------
>  include/linux/of.h |  34 ++++++++++

Please put the prototypes in drivers/of/of_private.h. I don't want any
code outside drivers/of using these functions.

>  2 files changed, 139 insertions(+), 87 deletions(-)
> 
> diff --git a/drivers/of/base.c b/drivers/of/base.c
> index 80fef33..42c735d 100644
> --- a/drivers/of/base.c
> +++ b/drivers/of/base.c
> @@ -382,7 +382,7 @@ EXPORT_SYMBOL(of_find_all_nodes);
>   * Find a property with a given name for a given node
>   * and return the value.
>   */
> -static const void *__of_get_property(const struct device_node *np,
> +const void *__of_get_property(const struct device_node *np,
>  				     const char *name, int *lenp)
>  {
>  	struct property *pp = __of_find_property(np, name, lenp);
> @@ -397,9 +397,13 @@ static const void *__of_get_property(const struct device_node *np,
>  const void *of_get_property(const struct device_node *np, const char *name,
>  			    int *lenp)
>  {
> -	struct property *pp = of_find_property(np, name, lenp);
> +	unsigned long flags;
> +	const void *value;
>  
> -	return pp ? pp->value : NULL;
> +	raw_spin_lock_irqsave(&devtree_lock, flags);
> +	value = __of_get_property(np, name, lenp);
> +	raw_spin_unlock_irqrestore(&devtree_lock, flags);
> +	return value;

Why is this changed?

>  }
>  EXPORT_SYMBOL(of_get_property);
>  
> @@ -536,7 +540,7 @@ EXPORT_SYMBOL(of_get_cpu_node);
>   * 10. type
>   * 11. name
>   */
> -static int __of_device_is_compatible(const struct device_node *device,
> +int __of_device_is_compatible(const struct device_node *device,
>  				     const char *compat, const char *type, const char *name)

I can't find the user for this one.

>  {
>  	struct property *prop;
> @@ -619,7 +623,7 @@ EXPORT_SYMBOL(of_machine_is_compatible);
>   *  Returns 1 if the status property is absent or set to "okay" or "ok",
>   *  0 otherwise
>   */
> -static int __of_device_is_available(const struct device_node *device)
> +int __of_device_is_available(const struct device_node *device)

I can't find the user for this one.

>  {
>  	const char *status;
>  	int statlen;
> @@ -709,7 +713,7 @@ struct device_node *of_get_next_parent(struct device_node *node)
>  }
>  EXPORT_SYMBOL(of_get_next_parent);
>  
> -static struct device_node *__of_get_next_child(const struct device_node *node,
> +struct device_node *__of_get_next_child(const struct device_node *node,
>  						struct device_node *prev)

Same here.

>  {
>  	struct device_node *next;
> @@ -724,9 +728,7 @@ static struct device_node *__of_get_next_child(const struct device_node *node,
>  	of_node_put(prev);
>  	return next;
>  }
> -#define __for_each_child_of_node(parent, child) \
> -	for (child = __of_get_next_child(parent, NULL); child != NULL; \
> -	     child = __of_get_next_child(parent, child))
> +EXPORT_SYMBOL(__of_get_next_child);

Again.

>  
>  /**
>   *	of_get_next_child - Iterate a node childs
> @@ -1820,7 +1822,7 @@ int of_count_phandle_with_args(const struct device_node *np, const char *list_na
>  EXPORT_SYMBOL(of_count_phandle_with_args);
>  
>  #if defined(CONFIG_OF_DYNAMIC)
> -static int of_property_notify(int action, struct device_node *np,
> +int of_property_notify(int action, struct device_node *np,
>  			      struct property *prop)
>  {
>  	struct of_prop_reconfig pr;
> @@ -1833,18 +1835,12 @@ static int of_property_notify(int action, struct device_node *np,
>  	pr.prop = prop;
>  	return of_reconfig_notify(action, &pr);
>  }
> -#else
> -static int of_property_notify(int action, struct device_node *np,
> -			      struct property *prop)
> -{
> -	return 0;
> -}
>  #endif
>  
>  /**
>   * __of_add_property - Add a property to a node without lock operations
>   */
> -static int __of_add_property(struct device_node *np, struct property *prop)
> +int __of_add_property(struct device_node *np, struct property *prop)
>  {
>  	struct property **next;
>  
> @@ -1886,6 +1882,25 @@ int of_add_property(struct device_node *np, struct property *prop)
>  	return rc;
>  }
>  
> +int __of_remove_property(struct device_node *np, struct property *prop)
> +{
> +	struct property **next;
> +
> +	for (next = &np->properties; *next; next = &(*next)->next) {
> +		if (*next == prop)
> +			break;
> +	}
> +	if (*next == NULL)
> +		return -ENODEV;
> +
> +	/* found the node */
> +	*next = prop->next;
> +	prop->next = np->deadprops;
> +	np->deadprops = prop;
> +
> +	return 0;
> +}
> +
>  /**
>   * of_remove_property - Remove a property from a node.
>   *
> @@ -1896,9 +1911,7 @@ int of_add_property(struct device_node *np, struct property *prop)
>   */
>  int of_remove_property(struct device_node *np, struct property *prop)
>  {
> -	struct property **next;
>  	unsigned long flags;
> -	int found = 0;
>  	int rc;
>  
>  	rc = of_property_notify(OF_RECONFIG_REMOVE_PROPERTY, np, prop);
> @@ -1906,22 +1919,11 @@ int of_remove_property(struct device_node *np, struct property *prop)
>  		return rc;
>  
>  	raw_spin_lock_irqsave(&devtree_lock, flags);
> -	next = &np->properties;
> -	while (*next) {
> -		if (*next == prop) {
> -			/* found the node */
> -			*next = prop->next;
> -			prop->next = np->deadprops;
> -			np->deadprops = prop;
> -			found = 1;
> -			break;
> -		}
> -		next = &(*next)->next;
> -	}
> +	rc = __of_remove_property(np, prop);
>  	raw_spin_unlock_irqrestore(&devtree_lock, flags);
>  
> -	if (!found)
> -		return -ENODEV;
> +	if (rc)
> +		return rc;
>  
>  	/* at early boot, bail hear and defer setup to of_init() */
>  	if (!of_kset)
> @@ -1932,6 +1934,32 @@ int of_remove_property(struct device_node *np, struct property *prop)
>  	return 0;
>  }
>  
> +int __of_update_property(struct device_node *np, struct property *newprop,
> +		struct property **oldpropp)
> +{
> +	struct property **next, *oldprop;
> +
> +	for (next = &np->properties; *next; next = &(*next)->next) {
> +		if (of_prop_cmp((*next)->name, newprop->name) == 0)
> +			break;
> +	}
> +	*oldpropp = oldprop = *next;
> +
> +	if (oldprop) {
> +		/* replace the node */
> +		newprop->next = oldprop->next;
> +		*next = newprop;
> +		oldprop->next = np->deadprops;
> +		np->deadprops = oldprop;
> +	} else {
> +		/* new node */
> +		newprop->next = NULL;
> +		*next = newprop;
> +	}
> +
> +	return 0;
> +}
> +
>  /*
>   * of_update_property - Update a property in a node, if the property does
>   * not exist, add it.
> @@ -1941,36 +1969,21 @@ int of_remove_property(struct device_node *np, struct property *prop)
>   * Instead we just move the property to the "dead properties" list,
>   * and add the new property to the property list
>   */
> -int of_update_property(struct device_node *np, struct property *newprop)
> +int of_update_property(struct device_node *np, struct property *prop)
>  {
> -	struct property **next, *oldprop;
> +	struct property *oldprop;
>  	unsigned long flags;
>  	int rc;
>  
> -	rc = of_property_notify(OF_RECONFIG_UPDATE_PROPERTY, np, newprop);
> +	if (!prop->name)
> +		return -EINVAL;
> +
> +	rc = of_property_notify(OF_RECONFIG_UPDATE_PROPERTY, np, prop);
>  	if (rc)
>  		return rc;
>  
> -	if (!newprop->name)
> -		return -EINVAL;
> -
>  	raw_spin_lock_irqsave(&devtree_lock, flags);
> -	next = &np->properties;
> -	oldprop = __of_find_property(np, newprop->name, NULL);
> -	if (!oldprop) {
> -		/* add the new node */
> -		rc = __of_add_property(np, newprop);
> -	} else while (*next) {
> -		/* replace the node */
> -		if (*next == oldprop) {
> -			newprop->next = oldprop->next;
> -			*next = newprop;
> -			oldprop->next = np->deadprops;
> -			np->deadprops = oldprop;
> -			break;
> -		}
> -		next = &(*next)->next;
> -	}
> +	rc = __of_update_property(np, prop, &oldprop);
>  	raw_spin_unlock_irqrestore(&devtree_lock, flags);
>  	if (rc)
>  		return rc;
> @@ -1982,7 +1995,7 @@ int of_update_property(struct device_node *np, struct property *newprop)
>  	/* Update the sysfs attribute */
>  	if (oldprop)
>  		sysfs_remove_bin_file(&np->kobj, &oldprop->attr);
> -	__of_add_property_sysfs(np, newprop);
> +	__of_add_property_sysfs(np, prop);
>  
>  	return 0;
>  }
> @@ -2018,6 +2031,15 @@ int of_reconfig_notify(unsigned long action, void *p)
>  	return notifier_to_errno(rc);
>  }
>  
> +void __of_attach_node(struct device_node *np)
> +{
> +	np->sibling = np->parent->child;
> +	np->allnext = np->parent->allnext;
> +	np->parent->allnext = np;
> +	np->parent->child = np;
> +	of_node_clear_flag(np, OF_DETACHED);
> +}
> +
>  /**
>   * of_attach_node - Plug a device node into the tree and global list.
>   */
> @@ -2031,51 +2053,29 @@ int of_attach_node(struct device_node *np)
>  		return rc;
>  
>  	raw_spin_lock_irqsave(&devtree_lock, flags);
> -	np->sibling = np->parent->child;
> -	np->allnext = np->parent->allnext;
> -	np->parent->allnext = np;
> -	np->parent->child = np;
> -	of_node_clear_flag(np, OF_DETACHED);
> +	__of_attach_node(np);
>  	raw_spin_unlock_irqrestore(&devtree_lock, flags);
>  
>  	of_node_add(np);
>  	return 0;
>  }
>  
> -/**
> - * of_detach_node - "Unplug" a node from the device tree.
> - *
> - * The caller must hold a reference to the node.  The memory associated with
> - * the node is not freed until its refcount goes to zero.
> - */
> -int of_detach_node(struct device_node *np)
> +void __of_detach_node(struct device_node *np)
>  {
>  	struct device_node *parent;
> -	unsigned long flags;
> -	int rc = 0;
> -
> -	rc = of_reconfig_notify(OF_RECONFIG_DETACH_NODE, np);
> -	if (rc)
> -		return rc;
> +	struct device_node *prev;
> +	struct device_node *prevsib;
>  
> -	raw_spin_lock_irqsave(&devtree_lock, flags);
> -
> -	if (of_node_check_flag(np, OF_DETACHED)) {
> -		/* someone already detached it */
> -		raw_spin_unlock_irqrestore(&devtree_lock, flags);
> -		return rc;
> -	}
> +	if (WARN_ON(of_node_check_flag(np, OF_DETACHED)))
> +		return;
>  
>  	parent = np->parent;
> -	if (!parent) {
> -		raw_spin_unlock_irqrestore(&devtree_lock, flags);
> -		return rc;
> -	}
> +	if (WARN_ON(!parent))
> +		return;
>  
>  	if (of_allnodes == np)
>  		of_allnodes = np->allnext;
>  	else {
> -		struct device_node *prev;
>  		for (prev = of_allnodes;
>  		     prev->allnext != np;
>  		     prev = prev->allnext)
> @@ -2086,7 +2086,6 @@ int of_detach_node(struct device_node *np)
>  	if (parent->child == np)
>  		parent->child = np->sibling;
>  	else {
> -		struct device_node *prevsib;
>  		for (prevsib = np->parent->child;
>  		     prevsib->sibling != np;
>  		     prevsib = prevsib->sibling)
> @@ -2095,6 +2094,25 @@ int of_detach_node(struct device_node *np)
>  	}
>  
>  	of_node_set_flag(np, OF_DETACHED);
> +}
> +
> +/**
> + * of_detach_node - "Unplug" a node from the device tree.
> + *
> + * The caller must hold a reference to the node.  The memory associated with
> + * the node is not freed until its refcount goes to zero.
> + */
> +int of_detach_node(struct device_node *np)
> +{
> +	unsigned long flags;
> +	int rc = 0;
> +
> +	rc = of_reconfig_notify(OF_RECONFIG_DETACH_NODE, np);
> +	if (rc)
> +		return rc;
> +
> +	raw_spin_lock_irqsave(&devtree_lock, flags);
> +	__of_detach_node(np);
>  	raw_spin_unlock_irqrestore(&devtree_lock, flags);
>  
>  	of_node_remove(np);
> diff --git a/include/linux/of.h b/include/linux/of.h
> index f7392c0..5e4e1b3 100644
> --- a/include/linux/of.h
> +++ b/include/linux/of.h
> @@ -98,6 +98,8 @@ static inline int of_node_is_attached(struct device_node *node)
>  #ifdef CONFIG_OF_DYNAMIC
>  extern struct device_node *of_node_get(struct device_node *node);
>  extern void of_node_put(struct device_node *node);
> +extern int of_property_notify(int action, struct device_node *np,
> +			      struct property *prop);
>  #else /* CONFIG_OF_DYNAMIC */
>  /* Dummy ref counting routines - to be implemented later */
>  static inline struct device_node *of_node_get(struct device_node *node)
> @@ -105,6 +107,11 @@ static inline struct device_node *of_node_get(struct device_node *node)
>  	return node;
>  }
>  static inline void of_node_put(struct device_node *node) { }
> +static inline int of_property_notify(int action, struct device_node *np,
> +			      struct property *prop)
> +{
> +	return 0;
> +}
>  #endif /* !CONFIG_OF_DYNAMIC */
>  
>  #ifdef CONFIG_OF
> @@ -238,6 +245,8 @@ extern struct device_node *of_get_parent(const struct device_node *node);
>  extern struct device_node *of_get_next_parent(struct device_node *node);
>  extern struct device_node *of_get_next_child(const struct device_node *node,
>  					     struct device_node *prev);
> +struct device_node *__of_get_next_child(const struct device_node *node,
> +						struct device_node *prev);
>  extern struct device_node *of_get_next_available_child(
>  	const struct device_node *node, struct device_node *prev);
>  
> @@ -279,9 +288,17 @@ extern int of_property_match_string(struct device_node *np,
>  				    const char *string);
>  extern int of_property_count_strings(struct device_node *np,
>  				     const char *propname);
> +int __of_device_is_compatible(const struct device_node *device,
> +				     const char *compat, const char *type,
> +				     const char *name);
>  extern int of_device_is_compatible(const struct device_node *device,
>  				   const char *);
> +extern int __of_device_is_available(const struct device_node *device);
>  extern int of_device_is_available(const struct device_node *device);
> +
> +extern const void *__of_get_property(const struct device_node *node,
> +				const char *name,
> +				int *lenp);
>  extern const void *of_get_property(const struct device_node *node,
>  				const char *name,
>  				int *lenp);
> @@ -312,6 +329,11 @@ extern int of_alias_get_id(struct device_node *np, const char *stem);
>  
>  extern int of_machine_is_compatible(const char *compat);
>  
> +int __of_add_property(struct device_node *np, struct property *prop);
> +int __of_remove_property(struct device_node *np, struct property *prop);
> +int __of_update_property(struct device_node *np, struct property *newprop,
> +		struct property **oldprop);
> +
>  extern int of_add_property(struct device_node *np, struct property *prop);
>  extern int of_remove_property(struct device_node *np, struct property *prop);
>  extern int of_update_property(struct device_node *np, struct property *newprop);
> @@ -332,6 +354,9 @@ extern int of_reconfig_notifier_register(struct notifier_block *);
>  extern int of_reconfig_notifier_unregister(struct notifier_block *);
>  extern int of_reconfig_notify(unsigned long, void *);
>  
> +void __of_attach_node(struct device_node *np);
> +void __of_detach_node(struct device_node *np);
> +
>  extern int of_attach_node(struct device_node *);
>  extern int of_detach_node(struct device_node *);
>  
> @@ -401,6 +426,12 @@ static inline struct device_node *of_get_next_child(
>  	return NULL;
>  }
>  
> +static inline struct device_node *__of_get_next_child(
> +	const struct device_node *node, struct device_node *prev)
> +{
> +	return NULL;
> +}
> +
>  static inline struct device_node *of_get_next_available_child(
>  	const struct device_node *node, struct device_node *prev)
>  {
> @@ -738,6 +769,9 @@ static inline int of_property_read_u32(const struct device_node *np,
>  #define for_each_child_of_node(parent, child) \
>  	for (child = of_get_next_child(parent, NULL); child != NULL; \
>  	     child = of_get_next_child(parent, child))
> +#define __for_each_child_of_node(parent, child) \
> +	for (child = __of_get_next_child(parent, NULL); child != NULL; \
> +	     child = __of_get_next_child(parent, child))
>  #define for_each_available_child_of_node(parent, child) \
>  	for (child = of_get_next_available_child(parent, NULL); child != NULL; \
>  	     child = of_get_next_available_child(parent, child))
> -- 
> 1.7.12
> 

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

* Re: [PATCH 4/6] OF: Export a number of __of_* methods
  2014-06-24 19:27   ` Grant Likely
@ 2014-06-24 19:38     ` Pantelis Antoniou
  2014-06-24 20:19       ` Grant Likely
  0 siblings, 1 reply; 63+ messages in thread
From: Pantelis Antoniou @ 2014-06-24 19:38 UTC (permalink / raw)
  To: Grant Likely
  Cc: Rob Herring, Stephen Warren, Matt Porter, Koen Kooi,
	Greg Kroah-Hartman, Alison Chaiken, Dinh Nguyen, Jan Lubbe,
	Alexander Sverdlin, Michael Stickel, Guenter Roeck, Dirk Behme,
	Alan Tull, Sascha Hauer, Michael Bohan, Ionut Nicu, Michal Simek,
	Matt Ranostay, Joel Becker, devicetree, Wolfram Sang, linux-i2c,
	Mark Brown, linux-spi, linux-kernel, Pete Popov, Dan Malek,
	Georgi Vlaev

Hi Grant,

On Jun 24, 2014, at 10:27 PM, Grant Likely wrote:

> On Sun, 22 Jun 2014 12:40:37 +0300, Pantelis Antoniou <pantelis.antoniou@konsulko.com> wrote:
>> As part of moving to transactional DT, a number of methods are
>> reworked and exported.
>> 
>> The methods exported are:
> 
> The above is misleasing. The functions aren't exported, but the
> prototypes are put into a header file.
> 
>> __of_get_next_child, __for_each_child_of_node, __of_add_property,
>> __of_remove_property, __of_update_property, __of_attach_node,
>> __of_detach_node, __of_device_is_compatible, __of_device_is_available,
>> __of_get_property.
>> 
>> __of_update_property has been reworked to be more efficient
>> (double walk of the property list eliminated)
>> of_get_property was reworked to use __of_get_property internally.
>> 
>> Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
> 
> For the next posting, please include this patch in the same series as
> the patch that uses it. It isn't a bug fix, but rather a reorg required
> by the transational patch.
> 

OK

>> ---
>> drivers/of/base.c  | 192 +++++++++++++++++++++++++++++------------------------
>> include/linux/of.h |  34 ++++++++++
> 
> Please put the prototypes in drivers/of/of_private.h. I don't want any
> code outside drivers/of using these functions.
> 

OK

>> 2 files changed, 139 insertions(+), 87 deletions(-)
>> 
>> diff --git a/drivers/of/base.c b/drivers/of/base.c
>> index 80fef33..42c735d 100644
>> --- a/drivers/of/base.c
>> +++ b/drivers/of/base.c
>> @@ -382,7 +382,7 @@ EXPORT_SYMBOL(of_find_all_nodes);
>>  * Find a property with a given name for a given node
>>  * and return the value.
>>  */
>> -static const void *__of_get_property(const struct device_node *np,
>> +const void *__of_get_property(const struct device_node *np,
>> 				     const char *name, int *lenp)
>> {
>> 	struct property *pp = __of_find_property(np, name, lenp);
>> @@ -397,9 +397,13 @@ static const void *__of_get_property(const struct device_node *np,
>> const void *of_get_property(const struct device_node *np, const char *name,
>> 			    int *lenp)
>> {
>> -	struct property *pp = of_find_property(np, name, lenp);
>> +	unsigned long flags;
>> +	const void *value;
>> 
>> -	return pp ? pp->value : NULL;
>> +	raw_spin_lock_irqsave(&devtree_lock, flags);
>> +	value = __of_get_property(np, name, lenp);
>> +	raw_spin_unlock_irqrestore(&devtree_lock, flags);
>> +	return value;
> 
> Why is this changed?
> 

Symmetry. All the others follow the same pattern.
 

>> }
>> EXPORT_SYMBOL(of_get_property);
>> 
>> @@ -536,7 +540,7 @@ EXPORT_SYMBOL(of_get_cpu_node);
>>  * 10. type
>>  * 11. name
>>  */
>> -static int __of_device_is_compatible(const struct device_node *device,
>> +int __of_device_is_compatible(const struct device_node *device,
>> 				     const char *compat, const char *type, const char *name)
> 
> I can't find the user for this one.
> 

Right. Internal tree uses it. I will remove.

>> {
>> 	struct property *prop;
>> @@ -619,7 +623,7 @@ EXPORT_SYMBOL(of_machine_is_compatible);
>>  *  Returns 1 if the status property is absent or set to "okay" or "ok",
>>  *  0 otherwise
>>  */
>> -static int __of_device_is_available(const struct device_node *device)
>> +int __of_device_is_available(const struct device_node *device)
> 
> I can't find the user for this one.
> 
Yep.


>> {
>> 	const char *status;
>> 	int statlen;
>> @@ -709,7 +713,7 @@ struct device_node *of_get_next_parent(struct device_node *node)
>> }
>> EXPORT_SYMBOL(of_get_next_parent);
>> 
>> -static struct device_node *__of_get_next_child(const struct device_node *node,
>> +struct device_node *__of_get_next_child(const struct device_node *node,
>> 						struct device_node *prev)
> 
> Same here.
> 

>> {
>> 	struct device_node *next;
>> @@ -724,9 +728,7 @@ static struct device_node *__of_get_next_child(const struct device_node *node,
>> 	of_node_put(prev);
>> 	return next;
>> }
>> -#define __for_each_child_of_node(parent, child) \
>> -	for (child = __of_get_next_child(parent, NULL); child != NULL; \
>> -	     child = __of_get_next_child(parent, child))
>> +EXPORT_SYMBOL(__of_get_next_child);
> 
> Again.
> 

All these are for use by subsequent patches. I will remove.

>> 
>> /**
>>  *	of_get_next_child - Iterate a node childs
>> @@ -1820,7 +1822,7 @@ int of_count_phandle_with_args(const struct device_node *np, const char *list_na
>> EXPORT_SYMBOL(of_count_phandle_with_args);
>> 
>> #if defined(CONFIG_OF_DYNAMIC)
>> -static int of_property_notify(int action, struct device_node *np,
>> +int of_property_notify(int action, struct device_node *np,
>> 			      struct property *prop)
>> {
>> 	struct of_prop_reconfig pr;
>> @@ -1833,18 +1835,12 @@ static int of_property_notify(int action, struct device_node *np,
>> 	pr.prop = prop;
>> 	return of_reconfig_notify(action, &pr);
>> }
>> -#else
>> -static int of_property_notify(int action, struct device_node *np,
>> -			      struct property *prop)
>> -{
>> -	return 0;
>> -}
>> #endif
>> 
>> /**
>>  * __of_add_property - Add a property to a node without lock operations
>>  */
>> -static int __of_add_property(struct device_node *np, struct property *prop)
>> +int __of_add_property(struct device_node *np, struct property *prop)
>> {
>> 	struct property **next;
>> 
>> @@ -1886,6 +1882,25 @@ int of_add_property(struct device_node *np, struct property *prop)
>> 	return rc;
>> }
>> 
>> +int __of_remove_property(struct device_node *np, struct property *prop)
>> +{
>> +	struct property **next;
>> +
>> +	for (next = &np->properties; *next; next = &(*next)->next) {
>> +		if (*next == prop)
>> +			break;
>> +	}
>> +	if (*next == NULL)
>> +		return -ENODEV;
>> +
>> +	/* found the node */
>> +	*next = prop->next;
>> +	prop->next = np->deadprops;
>> +	np->deadprops = prop;
>> +
>> +	return 0;
>> +}
>> +
>> /**
>>  * of_remove_property - Remove a property from a node.
>>  *
>> @@ -1896,9 +1911,7 @@ int of_add_property(struct device_node *np, struct property *prop)
>>  */
>> int of_remove_property(struct device_node *np, struct property *prop)
>> {
>> -	struct property **next;
>> 	unsigned long flags;
>> -	int found = 0;
>> 	int rc;
>> 
>> 	rc = of_property_notify(OF_RECONFIG_REMOVE_PROPERTY, np, prop);
>> @@ -1906,22 +1919,11 @@ int of_remove_property(struct device_node *np, struct property *prop)
>> 		return rc;
>> 
>> 	raw_spin_lock_irqsave(&devtree_lock, flags);
>> -	next = &np->properties;
>> -	while (*next) {
>> -		if (*next == prop) {
>> -			/* found the node */
>> -			*next = prop->next;
>> -			prop->next = np->deadprops;
>> -			np->deadprops = prop;
>> -			found = 1;
>> -			break;
>> -		}
>> -		next = &(*next)->next;
>> -	}
>> +	rc = __of_remove_property(np, prop);
>> 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
>> 
>> -	if (!found)
>> -		return -ENODEV;
>> +	if (rc)
>> +		return rc;
>> 
>> 	/* at early boot, bail hear and defer setup to of_init() */
>> 	if (!of_kset)
>> @@ -1932,6 +1934,32 @@ int of_remove_property(struct device_node *np, struct property *prop)
>> 	return 0;
>> }
>> 
>> +int __of_update_property(struct device_node *np, struct property *newprop,
>> +		struct property **oldpropp)
>> +{
>> +	struct property **next, *oldprop;
>> +
>> +	for (next = &np->properties; *next; next = &(*next)->next) {
>> +		if (of_prop_cmp((*next)->name, newprop->name) == 0)
>> +			break;
>> +	}
>> +	*oldpropp = oldprop = *next;
>> +
>> +	if (oldprop) {
>> +		/* replace the node */
>> +		newprop->next = oldprop->next;
>> +		*next = newprop;
>> +		oldprop->next = np->deadprops;
>> +		np->deadprops = oldprop;
>> +	} else {
>> +		/* new node */
>> +		newprop->next = NULL;
>> +		*next = newprop;
>> +	}
>> +
>> +	return 0;
>> +}
>> +
>> /*
>>  * of_update_property - Update a property in a node, if the property does
>>  * not exist, add it.
>> @@ -1941,36 +1969,21 @@ int of_remove_property(struct device_node *np, struct property *prop)
>>  * Instead we just move the property to the "dead properties" list,
>>  * and add the new property to the property list
>>  */
>> -int of_update_property(struct device_node *np, struct property *newprop)
>> +int of_update_property(struct device_node *np, struct property *prop)
>> {
>> -	struct property **next, *oldprop;
>> +	struct property *oldprop;
>> 	unsigned long flags;
>> 	int rc;
>> 
>> -	rc = of_property_notify(OF_RECONFIG_UPDATE_PROPERTY, np, newprop);
>> +	if (!prop->name)
>> +		return -EINVAL;
>> +
>> +	rc = of_property_notify(OF_RECONFIG_UPDATE_PROPERTY, np, prop);
>> 	if (rc)
>> 		return rc;
>> 
>> -	if (!newprop->name)
>> -		return -EINVAL;
>> -
>> 	raw_spin_lock_irqsave(&devtree_lock, flags);
>> -	next = &np->properties;
>> -	oldprop = __of_find_property(np, newprop->name, NULL);
>> -	if (!oldprop) {
>> -		/* add the new node */
>> -		rc = __of_add_property(np, newprop);
>> -	} else while (*next) {
>> -		/* replace the node */
>> -		if (*next == oldprop) {
>> -			newprop->next = oldprop->next;
>> -			*next = newprop;
>> -			oldprop->next = np->deadprops;
>> -			np->deadprops = oldprop;
>> -			break;
>> -		}
>> -		next = &(*next)->next;
>> -	}
>> +	rc = __of_update_property(np, prop, &oldprop);
>> 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
>> 	if (rc)
>> 		return rc;
>> @@ -1982,7 +1995,7 @@ int of_update_property(struct device_node *np, struct property *newprop)
>> 	/* Update the sysfs attribute */
>> 	if (oldprop)
>> 		sysfs_remove_bin_file(&np->kobj, &oldprop->attr);
>> -	__of_add_property_sysfs(np, newprop);
>> +	__of_add_property_sysfs(np, prop);
>> 
>> 	return 0;
>> }
>> @@ -2018,6 +2031,15 @@ int of_reconfig_notify(unsigned long action, void *p)
>> 	return notifier_to_errno(rc);
>> }
>> 
>> +void __of_attach_node(struct device_node *np)
>> +{
>> +	np->sibling = np->parent->child;
>> +	np->allnext = np->parent->allnext;
>> +	np->parent->allnext = np;
>> +	np->parent->child = np;
>> +	of_node_clear_flag(np, OF_DETACHED);
>> +}
>> +
>> /**
>>  * of_attach_node - Plug a device node into the tree and global list.
>>  */
>> @@ -2031,51 +2053,29 @@ int of_attach_node(struct device_node *np)
>> 		return rc;
>> 
>> 	raw_spin_lock_irqsave(&devtree_lock, flags);
>> -	np->sibling = np->parent->child;
>> -	np->allnext = np->parent->allnext;
>> -	np->parent->allnext = np;
>> -	np->parent->child = np;
>> -	of_node_clear_flag(np, OF_DETACHED);
>> +	__of_attach_node(np);
>> 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
>> 
>> 	of_node_add(np);
>> 	return 0;
>> }
>> 
>> -/**
>> - * of_detach_node - "Unplug" a node from the device tree.
>> - *
>> - * The caller must hold a reference to the node.  The memory associated with
>> - * the node is not freed until its refcount goes to zero.
>> - */
>> -int of_detach_node(struct device_node *np)
>> +void __of_detach_node(struct device_node *np)
>> {
>> 	struct device_node *parent;
>> -	unsigned long flags;
>> -	int rc = 0;
>> -
>> -	rc = of_reconfig_notify(OF_RECONFIG_DETACH_NODE, np);
>> -	if (rc)
>> -		return rc;
>> +	struct device_node *prev;
>> +	struct device_node *prevsib;
>> 
>> -	raw_spin_lock_irqsave(&devtree_lock, flags);
>> -
>> -	if (of_node_check_flag(np, OF_DETACHED)) {
>> -		/* someone already detached it */
>> -		raw_spin_unlock_irqrestore(&devtree_lock, flags);
>> -		return rc;
>> -	}
>> +	if (WARN_ON(of_node_check_flag(np, OF_DETACHED)))
>> +		return;
>> 
>> 	parent = np->parent;
>> -	if (!parent) {
>> -		raw_spin_unlock_irqrestore(&devtree_lock, flags);
>> -		return rc;
>> -	}
>> +	if (WARN_ON(!parent))
>> +		return;
>> 
>> 	if (of_allnodes == np)
>> 		of_allnodes = np->allnext;
>> 	else {
>> -		struct device_node *prev;
>> 		for (prev = of_allnodes;
>> 		     prev->allnext != np;
>> 		     prev = prev->allnext)
>> @@ -2086,7 +2086,6 @@ int of_detach_node(struct device_node *np)
>> 	if (parent->child == np)
>> 		parent->child = np->sibling;
>> 	else {
>> -		struct device_node *prevsib;
>> 		for (prevsib = np->parent->child;
>> 		     prevsib->sibling != np;
>> 		     prevsib = prevsib->sibling)
>> @@ -2095,6 +2094,25 @@ int of_detach_node(struct device_node *np)
>> 	}
>> 
>> 	of_node_set_flag(np, OF_DETACHED);
>> +}
>> +
>> +/**
>> + * of_detach_node - "Unplug" a node from the device tree.
>> + *
>> + * The caller must hold a reference to the node.  The memory associated with
>> + * the node is not freed until its refcount goes to zero.
>> + */
>> +int of_detach_node(struct device_node *np)
>> +{
>> +	unsigned long flags;
>> +	int rc = 0;
>> +
>> +	rc = of_reconfig_notify(OF_RECONFIG_DETACH_NODE, np);
>> +	if (rc)
>> +		return rc;
>> +
>> +	raw_spin_lock_irqsave(&devtree_lock, flags);
>> +	__of_detach_node(np);
>> 	raw_spin_unlock_irqrestore(&devtree_lock, flags);
>> 
>> 	of_node_remove(np);
>> diff --git a/include/linux/of.h b/include/linux/of.h
>> index f7392c0..5e4e1b3 100644
>> --- a/include/linux/of.h
>> +++ b/include/linux/of.h
>> @@ -98,6 +98,8 @@ static inline int of_node_is_attached(struct device_node *node)
>> #ifdef CONFIG_OF_DYNAMIC
>> extern struct device_node *of_node_get(struct device_node *node);
>> extern void of_node_put(struct device_node *node);
>> +extern int of_property_notify(int action, struct device_node *np,
>> +			      struct property *prop);
>> #else /* CONFIG_OF_DYNAMIC */
>> /* Dummy ref counting routines - to be implemented later */
>> static inline struct device_node *of_node_get(struct device_node *node)
>> @@ -105,6 +107,11 @@ static inline struct device_node *of_node_get(struct device_node *node)
>> 	return node;
>> }
>> static inline void of_node_put(struct device_node *node) { }
>> +static inline int of_property_notify(int action, struct device_node *np,
>> +			      struct property *prop)
>> +{
>> +	return 0;
>> +}
>> #endif /* !CONFIG_OF_DYNAMIC */
>> 
>> #ifdef CONFIG_OF
>> @@ -238,6 +245,8 @@ extern struct device_node *of_get_parent(const struct device_node *node);
>> extern struct device_node *of_get_next_parent(struct device_node *node);
>> extern struct device_node *of_get_next_child(const struct device_node *node,
>> 					     struct device_node *prev);
>> +struct device_node *__of_get_next_child(const struct device_node *node,
>> +						struct device_node *prev);
>> extern struct device_node *of_get_next_available_child(
>> 	const struct device_node *node, struct device_node *prev);
>> 
>> @@ -279,9 +288,17 @@ extern int of_property_match_string(struct device_node *np,
>> 				    const char *string);
>> extern int of_property_count_strings(struct device_node *np,
>> 				     const char *propname);
>> +int __of_device_is_compatible(const struct device_node *device,
>> +				     const char *compat, const char *type,
>> +				     const char *name);
>> extern int of_device_is_compatible(const struct device_node *device,
>> 				   const char *);
>> +extern int __of_device_is_available(const struct device_node *device);
>> extern int of_device_is_available(const struct device_node *device);
>> +
>> +extern const void *__of_get_property(const struct device_node *node,
>> +				const char *name,
>> +				int *lenp);
>> extern const void *of_get_property(const struct device_node *node,
>> 				const char *name,
>> 				int *lenp);
>> @@ -312,6 +329,11 @@ extern int of_alias_get_id(struct device_node *np, const char *stem);
>> 
>> extern int of_machine_is_compatible(const char *compat);
>> 
>> +int __of_add_property(struct device_node *np, struct property *prop);
>> +int __of_remove_property(struct device_node *np, struct property *prop);
>> +int __of_update_property(struct device_node *np, struct property *newprop,
>> +		struct property **oldprop);
>> +
>> extern int of_add_property(struct device_node *np, struct property *prop);
>> extern int of_remove_property(struct device_node *np, struct property *prop);
>> extern int of_update_property(struct device_node *np, struct property *newprop);
>> @@ -332,6 +354,9 @@ extern int of_reconfig_notifier_register(struct notifier_block *);
>> extern int of_reconfig_notifier_unregister(struct notifier_block *);
>> extern int of_reconfig_notify(unsigned long, void *);
>> 
>> +void __of_attach_node(struct device_node *np);
>> +void __of_detach_node(struct device_node *np);
>> +
>> extern int of_attach_node(struct device_node *);
>> extern int of_detach_node(struct device_node *);
>> 
>> @@ -401,6 +426,12 @@ static inline struct device_node *of_get_next_child(
>> 	return NULL;
>> }
>> 
>> +static inline struct device_node *__of_get_next_child(
>> +	const struct device_node *node, struct device_node *prev)
>> +{
>> +	return NULL;
>> +}
>> +
>> static inline struct device_node *of_get_next_available_child(
>> 	const struct device_node *node, struct device_node *prev)
>> {
>> @@ -738,6 +769,9 @@ static inline int of_property_read_u32(const struct device_node *np,
>> #define for_each_child_of_node(parent, child) \
>> 	for (child = of_get_next_child(parent, NULL); child != NULL; \
>> 	     child = of_get_next_child(parent, child))
>> +#define __for_each_child_of_node(parent, child) \
>> +	for (child = __of_get_next_child(parent, NULL); child != NULL; \
>> +	     child = __of_get_next_child(parent, child))
>> #define for_each_available_child_of_node(parent, child) \
>> 	for (child = of_get_next_available_child(parent, NULL); child != NULL; \
>> 	     child = of_get_next_available_child(parent, child))
>> -- 
>> 1.7.12
>> 
> 

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

* Re: [PATCH 4/6] OF: Export a number of __of_* methods
  2014-06-24 19:38     ` Pantelis Antoniou
@ 2014-06-24 20:19       ` Grant Likely
  0 siblings, 0 replies; 63+ messages in thread
From: Grant Likely @ 2014-06-24 20:19 UTC (permalink / raw)
  To: Pantelis Antoniou
  Cc: Rob Herring, Stephen Warren, Matt Porter, Koen Kooi,
	Greg Kroah-Hartman, Alison Chaiken, Dinh Nguyen, Jan Lubbe,
	Alexander Sverdlin, Michael Stickel, Guenter Roeck, Dirk Behme,
	Alan Tull, Sascha Hauer, Michael Bohan, Ionut Nicu, Michal Simek,
	Matt Ranostay, Joel Becker, devicetree, Wolfram Sang, linux-i2c,
	Mark Brown, linux-spi, linux-kernel, Pete Popov, Dan Malek,
	Georgi Vlaev

On Tue, 24 Jun 2014 22:38:25 +0300, Pantelis Antoniou <pantelis.antoniou@konsulko.com> wrote:
> > On Sun, 22 Jun 2014 12:40:37 +0300, Pantelis Antoniou <pantelis.antoniou@konsulko.com> wrote:
> >> @@ -382,7 +382,7 @@ EXPORT_SYMBOL(of_find_all_nodes);
> >>  * Find a property with a given name for a given node
> >>  * and return the value.
> >>  */
> >> -static const void *__of_get_property(const struct device_node *np,
> >> +const void *__of_get_property(const struct device_node *np,
> >> 				     const char *name, int *lenp)
> >> {
> >> 	struct property *pp = __of_find_property(np, name, lenp);
> >> @@ -397,9 +397,13 @@ static const void *__of_get_property(const struct device_node *np,
> >> const void *of_get_property(const struct device_node *np, const char *name,
> >> 			    int *lenp)
> >> {
> >> -	struct property *pp = of_find_property(np, name, lenp);
> >> +	unsigned long flags;
> >> +	const void *value;
> >> 
> >> -	return pp ? pp->value : NULL;
> >> +	raw_spin_lock_irqsave(&devtree_lock, flags);
> >> +	value = __of_get_property(np, name, lenp);
> >> +	raw_spin_unlock_irqrestore(&devtree_lock, flags);
> >> +	return value;
> > 
> > Why is this changed?
> > 
> 
> Symmetry. All the others follow the same pattern.

Drop it, or split into a separate patch. I don't like patches that lump
together unrelated changes.

g.

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

* Re: [PATCH 1/6] of: Do not free memory at of_node_release
  2014-06-24 14:23     ` Pantelis Antoniou
@ 2014-06-24 20:21       ` Grant Likely
  2014-06-24 20:23         ` Pantelis Antoniou
  0 siblings, 1 reply; 63+ messages in thread
From: Grant Likely @ 2014-06-24 20:21 UTC (permalink / raw)
  To: Pantelis Antoniou
  Cc: Rob Herring, Stephen Warren, Matt Porter, Koen Kooi,
	Greg Kroah-Hartman, Alison Chaiken, Dinh Nguyen, Jan Lubbe,
	Alexander Sverdlin, Michael Stickel, Guenter Roeck, Dirk Behme,
	Alan Tull, Sascha Hauer, Michael Bohan, Ionut Nicu, Michal Simek,
	Matt Ranostay, Joel Becker, devicetree, Wolfram Sang, linux-i2c,
	Mark Brown, linux-spi, linux-kernel, Pete Popov, Dan Malek,
	Georgi Vlaev

On Tue, 24 Jun 2014 17:23:35 +0300, Pantelis Antoniou <pantelis.antoniou@konsulko.com> wrote:
> Hi Grant,
> 
> On Jun 24, 2014, at 5:10 PM, Grant Likely wrote:
> 
> > On Sun, 22 Jun 2014 12:40:34 +0300, Pantelis Antoniou <pantelis.antoniou@konsulko.com> wrote:
> >> The life-cycle of nodes and properties does not allow us to release
> >> the memory taken by a device_node. Pointer to properties and nodes
> >> might still be in use in drivers, so any memory free'ing is dangerous.
> >> 
> >> Simply move all the properties to the deadprops list, and the node
> >> itself to of_alldeadnodes until the life-cycles issues are resolved.
> > 
> > Ummm. this looks wrong. The release function is supposed to be the place
> > to do the freeing, and with our discussion the other day about moving to
> > rcu, but keeping of_node_get/put() for anything that needs to hold a
> > long term reference, that means the lifecycle issues are pretty much
> > resolved. I don't think this patch is necessary.
> > 
> 
> Well, I thought about it too. This is the culmination of that process :)
> 
> The problem is not the node life-cycle, it's the properties. We can't
> tell for sure who and where has a pointer to the properties of the node,
> and when we free the node, the current code iterates over the properties
> list and frees them. This works only because in my tests, of_node_release
> only gets called when using overlays created nodes.

If a caller want's to use the value of a property, then it needs to
of_node_get() the node. Property lifecycle is strictly attached to the
lifecycle of it's node.

g.

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

* Re: [PATCH 1/6] of: Do not free memory at of_node_release
  2014-06-24 20:21       ` Grant Likely
@ 2014-06-24 20:23         ` Pantelis Antoniou
  2014-06-24 20:33           ` Guenter Roeck
  2014-06-25 19:24           ` Grant Likely
  0 siblings, 2 replies; 63+ messages in thread
From: Pantelis Antoniou @ 2014-06-24 20:23 UTC (permalink / raw)
  To: Grant Likely
  Cc: Rob Herring, Stephen Warren, Matt Porter, Koen Kooi,
	Greg Kroah-Hartman, Alison Chaiken, Dinh Nguyen, Jan Lubbe,
	Alexander Sverdlin, Michael Stickel, Guenter Roeck, Dirk Behme,
	Alan Tull, Sascha Hauer, Michael Bohan, Ionut Nicu, Michal Simek,
	Matt Ranostay, Joel Becker, devicetree, Wolfram Sang, linux-i2c,
	Mark Brown, linux-spi, linux-kernel, Pete Popov, Dan Malek,
	Georgi Vlaev

Hi Grant,

On Jun 24, 2014, at 11:21 PM, Grant Likely wrote:

> On Tue, 24 Jun 2014 17:23:35 +0300, Pantelis Antoniou <pantelis.antoniou@konsulko.com> wrote:
>> Hi Grant,
>> 
>> On Jun 24, 2014, at 5:10 PM, Grant Likely wrote:
>> 
>>> On Sun, 22 Jun 2014 12:40:34 +0300, Pantelis Antoniou <pantelis.antoniou@konsulko.com> wrote:
>>>> The life-cycle of nodes and properties does not allow us to release
>>>> the memory taken by a device_node. Pointer to properties and nodes
>>>> might still be in use in drivers, so any memory free'ing is dangerous.
>>>> 
>>>> Simply move all the properties to the deadprops list, and the node
>>>> itself to of_alldeadnodes until the life-cycles issues are resolved.
>>> 
>>> Ummm. this looks wrong. The release function is supposed to be the place
>>> to do the freeing, and with our discussion the other day about moving to
>>> rcu, but keeping of_node_get/put() for anything that needs to hold a
>>> long term reference, that means the lifecycle issues are pretty much
>>> resolved. I don't think this patch is necessary.
>>> 
>> 
>> Well, I thought about it too. This is the culmination of that process :)
>> 
>> The problem is not the node life-cycle, it's the properties. We can't
>> tell for sure who and where has a pointer to the properties of the node,
>> and when we free the node, the current code iterates over the properties
>> list and frees them. This works only because in my tests, of_node_release
>> only gets called when using overlays created nodes.
> 
> If a caller want's to use the value of a property, then it needs to
> of_node_get() the node. Property lifecycle is strictly attached to the
> lifecycle of it's node.
> 

Taking bets if that's always the case?

> g.

Regards

-- Pantelis

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

* Re: [PATCH 1/6] of: Do not free memory at of_node_release
  2014-06-24 20:23         ` Pantelis Antoniou
@ 2014-06-24 20:33           ` Guenter Roeck
  2014-06-24 21:02             ` Pantelis Antoniou
  2014-06-25 19:24           ` Grant Likely
  1 sibling, 1 reply; 63+ messages in thread
From: Guenter Roeck @ 2014-06-24 20:33 UTC (permalink / raw)
  To: Pantelis Antoniou
  Cc: Grant Likely, Rob Herring, Stephen Warren, Matt Porter,
	Koen Kooi, Greg Kroah-Hartman, Alison Chaiken, Dinh Nguyen,
	Jan Lubbe, Alexander Sverdlin, Michael Stickel, Dirk Behme,
	Alan Tull, Sascha Hauer, Michael Bohan, Ionut Nicu, Michal Simek,
	Matt Ranostay, Joel Becker, devicetree, Wolfram Sang, linux-i2c,
	Mark Brown, linux-spi, linux-kernel, Pete Popov, Dan Malek,
	Georgi Vlaev

On Tue, Jun 24, 2014 at 11:23:35PM +0300, Pantelis Antoniou wrote:
> Hi Grant,
> 
> On Jun 24, 2014, at 11:21 PM, Grant Likely wrote:
> 
> > On Tue, 24 Jun 2014 17:23:35 +0300, Pantelis Antoniou <pantelis.antoniou@konsulko.com> wrote:
> >> Hi Grant,
> >> 
> >> On Jun 24, 2014, at 5:10 PM, Grant Likely wrote:
> >> 
> >>> On Sun, 22 Jun 2014 12:40:34 +0300, Pantelis Antoniou <pantelis.antoniou@konsulko.com> wrote:
> >>>> The life-cycle of nodes and properties does not allow us to release
> >>>> the memory taken by a device_node. Pointer to properties and nodes
> >>>> might still be in use in drivers, so any memory free'ing is dangerous.
> >>>> 
> >>>> Simply move all the properties to the deadprops list, and the node
> >>>> itself to of_alldeadnodes until the life-cycles issues are resolved.
> >>> 
> >>> Ummm. this looks wrong. The release function is supposed to be the place
> >>> to do the freeing, and with our discussion the other day about moving to
> >>> rcu, but keeping of_node_get/put() for anything that needs to hold a
> >>> long term reference, that means the lifecycle issues are pretty much
> >>> resolved. I don't think this patch is necessary.
> >>> 
> >> 
> >> Well, I thought about it too. This is the culmination of that process :)
> >> 
> >> The problem is not the node life-cycle, it's the properties. We can't
> >> tell for sure who and where has a pointer to the properties of the node,
> >> and when we free the node, the current code iterates over the properties
> >> list and frees them. This works only because in my tests, of_node_release
> >> only gets called when using overlays created nodes.
> > 
> > If a caller want's to use the value of a property, then it needs to
> > of_node_get() the node. Property lifecycle is strictly attached to the
> > lifecycle of it's node.
> > 
> 
> Taking bets if that's always the case?
> 
For my part I prefer to take the bet (and handle the consequences) over
a potential memory leak.

Guenter

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

* Re: [PATCH 1/6] of: Do not free memory at of_node_release
  2014-06-24 20:33           ` Guenter Roeck
@ 2014-06-24 21:02             ` Pantelis Antoniou
  2014-06-24 23:20               ` Guenter Roeck
  0 siblings, 1 reply; 63+ messages in thread
From: Pantelis Antoniou @ 2014-06-24 21:02 UTC (permalink / raw)
  To: Guenter Roeck
  Cc: Grant Likely, Rob Herring, Stephen Warren, Matt Porter,
	Koen Kooi, Greg Kroah-Hartman, Alison Chaiken, Dinh Nguyen,
	Jan Lubbe, Alexander Sverdlin, Michael Stickel, Dirk Behme,
	Alan Tull, Sascha Hauer, Michael Bohan, Ionut Nicu, Michal Simek,
	Matt Ranostay, Joel Becker, devicetree, Wolfram Sang, linux-i2c,
	Mark Brown, linux-spi, linux-kernel, Pete Popov, Dan Malek,
	Georgi Vlaev

Hi Guenter,

On Jun 24, 2014, at 11:33 PM, Guenter Roeck wrote:

> On Tue, Jun 24, 2014 at 11:23:35PM +0300, Pantelis Antoniou wrote:
>> Hi Grant,
>> 
>> On Jun 24, 2014, at 11:21 PM, Grant Likely wrote:
>> 
>>> On Tue, 24 Jun 2014 17:23:35 +0300, Pantelis Antoniou <pantelis.antoniou@konsulko.com> wrote:
>>>> Hi Grant,
>>>> 
>>>> On Jun 24, 2014, at 5:10 PM, Grant Likely wrote:
>>>> 
>>>>> On Sun, 22 Jun 2014 12:40:34 +0300, Pantelis Antoniou <pantelis.antoniou@konsulko.com> wrote:
>>>>>> The life-cycle of nodes and properties does not allow us to release
>>>>>> the memory taken by a device_node. Pointer to properties and nodes
>>>>>> might still be in use in drivers, so any memory free'ing is dangerous.
>>>>>> 
>>>>>> Simply move all the properties to the deadprops list, and the node
>>>>>> itself to of_alldeadnodes until the life-cycles issues are resolved.
>>>>> 
>>>>> Ummm. this looks wrong. The release function is supposed to be the place
>>>>> to do the freeing, and with our discussion the other day about moving to
>>>>> rcu, but keeping of_node_get/put() for anything that needs to hold a
>>>>> long term reference, that means the lifecycle issues are pretty much
>>>>> resolved. I don't think this patch is necessary.
>>>>> 
>>>> 
>>>> Well, I thought about it too. This is the culmination of that process :)
>>>> 
>>>> The problem is not the node life-cycle, it's the properties. We can't
>>>> tell for sure who and where has a pointer to the properties of the node,
>>>> and when we free the node, the current code iterates over the properties
>>>> list and frees them. This works only because in my tests, of_node_release
>>>> only gets called when using overlays created nodes.
>>> 
>>> If a caller want's to use the value of a property, then it needs to
>>> of_node_get() the node. Property lifecycle is strictly attached to the
>>> lifecycle of it's node.
>>> 
>> 
>> Taking bets if that's always the case?
>> 
> For my part I prefer to take the bet (and handle the consequences) over
> a potential memory leak.
> 

It's your call really. But let me just demonstrate why this is harder than it appears,
with a small example.

The of_node_get() method is not invoked for instance when reading string properties.

The of_property_read_string() method will return a pointer to the string property value.
That means that potentially all drivers that call of_property_read_string() will have to
be converted to taking a reference of the node using of_node_get(), or the of_property_read_string()
must do so in the background.

Also note that the release method is never called on non-dynamic node since that memory is
never released.

FWIW, the overlay code until now operated just fine releasing the nodes, but I can't 
guarantee you won't be screwed sometime by an errand driver :)

> Guenter

Regards

-- Pantelis

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

* Re: [PATCH 1/6] of: Do not free memory at of_node_release
  2014-06-24 21:02             ` Pantelis Antoniou
@ 2014-06-24 23:20               ` Guenter Roeck
  0 siblings, 0 replies; 63+ messages in thread
From: Guenter Roeck @ 2014-06-24 23:20 UTC (permalink / raw)
  To: Pantelis Antoniou
  Cc: Grant Likely, Rob Herring, Stephen Warren, Matt Porter,
	Koen Kooi, Greg Kroah-Hartman, Alison Chaiken, Dinh Nguyen,
	Jan Lubbe, Alexander Sverdlin, Michael Stickel, Dirk Behme,
	Alan Tull, Sascha Hauer, Michael Bohan, Ionut Nicu, Michal Simek,
	Matt Ranostay, Joel Becker, devicetree, Wolfram Sang, linux-i2c,
	Mark Brown, linux-spi, linux-kernel, Pete Popov, Dan Malek,
	Georgi Vlaev

On 06/24/2014 02:02 PM, Pantelis Antoniou wrote:
> Hi Guenter,
>
> On Jun 24, 2014, at 11:33 PM, Guenter Roeck wrote:
>
>> On Tue, Jun 24, 2014 at 11:23:35PM +0300, Pantelis Antoniou wrote:
>>> Hi Grant,
>>>
>>> On Jun 24, 2014, at 11:21 PM, Grant Likely wrote:
>>>
>>>> On Tue, 24 Jun 2014 17:23:35 +0300, Pantelis Antoniou <pantelis.antoniou@konsulko.com> wrote:
>>>>> Hi Grant,
>>>>>
>>>>> On Jun 24, 2014, at 5:10 PM, Grant Likely wrote:
>>>>>
>>>>>> On Sun, 22 Jun 2014 12:40:34 +0300, Pantelis Antoniou <pantelis.antoniou@konsulko.com> wrote:
>>>>>>> The life-cycle of nodes and properties does not allow us to release
>>>>>>> the memory taken by a device_node. Pointer to properties and nodes
>>>>>>> might still be in use in drivers, so any memory free'ing is dangerous.
>>>>>>>
>>>>>>> Simply move all the properties to the deadprops list, and the node
>>>>>>> itself to of_alldeadnodes until the life-cycles issues are resolved.
>>>>>>
>>>>>> Ummm. this looks wrong. The release function is supposed to be the place
>>>>>> to do the freeing, and with our discussion the other day about moving to
>>>>>> rcu, but keeping of_node_get/put() for anything that needs to hold a
>>>>>> long term reference, that means the lifecycle issues are pretty much
>>>>>> resolved. I don't think this patch is necessary.
>>>>>>
>>>>>
>>>>> Well, I thought about it too. This is the culmination of that process :)
>>>>>
>>>>> The problem is not the node life-cycle, it's the properties. We can't
>>>>> tell for sure who and where has a pointer to the properties of the node,
>>>>> and when we free the node, the current code iterates over the properties
>>>>> list and frees them. This works only because in my tests, of_node_release
>>>>> only gets called when using overlays created nodes.
>>>>
>>>> If a caller want's to use the value of a property, then it needs to
>>>> of_node_get() the node. Property lifecycle is strictly attached to the
>>>> lifecycle of it's node.
>>>>
>>>
>>> Taking bets if that's always the case?
>>>
>> For my part I prefer to take the bet (and handle the consequences) over
>> a potential memory leak.
>>
>
> It's your call really. But let me just demonstrate why this is harder than it appears,
> with a small example.
>
Nothing is easy in life.

> The of_node_get() method is not invoked for instance when reading string properties.
>
> The of_property_read_string() method will return a pointer to the string property value.
> That means that potentially all drivers that call of_property_read_string() will have to
> be converted to taking a reference of the node using of_node_get(), or the of_property_read_string()
> must do so in the background.
>
Or the caller must duplicate the string if it is used later on.

Yes, I understand that there is potential for problems. I am still more concerned
about memory leaks, though. Given that, I am actually more concerned about code
which does not call of_node_put() even if it should, and I suspect we may have to
spend some time going through the code to identify and fix as many of those as we
can. Again, keep in mind that the systems I am dealing with tend to run for months
if not years without reboot.

Guenter

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

* Re: [PATCH 5/6] OF: Utility helper functions for dynamic nodes
  2014-06-24  8:10           ` Alexander Sverdlin
  (?)
@ 2014-06-25  9:09             ` Grant Likely
  -1 siblings, 0 replies; 63+ messages in thread
From: Grant Likely @ 2014-06-25  9:09 UTC (permalink / raw)
  To: Alexander Sverdlin, Ioan Nicu, ext Pantelis Antoniou
  Cc: Rob Herring, Stephen Warren, Matt Porter, Koen Kooi,
	Greg Kroah-Hartman, Alison Chaiken, Dinh Nguyen, Jan Lubbe,
	Michael Stickel, Guenter Roeck, Dirk Behme, Alan Tull,
	Sascha Hauer, Michael Bohan, Michal Simek, Matt Ranostay,
	Joel Becker, devicetree, Wolfram Sang, linux-i2c, Mark Brown,
	linux-spi, linux-kernel, Pete Popov, Dan Malek, Georgi Vlaev

On Tue, 24 Jun 2014 10:10:01 +0200, Alexander Sverdlin <alexander.sverdlin@nsn.com> wrote:
> Hi Pantelis, Grant,
> 
> On 23/06/14 20:33, Ioan Nicu wrote:
> >>> On 22/06/14 11:40, ext Pantelis Antoniou wrote:
> >>>> Introduce helper functions for working with the live DT tree,
> >>>> all of them related to dynamically adding/removing nodes and
> >>>> properties.
> >>>>
> >>>> __of_copy_property() copies a property dynamically
> >>>> __of_create_empty_node() creates an empty node
> >>>>
> >>>> Bug fix about prop->len == 0 by Ionut Nicu <ioan.nicu.ext@nsn.com>
> >>>
> >>> Are you sure about this? (see below...)
> >>>
> > 
> > Alexander is right, my fix was lost even though it's mentioned in this patch.
> > 
> >>>> Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
> >>>> ---
> >>
> >> [snip]
> >>>> +
> >>>> +	if (prop->length > 0) {
> >>>        ^^^^^^^^^^^^^^^^^^^^^
> >>> Seems, that length==0 case will still produce value==NULL results,
> >>> which will brake some checks in the kernel... Or am I missing something in
> >>> the new version?
> >>>
> >>
> >> prop->value will be set to NULL, and length will be set to zero (kzalloc).
> >> This is a normal zero length property.
> >>
> >> I don't know of any place in the kernel accessing the value if prop->length==0
> >>
> > 
> > We have a simple use case. We have an overlay which adds an interrupt controller.
> > If you look in drivers/of/irq.c, in of_irq_parse_raw():
> > 
> > [...]
> > 	/* Now start the actual "proper" walk of the interrupt tree */
> > 	while (ipar != NULL) {
> > 		/* Now check if cursor is an interrupt-controller and if it is
> > 		 * then we are done
> > 		 */
> > 		if (of_get_property(ipar, "interrupt-controller", NULL) !=
> 
> We have to define, if it's allowed for an empty property to have NULL value.
> Several places in the kernel use of_get_property() to check for property existence.
> We either have to make a tree-wide patch and replace of_get_property() with of_find_property() in those cases,
> or ensure value != NULL in this copy function...
> 
> Grant, what do you think?

I think it's a good cleanup, but until it happens, any new code needs to
match the behaviour of fdt.c. In that case, making the value point to an
empty string is a sane choice.  If you do the legwork of finding callers
and fixing them up, then I'll apply it. Once done we can make the
following change to fdt.c:

- 			pp->value = (__be32 *)p;
+ 			pp->value = sz ? (__be32 *)p : 0;

pdt.c similarly needs to be updated.

I'm not overly worried though. That code has been in place for a very
long time, so there is no rush. It can exist a while longer.

g.

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

* Re: [PATCH 5/6] OF: Utility helper functions for dynamic nodes
@ 2014-06-25  9:09             ` Grant Likely
  0 siblings, 0 replies; 63+ messages in thread
From: Grant Likely @ 2014-06-25  9:09 UTC (permalink / raw)
  To: Alexander Sverdlin, Ioan Nicu, ext Pantelis Antoniou
  Cc: Rob Herring, Stephen Warren, Matt Porter, Koen Kooi,
	Greg Kroah-Hartman, Alison Chaiken, Dinh Nguyen, Jan Lubbe,
	Michael Stickel, Guenter Roeck, Dirk Behme, Alan Tull,
	Sascha Hauer, Michael Bohan, Michal Simek, Matt Ranostay,
	Joel Becker, devicetree, Wolfram Sang, linux-i2c, Mark Brown,
	linux-spi, linux-kernel, Pete Popov, Dan Malek

On Tue, 24 Jun 2014 10:10:01 +0200, Alexander Sverdlin <alexander.sverdlin@nsn.com> wrote:
> Hi Pantelis, Grant,
> 
> On 23/06/14 20:33, Ioan Nicu wrote:
> >>> On 22/06/14 11:40, ext Pantelis Antoniou wrote:
> >>>> Introduce helper functions for working with the live DT tree,
> >>>> all of them related to dynamically adding/removing nodes and
> >>>> properties.
> >>>>
> >>>> __of_copy_property() copies a property dynamically
> >>>> __of_create_empty_node() creates an empty node
> >>>>
> >>>> Bug fix about prop->len == 0 by Ionut Nicu <ioan.nicu.ext@nsn.com>
> >>>
> >>> Are you sure about this? (see below...)
> >>>
> > 
> > Alexander is right, my fix was lost even though it's mentioned in this patch.
> > 
> >>>> Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
> >>>> ---
> >>
> >> [snip]
> >>>> +
> >>>> +	if (prop->length > 0) {
> >>>        ^^^^^^^^^^^^^^^^^^^^^
> >>> Seems, that length==0 case will still produce value==NULL results,
> >>> which will brake some checks in the kernel... Or am I missing something in
> >>> the new version?
> >>>
> >>
> >> prop->value will be set to NULL, and length will be set to zero (kzalloc).
> >> This is a normal zero length property.
> >>
> >> I don't know of any place in the kernel accessing the value if prop->length==0
> >>
> > 
> > We have a simple use case. We have an overlay which adds an interrupt controller.
> > If you look in drivers/of/irq.c, in of_irq_parse_raw():
> > 
> > [...]
> > 	/* Now start the actual "proper" walk of the interrupt tree */
> > 	while (ipar != NULL) {
> > 		/* Now check if cursor is an interrupt-controller and if it is
> > 		 * then we are done
> > 		 */
> > 		if (of_get_property(ipar, "interrupt-controller", NULL) !=
> 
> We have to define, if it's allowed for an empty property to have NULL value.
> Several places in the kernel use of_get_property() to check for property existence.
> We either have to make a tree-wide patch and replace of_get_property() with of_find_property() in those cases,
> or ensure value != NULL in this copy function...
> 
> Grant, what do you think?

I think it's a good cleanup, but until it happens, any new code needs to
match the behaviour of fdt.c. In that case, making the value point to an
empty string is a sane choice.  If you do the legwork of finding callers
and fixing them up, then I'll apply it. Once done we can make the
following change to fdt.c:

- 			pp->value = (__be32 *)p;
+ 			pp->value = sz ? (__be32 *)p : 0;

pdt.c similarly needs to be updated.

I'm not overly worried though. That code has been in place for a very
long time, so there is no rush. It can exist a while longer.

g.

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

* Re: [PATCH 5/6] OF: Utility helper functions for dynamic nodes
@ 2014-06-25  9:09             ` Grant Likely
  0 siblings, 0 replies; 63+ messages in thread
From: Grant Likely @ 2014-06-25  9:09 UTC (permalink / raw)
  To: Alexander Sverdlin, Ioan Nicu, ext Pantelis Antoniou
  Cc: Rob Herring, Stephen Warren, Matt Porter, Koen Kooi,
	Greg Kroah-Hartman, Alison Chaiken, Dinh Nguyen, Jan Lubbe,
	Michael Stickel, Guenter Roeck, Dirk Behme, Alan Tull,
	Sascha Hauer, Michael Bohan, Michal Simek, Matt Ranostay,
	Joel Becker, devicetree, Wolfram Sang, linux-i2c, Mark Brown,
	linux-spi, linux-kernel, Pete Popov, Dan Malek

On Tue, 24 Jun 2014 10:10:01 +0200, Alexander Sverdlin <alexander.sverdlin@nsn.com> wrote:
> Hi Pantelis, Grant,
> 
> On 23/06/14 20:33, Ioan Nicu wrote:
> >>> On 22/06/14 11:40, ext Pantelis Antoniou wrote:
> >>>> Introduce helper functions for working with the live DT tree,
> >>>> all of them related to dynamically adding/removing nodes and
> >>>> properties.
> >>>>
> >>>> __of_copy_property() copies a property dynamically
> >>>> __of_create_empty_node() creates an empty node
> >>>>
> >>>> Bug fix about prop->len == 0 by Ionut Nicu <ioan.nicu.ext@nsn.com>
> >>>
> >>> Are you sure about this? (see below...)
> >>>
> > 
> > Alexander is right, my fix was lost even though it's mentioned in this patch.
> > 
> >>>> Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
> >>>> ---
> >>
> >> [snip]
> >>>> +
> >>>> +	if (prop->length > 0) {
> >>>        ^^^^^^^^^^^^^^^^^^^^^
> >>> Seems, that length==0 case will still produce value==NULL results,
> >>> which will brake some checks in the kernel... Or am I missing something in
> >>> the new version?
> >>>
> >>
> >> prop->value will be set to NULL, and length will be set to zero (kzalloc).
> >> This is a normal zero length property.
> >>
> >> I don't know of any place in the kernel accessing the value if prop->length==0
> >>
> > 
> > We have a simple use case. We have an overlay which adds an interrupt controller.
> > If you look in drivers/of/irq.c, in of_irq_parse_raw():
> > 
> > [...]
> > 	/* Now start the actual "proper" walk of the interrupt tree */
> > 	while (ipar != NULL) {
> > 		/* Now check if cursor is an interrupt-controller and if it is
> > 		 * then we are done
> > 		 */
> > 		if (of_get_property(ipar, "interrupt-controller", NULL) !=
> 
> We have to define, if it's allowed for an empty property to have NULL value.
> Several places in the kernel use of_get_property() to check for property existence.
> We either have to make a tree-wide patch and replace of_get_property() with of_find_property() in those cases,
> or ensure value != NULL in this copy function...
> 
> Grant, what do you think?

I think it's a good cleanup, but until it happens, any new code needs to
match the behaviour of fdt.c. In that case, making the value point to an
empty string is a sane choice.  If you do the legwork of finding callers
and fixing them up, then I'll apply it. Once done we can make the
following change to fdt.c:

- 			pp->value = (__be32 *)p;
+ 			pp->value = sz ? (__be32 *)p : 0;

pdt.c similarly needs to be updated.

I'm not overly worried though. That code has been in place for a very
long time, so there is no rush. It can exist a while longer.

g.

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

* Re: [PATCH 5/6] OF: Utility helper functions for dynamic nodes
  2014-06-22  9:40 ` [PATCH 5/6] OF: Utility helper functions for dynamic nodes Pantelis Antoniou
  2014-06-23 16:26     ` Alexander Sverdlin
@ 2014-06-25 11:14   ` Grant Likely
  2014-06-25 11:22     ` Pantelis Antoniou
  1 sibling, 1 reply; 63+ messages in thread
From: Grant Likely @ 2014-06-25 11:14 UTC (permalink / raw)
  To: Pantelis Antoniou
  Cc: Rob Herring, Stephen Warren, Matt Porter, Koen Kooi,
	Greg Kroah-Hartman, Alison Chaiken, Dinh Nguyen, Jan Lubbe,
	Alexander Sverdlin, Michael Stickel, Guenter Roeck, Dirk Behme,
	Alan Tull, Sascha Hauer, Michael Bohan, Ionut Nicu, Michal Simek,
	Matt Ranostay, Joel Becker, devicetree, Wolfram Sang, linux-i2c,
	Mark Brown, linux-spi, linux-kernel, Pete Popov, Dan Malek,
	Georgi Vlaev, Pantelis Antoniou

On Sun, 22 Jun 2014 12:40:38 +0300, Pantelis Antoniou <pantelis.antoniou@konsulko.com> wrote:
> Introduce helper functions for working with the live DT tree,
> all of them related to dynamically adding/removing nodes and
> properties.
> 
> __of_copy_property() copies a property dynamically
> __of_create_empty_node() creates an empty node
> 
> Bug fix about prop->len == 0 by Ionut Nicu <ioan.nicu.ext@nsn.com>
> 
> Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>

So, despite our my earlier comments about wanting to reusing the
pointers from unflattening the fdt, the addition of fine-grained flags
just makes things worse. While I still think it would be best to
directly modify and add the nodes that were created by unflattening
instead of duplicating them, to do so requires rework of the full_name
handling that I'm not going to ask you to do.

I won't hold things up on that point. It can be reworked later and you
can drop the new flags and fine-grained tracking from this patch.

For next version, keep this patch in the same series as the patch
actually using it.

More comments below...

> ---
>  drivers/of/Makefile |   2 +-
>  drivers/of/util.c   | 141 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>  include/linux/of.h  |  42 ++++++++++++++++

Similar to the other patches, this will never get used by non-OF core
code. Put the prototypes into of_private.h

>  3 files changed, 184 insertions(+), 1 deletion(-)
>  create mode 100644 drivers/of/util.c
> 
> diff --git a/drivers/of/Makefile b/drivers/of/Makefile
> index 099b1fb..734d3e2 100644
> --- a/drivers/of/Makefile
> +++ b/drivers/of/Makefile
> @@ -1,4 +1,4 @@
> -obj-y = base.o device.o platform.o
> +obj-y = base.o device.o platform.o util.o

obj-$(CONFIG_OF_DYNAMIC) perhaps? We won't use these for anything else.

>  obj-$(CONFIG_OF_FLATTREE) += fdt.o
>  obj-$(CONFIG_OF_EARLY_FLATTREE) += fdt_address.o
>  obj-$(CONFIG_OF_PROMTREE) += pdt.o
> diff --git a/drivers/of/util.c b/drivers/of/util.c
> new file mode 100644
> index 0000000..f4211f8
> --- /dev/null
> +++ b/drivers/of/util.c
> @@ -0,0 +1,141 @@
> +/*
> + * Utility functions for working with device tree(s)
> + *
> + * Copyright (C) 2012 Pantelis Antoniou <panto@antoniou-consulting.com>
> + * Copyright (C) 2012 Texas Instruments Inc.
> + *
> + * This program is free software; you can redistribute it and/or
> + * modify it under the terms of the GNU General Public License
> + * version 2 as published by the Free Software Foundation.
> + */
> +
> +#include <linux/kernel.h>
> +#include <linux/module.h>
> +#include <linux/of.h>
> +#include <linux/of_device.h>
> +#include <linux/string.h>
> +#include <linux/ctype.h>
> +#include <linux/errno.h>
> +#include <linux/string.h>
> +#include <linux/slab.h>
> +#include <linux/err.h>
> +
> +/**
> + * __of_copy_property - Copy a property dynamically.
> + * @prop:	Property to copy
> + * @allocflags:	Allocation flags (typically pass GFP_KERNEL)
> + * @propflags:	Property flags
> + *
> + * Copy a property by dynamically allocating the memory of both the
> + * property stucture and the property name & contents. The property's
> + * flags have the OF_DYNAMIC bit set so that we can differentiate between
> + * dynamically allocated properties and not.
> + * Returns the newly allocated property or NULL on out of memory error.
> + */
> +struct property *__of_copy_property(const struct property *prop,
> +		gfp_t allocflags, unsigned long propflags)

of_property_dup()?

What is the reason for the double underscore prefix? There isn't a
non-double-underscore version to differentiate between it, there is no
locking involved at all, and __ isn't used to designate private
functions.

> +{
> +	struct property *propn;
> +
> +	propn = kzalloc(sizeof(*prop), allocflags);
> +	if (propn == NULL)

Nit: I prefer 'if (!propn)' for pointer checks.

> +		return NULL;
> +
> +	propn->_flags = propflags;
> +
> +	if (of_property_check_flag(propn, OF_ALLOCNAME)) {
> +		propn->name = kstrdup(prop->name, allocflags);
> +		if (propn->name == NULL)
> +			goto err_fail_name;
> +	} else
> +		propn->name = prop->name;
> +
> +	if (prop->length > 0) {
> +		if (of_property_check_flag(propn, OF_ALLOCVALUE)) {
> +			propn->value = kmalloc(prop->length, allocflags);
> +			if (propn->value == NULL)
> +				goto err_fail_value;
> +			memcpy(propn->value, prop->value, prop->length);
> +		} else
> +			propn->value = prop->value;
> +
> +		propn->length = prop->length;
> +	}
> +
> +	/* mark the property as dynamic */
> +	of_property_set_flag(propn, OF_DYNAMIC);
> +
> +	return propn;
> +
> +err_fail_value:
> +	if (of_property_check_flag(propn, OF_ALLOCNAME))
> +		kfree(propn->name);
> +err_fail_name:
> +	kfree(propn);
> +	return NULL;
> +}
> +
> +/**
> + * __of_create_empty_node - Create an empty device node dynamically.
> + * @name:	Name of the new device node
> + * @type:	Type of the new device node
> + * @full_name:	Full name of the new device node
> + * @phandle:	Phandle of the new device node
> + * @allocflags:	Allocation flags (typically pass GFP_KERNEL)
> + * @nodeflags:	Node flags
> + *
> + * Create an empty device tree node, suitable for further modification.
> + * The node data are dynamically allocated and all the node flags
> + * have the OF_DYNAMIC & OF_DETACHED bits set.
> + * Returns the newly allocated node or NULL on out of memory error.
> + */
> +struct device_node *__of_create_empty_node(
> +		const char *name, const char *type, const char *full_name,
> +		phandle phandle, gfp_t allocflags, unsigned long nodeflags)
> +{
> +	struct device_node *node;
> +
> +	node = kzalloc(sizeof(*node), allocflags);
> +	if (node == NULL)
> +		return NULL;
> +
> +	node->_flags = nodeflags;
> +
> +	if (of_node_check_flag(node, OF_ALLOCNAME)) {
> +		node->name = kstrdup(name, allocflags);
> +		if (node->name == NULL)
> +			goto err_free_node;
> +	} else
> +		node->name = name;
> +
> +	if (of_node_check_flag(node, OF_ALLOCTYPE)) {
> +		node->type = kstrdup(type, allocflags);
> +		if (node->type == NULL)
> +			goto err_free_name;
> +	} else
> +		node->type = type;
> +
> +	if (of_node_check_flag(node, OF_ALLOCFULL)) {
> +		node->full_name = kstrdup(full_name, allocflags);
> +		if (node->full_name == NULL)
> +			goto err_free_type;
> +	} else
> +		node->full_name = full_name;
> +
> +	node->phandle = phandle;
> +	of_node_set_flag(node, OF_DYNAMIC);
> +	of_node_set_flag(node, OF_DETACHED);
> +
> +	of_node_init(node);
> +
> +	return node;
> +err_free_type:
> +	if (of_node_check_flag(node, OF_ALLOCTYPE))
> +		kfree(node->type);
> +err_free_name:
> +	if (of_node_check_flag(node, OF_ALLOCNAME))
> +		kfree(node->name);
> +err_free_node:
> +	kfree(node);
> +	return NULL;
> +}
> diff --git a/include/linux/of.h b/include/linux/of.h
> index 5e4e1b3..d381eb5 100644
> --- a/include/linux/of.h
> +++ b/include/linux/of.h
> @@ -211,6 +211,15 @@ static inline unsigned long of_read_ulong(const __be32 *cell, int size)
>  #define OF_DYNAMIC	1 /* node and properties were allocated via kmalloc */
>  #define OF_DETACHED	2 /* node has been detached from the device tree */
>  #define OF_POPULATED	3 /* device already created for the node */
> +#define OF_ALLOCNAME	4 /* name was kmalloc-ed */
> +#define OF_ALLOCTYPE	5 /* type was kmalloc-ed */
> +#define OF_ALLOCFULL	6 /* full_name was kmalloc-ed */
> +#define OF_ALLOCVALUE	7 /* value was kmalloc-ed */
> +
> +#define OF_NODE_ALLOCALL \
> +	((1 << OF_ALLOCNAME) | (1 << OF_ALLOCTYPE) | (1 << OF_ALLOCFULL))
> +#define OF_PROP_ALLOCALL \
> +	((1 << OF_ALLOCNAME) | (1 << OF_ALLOCVALUE))
>  
>  #define OF_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags)
>  #define OF_MARK_DYNAMIC(x) set_bit(OF_DYNAMIC, &x->_flags)
> @@ -824,4 +833,37 @@ typedef void (*of_init_fn_1)(struct device_node *);
>  #define OF_DECLARE_2(table, name, compat, fn) \
>  		_OF_DECLARE(table, name, compat, fn, of_init_fn_2)
>  
> +/**
> + * General utilities for working with live trees.
> + *
> + * All functions with two leading underscores operate
> + * without taking node references, so you either have to
> + * own the devtree lock or work on detached trees only.
> + */
> +
> +#ifdef CONFIG_OF

#ifdef CONFIG_OF_DYNAMIC perhaps? This will never get used for
non-dynamic trees.

> +
> +struct property *__of_copy_property(const struct property *prop,
> +		gfp_t allocflags, unsigned long propflags);
> +struct device_node *__of_create_empty_node(const char *name,
> +		const char *type, const char *full_name,
> +		phandle phandle, gfp_t allocflags, unsigned long nodeflags);
> +
> +#else /* !CONFIG_OF */
> +
> +static inline struct property *__of_copy_property(const struct property *prop,
> +		gfp_t allocflags, unsigned long propflags)
> +{
> +	return NULL;
> +}
> +
> +static inline struct device_node *__of_create_empty_node(const char *name,
> +		const char *type, const char *full_name,
> +		phandle phandle, gfp_t allocflags, unsigned long nodeflags)
> +{
> +	return NULL;
> +}

There is absolutely no way these functions should ever get called by
non-OF code. Don't tempt people to call them by adding empty versions.

g.

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

* Re: [PATCH 5/6] OF: Utility helper functions for dynamic nodes
  2014-06-25 11:14   ` Grant Likely
@ 2014-06-25 11:22     ` Pantelis Antoniou
  0 siblings, 0 replies; 63+ messages in thread
From: Pantelis Antoniou @ 2014-06-25 11:22 UTC (permalink / raw)
  To: Grant Likely
  Cc: Rob Herring, Stephen Warren, Matt Porter, Koen Kooi,
	Greg Kroah-Hartman, Alison Chaiken, Dinh Nguyen, Jan Lubbe,
	Alexander Sverdlin, Michael Stickel, Guenter Roeck, Dirk Behme,
	Alan Tull, Sascha Hauer, Michael Bohan, Ionut Nicu, Michal Simek,
	Matt Ranostay, Joel Becker, devicetree, Wolfram Sang, linux-i2c,
	Mark Brown, linux-spi, linux-kernel, Pete Popov, Dan Malek,
	Georgi Vlaev

Hi Grant,

On Jun 25, 2014, at 2:14 PM, Grant Likely wrote:

> On Sun, 22 Jun 2014 12:40:38 +0300, Pantelis Antoniou <pantelis.antoniou@konsulko.com> wrote:
>> Introduce helper functions for working with the live DT tree,
>> all of them related to dynamically adding/removing nodes and
>> properties.
>> 
>> __of_copy_property() copies a property dynamically
>> __of_create_empty_node() creates an empty node
>> 
>> Bug fix about prop->len == 0 by Ionut Nicu <ioan.nicu.ext@nsn.com>
>> 
>> Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
> 
> So, despite our my earlier comments about wanting to reusing the
> pointers from unflattening the fdt, the addition of fine-grained flags
> just makes things worse. While I still think it would be best to
> directly modify and add the nodes that were created by unflattening
> instead of duplicating them, to do so requires rework of the full_name
> handling that I'm not going to ask you to do.
> 
> I won't hold things up on that point. It can be reworked later and you
> can drop the new flags and fine-grained tracking from this patch.
> 
> For next version, keep this patch in the same series as the patch
> actually using it.
> 

OK. For what is worth, it's easy enough to plonk a check about a zero
length property and substitute an empty string pointer.

I haven't realized there was such a big mess.

> More comments below...
> 
>> ---
>> drivers/of/Makefile |   2 +-
>> drivers/of/util.c   | 141 ++++++++++++++++++++++++++++++++++++++++++++++++++++
>> include/linux/of.h  |  42 ++++++++++++++++
> 
> Similar to the other patches, this will never get used by non-OF core
> code. Put the prototypes into of_private.h
> 

OK.

>> 3 files changed, 184 insertions(+), 1 deletion(-)
>> create mode 100644 drivers/of/util.c
>> 
>> diff --git a/drivers/of/Makefile b/drivers/of/Makefile
>> index 099b1fb..734d3e2 100644
>> --- a/drivers/of/Makefile
>> +++ b/drivers/of/Makefile
>> @@ -1,4 +1,4 @@
>> -obj-y = base.o device.o platform.o
>> +obj-y = base.o device.o platform.o util.o
> 
> obj-$(CONFIG_OF_DYNAMIC) perhaps? We won't use these for anything else.
> 

OK.

>> obj-$(CONFIG_OF_FLATTREE) += fdt.o
>> obj-$(CONFIG_OF_EARLY_FLATTREE) += fdt_address.o
>> obj-$(CONFIG_OF_PROMTREE) += pdt.o
>> diff --git a/drivers/of/util.c b/drivers/of/util.c
>> new file mode 100644
>> index 0000000..f4211f8
>> --- /dev/null
>> +++ b/drivers/of/util.c
>> @@ -0,0 +1,141 @@
>> +/*
>> + * Utility functions for working with device tree(s)
>> + *
>> + * Copyright (C) 2012 Pantelis Antoniou <panto@antoniou-consulting.com>
>> + * Copyright (C) 2012 Texas Instruments Inc.
>> + *
>> + * This program is free software; you can redistribute it and/or
>> + * modify it under the terms of the GNU General Public License
>> + * version 2 as published by the Free Software Foundation.
>> + */
>> +
>> +#include <linux/kernel.h>
>> +#include <linux/module.h>
>> +#include <linux/of.h>
>> +#include <linux/of_device.h>
>> +#include <linux/string.h>
>> +#include <linux/ctype.h>
>> +#include <linux/errno.h>
>> +#include <linux/string.h>
>> +#include <linux/slab.h>
>> +#include <linux/err.h>
>> +
>> +/**
>> + * __of_copy_property - Copy a property dynamically.
>> + * @prop:	Property to copy
>> + * @allocflags:	Allocation flags (typically pass GFP_KERNEL)
>> + * @propflags:	Property flags
>> + *
>> + * Copy a property by dynamically allocating the memory of both the
>> + * property stucture and the property name & contents. The property's
>> + * flags have the OF_DYNAMIC bit set so that we can differentiate between
>> + * dynamically allocated properties and not.
>> + * Returns the newly allocated property or NULL on out of memory error.
>> + */
>> +struct property *__of_copy_property(const struct property *prop,
>> +		gfp_t allocflags, unsigned long propflags)
> 
> of_property_dup()?
> 
> What is the reason for the double underscore prefix? There isn't a
> non-double-underscore version to differentiate between it, there is no
> locking involved at all, and __ isn't used to designate private
> functions.
> 

Double underscore prefix == function not meant to be used by drivers, only
by core OF code. The move of the prototype to the of_private.h will make this
point moot.

>> +{
>> +	struct property *propn;
>> +
>> +	propn = kzalloc(sizeof(*prop), allocflags);
>> +	if (propn == NULL)
> 
> Nit: I prefer 'if (!propn)' for pointer checks.
> 

OK.

>> +		return NULL;
>> +
>> +	propn->_flags = propflags;
>> +
>> +	if (of_property_check_flag(propn, OF_ALLOCNAME)) {
>> +		propn->name = kstrdup(prop->name, allocflags);
>> +		if (propn->name == NULL)
>> +			goto err_fail_name;
>> +	} else
>> +		propn->name = prop->name;
>> +
>> +	if (prop->length > 0) {
>> +		if (of_property_check_flag(propn, OF_ALLOCVALUE)) {
>> +			propn->value = kmalloc(prop->length, allocflags);
>> +			if (propn->value == NULL)
>> +				goto err_fail_value;
>> +			memcpy(propn->value, prop->value, prop->length);
>> +		} else
>> +			propn->value = prop->value;
>> +
>> +		propn->length = prop->length;
>> +	}
>> +
>> +	/* mark the property as dynamic */
>> +	of_property_set_flag(propn, OF_DYNAMIC);
>> +
>> +	return propn;
>> +
>> +err_fail_value:
>> +	if (of_property_check_flag(propn, OF_ALLOCNAME))
>> +		kfree(propn->name);
>> +err_fail_name:
>> +	kfree(propn);
>> +	return NULL;
>> +}
>> +
>> +/**
>> + * __of_create_empty_node - Create an empty device node dynamically.
>> + * @name:	Name of the new device node
>> + * @type:	Type of the new device node
>> + * @full_name:	Full name of the new device node
>> + * @phandle:	Phandle of the new device node
>> + * @allocflags:	Allocation flags (typically pass GFP_KERNEL)
>> + * @nodeflags:	Node flags
>> + *
>> + * Create an empty device tree node, suitable for further modification.
>> + * The node data are dynamically allocated and all the node flags
>> + * have the OF_DYNAMIC & OF_DETACHED bits set.
>> + * Returns the newly allocated node or NULL on out of memory error.
>> + */
>> +struct device_node *__of_create_empty_node(
>> +		const char *name, const char *type, const char *full_name,
>> +		phandle phandle, gfp_t allocflags, unsigned long nodeflags)
>> +{
>> +	struct device_node *node;
>> +
>> +	node = kzalloc(sizeof(*node), allocflags);
>> +	if (node == NULL)
>> +		return NULL;
>> +
>> +	node->_flags = nodeflags;
>> +
>> +	if (of_node_check_flag(node, OF_ALLOCNAME)) {
>> +		node->name = kstrdup(name, allocflags);
>> +		if (node->name == NULL)
>> +			goto err_free_node;
>> +	} else
>> +		node->name = name;
>> +
>> +	if (of_node_check_flag(node, OF_ALLOCTYPE)) {
>> +		node->type = kstrdup(type, allocflags);
>> +		if (node->type == NULL)
>> +			goto err_free_name;
>> +	} else
>> +		node->type = type;
>> +
>> +	if (of_node_check_flag(node, OF_ALLOCFULL)) {
>> +		node->full_name = kstrdup(full_name, allocflags);
>> +		if (node->full_name == NULL)
>> +			goto err_free_type;
>> +	} else
>> +		node->full_name = full_name;
>> +
>> +	node->phandle = phandle;
>> +	of_node_set_flag(node, OF_DYNAMIC);
>> +	of_node_set_flag(node, OF_DETACHED);
>> +
>> +	of_node_init(node);
>> +
>> +	return node;
>> +err_free_type:
>> +	if (of_node_check_flag(node, OF_ALLOCTYPE))
>> +		kfree(node->type);
>> +err_free_name:
>> +	if (of_node_check_flag(node, OF_ALLOCNAME))
>> +		kfree(node->name);
>> +err_free_node:
>> +	kfree(node);
>> +	return NULL;
>> +}
>> diff --git a/include/linux/of.h b/include/linux/of.h
>> index 5e4e1b3..d381eb5 100644
>> --- a/include/linux/of.h
>> +++ b/include/linux/of.h
>> @@ -211,6 +211,15 @@ static inline unsigned long of_read_ulong(const __be32 *cell, int size)
>> #define OF_DYNAMIC	1 /* node and properties were allocated via kmalloc */
>> #define OF_DETACHED	2 /* node has been detached from the device tree */
>> #define OF_POPULATED	3 /* device already created for the node */
>> +#define OF_ALLOCNAME	4 /* name was kmalloc-ed */
>> +#define OF_ALLOCTYPE	5 /* type was kmalloc-ed */
>> +#define OF_ALLOCFULL	6 /* full_name was kmalloc-ed */
>> +#define OF_ALLOCVALUE	7 /* value was kmalloc-ed */
>> +
>> +#define OF_NODE_ALLOCALL \
>> +	((1 << OF_ALLOCNAME) | (1 << OF_ALLOCTYPE) | (1 << OF_ALLOCFULL))
>> +#define OF_PROP_ALLOCALL \
>> +	((1 << OF_ALLOCNAME) | (1 << OF_ALLOCVALUE))
>> 
>> #define OF_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags)
>> #define OF_MARK_DYNAMIC(x) set_bit(OF_DYNAMIC, &x->_flags)
>> @@ -824,4 +833,37 @@ typedef void (*of_init_fn_1)(struct device_node *);
>> #define OF_DECLARE_2(table, name, compat, fn) \
>> 		_OF_DECLARE(table, name, compat, fn, of_init_fn_2)
>> 
>> +/**
>> + * General utilities for working with live trees.
>> + *
>> + * All functions with two leading underscores operate
>> + * without taking node references, so you either have to
>> + * own the devtree lock or work on detached trees only.
>> + */
>> +
>> +#ifdef CONFIG_OF
> 
> #ifdef CONFIG_OF_DYNAMIC perhaps? This will never get used for
> non-dynamic trees.
> 

OK.

>> +
>> +struct property *__of_copy_property(const struct property *prop,
>> +		gfp_t allocflags, unsigned long propflags);
>> +struct device_node *__of_create_empty_node(const char *name,
>> +		const char *type, const char *full_name,
>> +		phandle phandle, gfp_t allocflags, unsigned long nodeflags);
>> +
>> +#else /* !CONFIG_OF */
>> +
>> +static inline struct property *__of_copy_property(const struct property *prop,
>> +		gfp_t allocflags, unsigned long propflags)
>> +{
>> +	return NULL;
>> +}
>> +
>> +static inline struct device_node *__of_create_empty_node(const char *name,
>> +		const char *type, const char *full_name,
>> +		phandle phandle, gfp_t allocflags, unsigned long nodeflags)
>> +{
>> +	return NULL;
>> +}
> 
> There is absolutely no way these functions should ever get called by
> non-OF code. Don't tempt people to call them by adding empty versions.
> 

Heh, OK.

> g.

Regards

-- Pantelis

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

* Re: [PATCH 1/6] of: Do not free memory at of_node_release
  2014-06-24 20:23         ` Pantelis Antoniou
  2014-06-24 20:33           ` Guenter Roeck
@ 2014-06-25 19:24           ` Grant Likely
  1 sibling, 0 replies; 63+ messages in thread
From: Grant Likely @ 2014-06-25 19:24 UTC (permalink / raw)
  To: Pantelis Antoniou
  Cc: Rob Herring, Stephen Warren, Matt Porter, Koen Kooi,
	Greg Kroah-Hartman, Alison Chaiken, Dinh Nguyen, Jan Lubbe,
	Alexander Sverdlin, Michael Stickel, Guenter Roeck, Dirk Behme,
	Alan Tull, Sascha Hauer, Michael Bohan, Ionut Nicu, Michal Simek,
	Matt Ranostay, Joel Becker, devicetree, Wolfram Sang, linux-i2c,
	Mark Brown, linux-spi, linux-kernel, Pete Popov, Dan Malek,
	Georgi Vlaev

On Tue, 24 Jun 2014 23:23:35 +0300, Pantelis Antoniou <pantelis.antoniou@konsulko.com> wrote:
> Hi Grant,
> 
> On Jun 24, 2014, at 11:21 PM, Grant Likely wrote:
> 
> > On Tue, 24 Jun 2014 17:23:35 +0300, Pantelis Antoniou <pantelis.antoniou@konsulko.com> wrote:
> >> Hi Grant,
> >> 
> >> On Jun 24, 2014, at 5:10 PM, Grant Likely wrote:
> >> 
> >>> On Sun, 22 Jun 2014 12:40:34 +0300, Pantelis Antoniou <pantelis.antoniou@konsulko.com> wrote:
> >>>> The life-cycle of nodes and properties does not allow us to release
> >>>> the memory taken by a device_node. Pointer to properties and nodes
> >>>> might still be in use in drivers, so any memory free'ing is dangerous.
> >>>> 
> >>>> Simply move all the properties to the deadprops list, and the node
> >>>> itself to of_alldeadnodes until the life-cycles issues are resolved.
> >>> 
> >>> Ummm. this looks wrong. The release function is supposed to be the place
> >>> to do the freeing, and with our discussion the other day about moving to
> >>> rcu, but keeping of_node_get/put() for anything that needs to hold a
> >>> long term reference, that means the lifecycle issues are pretty much
> >>> resolved. I don't think this patch is necessary.
> >>> 
> >> 
> >> Well, I thought about it too. This is the culmination of that process :)
> >> 
> >> The problem is not the node life-cycle, it's the properties. We can't
> >> tell for sure who and where has a pointer to the properties of the node,
> >> and when we free the node, the current code iterates over the properties
> >> list and frees them. This works only because in my tests, of_node_release
> >> only gets called when using overlays created nodes.
> > 
> > If a caller want's to use the value of a property, then it needs to
> > of_node_get() the node. Property lifecycle is strictly attached to the
> > lifecycle of it's node.
> > 
> 
> Taking bets if that's always the case?

Any users that do are buggy. I don't want to change the lifecycle model.

That said, what I would consider merging a patch that makes a
configuration or runtime option to never free nodes or properties,
and/or clears the memory so we know if anyone tries to manipulate them.

g.

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

end of thread, other threads:[~2014-06-25 19:24 UTC | newest]

Thread overview: 63+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2014-06-22  9:40 [PATCH 0/6] OF: Fixes preparing transactions/overlays Pantelis Antoniou
2014-06-22  9:40 ` [PATCH 1/6] of: Do not free memory at of_node_release Pantelis Antoniou
2014-06-24 14:10   ` Grant Likely
2014-06-24 14:23     ` Pantelis Antoniou
2014-06-24 20:21       ` Grant Likely
2014-06-24 20:23         ` Pantelis Antoniou
2014-06-24 20:33           ` Guenter Roeck
2014-06-24 21:02             ` Pantelis Antoniou
2014-06-24 23:20               ` Guenter Roeck
2014-06-25 19:24           ` Grant Likely
2014-06-24 14:53     ` Guenter Roeck
2014-06-22  9:40 ` [PATCH 2/6] OF: Add [__]of_find_node_by_full_name Pantelis Antoniou
2014-06-23 17:58   ` Guenter Roeck
2014-06-23 18:00     ` Pantelis Antoniou
2014-06-24 13:55       ` Grant Likely
2014-06-24 13:55         ` Grant Likely
2014-06-24 13:55         ` Grant Likely
2014-06-24 14:12   ` Grant Likely
2014-06-24 14:23     ` Pantelis Antoniou
2014-06-22  9:40 ` [PATCH 3/6] of: platform: Fix and export of_platform_device_destroy Pantelis Antoniou
2014-06-24 14:23   ` Grant Likely
2014-06-24 15:13   ` Grant Likely
2014-06-22  9:40 ` [PATCH 4/6] OF: Export a number of __of_* methods Pantelis Antoniou
2014-06-24 19:27   ` Grant Likely
2014-06-24 19:38     ` Pantelis Antoniou
2014-06-24 20:19       ` Grant Likely
2014-06-22  9:40 ` [PATCH 5/6] OF: Utility helper functions for dynamic nodes Pantelis Antoniou
2014-06-23 16:26   ` Alexander Sverdlin
2014-06-23 16:26     ` Alexander Sverdlin
2014-06-23 16:26     ` Alexander Sverdlin
2014-06-23 16:57     ` Pantelis Antoniou
2014-06-23 18:33       ` Ioan Nicu
2014-06-23 19:13         ` Pantelis Antoniou
2014-06-23 19:48           ` Guenter Roeck
2014-06-23 19:48             ` Guenter Roeck
2014-06-23 19:48             ` Guenter Roeck
2014-06-23 20:39             ` Ioan Nicu
2014-06-24  9:08             ` Pantelis Antoniou
2014-06-24 13:46               ` Rob Herring
2014-06-24 13:53                 ` Alexander Sverdlin
2014-06-24 14:49                   ` Rob Herring
2014-06-24 15:43                     ` Alexander Sverdlin
2014-06-24 15:59                       ` Pantelis Antoniou
2014-06-24 18:23                         ` Ioan Nicu
2014-06-24 18:31                           ` Ioan Nicu
2014-06-24 18:43                           ` Pantelis Antoniou
2014-06-24  8:12           ` Alexander Sverdlin
2014-06-24  8:12             ` Alexander Sverdlin
2014-06-24  8:12             ` Alexander Sverdlin
2014-06-24  8:19             ` Pantelis Antoniou
2014-06-24  8:38               ` Alexander Sverdlin
2014-06-24  8:54                 ` Pantelis Antoniou
2014-06-24  9:00                   ` Alexander Sverdlin
2014-06-24  9:09                     ` Pantelis Antoniou
2014-06-24  8:10         ` Alexander Sverdlin
2014-06-24  8:10           ` Alexander Sverdlin
2014-06-24  8:10           ` Alexander Sverdlin
2014-06-25  9:09           ` Grant Likely
2014-06-25  9:09             ` Grant Likely
2014-06-25  9:09             ` Grant Likely
2014-06-25 11:14   ` Grant Likely
2014-06-25 11:22     ` Pantelis Antoniou
2014-06-22  9:40 ` [PATCH 6/6] of: Introduce tree change __foo_post methods Pantelis Antoniou

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.