Exemplo n.º 1
0
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;
}
Exemplo n.º 2
0
Arquivo: dlpar.c Projeto: 3null/linux
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;
}
Exemplo n.º 3
0
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;
}
Exemplo n.º 4
0
/**
 * 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;
}
Exemplo n.º 5
0
Arquivo: dlpar.c Projeto: 08opt/linux
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;
}
Exemplo n.º 6
0
Arquivo: fdt.c Projeto: acton393/linux
/**
 * __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;
}
Exemplo n.º 7
0
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
Exemplo n.º 8
0
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;
}
Exemplo n.º 9
0
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;
}
Exemplo n.º 10
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);
}