diff -Nru a/arch/ppc64/kernel/prom.c b/arch/ppc64/kernel/prom.c --- a/arch/ppc64/kernel/prom.c Mon Nov 24 22:35:28 2003 +++ b/arch/ppc64/kernel/prom.c Mon Nov 24 22:35:28 2003 @@ -1618,6 +1618,8 @@ mem_start = DOUBLEWORD_ALIGN(mem_start + l + 1); } + spin_lock_init(&np->properties_lock); + /* do all our children */ child = call_prom(RELOC("child"), 1, 1, node); while (child != (phandle)0) { @@ -2455,6 +2457,7 @@ } strcpy(np->full_name, path); + spin_lock_init(&np->properties_lock); np->properties = proplist; OF_MARK_DYNAMIC(np); of_node_get(np); @@ -2535,6 +2538,26 @@ } write_unlock(&devtree_lock); of_node_put(parent); + return 0; +} + +/* + * Add a property to a device_node, adding an entry in /proc/device-tree + * if appropriate. + */ +int of_add_property(struct device_node *np, struct property *pp) +{ + unsigned long flags; + + if (np->pde && !proc_device_tree_add_property(np->pde, pp)) + return -ENOMEM; + + spin_lock_irqsave(&np->properties_lock, flags); + pp->next = np->properties; + wmb(); /* prevents us from dying in get_property for now */ + np->properties = pp; + spin_unlock_irqrestore(&np->properties_lock, flags); + return 0; } diff -Nru a/fs/proc/proc_devtree.c b/fs/proc/proc_devtree.c --- a/fs/proc/proc_devtree.c Mon Nov 24 22:35:28 2003 +++ b/fs/proc/proc_devtree.c Mon Nov 24 22:35:28 2003 @@ -26,6 +26,24 @@ #endif static struct proc_dir_entry *proc_device_tree; +static int property_read_proc(char *, char **, off_t, int, int *, void *); + +struct proc_dir_entry *proc_device_tree_add_property(struct proc_dir_entry *de, struct property *pp) +{ + struct proc_dir_entry *ent; + + ent = create_proc_read_entry(pp->name, strncmp(pp->name, "security-", 9) ? S_IRUGO : S_IRUSR, de, property_read_proc, pp); + + if (!ent) + return NULL; + + if (!strncmp(pp->name, "security-", 9)) + ent->size = 0; /* don't leak number of password chars */ + else + ent->size = pp->length; + + return ent; +} /* * Supply data on a read from /proc/device-tree/node/property. @@ -74,14 +92,9 @@ * Unfortunately proc_register puts each new entry * at the beginning of the list. So we rearrange them. */ - ent = create_proc_read_entry(pp->name, strncmp(pp->name, "security-", 9) ? - S_IRUGO : S_IRUSR, de, property_read_proc, pp); + ent = proc_device_tree_add_property(de, pp); if (ent == 0) break; - if (!strncmp(pp->name, "security-", 9)) - ent->size = 0; /* don't leak number of password chars */ - else - ent->size = pp->length; *lastp = ent; lastp = &ent->next; } diff -Nru a/include/asm-ppc64/prom.h b/include/asm-ppc64/prom.h --- a/include/asm-ppc64/prom.h Mon Nov 24 22:35:28 2003 +++ b/include/asm-ppc64/prom.h Mon Nov 24 22:35:28 2003 @@ -16,6 +16,7 @@ */ #include #include +#include #define PTRRELOC(x) ((typeof(x))((unsigned long)(x) - offset)) #define PTRUNRELOC(x) ((typeof(x))((unsigned long)(x) + offset)) @@ -151,6 +152,7 @@ struct pci_controller *phb; /* for pci devices */ struct TceTable *tce_table; /* for phb's or bridges */ + spinlock_t properties_lock; /* for traversal of properties list */ struct property *properties; struct device_node *parent; struct device_node *child; @@ -229,6 +231,7 @@ extern struct device_node *find_compatible_devices(const char *type, const char *compat); extern struct device_node *find_all_nodes(void); +extern void prom_add_property(struct device_node* np, struct property* prop); /* New style node lookup */ extern struct device_node *of_find_node_by_name(struct device_node *from, @@ -248,6 +251,7 @@ /* For updating the device tree at runtime */ extern int of_add_node(const char *path, struct property *proplist); extern int of_remove_node(struct device_node *np); +extern int of_add_property(struct device_node *np, struct property *pp); /* Other Prototypes */ extern unsigned long prom_init(unsigned long, unsigned long, unsigned long, @@ -263,6 +267,5 @@ extern int prom_n_addr_cells(struct device_node* np); extern int prom_n_size_cells(struct device_node* np); extern void prom_get_irq_senses(unsigned char *senses, int off, int max); -extern void prom_add_property(struct device_node* np, struct property* prop); #endif /* _PPC64_PROM_H */ diff -Nru a/include/linux/proc_fs.h b/include/linux/proc_fs.h --- a/include/linux/proc_fs.h Mon Nov 24 22:35:28 2003 +++ b/include/linux/proc_fs.h Mon Nov 24 22:35:28 2003 @@ -131,9 +131,11 @@ /* * proc_devtree.c */ +struct property; struct device_node; extern void proc_device_tree_init(void); extern void proc_device_tree_add_node(struct device_node *, struct proc_dir_entry *); +extern struct proc_dir_entry * proc_device_tree_add_property(struct proc_dir_entry *, struct property *); /* * proc_rtas.c