Commit d6d3c4e6 authored by Thomas Gleixner's avatar Thomas Gleixner Committed by Rob Herring

OF: convert devtree lock from rw_lock to raw spinlock

With the locking cleanup in place (from "OF: Fixup resursive
locking code paths"), we can now do the conversion from the
rw_lock to a raw spinlock as required for preempt-rt.

The previous cleanup and this conversion were originally
separate since they predated when mainline got raw spinlock (in
commit c2f21ce2 "locking: Implement new raw_spinlock").

So, at that point in time, the cleanup was considered plausible
for mainline, but not this conversion.  In any case, we've kept
them separate as it makes for easier review and better bisection.
Signed-off-by: default avatarThomas Gleixner <tglx@linutronix.de>
[PG: taken from preempt-rt, update subject & add a commit log]
Signed-off-by: default avatarPaul Gortmaker <paul.gortmaker@windriver.com>
Signed-off-by: default avatarRob Herring <rob.herring@calxeda.com>
parent eb7ccb81
...@@ -64,7 +64,7 @@ int of_set_property(struct device_node *dp, const char *name, void *val, int len ...@@ -64,7 +64,7 @@ int of_set_property(struct device_node *dp, const char *name, void *val, int len
err = -ENODEV; err = -ENODEV;
mutex_lock(&of_set_property_mutex); mutex_lock(&of_set_property_mutex);
write_lock(&devtree_lock); raw_spin_lock(&devtree_lock);
prevp = &dp->properties; prevp = &dp->properties;
while (*prevp) { while (*prevp) {
struct property *prop = *prevp; struct property *prop = *prevp;
...@@ -91,7 +91,7 @@ int of_set_property(struct device_node *dp, const char *name, void *val, int len ...@@ -91,7 +91,7 @@ int of_set_property(struct device_node *dp, const char *name, void *val, int len
} }
prevp = &(*prevp)->next; prevp = &(*prevp)->next;
} }
write_unlock(&devtree_lock); raw_spin_unlock(&devtree_lock);
mutex_unlock(&of_set_property_mutex); mutex_unlock(&of_set_property_mutex);
/* XXX Upate procfs if necessary... */ /* XXX Upate procfs if necessary... */
......
...@@ -55,7 +55,7 @@ static DEFINE_MUTEX(of_aliases_mutex); ...@@ -55,7 +55,7 @@ static DEFINE_MUTEX(of_aliases_mutex);
/* use when traversing tree through the allnext, child, sibling, /* use when traversing tree through the allnext, child, sibling,
* or parent members of struct device_node. * or parent members of struct device_node.
*/ */
DEFINE_RWLOCK(devtree_lock); DEFINE_RAW_SPINLOCK(devtree_lock);
int of_n_addr_cells(struct device_node *np) int of_n_addr_cells(struct device_node *np)
{ {
...@@ -188,10 +188,11 @@ struct property *of_find_property(const struct device_node *np, ...@@ -188,10 +188,11 @@ struct property *of_find_property(const struct device_node *np,
int *lenp) int *lenp)
{ {
struct property *pp; struct property *pp;
unsigned long flags;
read_lock(&devtree_lock); raw_spin_lock_irqsave(&devtree_lock, flags);
pp = __of_find_property(np, name, lenp); pp = __of_find_property(np, name, lenp);
read_unlock(&devtree_lock); raw_spin_unlock_irqrestore(&devtree_lock, flags);
return pp; return pp;
} }
...@@ -209,13 +210,13 @@ struct device_node *of_find_all_nodes(struct device_node *prev) ...@@ -209,13 +210,13 @@ struct device_node *of_find_all_nodes(struct device_node *prev)
{ {
struct device_node *np; struct device_node *np;
read_lock(&devtree_lock); raw_spin_lock(&devtree_lock);
np = prev ? prev->allnext : of_allnodes; np = prev ? prev->allnext : of_allnodes;
for (; np != NULL; np = np->allnext) for (; np != NULL; np = np->allnext)
if (of_node_get(np)) if (of_node_get(np))
break; break;
of_node_put(prev); of_node_put(prev);
read_unlock(&devtree_lock); raw_spin_unlock(&devtree_lock);
return np; return np;
} }
EXPORT_SYMBOL(of_find_all_nodes); EXPORT_SYMBOL(of_find_all_nodes);
...@@ -274,11 +275,12 @@ static int __of_device_is_compatible(const struct device_node *device, ...@@ -274,11 +275,12 @@ static int __of_device_is_compatible(const struct device_node *device,
int of_device_is_compatible(const struct device_node *device, int of_device_is_compatible(const struct device_node *device,
const char *compat) const char *compat)
{ {
unsigned long flags;
int res; int res;
read_lock(&devtree_lock); raw_spin_lock_irqsave(&devtree_lock, flags);
res = __of_device_is_compatible(device, compat); res = __of_device_is_compatible(device, compat);
read_unlock(&devtree_lock); raw_spin_unlock_irqrestore(&devtree_lock, flags);
return res; return res;
} }
EXPORT_SYMBOL(of_device_is_compatible); EXPORT_SYMBOL(of_device_is_compatible);
...@@ -340,13 +342,14 @@ EXPORT_SYMBOL(of_device_is_available); ...@@ -340,13 +342,14 @@ EXPORT_SYMBOL(of_device_is_available);
struct device_node *of_get_parent(const struct device_node *node) struct device_node *of_get_parent(const struct device_node *node)
{ {
struct device_node *np; struct device_node *np;
unsigned long flags;
if (!node) if (!node)
return NULL; return NULL;
read_lock(&devtree_lock); raw_spin_lock_irqsave(&devtree_lock, flags);
np = of_node_get(node->parent); np = of_node_get(node->parent);
read_unlock(&devtree_lock); raw_spin_unlock_irqrestore(&devtree_lock, flags);
return np; return np;
} }
EXPORT_SYMBOL(of_get_parent); EXPORT_SYMBOL(of_get_parent);
...@@ -365,14 +368,15 @@ EXPORT_SYMBOL(of_get_parent); ...@@ -365,14 +368,15 @@ EXPORT_SYMBOL(of_get_parent);
struct device_node *of_get_next_parent(struct device_node *node) struct device_node *of_get_next_parent(struct device_node *node)
{ {
struct device_node *parent; struct device_node *parent;
unsigned long flags;
if (!node) if (!node)
return NULL; return NULL;
read_lock(&devtree_lock); raw_spin_lock_irqsave(&devtree_lock, flags);
parent = of_node_get(node->parent); parent = of_node_get(node->parent);
of_node_put(node); of_node_put(node);
read_unlock(&devtree_lock); raw_spin_unlock_irqrestore(&devtree_lock, flags);
return parent; return parent;
} }
...@@ -388,14 +392,15 @@ struct device_node *of_get_next_child(const struct device_node *node, ...@@ -388,14 +392,15 @@ struct device_node *of_get_next_child(const struct device_node *node,
struct device_node *prev) struct device_node *prev)
{ {
struct device_node *next; struct device_node *next;
unsigned long flags;
read_lock(&devtree_lock); raw_spin_lock_irqsave(&devtree_lock, flags);
next = prev ? prev->sibling : node->child; next = prev ? prev->sibling : node->child;
for (; next; next = next->sibling) for (; next; next = next->sibling)
if (of_node_get(next)) if (of_node_get(next))
break; break;
of_node_put(prev); of_node_put(prev);
read_unlock(&devtree_lock); raw_spin_unlock_irqrestore(&devtree_lock, flags);
return next; return next;
} }
EXPORT_SYMBOL(of_get_next_child); EXPORT_SYMBOL(of_get_next_child);
...@@ -413,7 +418,7 @@ struct device_node *of_get_next_available_child(const struct device_node *node, ...@@ -413,7 +418,7 @@ struct device_node *of_get_next_available_child(const struct device_node *node,
{ {
struct device_node *next; struct device_node *next;
read_lock(&devtree_lock); raw_spin_lock(&devtree_lock);
next = prev ? prev->sibling : node->child; next = prev ? prev->sibling : node->child;
for (; next; next = next->sibling) { for (; next; next = next->sibling) {
if (!of_device_is_available(next)) if (!of_device_is_available(next))
...@@ -422,7 +427,7 @@ struct device_node *of_get_next_available_child(const struct device_node *node, ...@@ -422,7 +427,7 @@ struct device_node *of_get_next_available_child(const struct device_node *node,
break; break;
} }
of_node_put(prev); of_node_put(prev);
read_unlock(&devtree_lock); raw_spin_unlock(&devtree_lock);
return next; return next;
} }
EXPORT_SYMBOL(of_get_next_available_child); EXPORT_SYMBOL(of_get_next_available_child);
...@@ -460,14 +465,15 @@ EXPORT_SYMBOL(of_get_child_by_name); ...@@ -460,14 +465,15 @@ EXPORT_SYMBOL(of_get_child_by_name);
struct device_node *of_find_node_by_path(const char *path) struct device_node *of_find_node_by_path(const char *path)
{ {
struct device_node *np = of_allnodes; struct device_node *np = of_allnodes;
unsigned long flags;
read_lock(&devtree_lock); raw_spin_lock_irqsave(&devtree_lock, flags);
for (; np; np = np->allnext) { for (; np; np = np->allnext) {
if (np->full_name && (of_node_cmp(np->full_name, path) == 0) if (np->full_name && (of_node_cmp(np->full_name, path) == 0)
&& of_node_get(np)) && of_node_get(np))
break; break;
} }
read_unlock(&devtree_lock); raw_spin_unlock_irqrestore(&devtree_lock, flags);
return np; return np;
} }
EXPORT_SYMBOL(of_find_node_by_path); EXPORT_SYMBOL(of_find_node_by_path);
...@@ -487,15 +493,16 @@ struct device_node *of_find_node_by_name(struct device_node *from, ...@@ -487,15 +493,16 @@ struct device_node *of_find_node_by_name(struct device_node *from,
const char *name) const char *name)
{ {
struct device_node *np; struct device_node *np;
unsigned long flags;
read_lock(&devtree_lock); raw_spin_lock_irqsave(&devtree_lock, flags);
np = from ? from->allnext : of_allnodes; np = from ? from->allnext : of_allnodes;
for (; np; np = np->allnext) for (; np; np = np->allnext)
if (np->name && (of_node_cmp(np->name, name) == 0) if (np->name && (of_node_cmp(np->name, name) == 0)
&& of_node_get(np)) && of_node_get(np))
break; break;
of_node_put(from); of_node_put(from);
read_unlock(&devtree_lock); raw_spin_unlock_irqrestore(&devtree_lock, flags);
return np; return np;
} }
EXPORT_SYMBOL(of_find_node_by_name); EXPORT_SYMBOL(of_find_node_by_name);
...@@ -516,15 +523,16 @@ struct device_node *of_find_node_by_type(struct device_node *from, ...@@ -516,15 +523,16 @@ struct device_node *of_find_node_by_type(struct device_node *from,
const char *type) const char *type)
{ {
struct device_node *np; struct device_node *np;
unsigned long flags;
read_lock(&devtree_lock); raw_spin_lock_irqsave(&devtree_lock, flags);
np = from ? from->allnext : of_allnodes; np = from ? from->allnext : of_allnodes;
for (; np; np = np->allnext) for (; np; np = np->allnext)
if (np->type && (of_node_cmp(np->type, type) == 0) if (np->type && (of_node_cmp(np->type, type) == 0)
&& of_node_get(np)) && of_node_get(np))
break; break;
of_node_put(from); of_node_put(from);
read_unlock(&devtree_lock); raw_spin_unlock_irqrestore(&devtree_lock, flags);
return np; return np;
} }
EXPORT_SYMBOL(of_find_node_by_type); EXPORT_SYMBOL(of_find_node_by_type);
...@@ -547,8 +555,9 @@ struct device_node *of_find_compatible_node(struct device_node *from, ...@@ -547,8 +555,9 @@ struct device_node *of_find_compatible_node(struct device_node *from,
const char *type, const char *compatible) const char *type, const char *compatible)
{ {
struct device_node *np; struct device_node *np;
unsigned long flags;
read_lock(&devtree_lock); raw_spin_lock_irqsave(&devtree_lock, flags);
np = from ? from->allnext : of_allnodes; np = from ? from->allnext : of_allnodes;
for (; np; np = np->allnext) { for (; np; np = np->allnext) {
if (type if (type
...@@ -559,7 +568,7 @@ struct device_node *of_find_compatible_node(struct device_node *from, ...@@ -559,7 +568,7 @@ struct device_node *of_find_compatible_node(struct device_node *from,
break; break;
} }
of_node_put(from); of_node_put(from);
read_unlock(&devtree_lock); raw_spin_unlock_irqrestore(&devtree_lock, flags);
return np; return np;
} }
EXPORT_SYMBOL(of_find_compatible_node); EXPORT_SYMBOL(of_find_compatible_node);
...@@ -581,8 +590,9 @@ struct device_node *of_find_node_with_property(struct device_node *from, ...@@ -581,8 +590,9 @@ struct device_node *of_find_node_with_property(struct device_node *from,
{ {
struct device_node *np; struct device_node *np;
struct property *pp; struct property *pp;
unsigned long flags;
read_lock(&devtree_lock); raw_spin_lock_irqsave(&devtree_lock, flags);
np = from ? from->allnext : of_allnodes; np = from ? from->allnext : of_allnodes;
for (; np; np = np->allnext) { for (; np; np = np->allnext) {
for (pp = np->properties; pp; pp = pp->next) { for (pp = np->properties; pp; pp = pp->next) {
...@@ -594,7 +604,7 @@ struct device_node *of_find_node_with_property(struct device_node *from, ...@@ -594,7 +604,7 @@ struct device_node *of_find_node_with_property(struct device_node *from,
} }
out: out:
of_node_put(from); of_node_put(from);
read_unlock(&devtree_lock); raw_spin_unlock_irqrestore(&devtree_lock, flags);
return np; return np;
} }
EXPORT_SYMBOL(of_find_node_with_property); EXPORT_SYMBOL(of_find_node_with_property);
...@@ -635,10 +645,11 @@ const struct of_device_id *of_match_node(const struct of_device_id *matches, ...@@ -635,10 +645,11 @@ const struct of_device_id *of_match_node(const struct of_device_id *matches,
const struct device_node *node) const struct device_node *node)
{ {
const struct of_device_id *match; const struct of_device_id *match;
unsigned long flags;
read_lock(&devtree_lock); raw_spin_lock_irqsave(&devtree_lock, flags);
match = __of_match_node(matches, node); match = __of_match_node(matches, node);
read_unlock(&devtree_lock); raw_spin_unlock_irqrestore(&devtree_lock, flags);
return match; return match;
} }
EXPORT_SYMBOL(of_match_node); EXPORT_SYMBOL(of_match_node);
...@@ -662,11 +673,12 @@ struct device_node *of_find_matching_node_and_match(struct device_node *from, ...@@ -662,11 +673,12 @@ struct device_node *of_find_matching_node_and_match(struct device_node *from,
{ {
struct device_node *np; struct device_node *np;
const struct of_device_id *m; const struct of_device_id *m;
unsigned long flags;
if (match) if (match)
*match = NULL; *match = NULL;
read_lock(&devtree_lock); raw_spin_lock_irqsave(&devtree_lock, flags);
np = from ? from->allnext : of_allnodes; np = from ? from->allnext : of_allnodes;
for (; np; np = np->allnext) { for (; np; np = np->allnext) {
m = __of_match_node(matches, np); m = __of_match_node(matches, np);
...@@ -677,7 +689,7 @@ struct device_node *of_find_matching_node_and_match(struct device_node *from, ...@@ -677,7 +689,7 @@ struct device_node *of_find_matching_node_and_match(struct device_node *from,
} }
} }
of_node_put(from); of_node_put(from);
read_unlock(&devtree_lock); raw_spin_unlock_irqrestore(&devtree_lock, flags);
return np; return np;
} }
EXPORT_SYMBOL(of_find_matching_node_and_match); EXPORT_SYMBOL(of_find_matching_node_and_match);
...@@ -720,12 +732,12 @@ struct device_node *of_find_node_by_phandle(phandle handle) ...@@ -720,12 +732,12 @@ struct device_node *of_find_node_by_phandle(phandle handle)
{ {
struct device_node *np; struct device_node *np;
read_lock(&devtree_lock); raw_spin_lock(&devtree_lock);
for (np = of_allnodes; np; np = np->allnext) for (np = of_allnodes; np; np = np->allnext)
if (np->phandle == handle) if (np->phandle == handle)
break; break;
of_node_get(np); of_node_get(np);
read_unlock(&devtree_lock); raw_spin_unlock(&devtree_lock);
return np; return np;
} }
EXPORT_SYMBOL(of_find_node_by_phandle); EXPORT_SYMBOL(of_find_node_by_phandle);
...@@ -1197,18 +1209,18 @@ int of_add_property(struct device_node *np, struct property *prop) ...@@ -1197,18 +1209,18 @@ int of_add_property(struct device_node *np, struct property *prop)
return rc; return rc;
prop->next = NULL; prop->next = NULL;
write_lock_irqsave(&devtree_lock, flags); raw_spin_lock_irqsave(&devtree_lock, flags);
next = &np->properties; next = &np->properties;
while (*next) { while (*next) {
if (strcmp(prop->name, (*next)->name) == 0) { if (strcmp(prop->name, (*next)->name) == 0) {
/* duplicate ! don't insert it */ /* duplicate ! don't insert it */
write_unlock_irqrestore(&devtree_lock, flags); raw_spin_unlock_irqrestore(&devtree_lock, flags);
return -1; return -1;
} }
next = &(*next)->next; next = &(*next)->next;
} }
*next = prop; *next = prop;
write_unlock_irqrestore(&devtree_lock, flags); raw_spin_unlock_irqrestore(&devtree_lock, flags);
#ifdef CONFIG_PROC_DEVICETREE #ifdef CONFIG_PROC_DEVICETREE
/* try to add to proc as well if it was initialized */ /* try to add to proc as well if it was initialized */
...@@ -1238,7 +1250,7 @@ int of_remove_property(struct device_node *np, struct property *prop) ...@@ -1238,7 +1250,7 @@ int of_remove_property(struct device_node *np, struct property *prop)
if (rc) if (rc)
return rc; return rc;
write_lock_irqsave(&devtree_lock, flags); raw_spin_lock_irqsave(&devtree_lock, flags);
next = &np->properties; next = &np->properties;
while (*next) { while (*next) {
if (*next == prop) { if (*next == prop) {
...@@ -1251,7 +1263,7 @@ int of_remove_property(struct device_node *np, struct property *prop) ...@@ -1251,7 +1263,7 @@ int of_remove_property(struct device_node *np, struct property *prop)
} }
next = &(*next)->next; next = &(*next)->next;
} }
write_unlock_irqrestore(&devtree_lock, flags); raw_spin_unlock_irqrestore(&devtree_lock, flags);
if (!found) if (!found)
return -ENODEV; return -ENODEV;
...@@ -1291,7 +1303,7 @@ int of_update_property(struct device_node *np, struct property *newprop) ...@@ -1291,7 +1303,7 @@ int of_update_property(struct device_node *np, struct property *newprop)
if (!oldprop) if (!oldprop)
return of_add_property(np, newprop); return of_add_property(np, newprop);
write_lock_irqsave(&devtree_lock, flags); raw_spin_lock_irqsave(&devtree_lock, flags);
next = &np->properties; next = &np->properties;
while (*next) { while (*next) {
if (*next == oldprop) { if (*next == oldprop) {
...@@ -1305,7 +1317,7 @@ int of_update_property(struct device_node *np, struct property *newprop) ...@@ -1305,7 +1317,7 @@ int of_update_property(struct device_node *np, struct property *newprop)
} }
next = &(*next)->next; next = &(*next)->next;
} }
write_unlock_irqrestore(&devtree_lock, flags); raw_spin_unlock_irqrestore(&devtree_lock, flags);
if (!found) if (!found)
return -ENODEV; return -ENODEV;
...@@ -1378,12 +1390,12 @@ int of_attach_node(struct device_node *np) ...@@ -1378,12 +1390,12 @@ int of_attach_node(struct device_node *np)
if (rc) if (rc)
return rc; return rc;
write_lock_irqsave(&devtree_lock, flags); raw_spin_lock_irqsave(&devtree_lock, flags);
np->sibling = np->parent->child; np->sibling = np->parent->child;
np->allnext = of_allnodes; np->allnext = of_allnodes;
np->parent->child = np; np->parent->child = np;
of_allnodes = np; of_allnodes = np;
write_unlock_irqrestore(&devtree_lock, flags); raw_spin_unlock_irqrestore(&devtree_lock, flags);
of_add_proc_dt_entry(np); of_add_proc_dt_entry(np);
return 0; return 0;
...@@ -1426,17 +1438,17 @@ int of_detach_node(struct device_node *np) ...@@ -1426,17 +1438,17 @@ int of_detach_node(struct device_node *np)
if (rc) if (rc)
return rc; return rc;
write_lock_irqsave(&devtree_lock, flags); raw_spin_lock_irqsave(&devtree_lock, flags);
if (of_node_check_flag(np, OF_DETACHED)) { if (of_node_check_flag(np, OF_DETACHED)) {
/* someone already detached it */ /* someone already detached it */
write_unlock_irqrestore(&devtree_lock, flags); raw_spin_unlock_irqrestore(&devtree_lock, flags);
return rc; return rc;
} }
parent = np->parent; parent = np->parent;
if (!parent) { if (!parent) {
write_unlock_irqrestore(&devtree_lock, flags); raw_spin_unlock_irqrestore(&devtree_lock, flags);
return rc; return rc;
} }
...@@ -1463,7 +1475,7 @@ int of_detach_node(struct device_node *np) ...@@ -1463,7 +1475,7 @@ int of_detach_node(struct device_node *np)
} }
of_node_set_flag(np, OF_DETACHED); of_node_set_flag(np, OF_DETACHED);
write_unlock_irqrestore(&devtree_lock, flags); raw_spin_unlock_irqrestore(&devtree_lock, flags);
of_remove_proc_dt_entry(np); of_remove_proc_dt_entry(np);
return rc; return rc;
......
...@@ -92,7 +92,7 @@ static inline void of_node_put(struct device_node *node) { } ...@@ -92,7 +92,7 @@ static inline void of_node_put(struct device_node *node) { }
extern struct device_node *of_allnodes; extern struct device_node *of_allnodes;
extern struct device_node *of_chosen; extern struct device_node *of_chosen;
extern struct device_node *of_aliases; extern struct device_node *of_aliases;
extern rwlock_t devtree_lock; extern raw_spinlock_t devtree_lock;
static inline bool of_have_populated_dt(void) static inline bool of_have_populated_dt(void)
{ {
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment