* [RFC PATCH 1/5] Move devtree_lock and allnodes declaration to of.h
2009-11-04 22:07 [RFC PATCH 0/5] Merge common dynamic OF device tree code Nathan Fontenot
@ 2009-11-04 22:14 ` Nathan Fontenot
2009-11-04 22:16 ` [RFC PATCH 2/5] Merge dynamic OF code to of_dynamic.c Nathan Fontenot
` (3 subsequent siblings)
4 siblings, 0 replies; 8+ messages in thread
From: Nathan Fontenot @ 2009-11-04 22:14 UTC (permalink / raw)
To: devicetree-discuss, linuxppc-dev, microblaze-uclinux
Move the declaration of devtree_lock and allnodes from powerpc/microblaze
asm/prom.h to linux/of.h
Signed-off-by: Nathan Fontenot <nfont@austin.ibm.com>
---
Index: linux-next/include/linux/of.h
===================================================================
--- linux-next.orig/include/linux/of.h 2009-11-02 13:39:46.000000000 -0600
+++ linux-next/include/linux/of.h 2009-11-02 14:17:29.000000000 -0600
@@ -19,6 +19,7 @@
#include <linux/bitops.h>
#include <linux/kref.h>
#include <linux/mod_devicetable.h>
+#include <linux/spinlock.h>
typedef u32 phandle;
typedef u32 ihandle;
@@ -63,6 +64,9 @@
#endif
};
+extern rwlock_t devtree_lock;
+extern struct device_node *allnodes;
+
static inline int of_node_check_flag(struct device_node *n, unsigned long flag)
{
return test_bit(flag, &n->_flags);
Index: linux-next/arch/powerpc/kernel/prom.c
===================================================================
--- linux-next.orig/arch/powerpc/kernel/prom.c 2009-11-02 13:39:40.000000000 -0600
+++ linux-next/arch/powerpc/kernel/prom.c 2009-11-02 14:07:43.000000000 -0600
@@ -32,6 +32,7 @@
#include <linux/debugfs.h>
#include <linux/irq.h>
#include <linux/lmb.h>
+#include <linux/of.h>
#include <asm/prom.h>
#include <asm/rtas.h>
@@ -79,10 +80,6 @@
struct boot_param_header *initial_boot_params;
#endif
-extern struct device_node *allnodes; /* temporary while merging */
-
-extern rwlock_t devtree_lock; /* temporary while merging */
-
/* export that to outside world */
struct device_node *of_chosen;
Index: linux-next/arch/microblaze/include/asm/prom.h
===================================================================
--- linux-next.orig/arch/microblaze/include/asm/prom.h 2009-11-02 13:39:39.000000000 -0600
+++ linux-next/arch/microblaze/include/asm/prom.h 2009-11-02 14:10:13.000000000 -0600
@@ -23,6 +23,7 @@
#include <linux/of_fdt.h>
#include <linux/proc_fs.h>
#include <linux/platform_device.h>
+#include <linux/of.h>
#include <asm/irq.h>
#include <asm/atomic.h>
@@ -37,9 +38,6 @@
#define HAVE_ARCH_DEVTREE_FIXUPS
-extern struct device_node *allnodes; /* temporary while merging */
-extern rwlock_t devtree_lock; /* temporary while merging */
-
/* For updating the device tree at runtime */
extern void of_attach_node(struct device_node *);
extern void of_detach_node(struct device_node *);
Index: linux-next/arch/sparc/kernel/prom.h
===================================================================
--- linux-next.orig/arch/sparc/kernel/prom.h 2009-11-02 13:39:40.000000000 -0600
+++ linux-next/arch/sparc/kernel/prom.h 2009-11-02 14:12:46.000000000 -0600
@@ -2,11 +2,9 @@
#define __PROM_H
#include <linux/spinlock.h>
+#include <linux/of.h>
#include <asm/prom.h>
-extern struct device_node *allnodes; /* temporary while merging */
-extern rwlock_t devtree_lock; /* temporary while merging */
-
extern void * prom_early_alloc(unsigned long size);
extern void irq_trans_init(struct device_node *dp);
^ permalink raw reply [flat|nested] 8+ messages in thread* [RFC PATCH 2/5] Merge dynamic OF code to of_dynamic.c
2009-11-04 22:07 [RFC PATCH 0/5] Merge common dynamic OF device tree code Nathan Fontenot
2009-11-04 22:14 ` [RFC PATCH 1/5] Move devtree_lock and allnodes declaration to of.h Nathan Fontenot
@ 2009-11-04 22:16 ` Nathan Fontenot
2009-11-05 7:55 ` Grant Likely
2009-11-04 22:18 ` [RFC PATCH 3/5] powerpc and pseries updates for new OF dynamic code Nathan Fontenot
` (2 subsequent siblings)
4 siblings, 1 reply; 8+ messages in thread
From: Nathan Fontenot @ 2009-11-04 22:16 UTC (permalink / raw)
To: devicetree-discuss, linuxppc-dev, microblaze-uclinux
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 <nfont@austin.ibm.com>
---
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
^ permalink raw reply [flat|nested] 8+ messages in thread* Re: [RFC PATCH 2/5] Merge dynamic OF code to of_dynamic.c
2009-11-04 22:16 ` [RFC PATCH 2/5] Merge dynamic OF code to of_dynamic.c Nathan Fontenot
@ 2009-11-05 7:55 ` Grant Likely
2009-11-05 16:59 ` Nathan Fontenot
0 siblings, 1 reply; 8+ messages in thread
From: Grant Likely @ 2009-11-05 7:55 UTC (permalink / raw)
To: Nathan Fontenot; +Cc: linuxppc-dev, devicetree-discuss, microblaze-uclinux
Hi Nathan,
Thanks for the patches. Comments below.
On Wed, Nov 4, 2009 at 3:16 PM, Nathan Fontenot <nfont@austin.ibm.com> wrot=
e:
> Creation of the OF dynamic device tree update code in drivers/of. =A0This
> merges the common device tree updating routines to add/remove nodes and
> properties from powerpc and microblaze. =A0All of the new code is conditi=
onal
> based on a new OF_DYNAMIC config option.
Rather than one patch to create all the moved functions, and then
subsequent patches to remove the duplicates from each arch, I've been
using the pattern of one patch for each function or couple of
functions to both remove from the old files and add to the new home.
Would you be able to do the same for your patches here? The merging
is complicated enough without having to track changes to a function
between separate commits. Moving one function at a time will also
make bisecting more friendly.
Also, have you checked what impact these changes have on SPARC?
> --- linux-next.orig/drivers/of/Makefile 2009-11-03 11:18:08.000000000 -06=
00
> +++ linux-next/drivers/of/Makefile =A0 =A0 =A02009-11-03 13:42:35.0000000=
00 -0600
> @@ -1,6 +1,7 @@
> obj-y =3D base.o
> -obj-$(CONFIG_OF_DEVICE) +=3D device.o platform.o
> -obj-$(CONFIG_OF_GPIO) =A0 +=3D gpio.o
> -obj-$(CONFIG_OF_I2C) =A0 +=3D of_i2c.o
> -obj-$(CONFIG_OF_SPI) =A0 +=3D of_spi.o
> -obj-$(CONFIG_OF_MDIO) =A0+=3D of_mdio.o
> +obj-$(CONFIG_OF_DEVICE) =A0 =A0 =A0 =A0 =A0 =A0 =A0 =A0+=3D device.o pla=
tform.o
> +obj-$(CONFIG_OF_GPIO) =A0 =A0 =A0 =A0 =A0+=3D gpio.o
> +obj-$(CONFIG_OF_I2C) =A0 =A0 =A0 =A0 =A0 +=3D of_i2c.o
> +obj-$(CONFIG_OF_SPI) =A0 =A0 =A0 =A0 =A0 +=3D of_spi.o
> +obj-$(CONFIG_OF_MDIO) =A0 =A0 =A0 =A0 =A0+=3D of_mdio.o
> +obj-$(CONFIG_OF_DYNAMIC) =A0 =A0 =A0 +=3D of_dynamic.o
Unrelated whitespace churn makes it hard to see what actually changed.
Thanks,
g.
--=20
Grant Likely, B.Sc., P.Eng.
Secret Lab Technologies Ltd.
^ permalink raw reply [flat|nested] 8+ messages in thread
* Re: [RFC PATCH 2/5] Merge dynamic OF code to of_dynamic.c
2009-11-05 7:55 ` Grant Likely
@ 2009-11-05 16:59 ` Nathan Fontenot
0 siblings, 0 replies; 8+ messages in thread
From: Nathan Fontenot @ 2009-11-05 16:59 UTC (permalink / raw)
To: Grant Likely; +Cc: linuxppc-dev, devicetree-discuss, microblaze-uclinux
Grant Likely wrote:
> Hi Nathan,
>
> Thanks for the patches. Comments below.
>
> On Wed, Nov 4, 2009 at 3:16 PM, Nathan Fontenot <nfont@austin.ibm.com> wrote:
>> 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.
>
> Rather than one patch to create all the moved functions, and then
> subsequent patches to remove the duplicates from each arch, I've been
> using the pattern of one patch for each function or couple of
> functions to both remove from the old files and add to the new home.
> Would you be able to do the same for your patches here? The merging
> is complicated enough without having to track changes to a function
> between separate commits. Moving one function at a time will also
> make bisecting more friendly.
>
Shouldn't be a problem.
> Also, have you checked what impact these changes have on SPARC?
>
I took a look at sparc code, but will do again as I redo the patches to
make there are no impacts.
>> --- 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
>
> Unrelated whitespace churn makes it hard to see what actually changed.
>
ok.
-Nathan Fontenot
^ permalink raw reply [flat|nested] 8+ messages in thread
* [RFC PATCH 3/5] powerpc and pseries updates for new OF dynamic code
2009-11-04 22:07 [RFC PATCH 0/5] Merge common dynamic OF device tree code Nathan Fontenot
2009-11-04 22:14 ` [RFC PATCH 1/5] Move devtree_lock and allnodes declaration to of.h Nathan Fontenot
2009-11-04 22:16 ` [RFC PATCH 2/5] Merge dynamic OF code to of_dynamic.c Nathan Fontenot
@ 2009-11-04 22:18 ` Nathan Fontenot
2009-11-04 22:19 ` [RFC PATCH 4/5] Microblaze updates for " Nathan Fontenot
2009-11-04 22:20 ` [RFC PATCH 5/5] powerpc/iseries updates for new " Nathan Fontenot
4 siblings, 0 replies; 8+ messages in thread
From: Nathan Fontenot @ 2009-11-04 22:18 UTC (permalink / raw)
To: devicetree-discuss, linuxppc-dev, microblaze-uclinux
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 <nfont@austin.ibm.com>
---
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
^ permalink raw reply [flat|nested] 8+ messages in thread* [RFC PATCH 4/5] Microblaze updates for OF dynamic code
2009-11-04 22:07 [RFC PATCH 0/5] Merge common dynamic OF device tree code Nathan Fontenot
` (2 preceding siblings ...)
2009-11-04 22:18 ` [RFC PATCH 3/5] powerpc and pseries updates for new OF dynamic code Nathan Fontenot
@ 2009-11-04 22:19 ` Nathan Fontenot
2009-11-04 22:20 ` [RFC PATCH 5/5] powerpc/iseries updates for new " Nathan Fontenot
4 siblings, 0 replies; 8+ messages in thread
From: Nathan Fontenot @ 2009-11-04 22:19 UTC (permalink / raw)
To: devicetree-discuss, linuxppc-dev, microblaze-uclinux
This patch removes the common OF dynamic device tree updating from the
microblaze prom.c file to now use the generic OF code.
NOTE: I have no means of building and testing for the microblaze architecture.
I'll sign off on this with the understanding that it has not even passed the
compile test yet.
Signed-off-by: Nathan Fontenot <nfont@austin.ibm.com>
---
Index: linux-next/arch/microblaze/kernel/prom.c
===================================================================
--- linux-next.orig/arch/microblaze/kernel/prom.c 2009-11-03 13:20:25.000000000 -0600
+++ linux-next/arch/microblaze/kernel/prom.c 2009-11-03 14:01:34.000000000 -0600
@@ -30,6 +30,7 @@
#include <linux/debugfs.h>
#include <linux/irq.h>
#include <linux/lmb.h>
+#include <linux/of.h>
#include <asm/prom.h>
#include <asm/page.h>
@@ -859,252 +860,6 @@
}
EXPORT_SYMBOL(of_find_node_by_phandle);
-/**
- * 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_INFO "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);
-}
-
-/*
- * 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;
-}
-
#if defined(CONFIG_DEBUG_FS) && defined(DEBUG)
static struct debugfs_blob_wrapper flat_dt_blob;
Index: linux-next/arch/microblaze/include/asm/prom.h
===================================================================
--- linux-next.orig/arch/microblaze/include/asm/prom.h 2009-11-03 13:20:25.000000000 -0600
+++ linux-next/arch/microblaze/include/asm/prom.h 2009-11-03 14:01:34.000000000 -0600
@@ -38,10 +38,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 *);
-
/* Other Prototypes */
extern int early_uartlite_console(void);
Index: linux-next/arch/microblaze/Kconfig
===================================================================
--- linux-next.orig/arch/microblaze/Kconfig 2009-11-02 13:39:39.000000000 -0600
+++ linux-next/arch/microblaze/Kconfig 2009-11-03 14:02:21.000000000 -0600
@@ -112,6 +112,9 @@
config OF
def_bool y
+config OF_DYNAMIC
+ def_bool y
+
config PROC_DEVICETREE
bool "Support for device tree in /proc"
depends on PROC_FS
^ permalink raw reply [flat|nested] 8+ messages in thread* [RFC PATCH 5/5] powerpc/iseries updates for new OF dynamic code
2009-11-04 22:07 [RFC PATCH 0/5] Merge common dynamic OF device tree code Nathan Fontenot
` (3 preceding siblings ...)
2009-11-04 22:19 ` [RFC PATCH 4/5] Microblaze updates for " Nathan Fontenot
@ 2009-11-04 22:20 ` Nathan Fontenot
4 siblings, 0 replies; 8+ messages in thread
From: Nathan Fontenot @ 2009-11-04 22:20 UTC (permalink / raw)
To: devicetree-discuss, linuxppc-dev, microblaze-uclinux
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 <nfont@austin.ibm.com>
---
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;
}
^ permalink raw reply [flat|nested] 8+ messages in thread