aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/prom.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc64/kernel/prom.c')
-rw-r--r--arch/sparc64/kernel/prom.c107
1 files changed, 89 insertions, 18 deletions
diff --git a/arch/sparc64/kernel/prom.c b/arch/sparc64/kernel/prom.c
index e9d703eea806..8e87e7ea0325 100644
--- a/arch/sparc64/kernel/prom.c
+++ b/arch/sparc64/kernel/prom.c
@@ -27,6 +27,11 @@
27 27
28static struct device_node *allnodes; 28static 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 */
33static DEFINE_RWLOCK(devtree_lock);
34
30int of_device_is_compatible(struct device_node *device, const char *compat) 35int 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}
186EXPORT_SYMBOL(of_getintprop_default); 191EXPORT_SYMBOL(of_getintprop_default);
187 192
193int 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}
239EXPORT_SYMBOL(of_set_property);
240
188static unsigned int prom_early_allocated; 241static unsigned int prom_early_allocated;
189 242
190static void * __init prom_early_alloc(unsigned long size) 243static void * __init prom_early_alloc(unsigned long size)
@@ -531,7 +584,9 @@ static char * __init build_full_name(struct device_node *dp)
531 return n; 584 return n;
532} 585}
533 586
534static struct property * __init build_one_prop(phandle node, char *prev) 587static unsigned int unique_id;
588
589static struct property * __init build_one_prop(phandle node, char *prev, char *special_name, void *special_val, int special_len)
535{ 590{
536 static struct property *tmp = NULL; 591 static struct property *tmp = NULL;
537 struct property *p; 592 struct property *p;
@@ -540,25 +595,35 @@ static struct property * __init build_one_prop(phandle node, char *prev)
540 p = tmp; 595 p = tmp;
541 memset(p, 0, sizeof(*p) + 32); 596 memset(p, 0, sizeof(*p) + 32);
542 tmp = NULL; 597 tmp = NULL;
543 } else 598 } else {
544 p = prom_early_alloc(sizeof(struct property) + 32); 599 p = prom_early_alloc(sizeof(struct property) + 32);
600 p->unique_id = unique_id++;
601 }
545 602
546 p->name = (char *) (p + 1); 603 p->name = (char *) (p + 1);
547 if (prev == NULL) { 604 if (special_name) {
548 prom_firstprop(node, p->name); 605 strcpy(p->name, special_name);
606 p->length = special_len;
607 p->value = prom_early_alloc(special_len);
608 memcpy(p->value, special_val, special_len);
549 } else { 609 } else {
550 prom_nextprop(node, prev, p->name); 610 if (prev == NULL) {
551 } 611 prom_firstprop(node, p->name);
552 if (strlen(p->name) == 0) { 612 } else {
553 tmp = p; 613 prom_nextprop(node, prev, p->name);
554 return NULL; 614 }
555 } 615 if (strlen(p->name) == 0) {
556 p->length = prom_getproplen(node, p->name); 616 tmp = p;
557 if (p->length <= 0) { 617 return NULL;
558 p->length = 0; 618 }
559 } else { 619 p->length = prom_getproplen(node, p->name);
560 p->value = prom_early_alloc(p->length); 620 if (p->length <= 0) {
561 prom_getproperty(node, p->name, p->value, p->length); 621 p->length = 0;
622 } else {
623 p->value = prom_early_alloc(p->length + 1);
624 prom_getproperty(node, p->name, p->value, p->length);
625 ((unsigned char *)p->value)[p->length] = '\0';
626 }
562 } 627 }
563 return p; 628 return p;
564} 629}
@@ -567,9 +632,14 @@ static struct property * __init build_prop_list(phandle node)
567{ 632{
568 struct property *head, *tail; 633 struct property *head, *tail;
569 634
570 head = tail = build_one_prop(node, NULL); 635 head = tail = build_one_prop(node, NULL,
636 ".node", &node, sizeof(node));
637
638 tail->next = build_one_prop(node, NULL, NULL, NULL, 0);
639 tail = tail->next;
571 while(tail) { 640 while(tail) {
572 tail->next = build_one_prop(node, tail->name); 641 tail->next = build_one_prop(node, tail->name,
642 NULL, NULL, 0);
573 tail = tail->next; 643 tail = tail->next;
574 } 644 }
575 645
@@ -598,6 +668,7 @@ static struct device_node * __init create_node(phandle node)
598 return NULL; 668 return NULL;
599 669
600 dp = prom_early_alloc(sizeof(*dp)); 670 dp = prom_early_alloc(sizeof(*dp));
671 dp->unique_id = unique_id++;
601 672
602 kref_init(&dp->kref); 673 kref_init(&dp->kref);
603 674