diff options
-rw-r--r-- | arch/sparc/kernel/prom.c | 53 | ||||
-rw-r--r-- | arch/sparc64/kernel/prom.c | 53 | ||||
-rw-r--r-- | include/asm-sparc/prom.h | 8 | ||||
-rw-r--r-- | include/asm-sparc64/prom.h | 8 |
4 files changed, 122 insertions, 0 deletions
diff --git a/arch/sparc/kernel/prom.c b/arch/sparc/kernel/prom.c index 63b2b9bd778e..f3f53f2e0e1e 100644 --- a/arch/sparc/kernel/prom.c +++ b/arch/sparc/kernel/prom.c | |||
@@ -27,6 +27,11 @@ | |||
27 | 27 | ||
28 | static struct device_node *allnodes; | 28 | static struct device_node *allnodes; |
29 | 29 | ||
30 | /* use when traversing tree through the allnext, child, sibling, | ||
31 | * or parent members of struct device_node. | ||
32 | */ | ||
33 | static DEFINE_RWLOCK(devtree_lock); | ||
34 | |||
30 | int of_device_is_compatible(struct device_node *device, const char *compat) | 35 | int of_device_is_compatible(struct device_node *device, const char *compat) |
31 | { | 36 | { |
32 | const char* cp; | 37 | const char* cp; |
@@ -185,6 +190,54 @@ int of_getintprop_default(struct device_node *np, const char *name, int def) | |||
185 | } | 190 | } |
186 | EXPORT_SYMBOL(of_getintprop_default); | 191 | EXPORT_SYMBOL(of_getintprop_default); |
187 | 192 | ||
193 | int of_set_property(struct device_node *dp, const char *name, void *val, int len) | ||
194 | { | ||
195 | struct property **prevp; | ||
196 | void *new_val; | ||
197 | int err; | ||
198 | |||
199 | new_val = kmalloc(len, GFP_KERNEL); | ||
200 | if (!new_val) | ||
201 | return -ENOMEM; | ||
202 | |||
203 | memcpy(new_val, val, len); | ||
204 | |||
205 | err = -ENODEV; | ||
206 | |||
207 | write_lock(&devtree_lock); | ||
208 | prevp = &dp->properties; | ||
209 | while (*prevp) { | ||
210 | struct property *prop = *prevp; | ||
211 | |||
212 | if (!strcmp(prop->name, name)) { | ||
213 | void *old_val = prop->value; | ||
214 | int ret; | ||
215 | |||
216 | ret = prom_setprop(dp->node, name, val, len); | ||
217 | err = -EINVAL; | ||
218 | if (ret >= 0) { | ||
219 | prop->value = new_val; | ||
220 | prop->length = len; | ||
221 | |||
222 | if (OF_IS_DYNAMIC(prop)) | ||
223 | kfree(old_val); | ||
224 | |||
225 | OF_MARK_DYNAMIC(prop); | ||
226 | |||
227 | err = 0; | ||
228 | } | ||
229 | break; | ||
230 | } | ||
231 | prevp = &(*prevp)->next; | ||
232 | } | ||
233 | write_unlock(&devtree_lock); | ||
234 | |||
235 | /* XXX Upate procfs if necessary... */ | ||
236 | |||
237 | return err; | ||
238 | } | ||
239 | EXPORT_SYMBOL(of_set_property); | ||
240 | |||
188 | static unsigned int prom_early_allocated; | 241 | static unsigned int prom_early_allocated; |
189 | 242 | ||
190 | static void * __init prom_early_alloc(unsigned long size) | 243 | static void * __init prom_early_alloc(unsigned long size) |
diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc64/kernel/prom.c index e9d703eea806..c62fd3e7a0f8 100644 --- a/arch/sparc64/kernel/prom.c +++ b/arch/sparc64/kernel/prom.c | |||
@@ -27,6 +27,11 @@ | |||
27 | 27 | ||
28 | static struct device_node *allnodes; | 28 | static struct device_node *allnodes; |
29 | 29 | ||
30 | /* use when traversing tree through the allnext, child, sibling, | ||
31 | * or parent members of struct device_node. | ||
32 | */ | ||
33 | static DEFINE_RWLOCK(devtree_lock); | ||
34 | |||
30 | int of_device_is_compatible(struct device_node *device, const char *compat) | 35 | int of_device_is_compatible(struct device_node *device, const char *compat) |
31 | { | 36 | { |
32 | const char* cp; | 37 | const char* cp; |
@@ -185,6 +190,54 @@ int of_getintprop_default(struct device_node *np, const char *name, int def) | |||
185 | } | 190 | } |
186 | EXPORT_SYMBOL(of_getintprop_default); | 191 | EXPORT_SYMBOL(of_getintprop_default); |
187 | 192 | ||
193 | int of_set_property(struct device_node *dp, const char *name, void *val, int len) | ||
194 | { | ||
195 | struct property **prevp; | ||
196 | void *new_val; | ||
197 | int err; | ||
198 | |||
199 | new_val = kmalloc(len, GFP_KERNEL); | ||
200 | if (!new_val) | ||
201 | return -ENOMEM; | ||
202 | |||
203 | memcpy(new_val, val, len); | ||
204 | |||
205 | err = -ENODEV; | ||
206 | |||
207 | write_lock(&devtree_lock); | ||
208 | prevp = &dp->properties; | ||
209 | while (*prevp) { | ||
210 | struct property *prop = *prevp; | ||
211 | |||
212 | if (!strcmp(prop->name, name)) { | ||
213 | void *old_val = prop->value; | ||
214 | int ret; | ||
215 | |||
216 | ret = prom_setprop(dp->node, name, val, len); | ||
217 | err = -EINVAL; | ||
218 | if (ret >= 0) { | ||
219 | prop->value = new_val; | ||
220 | prop->length = len; | ||
221 | |||
222 | if (OF_IS_DYNAMIC(prop)) | ||
223 | kfree(old_val); | ||
224 | |||
225 | OF_MARK_DYNAMIC(prop); | ||
226 | |||
227 | err = 0; | ||
228 | } | ||
229 | break; | ||
230 | } | ||
231 | prevp = &(*prevp)->next; | ||
232 | } | ||
233 | write_unlock(&devtree_lock); | ||
234 | |||
235 | /* XXX Upate procfs if necessary... */ | ||
236 | |||
237 | return err; | ||
238 | } | ||
239 | EXPORT_SYMBOL(of_set_property); | ||
240 | |||
188 | static unsigned int prom_early_allocated; | 241 | static unsigned int prom_early_allocated; |
189 | 242 | ||
190 | static void * __init prom_early_alloc(unsigned long size) | 243 | static void * __init prom_early_alloc(unsigned long size) |
diff --git a/include/asm-sparc/prom.h b/include/asm-sparc/prom.h index c5e3d26eabd3..e9b8047470fe 100644 --- a/include/asm-sparc/prom.h +++ b/include/asm-sparc/prom.h | |||
@@ -35,6 +35,7 @@ struct property { | |||
35 | int length; | 35 | int length; |
36 | void *value; | 36 | void *value; |
37 | struct property *next; | 37 | struct property *next; |
38 | unsigned long _flags; | ||
38 | }; | 39 | }; |
39 | 40 | ||
40 | struct device_node { | 41 | struct device_node { |
@@ -60,6 +61,12 @@ struct device_node { | |||
60 | void *data; | 61 | void *data; |
61 | }; | 62 | }; |
62 | 63 | ||
64 | /* flag descriptions */ | ||
65 | #define OF_DYNAMIC 1 /* node and properties were allocated via kmalloc */ | ||
66 | |||
67 | #define OF_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags) | ||
68 | #define OF_MARK_DYNAMIC(x) set_bit(OF_DYNAMIC, &x->_flags) | ||
69 | |||
63 | static inline void set_node_proc_entry(struct device_node *dn, struct proc_dir_entry *de) | 70 | static inline void set_node_proc_entry(struct device_node *dn, struct proc_dir_entry *de) |
64 | { | 71 | { |
65 | dn->pde = de; | 72 | dn->pde = de; |
@@ -88,6 +95,7 @@ extern struct property *of_find_property(struct device_node *np, | |||
88 | extern int of_device_is_compatible(struct device_node *device, const char *); | 95 | extern int of_device_is_compatible(struct device_node *device, const char *); |
89 | extern void *of_get_property(struct device_node *node, const char *name, | 96 | extern void *of_get_property(struct device_node *node, const char *name, |
90 | int *lenp); | 97 | int *lenp); |
98 | extern int of_set_property(struct device_node *node, const char *name, void *val, int len); | ||
91 | extern int of_getintprop_default(struct device_node *np, | 99 | extern int of_getintprop_default(struct device_node *np, |
92 | const char *name, | 100 | const char *name, |
93 | int def); | 101 | int def); |
diff --git a/include/asm-sparc64/prom.h b/include/asm-sparc64/prom.h index 6d1556c0c263..c8022a337380 100644 --- a/include/asm-sparc64/prom.h +++ b/include/asm-sparc64/prom.h | |||
@@ -35,6 +35,7 @@ struct property { | |||
35 | int length; | 35 | int length; |
36 | void *value; | 36 | void *value; |
37 | struct property *next; | 37 | struct property *next; |
38 | unsigned long _flags; | ||
38 | }; | 39 | }; |
39 | 40 | ||
40 | struct device_node { | 41 | struct device_node { |
@@ -60,6 +61,12 @@ struct device_node { | |||
60 | void *data; | 61 | void *data; |
61 | }; | 62 | }; |
62 | 63 | ||
64 | /* flag descriptions */ | ||
65 | #define OF_DYNAMIC 1 /* node and properties were allocated via kmalloc */ | ||
66 | |||
67 | #define OF_IS_DYNAMIC(x) test_bit(OF_DYNAMIC, &x->_flags) | ||
68 | #define OF_MARK_DYNAMIC(x) set_bit(OF_DYNAMIC, &x->_flags) | ||
69 | |||
63 | static inline void set_node_proc_entry(struct device_node *dn, struct proc_dir_entry *de) | 70 | static inline void set_node_proc_entry(struct device_node *dn, struct proc_dir_entry *de) |
64 | { | 71 | { |
65 | dn->pde = de; | 72 | dn->pde = de; |
@@ -88,6 +95,7 @@ extern struct property *of_find_property(struct device_node *np, | |||
88 | extern int of_device_is_compatible(struct device_node *device, const char *); | 95 | extern int of_device_is_compatible(struct device_node *device, const char *); |
89 | extern void *of_get_property(struct device_node *node, const char *name, | 96 | extern void *of_get_property(struct device_node *node, const char *name, |
90 | int *lenp); | 97 | int *lenp); |
98 | extern int of_set_property(struct device_node *node, const char *name, void *val, int len); | ||
91 | extern int of_getintprop_default(struct device_node *np, | 99 | extern int of_getintprop_default(struct device_node *np, |
92 | const char *name, | 100 | const char *name, |
93 | int def); | 101 | int def); |