Dynamic programming ops will modify the dt_host and there might be other
 function which are browsing the dt_host at the same time. To avoid the race
 conditions, adding rwlock for browsing the dt_host.

Signed-off-by: Vikram Garhwal <[email protected]>
---
 xen/common/device_tree.c      | 27 +++++++++++++++++++++++++++
 xen/include/xen/device_tree.h |  6 ++++++
 2 files changed, 33 insertions(+)

diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c
index acf26a411d..51ee2a5edf 100644
--- a/xen/common/device_tree.c
+++ b/xen/common/device_tree.c
@@ -140,6 +140,8 @@ const struct dt_property *dt_find_property(const struct 
dt_device_node *np,
     if ( !np )
         return NULL;
 
+    read_lock(&dt_host->lock);
+
     for ( pp = np->properties; pp; pp = pp->next )
     {
         if ( dt_prop_cmp(pp->name, name) == 0 )
@@ -150,6 +152,7 @@ const struct dt_property *dt_find_property(const struct 
dt_device_node *np,
         }
     }
 
+    read_unlock(&dt_host->lock);
     return pp;
 }
 
@@ -336,11 +339,14 @@ struct dt_device_node *dt_find_node_by_name(struct 
dt_device_node *from,
     struct dt_device_node *np;
     struct dt_device_node *dt;
 
+    read_lock(&dt_host->lock);
+
     dt = from ? from->allnext : dt_host;
     dt_for_each_device_node(dt, np)
         if ( np->name && (dt_node_cmp(np->name, name) == 0) )
             break;
 
+    read_unlock(&dt_host->lock);
     return np;
 }
 
@@ -350,11 +356,14 @@ struct dt_device_node *dt_find_node_by_type(struct 
dt_device_node *from,
     struct dt_device_node *np;
     struct dt_device_node *dt;
 
+    read_lock(&dt_host->lock);
+
     dt = from ? from->allnext : dt_host;
     dt_for_each_device_node(dt, np)
         if ( np->type && (dt_node_cmp(np->type, type) == 0) )
             break;
 
+    read_unlock(&dt_host->lock);
     return np;
 }
 
@@ -363,10 +372,13 @@ struct dt_device_node 
*device_tree_find_node_by_path(struct dt_device_node *dt,
 {
     struct dt_device_node *np;
 
+    read_lock(&dt_host->lock);
+
     dt_for_each_device_node(dt, np)
         if ( np->full_name && (dt_node_cmp(np->full_name, path) == 0) )
             break;
 
+    read_unlock(&dt_host->lock);
     return np;
 }
 
@@ -450,6 +462,8 @@ dt_find_compatible_node(struct dt_device_node *from,
     struct dt_device_node *np;
     struct dt_device_node *dt;
 
+    read_lock(&dt_host->lock);
+
     dt = from ? from->allnext : dt_host;
     dt_for_each_device_node(dt, np)
     {
@@ -460,6 +474,7 @@ dt_find_compatible_node(struct dt_device_node *from,
             break;
     }
 
+    read_unlock(&dt_host->lock);
     return np;
 }
 
@@ -470,13 +485,19 @@ dt_find_matching_node(struct dt_device_node *from,
     struct dt_device_node *np;
     struct dt_device_node *dt;
 
+    read_lock(&dt_host->lock);
+
     dt = from ? from->allnext : dt_host;
     dt_for_each_device_node(dt, np)
     {
         if ( dt_match_node(matches, np) )
+        {
+            read_unlock(&dt_host->lock);
             return np;
+        }
     }
 
+    read_unlock(&dt_host->lock);
     return NULL;
 }
 
@@ -1052,10 +1073,13 @@ struct dt_device_node 
*dt_find_node_by_phandle(dt_phandle handle)
 {
     struct dt_device_node *np;
 
+    read_lock(&dt_host->lock);
+
     dt_for_each_device_node(dt_host, np)
         if ( np->phandle == handle )
             break;
 
+    read_unlock(&dt_host->lock);
     return np;
 }
 
@@ -2102,6 +2126,9 @@ int unflatten_device_tree(const void *fdt, struct 
dt_device_node **mynodes)
 
     dt_dprintk(" <- unflatten_device_tree()\n");
 
+    /* Init r/w lock for host device tree. */
+    rwlock_init(&dt_host->lock);
+
     return 0;
 }
 
diff --git a/xen/include/xen/device_tree.h b/xen/include/xen/device_tree.h
index 51e251b0b4..bafc898f1c 100644
--- a/xen/include/xen/device_tree.h
+++ b/xen/include/xen/device_tree.h
@@ -18,6 +18,7 @@
 #include <xen/string.h>
 #include <xen/types.h>
 #include <xen/list.h>
+#include <xen/rwlock.h>
 
 #define DEVICE_TREE_MAX_DEPTH 16
 
@@ -106,6 +107,11 @@ struct dt_device_node {
     struct list_head domain_list;
 
     struct device dev;
+
+    /*
+     * Lock that protects r/w updates to unflattened device tree i.e. dt_host.
+     */
+    rwlock_t lock;
 };
 
 #define dt_to_dev(dt_node)  (&(dt_node)->dev)
-- 
2.17.1


Reply via email to