[RFC PATCH 0/5] Merge common dynamic OF device tree code

STALE6113d

4 messages, 1 author, 2009-11-04 · open the first message on its own page

[RFC PATCH 0/5] Merge common dynamic OF device tree code

From: Nathan Fontenot <hidden>
Date: 2009-11-04 22:07:37

This is a follow on to Grant Likely's patches, attempting to merge the common
pieces of dynamic OF device tree updating.  These patches move the common
code for adding and removing nodes and properties from the device tree to
drivers/of/of_dynamic.c and wraps them under the new OF_DYNAMIC config
option.  Additionally this makes the necessary updates to powerpc and
microblaze arch's for this move.

Nathan Fontenot (5)
	- Move the declaration of devtree_lock and allnodes to linux/of.h
	- Create drivers/of/of_dynamic.c from common code.
	- powerpc and pseries updates
	- microblaze updates
	- powerpc/iseries updates

[RFC PATCH 2/5] Merge dynamic OF code to of_dynamic.c

From: Nathan Fontenot <hidden>
Date: 2009-11-04 22:16:38

Creation of the OF dynamic device tree update code in drivers/of.  This
merges the common device tree updating routines to add/remove nodes and
properties from powerpc and microblaze.  All of the new code is conditional
based on a new OF_DYNAMIC config option.

There are two updates to the code.  First, the routines to update properties
are re-named from prom_* to of_*.  This seems correct as the routines no longer
reside in prom.c files.  Second, the addition of a notifier chain for when
nodes are added removed from the device tree.  This is a feature that currently
exists in powerpc.

Signed-off-by: Nathan Fontenot <redacted>
---

Index: linux-next/drivers/of/of_dynamic.c
===================================================================
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-next/drivers/of/of_dynamic.c	2009-11-04 14:45:11.000000000 -0600
@@ -0,0 +1,387 @@
+/*
+ * Definitions for talking to the Open Firmware PROM on
+ * Power Macintosh and other computers.
+ *
+ * Copyright (C) 1996-2005 Paul Mackerras.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version
+ * 2 of the License, or (at your option) any later version.
+ */
+
+#include <linux/of.h>
+
+BLOCKING_NOTIFIER_HEAD(of_update_chain);
+
+/**
+ *	of_node_get - Increment refcount of a node
+ *	@node:	Node to inc refcount, NULL is supported to
+ *		simplify writing of callers
+ *
+ *	Returns node.
+ */
+struct device_node *of_node_get(struct device_node *node)
+{
+	if (node)
+		kref_get(&node->kref);
+	return node;
+}
+EXPORT_SYMBOL(of_node_get);
+
+static inline struct device_node *kref_to_device_node(struct kref *kref)
+{
+	return container_of(kref, struct device_node, kref);
+}
+
+/**
+ *	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.
+ */
+static void of_node_release(struct kref *kref)
+{
+	struct device_node *node = kref_to_device_node(kref);
+	struct property *prop = node->properties;
+
+	/* We should never be releasing nodes that haven't been detached. */
+	if (!of_node_check_flag(node, OF_DETACHED)) {
+		printk(KERN_WARNING "Bad of_node_put() on %s\n",
+		       node->full_name);
+		dump_stack();
+		kref_init(&node->kref);
+		return;
+	}
+
+	if (!of_node_check_flag(node, OF_DYNAMIC))
+		return;
+
+	while (prop) {
+		struct property *next = prop->next;
+		kfree(prop->name);
+		kfree(prop->value);
+		kfree(prop);
+		prop = next;
+
+		if (!prop) {
+			prop = node->deadprops;
+			node->deadprops = NULL;
+		}
+	}
+	kfree(node->full_name);
+	kfree(node->data);
+	kfree(node);
+}
+
+/**
+ *	of_node_put - Decrement refcount of a node
+ *	@node:	Node to dec refcount, NULL is supported to
+ *		simplify writing of callers
+ *
+ */
+void of_node_put(struct device_node *node)
+{
+	if (node)
+		kref_put(&node->kref, of_node_release);
+}
+EXPORT_SYMBOL(of_node_put);
+
+static struct device_node *of_derive_parent(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;
+}
+
+static int of_attach_one_node(struct device_node *np)
+{
+	struct proc_dir_entry *ent;
+	unsigned long flags;
+	int rc;
+
+	of_node_set_flag(np, OF_DYNAMIC);
+	kref_init(&np->kref);
+
+	np->parent = of_derive_parent(np->full_name);
+	if (IS_ERR(np->parent))
+		return PTR_ERR(np->parent);
+
+	rc = of_update_notifier_call(OF_ATTACH_NODE, np);
+	if (rc == NOTIFY_BAD) {
+		printk(KERN_ERR "Failed to add device node %s\n",
+		       np->full_name);
+		return -ENOMEM;  /* For now, safe to assume kmalloc failure */
+	}
+
+	write_lock_irqsave(&devtree_lock, flags);
+	np->sibling = np->parent->child;
+	np->allnext = allnodes;
+	np->parent->child = np;
+
+	allnodes = np;
+	write_unlock_irqrestore(&devtree_lock, flags);
+
+#ifdef CONFIG_PROC_DEVICETREE
+	ent = proc_mkdir(strrchr(np->full_name, '/') + 1, np->parent->pde);
+	if (ent)
+		proc_device_tree_add_node(np, ent);
+#endif
+
+	of_node_put(np->parent);
+	return 0;
+}
+
+int of_attach_node(struct device_node *np)
+{
+	struct device_node *child = np->child;
+	struct device_node *sibling = np->sibling;
+	int rc;
+
+	np->child = NULL;
+	np->sibling = NULL;
+	np->parent = NULL;
+
+	rc = of_attach_one_node(np);
+	if (rc)
+		return rc;
+
+	if (child) {
+		rc = of_attach_node(child);
+		if (rc)
+			return rc;
+	}
+
+	if (sibling)
+		rc = of_attach_node(sibling);
+
+	return rc;
+}
+EXPORT_SYMBOL(of_attach_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.
+ */
+static int of_detach_one_node(struct device_node *np)
+{
+	struct device_node *parent = np->parent;
+	struct property *prop = np->properties;
+	unsigned long flags;
+
+	if (!parent)
+		return -1;
+
+#ifdef CONFIG_PROC_DEVICETREE
+	while (prop) {
+		remove_proc_entry(prop->name, np->pde);
+		prop = prop->next;
+	}
+
+	if (np->pde)
+		remove_proc_entry(np->pde->name, parent->pde);
+#endif
+
+	of_update_notifier_call(OF_DETACH_NODE, np);
+
+	write_lock_irqsave(&devtree_lock, flags);
+
+	if (allnodes == np)
+		allnodes = np->allnext;
+	else {
+		struct device_node *prev;
+		for (prev = allnodes;
+		     prev->allnext != np;
+		     prev = prev->allnext)
+			;
+		prev->allnext = np->allnext;
+	}
+
+	if (parent->child == np)
+		parent->child = np->sibling;
+	else {
+		struct device_node *prevsib;
+		for (prevsib = np->parent->child;
+		     prevsib->sibling != np;
+		     prevsib = prevsib->sibling)
+			;
+		prevsib->sibling = np->sibling;
+	}
+
+	of_node_set_flag(np, OF_DETACHED);
+	write_unlock_irqrestore(&devtree_lock, flags);
+	of_node_put(np);
+	return 0;
+}
+
+static int _of_detach_node(struct device_node *np)
+{
+	int rc;
+
+	if (np->child) {
+		rc = _of_detach_node(np->child);
+		if (rc)
+			return rc;
+	}
+
+	if (np->sibling) {
+		rc = _of_detach_node(np->sibling);
+		if (rc)
+			return rc;
+	}
+
+	rc = of_detach_one_node(np);
+	return rc;
+}
+
+int of_detach_node(struct device_node *np)
+{
+	int rc;
+
+	if (np->child) {
+		rc = _of_detach_node(np->child);
+		if (rc)
+			return rc;
+	}
+
+	rc = of_detach_one_node(np);
+	return rc;
+}
+EXPORT_SYMBOL(of_detach_node);
+
+/*
+ * Add a property to a node
+ */
+int of_property_attach(struct device_node *np, struct property* prop)
+{
+	struct property **next;
+	unsigned long flags;
+
+	prop->next = NULL;
+
+	write_lock_irqsave(&devtree_lock, flags);
+	next = &np->properties;
+	while (*next) {
+		if (strcmp(prop->name, (*next)->name) == 0) {
+			/* duplicate ! don't insert it */
+			write_unlock_irqrestore(&devtree_lock, flags);
+			return -1;
+		}
+		next = &(*next)->next;
+	}
+	*next = prop;
+	write_unlock_irqrestore(&devtree_lock, flags);
+
+#ifdef CONFIG_PROC_DEVICETREE
+	/* try to add to proc as well if it was initialized */
+	if (np->pde)
+		proc_device_tree_add_prop(np->pde, prop);
+#endif /* CONFIG_PROC_DEVICETREE */
+
+	return 0;
+}
+EXPORT_SYMBOL(of_property_attach);
+
+/*
+ * Remove a property from a node.  Note that we don't actually
+ * remove it, since we have given out who-knows-how-many pointers
+ * to the data using get-property.  Instead we just move the property
+ * to the "dead properties" list, so it won't be found any more.
+ */
+int of_property_detach(struct device_node *np, struct property *prop)
+{
+	struct property **next;
+	unsigned long flags;
+	int found = 0;
+
+	write_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;
+	}
+	write_unlock_irqrestore(&devtree_lock, flags);
+
+	if (!found)
+		return -ENODEV;
+
+#ifdef CONFIG_PROC_DEVICETREE
+	/* try to remove the proc node as well */
+	if (np->pde)
+		proc_device_tree_remove_prop(np->pde, prop);
+#endif /* CONFIG_PROC_DEVICETREE */
+
+	return 0;
+}
+EXPORT_SYMBOL(of_property_detach);
+
+/*
+ * Update a property in a node.  Note that we don't actually
+ * remove it, since we have given out who-knows-how-many pointers
+ * to the data using get-property.  Instead we just move the property
+ * to the "dead properties" list, and add the new property to the
+ * property list
+ */
+int of_property_update(struct device_node *np, struct property *newprop,
+		       struct property *oldprop)
+{
+	struct property **next;
+	unsigned long flags;
+	int found = 0;
+
+	write_lock_irqsave(&devtree_lock, flags);
+	next = &np->properties;
+	while (*next) {
+		if (*next == oldprop) {
+			/* found the node */
+			newprop->next = oldprop->next;
+			*next = newprop;
+			oldprop->next = np->deadprops;
+			np->deadprops = oldprop;
+			found = 1;
+			break;
+		}
+		next = &(*next)->next;
+	}
+	write_unlock_irqrestore(&devtree_lock, flags);
+
+	if (!found)
+		return -ENODEV;
+
+#ifdef CONFIG_PROC_DEVICETREE
+	/* try to add to proc as well if it was initialized */
+	if (np->pde)
+		proc_device_tree_update_prop(np->pde, newprop, oldprop);
+#endif /* CONFIG_PROC_DEVICETREE */
+
+	return 0;
+}
+EXPORT_SYMBOL(of_property_update);
Index: linux-next/include/linux/of.h
===================================================================
--- linux-next.orig/include/linux/of.h	2009-11-03 11:18:08.000000000 -0600
+++ linux-next/include/linux/of.h	2009-11-03 13:42:38.000000000 -0600
@@ -20,6 +20,8 @@
 #include <linux/kref.h>
 #include <linux/mod_devicetable.h>
 #include <linux/spinlock.h>
+#include <linux/proc_fs.h>
+#include <linux/notifier.h>
 
 typedef u32 phandle;
 typedef u32 ihandle;
@@ -191,4 +193,34 @@
 	const char *list_name, const char *cells_name, int index,
 	struct device_node **out_node, const void **out_args);
 
+#ifdef CONFIG_OF_DYNAMIC
+extern int of_attach_node(struct device_node *np);
+extern int of_detach_node(struct device_node *np);
+extern int of_property_attach(struct device_node *np, struct property *prop);
+extern int of_property_detach(struct device_node *np, struct property *prop);
+extern int of_property_update(struct device_node *np, struct property *newprop,
+			      struct property *oldprop);
+
+/* Dynamic Update Notifier Chain */
+extern struct blocking_notifier_head of_update_chain;
+
+#define OF_ATTACH_NODE		1
+#define OF_DETACH_NODE		2
+
+static inline int of_update_notifier_register(struct notifier_block *nb)
+{
+	return blocking_notifier_chain_register(&of_update_chain, nb);
+}
+
+static inline int of_update_notifier_unregister(struct notifier_block *nb)
+{
+	return blocking_notifier_chain_unregister(&of_update_chain, nb);
+}
+
+static inline int of_update_notifier_call(unsigned int value, void *data)
+{
+	return blocking_notifier_call_chain(&of_update_chain, value, data);
+}
+#endif /* CONFIG_OF_DYNAMIC */
+
 #endif /* _LINUX_OF_H */
Index: linux-next/drivers/of/Makefile
===================================================================
--- linux-next.orig/drivers/of/Makefile	2009-11-03 11:18:08.000000000 -0600
+++ linux-next/drivers/of/Makefile	2009-11-03 13:42:35.000000000 -0600
@@ -1,6 +1,7 @@
 obj-y = base.o
-obj-$(CONFIG_OF_DEVICE) += device.o platform.o
-obj-$(CONFIG_OF_GPIO)   += gpio.o
-obj-$(CONFIG_OF_I2C)	+= of_i2c.o
-obj-$(CONFIG_OF_SPI)	+= of_spi.o
-obj-$(CONFIG_OF_MDIO)	+= of_mdio.o
+obj-$(CONFIG_OF_DEVICE)		+= device.o platform.o
+obj-$(CONFIG_OF_GPIO)		+= gpio.o
+obj-$(CONFIG_OF_I2C)		+= of_i2c.o
+obj-$(CONFIG_OF_SPI)		+= of_spi.o
+obj-$(CONFIG_OF_MDIO)		+= of_mdio.o
+obj-$(CONFIG_OF_DYNAMIC)	+= of_dynamic.o

[RFC PATCH 3/5] powerpc and pseries updates for new OF dynamic code

From: Nathan Fontenot <hidden>
Date: 2009-11-04 22:18:35

Updates to powerpc generic and powerpc/pseries.  This patch removes the
dynamic device tree updating code from prom.c and deletes the no longer
neccessary pSeries_reconfig.h file,  all of the functionality is now in the
generic OF code.

The remaining changes deal with updating code for name changes with using
the OF code.

Signed-off-by: Nathan Fonteot <redacted>
---

Index: linux-next/arch/powerpc/include/asm/pSeries_reconfig.h
===================================================================
--- linux-next.orig/arch/powerpc/include/asm/pSeries_reconfig.h	2009-11-04 14:42:17.000000000 -0600
+++ /dev/null	1970-01-01 00:00:00.000000000 +0000
@@ -1,29 +0,0 @@
-#ifndef _PPC64_PSERIES_RECONFIG_H
-#define _PPC64_PSERIES_RECONFIG_H
-#ifdef __KERNEL__
-
-#include <linux/notifier.h>
-
-/*
- * Use this API if your code needs to know about OF device nodes being
- * added or removed on pSeries systems.
- */
-
-#define PSERIES_RECONFIG_ADD		0x0001
-#define PSERIES_RECONFIG_REMOVE		0x0002
-#define PSERIES_DRCONF_MEM_ADD		0x0003
-#define PSERIES_DRCONF_MEM_REMOVE	0x0004
-
-#ifdef CONFIG_PPC_PSERIES
-extern int pSeries_reconfig_notifier_register(struct notifier_block *);
-extern void pSeries_reconfig_notifier_unregister(struct notifier_block *);
-#else /* !CONFIG_PPC_PSERIES */
-static inline int pSeries_reconfig_notifier_register(struct notifier_block *nb)
-{
-	return 0;
-}
-static inline void pSeries_reconfig_notifier_unregister(struct notifier_block *nb) { }
-#endif /* CONFIG_PPC_PSERIES */
-
-#endif /* __KERNEL__ */
-#endif /* _PPC64_PSERIES_RECONFIG_H */
Index: linux-next/arch/powerpc/kernel/prom.c
===================================================================
--- linux-next.orig/arch/powerpc/kernel/prom.c	2009-11-04 14:42:17.000000000 -0600
+++ linux-next/arch/powerpc/kernel/prom.c	2009-11-04 14:45:43.000000000 -0600
@@ -50,7 +50,6 @@
 #include <asm/btext.h>
 #include <asm/sections.h>
 #include <asm/machdep.h>
-#include <asm/pSeries_reconfig.h>
 #include <asm/pci-bridge.h>
 #include <asm/phyp_dump.h>
 #include <asm/kexec.h>
@@ -1313,138 +1312,6 @@
 	return NULL;
 }
 
-/**
- *	of_node_get - Increment refcount of a node
- *	@node:	Node to inc refcount, NULL is supported to
- *		simplify writing of callers
- *
- *	Returns node.
- */
-struct device_node *of_node_get(struct device_node *node)
-{
-	if (node)
-		kref_get(&node->kref);
-	return node;
-}
-EXPORT_SYMBOL(of_node_get);
-
-static inline struct device_node * kref_to_device_node(struct kref *kref)
-{
-	return container_of(kref, struct device_node, kref);
-}
-
-/**
- *	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.
- */
-static void of_node_release(struct kref *kref)
-{
-	struct device_node *node = kref_to_device_node(kref);
-	struct property *prop = node->properties;
-
-	/* We should never be releasing nodes that haven't been detached. */
-	if (!of_node_check_flag(node, OF_DETACHED)) {
-		printk("WARNING: Bad of_node_put() on %s\n", node->full_name);
-		dump_stack();
-		kref_init(&node->kref);
-		return;
-	}
-
-	if (!of_node_check_flag(node, OF_DYNAMIC))
-		return;
-
-	while (prop) {
-		struct property *next = prop->next;
-		kfree(prop->name);
-		kfree(prop->value);
-		kfree(prop);
-		prop = next;
-
-		if (!prop) {
-			prop = node->deadprops;
-			node->deadprops = NULL;
-		}
-	}
-	kfree(node->full_name);
-	kfree(node->data);
-	kfree(node);
-}
-
-/**
- *	of_node_put - Decrement refcount of a node
- *	@node:	Node to dec refcount, NULL is supported to
- *		simplify writing of callers
- *
- */
-void of_node_put(struct device_node *node)
-{
-	if (node)
-		kref_put(&node->kref, of_node_release);
-}
-EXPORT_SYMBOL(of_node_put);
-
-/*
- * Plug a device node into the tree and global list.
- */
-void of_attach_node(struct device_node *np)
-{
-	unsigned long flags;
-
-	write_lock_irqsave(&devtree_lock, flags);
-	np->sibling = np->parent->child;
-	np->allnext = allnodes;
-	np->parent->child = np;
-	allnodes = np;
-	write_unlock_irqrestore(&devtree_lock, flags);
-}
-
-/*
- * "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.
- */
-void of_detach_node(struct device_node *np)
-{
-	struct device_node *parent;
-	unsigned long flags;
-
-	write_lock_irqsave(&devtree_lock, flags);
-
-	parent = np->parent;
-	if (!parent)
-		goto out_unlock;
-
-	if (allnodes == np)
-		allnodes = np->allnext;
-	else {
-		struct device_node *prev;
-		for (prev = allnodes;
-		     prev->allnext != np;
-		     prev = prev->allnext)
-			;
-		prev->allnext = np->allnext;
-	}
-
-	if (parent->child == np)
-		parent->child = np->sibling;
-	else {
-		struct device_node *prevsib;
-		for (prevsib = np->parent->child;
-		     prevsib->sibling != np;
-		     prevsib = prevsib->sibling)
-			;
-		prevsib->sibling = np->sibling;
-	}
-
-	of_node_set_flag(np, OF_DETACHED);
-
-out_unlock:
-	write_unlock_irqrestore(&devtree_lock, flags);
-}
-
 #ifdef CONFIG_PPC_PSERIES
 /*
  * Fix up the uninitialized fields in a new device node:
@@ -1491,7 +1358,7 @@
 	int err;
 
 	switch (action) {
-	case PSERIES_RECONFIG_ADD:
+	case OF_ATTACH_NODE:
 		err = of_finish_dynamic_node(node);
 		if (err < 0) {
 			printk(KERN_ERR "finish_node returned %d\n", err);
@@ -1512,125 +1379,11 @@
 
 static int __init prom_reconfig_setup(void)
 {
-	return pSeries_reconfig_notifier_register(&prom_reconfig_nb);
+	return of_update_notifier_register(&prom_reconfig_nb);
 }
 __initcall(prom_reconfig_setup);
 #endif
 
-/*
- * Add a property to a node
- */
-int prom_add_property(struct device_node* np, struct property* prop)
-{
-	struct property **next;
-	unsigned long flags;
-
-	prop->next = NULL;	
-	write_lock_irqsave(&devtree_lock, flags);
-	next = &np->properties;
-	while (*next) {
-		if (strcmp(prop->name, (*next)->name) == 0) {
-			/* duplicate ! don't insert it */
-			write_unlock_irqrestore(&devtree_lock, flags);
-			return -1;
-		}
-		next = &(*next)->next;
-	}
-	*next = prop;
-	write_unlock_irqrestore(&devtree_lock, flags);
-
-#ifdef CONFIG_PROC_DEVICETREE
-	/* try to add to proc as well if it was initialized */
-	if (np->pde)
-		proc_device_tree_add_prop(np->pde, prop);
-#endif /* CONFIG_PROC_DEVICETREE */
-
-	return 0;
-}
-
-/*
- * Remove a property from a node.  Note that we don't actually
- * remove it, since we have given out who-knows-how-many pointers
- * to the data using get-property.  Instead we just move the property
- * to the "dead properties" list, so it won't be found any more.
- */
-int prom_remove_property(struct device_node *np, struct property *prop)
-{
-	struct property **next;
-	unsigned long flags;
-	int found = 0;
-
-	write_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;
-	}
-	write_unlock_irqrestore(&devtree_lock, flags);
-
-	if (!found)
-		return -ENODEV;
-
-#ifdef CONFIG_PROC_DEVICETREE
-	/* try to remove the proc node as well */
-	if (np->pde)
-		proc_device_tree_remove_prop(np->pde, prop);
-#endif /* CONFIG_PROC_DEVICETREE */
-
-	return 0;
-}
-
-/*
- * Update a property in a node.  Note that we don't actually
- * remove it, since we have given out who-knows-how-many pointers
- * to the data using get-property.  Instead we just move the property
- * to the "dead properties" list, and add the new property to the
- * property list
- */
-int prom_update_property(struct device_node *np,
-			 struct property *newprop,
-			 struct property *oldprop)
-{
-	struct property **next;
-	unsigned long flags;
-	int found = 0;
-
-	write_lock_irqsave(&devtree_lock, flags);
-	next = &np->properties;
-	while (*next) {
-		if (*next == oldprop) {
-			/* found the node */
-			newprop->next = oldprop->next;
-			*next = newprop;
-			oldprop->next = np->deadprops;
-			np->deadprops = oldprop;
-			found = 1;
-			break;
-		}
-		next = &(*next)->next;
-	}
-	write_unlock_irqrestore(&devtree_lock, flags);
-
-	if (!found)
-		return -ENODEV;
-
-#ifdef CONFIG_PROC_DEVICETREE
-	/* try to add to proc as well if it was initialized */
-	if (np->pde)
-		proc_device_tree_update_prop(np->pde, newprop, oldprop);
-#endif /* CONFIG_PROC_DEVICETREE */
-
-	return 0;
-}
-
-
 /* Find the device node for a given logical cpu number, also returns the cpu
  * local thread number (index in ibm,interrupt-server#s) if relevant and
  * asked for (non NULL)
Index: linux-next/arch/powerpc/platforms/pseries/hotplug-cpu.c
===================================================================
--- linux-next.orig/arch/powerpc/platforms/pseries/hotplug-cpu.c	2009-11-04 14:42:17.000000000 -0600
+++ linux-next/arch/powerpc/platforms/pseries/hotplug-cpu.c	2009-11-04 14:45:43.000000000 -0600
@@ -21,13 +21,13 @@
 #include <linux/kernel.h>
 #include <linux/delay.h>
 #include <linux/cpu.h>
+#include <linux/of.h>
 #include <asm/system.h>
 #include <asm/prom.h>
 #include <asm/rtas.h>
 #include <asm/firmware.h>
 #include <asm/machdep.h>
 #include <asm/vdso_datapage.h>
-#include <asm/pSeries_reconfig.h>
 #include "xics.h"
 #include "plpar_wrappers.h"
 
@@ -234,11 +234,11 @@
 	int err = NOTIFY_OK;
 
 	switch (action) {
-	case PSERIES_RECONFIG_ADD:
+	case OF_ATTACH_NODE:
 		if (pseries_add_processor(node))
 			err = NOTIFY_BAD;
 		break;
-	case PSERIES_RECONFIG_REMOVE:
+	case OF_DETACH_NODE:
 		pseries_remove_processor(node);
 		break;
 	default:
@@ -284,7 +284,7 @@
 
 	/* Processors can be added/removed only on LPAR */
 	if (firmware_has_feature(FW_FEATURE_LPAR))
-		pSeries_reconfig_notifier_register(&pseries_smp_nb);
+		of_update_notifier_register(&pseries_smp_nb);
 
 	return 0;
 }
Index: linux-next/arch/powerpc/platforms/pseries/hotplug-memory.c
===================================================================
--- linux-next.orig/arch/powerpc/platforms/pseries/hotplug-memory.c	2009-11-04 14:42:17.000000000 -0600
+++ linux-next/arch/powerpc/platforms/pseries/hotplug-memory.c	2009-11-04 14:45:43.000000000 -0600
@@ -13,8 +13,8 @@
 #include <linux/lmb.h>
 #include <asm/firmware.h>
 #include <asm/machdep.h>
-#include <asm/pSeries_reconfig.h>
 #include <asm/sparsemem.h>
+#include "pseries.h"
 
 static int pseries_remove_lmb(unsigned long base, unsigned int lmb_size)
 {
@@ -118,7 +118,10 @@
 	return (ret < 0) ? -EINVAL : 0;
 }
 
-static int pseries_drconf_memory(unsigned long *base, unsigned int action)
+#define PSERIES_DRCONF_MEM_ADD		1
+#define PSERIES_DRCONF_MEM_REMOVE	2
+
+static int pseries_drconf_memory(unsigned long base, unsigned int action)
 {
 	struct device_node *np;
 	const unsigned long *lmb_size;
@@ -135,10 +138,10 @@
 	}
 
 	if (action == PSERIES_DRCONF_MEM_ADD) {
-		rc = lmb_add(*base, *lmb_size);
+		rc = lmb_add(base, *lmb_size);
 		rc = (rc < 0) ? -EINVAL : 0;
 	} else if (action == PSERIES_DRCONF_MEM_REMOVE) {
-		rc = pseries_remove_lmb(*base, *lmb_size);
+		rc = pseries_remove_lmb(base, *lmb_size);
 	} else {
 		rc = -EINVAL;
 	}
@@ -147,25 +150,30 @@
 	return rc;
 }
 
+int pseries_drconf_memory_add(unsigned long base)
+{
+	return pseries_drconf_memory(base, PSERIES_DRCONF_MEM_ADD);
+}
+
+int pseries_drconf_memory_remove(unsigned long base)
+{
+	return pseries_drconf_memory(base, PSERIES_DRCONF_MEM_REMOVE);
+}
+
 static int pseries_memory_notifier(struct notifier_block *nb,
 				unsigned long action, void *node)
 {
 	int err = NOTIFY_OK;
 
 	switch (action) {
-	case PSERIES_RECONFIG_ADD:
+	case OF_ATTACH_NODE:
 		if (pseries_add_memory(node))
 			err = NOTIFY_BAD;
 		break;
-	case PSERIES_RECONFIG_REMOVE:
+	case OF_DETACH_NODE:
 		if (pseries_remove_memory(node))
 			err = NOTIFY_BAD;
 		break;
-	case PSERIES_DRCONF_MEM_ADD:
-	case PSERIES_DRCONF_MEM_REMOVE:
-		if (pseries_drconf_memory(node, action))
-			err = NOTIFY_BAD;
-		break;
 	default:
 		err = NOTIFY_DONE;
 		break;
@@ -180,7 +188,7 @@
 static int __init pseries_memory_hotplug_init(void)
 {
 	if (firmware_has_feature(FW_FEATURE_LPAR))
-		pSeries_reconfig_notifier_register(&pseries_mem_nb);
+		of_update_notifier_register(&pseries_mem_nb);
 
 	return 0;
 }
Index: linux-next/arch/powerpc/platforms/pseries/iommu.c
===================================================================
--- linux-next.orig/arch/powerpc/platforms/pseries/iommu.c	2009-11-04 14:42:17.000000000 -0600
+++ linux-next/arch/powerpc/platforms/pseries/iommu.c	2009-11-04 14:45:43.000000000 -0600
@@ -33,6 +33,7 @@
 #include <linux/pci.h>
 #include <linux/dma-mapping.h>
 #include <linux/crash_dump.h>
+#include <linux/of.h>
 #include <asm/io.h>
 #include <asm/prom.h>
 #include <asm/rtas.h>
@@ -40,7 +41,6 @@
 #include <asm/pci-bridge.h>
 #include <asm/machdep.h>
 #include <asm/abs_addr.h>
-#include <asm/pSeries_reconfig.h>
 #include <asm/firmware.h>
 #include <asm/tce.h>
 #include <asm/ppc-pci.h>
@@ -570,7 +570,7 @@
 	struct pci_dn *pci = PCI_DN(np);
 
 	switch (action) {
-	case PSERIES_RECONFIG_REMOVE:
+	case OF_DETACH_NODE:
 		if (pci && pci->iommu_table &&
 		    of_get_property(np, "ibm,dma-window", NULL))
 			iommu_free_table(pci->iommu_table, np->full_name);
@@ -617,7 +617,7 @@
 	}
 
 
-	pSeries_reconfig_notifier_register(&iommu_reconfig_nb);
+	of_update_notifier_register(&iommu_reconfig_nb);
 
 	set_pci_dma_ops(&dma_iommu_ops);
 }
Index: linux-next/arch/powerpc/platforms/pseries/pseries.h
===================================================================
--- linux-next.orig/arch/powerpc/platforms/pseries/pseries.h	2009-11-04 14:42:17.000000000 -0600
+++ linux-next/arch/powerpc/platforms/pseries/pseries.h	2009-11-04 14:45:43.000000000 -0600
@@ -40,4 +40,18 @@
 
 extern void find_udbg_vterm(void);
 
+#ifdef CONFIG_MEMORY_HOTPLUG
+extern int pseries_drconf_memory_add(unsigned long);
+extern int pseries_drconf_memory_remove(unsigned long);
+#else
+static inline int pseries_drconf_memory_add(unsigned long base)
+{
+	return 0;
+}
+static inline int pseries_drconf_memory_remove(unsigned long base)
+{
+	return 0;
+}
+#endif
+
 #endif /* _PSERIES_PSERIES_H */
Index: linux-next/arch/powerpc/platforms/pseries/reconfig.c
===================================================================
--- linux-next.orig/arch/powerpc/platforms/pseries/reconfig.c	2009-11-04 14:42:17.000000000 -0600
+++ linux-next/arch/powerpc/platforms/pseries/reconfig.c	2009-11-04 14:57:47.000000000 -0600
@@ -13,100 +13,14 @@
 
 #include <linux/kernel.h>
 #include <linux/kref.h>
-#include <linux/notifier.h>
-#include <linux/proc_fs.h>
+#include <linux/of.h>
 
 #include <asm/prom.h>
 #include <asm/machdep.h>
 #include <asm/uaccess.h>
-#include <asm/pSeries_reconfig.h>
 #include <asm/mmu.h>
 
-
-
-/*
- * Routines for "runtime" addition and removal of device tree nodes.
- */
-#ifdef CONFIG_PROC_DEVICETREE
-/*
- * Add a node to /proc/device-tree.
- */
-static void add_node_proc_entries(struct device_node *np)
-{
-	struct proc_dir_entry *ent;
-
-	ent = proc_mkdir(strrchr(np->full_name, '/') + 1, np->parent->pde);
-	if (ent)
-		proc_device_tree_add_node(np, ent);
-}
-
-static void remove_node_proc_entries(struct device_node *np)
-{
-	struct property *pp = np->properties;
-	struct device_node *parent = np->parent;
-
-	while (pp) {
-		remove_proc_entry(pp->name, np->pde);
-		pp = pp->next;
-	}
-	if (np->pde)
-		remove_proc_entry(np->pde->name, parent->pde);
-}
-#else /* !CONFIG_PROC_DEVICETREE */
-static void add_node_proc_entries(struct device_node *np)
-{
-	return;
-}
-
-static void remove_node_proc_entries(struct device_node *np)
-{
-	return;
-}
-#endif /* CONFIG_PROC_DEVICETREE */
-
-/**
- *	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;
-}
-
-static BLOCKING_NOTIFIER_HEAD(pSeries_reconfig_chain);
-
-int pSeries_reconfig_notifier_register(struct notifier_block *nb)
-{
-	return blocking_notifier_chain_register(&pSeries_reconfig_chain, nb);
-}
-
-void pSeries_reconfig_notifier_unregister(struct notifier_block *nb)
-{
-	blocking_notifier_chain_unregister(&pSeries_reconfig_chain, nb);
-}
+#include "pseries.h"
 
 static int pSeries_reconfig_add_node(const char *path, struct property *proplist)
 {
@@ -124,34 +38,12 @@
 	strcpy(np->full_name, path);
 
 	np->properties = proplist;
-	of_node_set_flag(np, OF_DYNAMIC);
-	kref_init(&np->kref);
-
-	np->parent = derive_parent(path);
-	if (IS_ERR(np->parent)) {
-		err = PTR_ERR(np->parent);
-		goto out_err;
-	}
-
-	err = blocking_notifier_call_chain(&pSeries_reconfig_chain,
-				  PSERIES_RECONFIG_ADD, np);
-	if (err == NOTIFY_BAD) {
-		printk(KERN_ERR "Failed to add device node %s\n", path);
-		err = -ENOMEM; /* For now, safe to assume kmalloc failure */
-		goto out_err;
-	}
-
 	of_attach_node(np);
 
-	add_node_proc_entries(np);
-
-	of_node_put(np->parent);
-
 	return 0;
 
 out_err:
 	if (np) {
-		of_node_put(np->parent);
 		kfree(np->full_name);
 		kfree(np);
 	}
@@ -172,10 +64,6 @@
 		return -EBUSY;
 	}
 
-	remove_node_proc_entries(np);
-
-	blocking_notifier_call_chain(&pSeries_reconfig_chain,
-			    PSERIES_RECONFIG_REMOVE, np);
 	of_detach_node(np);
 
 	of_node_put(parent);
@@ -392,7 +280,7 @@
 	if (!prop)
 		return -ENOMEM;
 
-	prom_add_property(np, prop);
+	of_property_attach(np, prop);
 
 	return 0;
 }
@@ -416,7 +304,7 @@
 
 	prop = of_find_property(np, buf, NULL);
 
-	return prom_remove_property(np, prop);
+	return of_property_detach(np, prop);
 }
 
 static int do_update_property(char *buf, size_t bufsize)
@@ -446,37 +334,34 @@
 	oldprop = of_find_property(np, name,NULL);
 	if (!oldprop) {
 		if (strlen(name))
-			return prom_add_property(np, newprop);
+			return of_property_attach(np, newprop);
 		return -ENODEV;
 	}
 
-	rc = prom_update_property(np, newprop, oldprop);
+	rc = of_property_update(np, newprop, oldprop);
 	if (rc)
 		return rc;
 
 	/* For memory under the ibm,dynamic-reconfiguration-memory node
 	 * of the device tree, adding and removing memory is just an update
 	 * to the ibm,dynamic-memory property instead of adding/removing a
-	 * memory node in the device tree.  For these cases we still need to
-	 * involve the notifier chain.
+	 * memory node in the device tree.
 	 */
 	if (!strcmp(name, "ibm,dynamic-memory")) {
-		int action;
+		unsigned long *addr;
 
-		next_prop = parse_next_property(next_prop, end, &name,
-						&length, &value);
+		next_prop = parse_next_property(next_prop, end, &name, &length,
+						(unsigned char **)&addr);
 		if (!next_prop)
 			return -EINVAL;
 
 		if (!strcmp(name, "add"))
-			action = PSERIES_DRCONF_MEM_ADD;
+			rc = pseries_drconf_memory_add(*addr);
 		else
-			action = PSERIES_DRCONF_MEM_REMOVE;
+			rc = pseries_drconf_memory_remove(*addr);
 
-		rc = blocking_notifier_call_chain(&pSeries_reconfig_chain,
-						  action, value);
-		if (rc == NOTIFY_BAD) {
-			rc = prom_update_property(np, oldprop, newprop);
+		if (rc) {
+			rc = of_property_update(np, oldprop, newprop);
 			return -ENOMEM;
 		}
 	}
Index: linux-next/arch/powerpc/platforms/pseries/setup.c
===================================================================
--- linux-next.orig/arch/powerpc/platforms/pseries/setup.c	2009-11-04 14:42:17.000000000 -0600
+++ linux-next/arch/powerpc/platforms/pseries/setup.c	2009-11-04 14:45:43.000000000 -0600
@@ -40,6 +40,7 @@
 #include <linux/irq.h>
 #include <linux/seq_file.h>
 #include <linux/root_dev.h>
+#include <linux/of.h>
 
 #include <asm/mmu.h>
 #include <asm/processor.h>
@@ -63,7 +64,6 @@
 #include <asm/smp.h>
 #include <asm/firmware.h>
 #include <asm/eeh.h>
-#include <asm/pSeries_reconfig.h>
 
 #include "plpar_wrappers.h"
 #include "pseries.h"
@@ -258,7 +258,7 @@
 	int err = NOTIFY_OK;
 
 	switch (action) {
-	case PSERIES_RECONFIG_ADD:
+	case OF_ATTACH_NODE:
 		pci = np->parent->data;
 		if (pci)
 			update_dn_pci_info(np, pci->phb);
@@ -291,7 +291,7 @@
 	/* Find and initialize PCI host bridges */
 	init_pci_config_tokens();
 	find_and_init_phbs();
-	pSeries_reconfig_notifier_register(&pci_dn_reconfig_nb);
+	of_update_notifier_register(&pci_dn_reconfig_nb);
 	eeh_init();
 
 	pSeries_nvram_init();
Index: linux-next/arch/powerpc/platforms/pseries/smp.c
===================================================================
--- linux-next.orig/arch/powerpc/platforms/pseries/smp.c	2009-11-04 14:42:17.000000000 -0600
+++ linux-next/arch/powerpc/platforms/pseries/smp.c	2009-11-04 14:45:43.000000000 -0600
@@ -40,7 +40,6 @@
 #include <asm/firmware.h>
 #include <asm/system.h>
 #include <asm/rtas.h>
-#include <asm/pSeries_reconfig.h>
 #include <asm/mpic.h>
 #include <asm/vdso_datapage.h>
 #include <asm/cputhreads.h>
Index: linux-next/arch/powerpc/include/asm/prom.h
===================================================================
--- linux-next.orig/arch/powerpc/include/asm/prom.h	2009-11-04 14:42:17.000000000 -0600
+++ linux-next/arch/powerpc/include/asm/prom.h	2009-11-04 14:45:43.000000000 -0600
@@ -34,10 +34,6 @@
 
 #define HAVE_ARCH_DEVTREE_FIXUPS
 
-/* For updating the device tree at runtime */
-extern void of_attach_node(struct device_node *);
-extern void of_detach_node(struct device_node *);
-
 #ifdef CONFIG_PPC32
 /*
  * PCI <-> OF matching functions
Index: linux-next/arch/powerpc/kernel/machine_kexec.c
===================================================================
--- linux-next.orig/arch/powerpc/kernel/machine_kexec.c	2009-11-04 14:42:17.000000000 -0600
+++ linux-next/arch/powerpc/kernel/machine_kexec.c	2009-11-04 14:45:43.000000000 -0600
@@ -173,16 +173,16 @@
 	 * be sure what's in them, so remove them. */
 	prop = of_find_property(node, "linux,crashkernel-base", NULL);
 	if (prop)
-		prom_remove_property(node, prop);
+		of_property_detach(node, prop);
 
 	prop = of_find_property(node, "linux,crashkernel-size", NULL);
 	if (prop)
-		prom_remove_property(node, prop);
+		of_property_detach(node, prop);
 
 	if (crashk_res.start != 0) {
-		prom_add_property(node, &crashk_base_prop);
+		of_property_attach(node, &crashk_base_prop);
 		crashk_size = crashk_res.end - crashk_res.start + 1;
-		prom_add_property(node, &crashk_size_prop);
+		of_property_attach(node, &crashk_size_prop);
 	}
 }
 
@@ -198,11 +198,11 @@
 	/* remove any stale properties so ours can be found */
 	prop = of_find_property(node, kernel_end_prop.name, NULL);
 	if (prop)
-		prom_remove_property(node, prop);
+		of_property_detach(node, prop);
 
 	/* information needed by userspace when using default_machine_kexec */
 	kernel_end = __pa(_end);
-	prom_add_property(node, &kernel_end_prop);
+	of_property_attach(node, &kernel_end_prop);
 
 	export_crashk_values(node);
 
Index: linux-next/arch/powerpc/kernel/machine_kexec_64.c
===================================================================
--- linux-next.orig/arch/powerpc/kernel/machine_kexec_64.c	2009-11-04 14:42:17.000000000 -0600
+++ linux-next/arch/powerpc/kernel/machine_kexec_64.c	2009-11-04 14:45:43.000000000 -0600
@@ -15,6 +15,7 @@
 #include <linux/thread_info.h>
 #include <linux/init_task.h>
 #include <linux/errno.h>
+#include <linux/of.h>
 
 #include <asm/page.h>
 #include <asm/current.h>
@@ -320,14 +321,14 @@
 	/* remove any stale propertys so ours can be found */
 	prop = of_find_property(node, htab_base_prop.name, NULL);
 	if (prop)
-		prom_remove_property(node, prop);
+		of_property_detach(node, prop);
 	prop = of_find_property(node, htab_size_prop.name, NULL);
 	if (prop)
-		prom_remove_property(node, prop);
+		of_property_detach(node, prop);
 
 	htab_base = __pa(htab_address);
-	prom_add_property(node, &htab_base_prop);
-	prom_add_property(node, &htab_size_prop);
+	of_property_attach(node, &htab_base_prop);
+	of_property_attach(node, &htab_size_prop);
 
 	of_node_put(node);
 	return 0;
Index: linux-next/arch/powerpc/Kconfig
===================================================================
--- linux-next.orig/arch/powerpc/Kconfig	2009-11-04 14:42:17.000000000 -0600
+++ linux-next/arch/powerpc/Kconfig	2009-11-04 14:45:43.000000000 -0600
@@ -174,6 +174,9 @@
 config OF
 	def_bool y
 
+config OF_DYNAMIC
+	def_bool y
+
 config PPC_UDBG_16550
 	bool
 	default n

[RFC PATCH 5/5] powerpc/iseries updates for new OF dynamic code

From: Nathan Fontenot <hidden>
Date: 2009-11-04 22:20:45

Update the powerpc/iseries vio code to use the new generic OF dynamic code.

NOTE: I have no means of testing iseries kernels, this does at least pass the
compile test for me.

Signed-off-by: Nathan Fontenot <redacted>
---

Index: linux-next/arch/powerpc/platforms/iseries/vio.c
===================================================================
--- linux-next.orig/arch/powerpc/platforms/iseries/vio.c	2009-11-02 13:39:40.000000000 -0600
+++ linux-next/arch/powerpc/platforms/iseries/vio.c	2009-11-03 12:34:19.000000000 -0600
@@ -80,8 +80,7 @@
 	kfree(np);
 }
 
-static struct device_node *new_node(const char *path,
-		struct device_node *parent)
+static struct device_node *new_node(const char *path)
 {
 	struct device_node *np = kzalloc(sizeof(*np), GFP_KERNEL);
 
@@ -93,9 +92,6 @@
 		return NULL;
 	}
 	strcpy(np->full_name, path);
-	of_node_set_flag(np, OF_DYNAMIC);
-	kref_init(&np->kref);
-	np->parent = of_node_get(parent);
 	return np;
 }
 
@@ -122,7 +118,7 @@
 
 	if (!nprop)
 		return 0;
-	prom_add_property(np, nprop);
+	of_property_attach(np, nprop);
 	return 1;
 }
 
@@ -133,19 +129,19 @@
 
 	if (!nprop)
 		return 0;
-	prom_add_property(np, nprop);
+	of_property_attach(np, nprop);
 	return 1;
 }
 
-static struct device_node *do_device_node(struct device_node *parent,
-		const char *name, u32 reg, u32 unit, const char *type,
-		const char *compat, struct vio_resource *res)
+static struct device_node *do_device_node(const char *name, u32 reg,
+		u32 unit, const char *type, const char *compat,
+		struct vio_resource *res)
 {
 	struct device_node *np;
 	char path[32];
 
 	snprintf(path, sizeof(path), "/vdevice/%s@%08x", name, reg);
-	np = new_node(path, parent);
+	np = new_node(path);
 	if (!np)
 		return NULL;
 	if (!add_string_property(np, "name", name) ||
@@ -168,15 +164,6 @@
 	np->name = of_get_property(np, "name", NULL);
 	np->type = of_get_property(np, "device_type", NULL);
 	of_attach_node(np);
-#ifdef CONFIG_PROC_DEVICETREE
-	if (parent->pde) {
-		struct proc_dir_entry *ent;
-
-		ent = proc_mkdir(strrchr(np->full_name, '/') + 1, parent->pde);
-		if (ent)
-			proc_device_tree_add_node(np, ent);
-	}
-#endif
 	return np;
 
  node_free:
@@ -190,16 +177,11 @@
  */
 struct vio_dev *vio_create_viodasd(u32 unit)
 {
-	struct device_node *vio_root;
 	struct device_node *np;
 	struct vio_dev *vdev = NULL;
 
-	vio_root = of_find_node_by_path("/vdevice");
-	if (!vio_root)
-		return NULL;
-	np = do_device_node(vio_root, "viodasd", FIRST_VIODASD + unit, unit,
+	np = do_device_node("viodasd", FIRST_VIODASD + unit, unit,
 			"block", "IBM,iSeries-viodasd", NULL);
-	of_node_put(vio_root);
 	if (np) {
 		vdev = vio_register_device_node(np);
 		if (!vdev)
@@ -254,7 +236,7 @@
 	}
 }
 
-static void __init probe_disk(struct device_node *vio_root, u32 unit)
+static void __init probe_disk(u32 unit)
 {
 	HvLpEvent_Rc hvrc;
 	struct vio_waitevent we;
@@ -305,11 +287,11 @@
 		return;
 	}
 
-	do_device_node(vio_root, "viodasd", FIRST_VIODASD + unit, unit,
+	do_device_node("viodasd", FIRST_VIODASD + unit, unit,
 			"block", "IBM,iSeries-viodasd", NULL);
 }
 
-static void __init get_viodasd_info(struct device_node *vio_root)
+static void __init get_viodasd_info(void)
 {
 	int rc;
 	u32 unit;
@@ -326,7 +308,7 @@
 	vio_setHandler(viomajorsubtype_blockio, handle_block_event);
 
 	for (unit = 0; unit < HVMAXARCHITECTEDVIRTUALDISKS; unit++)
-		probe_disk(vio_root, unit);
+		probe_disk(unit);
 
 	vio_clearHandler(viomajorsubtype_blockio);
 	viopath_close(viopath_hostLp, viomajorsubtype_blockio, 2);
@@ -372,7 +354,7 @@
 	}
 }
 
-static void __init get_viocd_info(struct device_node *vio_root)
+static void __init get_viocd_info(void)
 {
 	HvLpEvent_Rc hvrc;
 	u32 unit;
@@ -430,7 +412,7 @@
 
 	for (unit = 0; (unit < HVMAXARCHITECTEDVIRTUALCDROMS) &&
 			unitinfo[unit].rsrcname[0]; unit++) {
-		if (!do_device_node(vio_root, "viocd", FIRST_VIOCD + unit, unit,
+		if (!do_device_node("viocd", FIRST_VIOCD + unit, unit,
 				"block", "IBM,iSeries-viocd", &unitinfo[unit]))
 			break;
 	}
@@ -464,7 +446,7 @@
 	}
 }
 
-static void __init get_viotape_info(struct device_node *vio_root)
+static void __init get_viotape_info(void)
 {
 	HvLpEvent_Rc hvrc;
 	u32 unit;
@@ -507,7 +489,7 @@
 
 	for (unit = 0; (unit < HVMAXARCHITECTEDVIRTUALTAPES) &&
 			unitinfo[unit].rsrcname[0]; unit++) {
-		if (!do_device_node(vio_root, "viotape", FIRST_VIOTAPE + unit,
+		if (!do_device_node("viotape", FIRST_VIOTAPE + unit,
 				unit, "byte", "IBM,iSeries-viotape",
 				&unitinfo[unit]))
 			break;
@@ -522,7 +504,6 @@
 
 static int __init iseries_vio_init(void)
 {
-	struct device_node *vio_root;
 	int ret = -ENODEV;
 
 	if (!firmware_has_feature(FW_FEATURE_ISERIES))
@@ -530,25 +511,19 @@
 
 	iommu_vio_init();
 
-	vio_root = of_find_node_by_path("/vdevice");
-	if (!vio_root)
-		goto out;
-
 	if (viopath_hostLp == HvLpIndexInvalid) {
 		vio_set_hostlp();
 		/* If we don't have a host, bail out */
 		if (viopath_hostLp == HvLpIndexInvalid)
-			goto put_node;
+			goto out;
 	}
 
-	get_viodasd_info(vio_root);
-	get_viocd_info(vio_root);
-	get_viotape_info(vio_root);
+	get_viodasd_info();
+	get_viocd_info();
+	get_viotape_info();
 
 	ret = 0;
 
- put_node:
-	of_node_put(vio_root);
  out:
 	return ret;
 }
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help