int dlpar_attach_node(struct device_node *dn) { struct proc_dir_entry *ent; int rc; of_node_set_flag(dn, OF_DYNAMIC); kref_init(&dn->kref); dn->parent = derive_parent(dn->full_name); if (!dn->parent) return -ENOMEM; rc = blocking_notifier_call_chain(&pSeries_reconfig_chain, PSERIES_RECONFIG_ADD, dn); if (rc == NOTIFY_BAD) { printk(KERN_ERR "Failed to add device node %s\n", dn->full_name); return -ENOMEM; /* For now, safe to assume kmalloc failure */ } of_attach_node(dn); #ifdef CONFIG_PROC_DEVICETREE ent = proc_mkdir(strrchr(dn->full_name, '/') + 1, dn->parent->pde); if (ent) proc_device_tree_add_node(dn, ent); #endif of_node_put(dn->parent); return 0; }
static struct device_node *dlpar_parse_cc_node(struct cc_workarea *ccwa, const char *path) { struct device_node *dn; char *name; /* If parent node path is "/" advance path to NULL terminator to * prevent double leading slashs in full_name. */ if (!path[1]) path++; dn = kzalloc(sizeof(*dn), GFP_KERNEL); if (!dn) return NULL; name = (char *)ccwa + be32_to_cpu(ccwa->name_offset); dn->full_name = kasprintf(GFP_KERNEL, "%s/%s", path, name); if (!dn->full_name) { kfree(dn); return NULL; } of_node_set_flag(dn, OF_DYNAMIC); of_node_init(dn); return dn; }
static struct device_node * __init tilcdc_get_overlay(struct kfree_table *kft) { const int size = __dtb_tilcdc_slave_compat_end - __dtb_tilcdc_slave_compat_begin; static void *overlay_data; struct device_node *overlay; int ret; if (!size) { pr_warn("%s: No overlay data\n", __func__); return NULL; } overlay_data = kmemdup(__dtb_tilcdc_slave_compat_begin, size, GFP_KERNEL); if (!overlay_data || kfree_table_add(kft, overlay_data)) return NULL; of_fdt_unflatten_tree(overlay_data, NULL, &overlay); if (!overlay) { pr_warn("%s: Unfattening overlay tree failed\n", __func__); return NULL; } of_node_set_flag(overlay, OF_DETACHED); ret = of_resolve_phandles(overlay); if (ret) { pr_err("%s: Failed to resolve phandles: %d\n", __func__, ret); return NULL; } return overlay; }
/** * dtbocfg_overlay_create() - Create Device Tree Overlay * @overlay: Pointer to Device Tree Overlay Item * return Success(0) or Error Status. */ static int dtbocfg_overlay_item_create(struct dtbocfg_overlay_item *overlay) { int ret_val; of_fdt_unflatten_tree(overlay->dtbo, &overlay->node); if (overlay->node == NULL) { pr_err("%s: failed to unflatten tree\n", __func__); ret_val = -EINVAL; goto failed; } pr_debug("%s: unflattened OK\n", __func__); of_node_set_flag(overlay->node, OF_DETACHED); ret_val = of_resolve_phandles(overlay->node); if (ret_val != 0) { pr_err("%s: Failed to resolve tree\n", __func__); goto failed; } pr_debug("%s: resolved OK\n", __func__); ret_val = of_overlay_create(overlay->node); if (ret_val < 0) { pr_err("%s: Failed to create overlay (ret_val=%d)\n", __func__, ret_val); goto failed; } overlay->id = ret_val; pr_debug("%s: create OK\n", __func__); return 0; failed: return ret_val; }
int dlpar_attach_node(struct device_node *dn) { #ifdef CONFIG_PROC_DEVICETREE struct proc_dir_entry *ent; #endif int rc; of_node_set_flag(dn, OF_DYNAMIC); kref_init(&dn->kref); dn->parent = derive_parent(dn->full_name); if (!dn->parent) return -ENOMEM; rc = pSeries_reconfig_notify(PSERIES_RECONFIG_ADD, dn); if (rc) { printk(KERN_ERR "Failed to add device node %s\n", dn->full_name); return rc; } of_attach_node(dn); #ifdef CONFIG_PROC_DEVICETREE ent = proc_mkdir(strrchr(dn->full_name, '/') + 1, dn->parent->pde); if (ent) proc_device_tree_add_node(dn, ent); #endif of_node_put(dn->parent); return 0; }
/** * __unflatten_device_tree - create tree of device_nodes from flat blob * * unflattens a device-tree, creating the * tree of struct device_node. It also fills the "name" and "type" * pointers of the nodes so the normal device-tree walking functions * can be used. * @blob: The blob to expand * @dad: Parent device node * @mynodes: The device_node tree created by the call * @dt_alloc: An allocator that provides a virtual address to memory * for the resulting tree * * Returns NULL on failure or the memory chunk containing the unflattened * device tree on success. */ static void *__unflatten_device_tree(const void *blob, struct device_node *dad, struct device_node **mynodes, void *(*dt_alloc)(u64 size, u64 align), bool detached) { int size; void *mem; pr_debug(" -> unflatten_device_tree()\n"); if (!blob) { pr_debug("No device tree pointer\n"); return NULL; } pr_debug("Unflattening device tree:\n"); pr_debug("magic: %08x\n", fdt_magic(blob)); pr_debug("size: %08x\n", fdt_totalsize(blob)); pr_debug("version: %08x\n", fdt_version(blob)); if (fdt_check_header(blob)) { pr_err("Invalid device tree blob header\n"); return NULL; } /* First pass, scan for size */ size = unflatten_dt_nodes(blob, NULL, dad, NULL); if (size < 0) return NULL; size = ALIGN(size, 4); pr_debug(" size is %d, allocating...\n", size); /* Allocate memory for the expanded device tree */ mem = dt_alloc(size + 4, __alignof__(struct device_node)); memset(mem, 0, size); *(__be32 *)(mem + size) = cpu_to_be32(0xdeadbeef); pr_debug(" unflattening %p...\n", mem); /* Second pass, do actual unflattening */ unflatten_dt_nodes(blob, mem, dad, mynodes); if (be32_to_cpup(mem + size) != 0xdeadbeef) pr_warning("End of tree marker overwritten: %08x\n", be32_to_cpup(mem + size)); if (detached && mynodes) { of_node_set_flag(*mynodes, OF_DETACHED); pr_debug("unflattened tree is detached\n"); } pr_debug(" <- unflatten_device_tree()\n"); return mem; }
int dlpar_attach_node(struct device_node *dn) { #ifdef CONFIG_PROC_DEVICETREE struct proc_dir_entry *ent; #endif int rc; of_node_set_flag(dn, OF_DYNAMIC); kref_init(&dn->kref); dn->parent = derive_parent(dn->full_name); if (!dn->parent) return -ENOMEM; <<<<<<< HEAD
static struct device_node *new_node(const char *path, struct device_node *parent) { struct device_node *np = kzalloc(sizeof(*np), GFP_KERNEL); if (!np) return NULL; np->full_name = kstrdup(path, GFP_KERNEL); if (!np->full_name) { kfree(np); return NULL; } of_node_set_flag(np, OF_DYNAMIC); kref_init(&np->kref); np->parent = of_node_get(parent); return np; }
int dlpar_attach_node(struct device_node *dn) { int rc; of_node_set_flag(dn, OF_DYNAMIC); kref_init(&dn->kref); dn->parent = derive_parent(dn->full_name); if (!dn->parent) return -ENOMEM; rc = of_attach_node(dn); if (rc) { printk(KERN_ERR "Failed to add device node %s\n", dn->full_name); return rc; } of_node_put(dn->parent); return 0; }
/** * of_detach_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. */ 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); }