]> xenbits.xensource.com Git - people/julieng/xen-unstable.git/commitdiff
xen/arm: Retrieve the correct number of cells when building dom0 DT
authorJulien Grall <julien.grall@citrix.com>
Tue, 29 Sep 2015 16:21:36 +0000 (17:21 +0100)
committerIan Campbell <ian.campbell@citrix.com>
Thu, 1 Oct 2015 12:51:29 +0000 (13:51 +0100)
The functions dt_n_*_cells return the number of cells for a "reg"
property of a given node. So those numbers won't be correct if the
parent of a given node is passed.

This is fine today because the parent is always the root node which
means there is no upper parent.

Introduce new helpers dt_child_n_*_cells to retrieve the number of
cells for the address and size that can be used to create the "reg"
property of the immediate child of a given parent. Also introduce
dt_child_set_range to pair up with dt_child_n_*_cells.

Use the new helpers when creating the hypervisor and memory node where
we only have the parent in hand. This is because those nodes are created
from scratch by Xen and therefore we don't have a dt_device_node for
them. The only thing we have is a pointer to their future parent.

Signed-off-by: Julien Grall <julien.grall@citrix.com>
Acked-by: Ian Campbell <ian.campbell@citrix.com>
xen/arch/arm/domain_build.c
xen/common/device_tree.c
xen/include/xen/device_tree.h

index 72b18452923329017469d9f1737977107dab670f..e8f024f7830e85244308ea137e8392980c386fdb 100644 (file)
@@ -569,7 +569,7 @@ static int make_memory_node(const struct domain *d,
                             const struct kernel_info *kinfo)
 {
     int res, i;
-    int reg_size = dt_n_addr_cells(parent) + dt_n_size_cells(parent);
+    int reg_size = dt_child_n_addr_cells(parent) + dt_child_n_size_cells(parent);
     int nr_cells = reg_size*kinfo->mem.nr_banks;
     __be32 reg[nr_cells];
     __be32 *cells;
@@ -594,7 +594,7 @@ static int make_memory_node(const struct domain *d,
         DPRINT("  Bank %d: %#"PRIx64"->%#"PRIx64"\n",
                 i, start, start + size);
 
-        dt_set_range(&cells, parent, start, size);
+        dt_child_set_range(&cells, parent, start, size);
     }
 
     res = fdt_property(fdt, "reg", reg, sizeof(reg));
@@ -617,8 +617,8 @@ static int make_hypervisor_node(const struct kernel_info *kinfo,
     __be32 *cells;
     int res;
     /* Convenience alias */
-    int addrcells = dt_n_addr_cells(parent);
-    int sizecells = dt_n_size_cells(parent);
+    int addrcells = dt_child_n_addr_cells(parent);
+    int sizecells = dt_child_n_size_cells(parent);
     void *fdt = kinfo->fdt;
 
     DPRINT("Create hypervisor node\n");
@@ -643,7 +643,7 @@ static int make_hypervisor_node(const struct kernel_info *kinfo,
 
     /* reg 0 is grant table space */
     cells = &reg[0];
-    dt_set_range(&cells, parent, kinfo->gnttab_start, kinfo->gnttab_size);
+    dt_child_set_range(&cells, parent, kinfo->gnttab_start, kinfo->gnttab_size);
     res = fdt_property(fdt, "reg", reg,
                        dt_cells_to_size(addrcells + sizecells));
     if ( res )
index 18cdb6f5f2065eb25c722c45a709a212ea923732..87c3f712da644ad741ee619a52cdc6c7324f46fc 100644 (file)
@@ -117,6 +117,13 @@ void dt_set_range(__be32 **cellp, const struct dt_device_node *np,
     dt_set_cell(cellp, dt_n_size_cells(np), size);
 }
 
+void dt_child_set_range(__be32 **cellp, const struct dt_device_node *parent,
+                        u64 address, u64 size)
+{
+    dt_set_cell(cellp, dt_child_n_addr_cells(parent), address);
+    dt_set_cell(cellp, dt_child_n_size_cells(parent), size);
+}
+
 static void __init *unflatten_dt_alloc(unsigned long *mem, unsigned long size,
                                        unsigned long align)
 {
@@ -386,13 +393,15 @@ dt_find_matching_node(struct dt_device_node *from,
     return NULL;
 }
 
-int dt_n_addr_cells(const struct dt_device_node *np)
+static int __dt_n_addr_cells(const struct dt_device_node *np, bool_t parent)
 {
     const __be32 *ip;
 
     do {
-        if ( np->parent )
+        if ( np->parent && !parent )
             np = np->parent;
+        parent = false;
+
         ip = dt_get_property(np, "#address-cells", NULL);
         if ( ip )
             return be32_to_cpup(ip);
@@ -401,13 +410,15 @@ int dt_n_addr_cells(const struct dt_device_node *np)
     return DT_ROOT_NODE_ADDR_CELLS_DEFAULT;
 }
 
-int dt_n_size_cells(const struct dt_device_node *np)
+int __dt_n_size_cells(const struct dt_device_node *np, bool_t parent)
 {
     const __be32 *ip;
 
     do {
-        if ( np->parent )
+        if ( np->parent && !parent )
             np = np->parent;
+        parent = false;
+
         ip = dt_get_property(np, "#size-cells", NULL);
         if ( ip )
             return be32_to_cpup(ip);
@@ -416,6 +427,26 @@ int dt_n_size_cells(const struct dt_device_node *np)
     return DT_ROOT_NODE_SIZE_CELLS_DEFAULT;
 }
 
+int dt_n_addr_cells(const struct dt_device_node *np)
+{
+    return __dt_n_addr_cells(np, false);
+}
+
+int dt_n_size_cells(const struct dt_device_node *np)
+{
+    return __dt_n_size_cells(np, false);
+}
+
+int dt_child_n_addr_cells(const struct dt_device_node *parent)
+{
+    return __dt_n_addr_cells(parent, true);
+}
+
+int dt_child_n_size_cells(const struct dt_device_node *parent)
+{
+    return __dt_n_size_cells(parent, true);
+}
+
 /*
  * These are defined in Linux where much of this code comes from, but
  * are currently unused outside this file in the context of Xen.
index 46c5ba8587ab16fe95a9486dce5caf8e9a9debf1..5c03f4027d51ab2a6467963abc61cfcfdc8a1715 100644 (file)
@@ -583,6 +583,25 @@ int dt_n_size_cells(const struct dt_device_node *np);
  */
 int dt_n_addr_cells(const struct dt_device_node *np);
 
+/**
+ * dt_child_n_size_cells - Helper to retrieve the number of cell for the size
+ * @parent: parent of the child to get the value
+ *
+ * This function retrieves for a given device-tree node the number of
+ * cell for the size field of there child
+ */
+int dt_child_n_size_cells(const struct dt_device_node *parent);
+
+/**
+ * dt_child_n_addr_cells - Helper to retrieve the number of cell for the
+ * address
+ * @parent: parent of the child to get the value
+ *
+ * This function retrieves for a given device-tree node the number of
+ * cell for the address field of there child
+ */
+int dt_child_n_addr_cells(const struct dt_device_node *parent);
+
 /**
  * dt_device_is_available - Check if a device is available for use
  *
@@ -654,6 +673,20 @@ void dt_set_cell(__be32 **cellp, int size, u64 val);
 void dt_set_range(__be32 **cellp, const struct dt_device_node *np,
                   u64 address, u64 size);
 
+/**
+ * dt_child_set_range - Write range into a series of cells
+ *
+ * @cellp: Pointer to cells
+ * @parent: Parent node which contains the encode for the address and the size
+ * @address: Start of range
+ * @size: Size of the range
+ *
+ * Write a range into a series of cells and update cellp to point to the
+ * cell just after.
+ */
+void dt_child_set_range(__be32 **cellp, const struct dt_device_node *parent,
+                        u64 address, u64 size);
+
 /**
  * dt_get_range - Read a range (address/size) from a series of cells
  *