]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - arch/powerpc/kernel/prom.c
Merge branch 'master' of /pub/scm/linux/kernel/git/torvalds/linux-2.6
[linux-2.6-omap-h63xx.git] / arch / powerpc / kernel / prom.c
index caef555f2dc06a1f1b20e225d3b272d36c378ee9..37ff99bd98b45ac892cab67a839b4110d68e26dd 100644 (file)
@@ -52,6 +52,7 @@
 #include <asm/pSeries_reconfig.h>
 #include <asm/pci-bridge.h>
 #include <asm/kexec.h>
+#include <asm/system.h>
 
 #ifdef DEBUG
 #define DBG(fmt...) printk(KERN_ERR fmt)
@@ -716,11 +717,40 @@ static int __init early_init_dt_scan_cpus(unsigned long node,
        return 0;
 }
 
+#ifdef CONFIG_BLK_DEV_INITRD
+static void __init early_init_dt_check_for_initrd(unsigned long node)
+{
+       unsigned long l;
+       u32 *prop;
+
+       DBG("Looking for initrd properties... ");
+
+       prop = of_get_flat_dt_prop(node, "linux,initrd-start", &l);
+       if (prop) {
+               initrd_start = (unsigned long)__va(of_read_ulong(prop, l/4));
+
+               prop = of_get_flat_dt_prop(node, "linux,initrd-end", &l);
+               if (prop) {
+                       initrd_end = (unsigned long)
+                                       __va(of_read_ulong(prop, l/4));
+                       initrd_below_start_ok = 1;
+               } else {
+                       initrd_start = 0;
+               }
+       }
+
+       DBG("initrd_start=0x%lx  initrd_end=0x%lx\n", initrd_start, initrd_end);
+}
+#else
+static inline void early_init_dt_check_for_initrd(unsigned long node)
+{
+}
+#endif /* CONFIG_BLK_DEV_INITRD */
+
 static int __init early_init_dt_scan_chosen(unsigned long node,
                                            const char *uname, int depth, void *data)
 {
        unsigned long *lprop;
-       u32 *prop;
        unsigned long l;
        char *p;
 
@@ -762,21 +792,7 @@ static int __init early_init_dt_scan_chosen(unsigned long node,
                crashk_res.end = crashk_res.start + *lprop - 1;
 #endif
 
-#ifdef CONFIG_BLK_DEV_INITRD
-       DBG("Looking for initrd properties... ");
-       prop = of_get_flat_dt_prop(node, "linux,initrd-start", &l);
-       if (prop) {
-               initrd_start = (unsigned long)__va(of_read_ulong(prop, l/4));
-               prop = of_get_flat_dt_prop(node, "linux,initrd-end", &l);
-               if (prop) {
-                       initrd_end = (unsigned long)__va(of_read_ulong(prop, l/4));
-                       initrd_below_start_ok = 1;
-               } else {
-                       initrd_start = 0;
-               }
-       }
-       DBG("initrd_start=0x%lx  initrd_end=0x%lx\n", initrd_start, initrd_end);
-#endif /* CONFIG_BLK_DEV_INITRD */
+       early_init_dt_check_for_initrd(node);
 
        /* Retreive command line */
        p = of_get_flat_dt_prop(node, "bootargs", &l);
@@ -990,7 +1006,7 @@ static void __init early_reserve_mem(void)
 
 void __init early_init_devtree(void *params)
 {
-       DBG(" -> early_init_devtree()\n");
+       DBG(" -> early_init_devtree(%p)\n", params);
 
        /* Setup flat device-tree pointer */
        initial_boot_params = params;
@@ -1040,8 +1056,6 @@ void __init early_init_devtree(void *params)
        DBG(" <- early_init_devtree()\n");
 }
 
-#undef printk
-
 int of_n_addr_cells(struct device_node* np)
 {
        const int *ip;
@@ -1156,11 +1170,12 @@ EXPORT_SYMBOL(of_find_node_by_name);
 
 /**
  *     of_find_node_by_type - Find a node by its "device_type" property
- *     @from:  The node to start searching from or NULL, the node
- *             you pass will not be searched, only the next one
- *             will; typically, you pass what the previous call
- *             returned. of_node_put() will be called on it
- *     @name:  The type string to match against
+ *     @from:  The node to start searching from, or NULL to start searching
+ *             the entire device tree. The node you pass will not be
+ *             searched, only the next one will; typically, you pass
+ *             what the previous call returned. of_node_put() will be
+ *             called on from for you.
+ *     @type:  The type string to match against
  *
  *     Returns a node pointer with refcount incremented, use
  *     of_node_put() on it when done.
@@ -1359,8 +1374,17 @@ static void of_node_release(struct kref *kref)
        struct device_node *node = kref_to_device_node(kref);
        struct property *prop = node->properties;
 
-       if (!OF_IS_DYNAMIC(node))
+       /* 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);
@@ -1416,6 +1440,8 @@ void of_detach_node(const struct device_node *np)
        write_lock(&devtree_lock);
 
        parent = np->parent;
+       if (!parent)
+               goto out_unlock;
 
        if (allnodes == np)
                allnodes = np->allnext;
@@ -1439,6 +1465,9 @@ void of_detach_node(const struct device_node *np)
                prevsib->sibling = np->sibling;
        }
 
+       of_node_set_flag(np, OF_DETACHED);
+
+out_unlock:
        write_unlock(&devtree_lock);
 }
 
@@ -1457,6 +1486,11 @@ static int of_finish_dynamic_node(struct device_node *node)
        node->name = of_get_property(node, "name", NULL);
        node->type = of_get_property(node, "device_type", NULL);
 
+       if (!node->name)
+               node->name = "<NULL>";
+       if (!node->type)
+               node->type = "<NULL>";
+
        if (!parent) {
                err = -ENODEV;
                goto out;
@@ -1695,22 +1729,18 @@ struct device_node *of_get_cpu_node(int cpu, unsigned int *thread)
 }
 EXPORT_SYMBOL(of_get_cpu_node);
 
-#ifdef DEBUG
+#if defined(CONFIG_DEBUG_FS) && defined(DEBUG)
 static struct debugfs_blob_wrapper flat_dt_blob;
 
 static int __init export_flat_device_tree(void)
 {
        struct dentry *d;
 
-       d = debugfs_create_dir("powerpc", NULL);
-       if (!d)
-               return 1;
-
        flat_dt_blob.data = initial_boot_params;
        flat_dt_blob.size = initial_boot_params->totalsize;
 
        d = debugfs_create_blob("flat-device-tree", S_IFREG | S_IRUSR,
-                               d, &flat_dt_blob);
+                               powerpc_debugfs_root, &flat_dt_blob);
        if (!d)
                return 1;