Skip to contentSkip to conversation

powerpc/pseries: bug fix and clean up

PATCH In review Andy Shevchenko 3 participants 8 messages Oct 1, 2015 – Oct 12, 2015 PowerPC

lore
Share & tools
lore
#0 lore raw

v3 cover powerpc/pseries: bug fix and clean up

Changelog v2:
- fix compiler error
- rebase on top of recent linux-next
- compile tested

Andy Shevchenko (5):
powerpc/pseries: extract of_helpers module powerpc/pseries: fix a potential memory leak powerpc/pseries: replace kmalloc + strlcpy powerpc/pseries: handle nodes without '/' powerpc/pseries: re-use code from of_helpers module

 arch/powerpc/platforms/pseries/Makefile     |  1 +
 arch/powerpc/platforms/pseries/dlpar.c      | 31 +++++--------------------
 arch/powerpc/platforms/pseries/of_helpers.c | 35 +++++++++++++++++++++++++++++
 arch/powerpc/platforms/pseries/of_helpers.h |  8 +++++++
 arch/powerpc/platforms/pseries/reconfig.c   | 34 ++--------------------------
 5 files changed, 51 insertions(+), 58 deletions(-)
 create mode 100644 arch/powerpc/platforms/pseries/of_helpers.c
 create mode 100644 arch/powerpc/platforms/pseries/of_helpers.h
Signature · 1 line
2.5.1
#1 lore raw

PATCH v3 1/5 powerpc/pseries: extract of_helpers module

Extract a new module to share the code between other modules.

There is no functional change.

---
 arch/powerpc/platforms/pseries/Makefile     |  1 +
 arch/powerpc/platforms/pseries/of_helpers.c | 38 +++++++++++++++++++++++++++++
 arch/powerpc/platforms/pseries/of_helpers.h |  8 ++++++
 arch/powerpc/platforms/pseries/reconfig.c   | 34 ++------------------------
 4 files changed, 49 insertions(+), 32 deletions(-)
 create mode 100644 arch/powerpc/platforms/pseries/of_helpers.c
 create mode 100644 arch/powerpc/platforms/pseries/of_helpers.h
arch/powerpc/platforms/pseries/Makefile +1 -0
index 0348079..2e857c2 100644
@@ -2,6 +2,7 @@ ccflags-$(CONFIG_PPC64)			:= $(NO_MINIMAL_TOC)
 ccflags-$(CONFIG_PPC_PSERIES_DEBUG)	+= -DDEBUG
 
 obj-y			:= lpar.o hvCall.o nvram.o reconfig.o \
+			   of_helpers.o \
 			   setup.o iommu.o event_sources.o ras.o \
 			   firmware.o power.o dlpar.o mobility.o rng.o
 obj-$(CONFIG_SMP)	+= smp.o
arch/powerpc/platforms/pseries/of_helpers.c new file +38 -0
new file mode 100644
index 0000000..1cbd896
@@ -0,0 +1,38 @@
+#include <linux/string.h>
+#include <linux/err.h>
+#include <linux/slab.h>
+#include <linux/of.h>
+
+#include "of_helpers.h"
+
+/**
+ * pseries_of_derive_parent - basically like dirname(1)
+ * @path:  the full_name of a node to be added to the tree
+ *
+ * Returns the node which should be the parent of the node
+ * described by path.  E.g., for path = "/foo/bar", returns
+ * the node with full_name = "/foo".
+ */
+struct device_node *pseries_of_derive_parent(const char *path)
+{
+	struct device_node *parent = NULL;
+	char *parent_path = "/";
+	size_t parent_path_len = strrchr(path, '/') - path + 1;
+
+	/* reject if path is "/" */
+	if (!strcmp(path, "/"))
+		return ERR_PTR(-EINVAL);
+
+	if (strrchr(path, '/') != path) {
+		parent_path = kmalloc(parent_path_len, GFP_KERNEL);
+		if (!parent_path)
+			return ERR_PTR(-ENOMEM);
+		strlcpy(parent_path, path, parent_path_len);
+	}
+	parent = of_find_node_by_path(parent_path);
+	if (!parent)
+		return ERR_PTR(-EINVAL);
+	if (strcmp(parent_path, "/"))
+		kfree(parent_path);
+	return parent;
+}
arch/powerpc/platforms/pseries/of_helpers.h new file +8 -0
new file mode 100644
index 0000000..bb83d39
@@ -0,0 +1,8 @@
+#ifndef _PSERIES_OF_HELPERS_H
+#define _PSERIES_OF_HELPERS_H
+
+#include <linux/of.h>
+
+struct device_node *pseries_of_derive_parent(const char *path);
+
+#endif /* _PSERIES_OF_HELPERS_H */
arch/powerpc/platforms/pseries/reconfig.c +2 -32
index 0f31952..7c7fcc0 100644
@@ -22,37 +22,7 @@
 #include <asm/uaccess.h>
 #include <asm/mmu.h>
 
-/**
- *	derive_parent - basically like dirname(1)
- *	@path:  the full_name of a node to be added to the tree
- *
- *	Returns the node which should be the parent of the node
- *	described by path.  E.g., for path = "/foo/bar", returns
- *	the node with full_name = "/foo".
- */
-static struct device_node *derive_parent(const char *path)
-{
-	struct device_node *parent = NULL;
-	char *parent_path = "/";
-	size_t parent_path_len = strrchr(path, '/') - path + 1;
-
-	/* reject if path is "/" */
-	if (!strcmp(path, "/"))
-		return ERR_PTR(-EINVAL);
-
-	if (strrchr(path, '/') != path) {
-		parent_path = kmalloc(parent_path_len, GFP_KERNEL);
-		if (!parent_path)
-			return ERR_PTR(-ENOMEM);
-		strlcpy(parent_path, path, parent_path_len);
-	}
-	parent = of_find_node_by_path(parent_path);
-	if (!parent)
-		return ERR_PTR(-EINVAL);
-	if (strcmp(parent_path, "/"))
-		kfree(parent_path);
-	return parent;
-}
+#include "of_helpers.h"
 
 static int pSeries_reconfig_add_node(const char *path, struct property *proplist)
 {
@@ -71,7 +41,7 @@ static int pSeries_reconfig_add_node(const char *path, struct property *proplist
 	of_node_set_flag(np, OF_DYNAMIC);
 	of_node_init(np);
 
-	np->parent = derive_parent(path);
+	np->parent = pseries_of_derive_parent(path);
 	if (IS_ERR(np->parent)) {
 		err = PTR_ERR(np->parent);
 		goto out_err;
Signature · 1 line
2.5.1
#3 lore raw

PATCH v3 2/5 powerpc/pseries: fix a potential memory leak

In reply to Andy Shevchenko

In case we have a full node name like /foo/bar and /foo is not found the parent_path left unfreed. So, free a memory before return to a caller.

---
 arch/powerpc/platforms/pseries/of_helpers.c | 6 ++----
 1 file changed, 2 insertions(+), 4 deletions(-)
arch/powerpc/platforms/pseries/of_helpers.c +2 -4
index 1cbd896..2f363e3 100644
@@ -15,7 +15,7 @@
  */
 struct device_node *pseries_of_derive_parent(const char *path)
 {
-	struct device_node *parent = NULL;
+	struct device_node *parent;
 	char *parent_path = "/";
 	size_t parent_path_len = strrchr(path, '/') - path + 1;
 
@@ -30,9 +30,7 @@ struct device_node *pseries_of_derive_parent(const char *path)
 		strlcpy(parent_path, path, parent_path_len);
 	}
 	parent = of_find_node_by_path(parent_path);
-	if (!parent)
-		return ERR_PTR(-EINVAL);
 	if (strcmp(parent_path, "/"))
 		kfree(parent_path);
-	return parent;
+	return parent ? parent : ERR_PTR(-EINVAL);
 }
Signature · 1 line
2.5.1
#4 lore raw

PATCH v3 3/5 powerpc/pseries: replace kmalloc + strlcpy

In reply to Andy Shevchenko

The helper kstrndup() will do the same in one line.

---
 arch/powerpc/platforms/pseries/of_helpers.c | 3 +--
 1 file changed, 1 insertion(+), 2 deletions(-)
arch/powerpc/platforms/pseries/of_helpers.c +1 -2
index 2f363e3..8c6b05a 100644
@@ -24,10 +24,9 @@ struct device_node *pseries_of_derive_parent(const char *path)
 		return ERR_PTR(-EINVAL);
 
 	if (strrchr(path, '/') != path) {
-		parent_path = kmalloc(parent_path_len, GFP_KERNEL);
+		parent_path = kstrndup(path, parent_path_len, GFP_KERNEL);
 		if (!parent_path)
 			return ERR_PTR(-ENOMEM);
-		strlcpy(parent_path, path, parent_path_len);
 	}
 	parent = of_find_node_by_path(parent_path);
 	if (strcmp(parent_path, "/"))
Signature · 1 line
2.5.1
#5 lore raw

PATCH v3 4/5 powerpc/pseries: handle nodes without '/'

In reply to Andy Shevchenko

In case we have node without '/' strrchr() returns NULL which might lead to crash. Replace strrchr() by kbasename() and modify condition to avoid such behaviour.

---
 arch/powerpc/platforms/pseries/of_helpers.c | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)
arch/powerpc/platforms/pseries/of_helpers.c +3 -3
index 8c6b05a..4417afe 100644
@@ -17,14 +17,14 @@ struct device_node *pseries_of_derive_parent(const char *path)
 {
 	struct device_node *parent;
 	char *parent_path = "/";
-	size_t parent_path_len = strrchr(path, '/') - path + 1;
+	const char *tail = kbasename(path);
 
 	/* reject if path is "/" */
 	if (!strcmp(path, "/"))
 		return ERR_PTR(-EINVAL);
 
-	if (strrchr(path, '/') != path) {
-		parent_path = kstrndup(path, parent_path_len, GFP_KERNEL);
+	if (tail > path + 1) {
+		parent_path = kstrndup(path, tail - path, GFP_KERNEL);
 		if (!parent_path)
 			return ERR_PTR(-ENOMEM);
 	}
Signature · 1 line
2.5.1
#6 lore raw

PATCH v3 5/5 powerpc/pseries: re-use code from of_helpers module

In reply to Andy Shevchenko

The derive_parent() has similar semantics to what we have in newly introduced of_helpers module. The replacement reduces code base and propagates the actual error code to the caller.

---
 arch/powerpc/platforms/pseries/dlpar.c | 31 +++++--------------------------
 1 file changed, 5 insertions(+), 26 deletions(-)
arch/powerpc/platforms/pseries/dlpar.c +5 -26
index db17827..f244dcb 100644
@@ -18,6 +18,8 @@
 #include <linux/cpu.h>
 #include <linux/slab.h>
 #include <linux/of.h>
+
+#include "of_helpers.h"
 #include "offline_states.h"
 #include "pseries.h"
 
@@ -244,36 +246,13 @@ cc_error:
 	return first_dn;
 }
 
-static struct device_node *derive_parent(const char *path)
-{
-	struct device_node *parent;
-	char *last_slash;
-
-	last_slash = strrchr(path, '/');
-	if (last_slash == path) {
-		parent = of_find_node_by_path("/");
-	} else {
-		char *parent_path;
-		int parent_path_len = last_slash - path + 1;
-		parent_path = kmalloc(parent_path_len, GFP_KERNEL);
-		if (!parent_path)
-			return NULL;
-
-		strlcpy(parent_path, path, parent_path_len);
-		parent = of_find_node_by_path(parent_path);
-		kfree(parent_path);
-	}
-
-	return parent;
-}
-
 int dlpar_attach_node(struct device_node *dn)
 {
 	int rc;
 
-	dn->parent = derive_parent(dn->full_name);
-	if (!dn->parent)
-		return -ENOMEM;
+	dn->parent = pseries_of_derive_parent(dn->full_name);
+	if (IS_ERR(dn->parent))
+		return PTR_ERR(dn->parent);
 
 	rc = of_attach_node(dn);
 	if (rc) {
Signature · 1 line
2.5.1
Tested-by on the v3 series
#7 lore raw
In reply to Andy Shevchenko
Quoted 11 lines · Andy Shevchenko

Changelog v2:
- fix compiler error
- rebase on top of recent linux-next
- compile tested

Andy Shevchenko (5):
powerpc/pseries: extract of_helpers module powerpc/pseries: fix a potential memory leak powerpc/pseries: replace kmalloc + strlcpy powerpc/pseries: handle nodes without '/' powerpc/pseries: re-use code from of_helpers module

Ok, looks like it's working for me.

Quoted 16 lines
 arch/powerpc/platforms/pseries/Makefile     |  1 +
 arch/powerpc/platforms/pseries/dlpar.c      | 31 +++++--------------------
 arch/powerpc/platforms/pseries/of_helpers.c | 35
+++++++++++++++++++++++++++++
 arch/powerpc/platforms/pseries/of_helpers.h |  8 +++++++
 arch/powerpc/platforms/pseries/reconfig.c   | 34
++--------------------------
 5 files changed, 51 insertions(+), 58 deletions(-)
 create mode 100644 arch/powerpc/platforms/pseries/of_helpers.c
 create mode 100644 arch/powerpc/platforms/pseries/of_helpers.h

--
2.5.1