Skip to content

Commit

Permalink
OF: convert devtree lock from rw_lock to raw spinlock
Browse files Browse the repository at this point in the history
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 c2f21ce "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: Thomas Gleixner <tglx@linutronix.de>
[PG: taken from preempt-rt, update subject & add a commit log]
Signed-off-by: Paul Gortmaker <paul.gortmaker@windriver.com>
Signed-off-by: Rob Herring <rob.herring@calxeda.com>
  • Loading branch information
Thomas Gleixner authored and Rob Herring committed Feb 8, 2013
1 parent eb7ccb8 commit d6d3c4e
Show file tree
Hide file tree
Showing 3 changed files with 59 additions and 47 deletions.
4 changes: 2 additions & 2 deletions arch/sparc/kernel/prom_common.c
Original file line number Diff line number Diff line change
Expand Up @@ -64,7 +64,7 @@ int of_set_property(struct device_node *dp, const char *name, void *val, int len
err = -ENODEV;

mutex_lock(&of_set_property_mutex);
write_lock(&devtree_lock);
raw_spin_lock(&devtree_lock);
prevp = &dp->properties;
while (*prevp) {
struct property *prop = *prevp;
Expand All @@ -91,7 +91,7 @@ int of_set_property(struct device_node *dp, const char *name, void *val, int len
}
prevp = &(*prevp)->next;
}
write_unlock(&devtree_lock);
raw_spin_unlock(&devtree_lock);
mutex_unlock(&of_set_property_mutex);

/* XXX Upate procfs if necessary... */
Expand Down
100 changes: 56 additions & 44 deletions drivers/of/base.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,7 +55,7 @@ static DEFINE_MUTEX(of_aliases_mutex);
/* use when traversing tree through the allnext, child, sibling,
* 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)
{
Expand Down Expand Up @@ -188,10 +188,11 @@ struct property *of_find_property(const struct device_node *np,
int *lenp)
{
struct property *pp;
unsigned long flags;

read_lock(&devtree_lock);
raw_spin_lock_irqsave(&devtree_lock, flags);
pp = __of_find_property(np, name, lenp);
read_unlock(&devtree_lock);
raw_spin_unlock_irqrestore(&devtree_lock, flags);

return pp;
}
Expand All @@ -209,13 +210,13 @@ struct device_node *of_find_all_nodes(struct device_node *prev)
{
struct device_node *np;

read_lock(&devtree_lock);
raw_spin_lock(&devtree_lock);
np = prev ? prev->allnext : of_allnodes;
for (; np != NULL; np = np->allnext)
if (of_node_get(np))
break;
of_node_put(prev);
read_unlock(&devtree_lock);
raw_spin_unlock(&devtree_lock);
return np;
}
EXPORT_SYMBOL(of_find_all_nodes);
Expand Down Expand Up @@ -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,
const char *compat)
{
unsigned long flags;
int res;

read_lock(&devtree_lock);
raw_spin_lock_irqsave(&devtree_lock, flags);
res = __of_device_is_compatible(device, compat);
read_unlock(&devtree_lock);
raw_spin_unlock_irqrestore(&devtree_lock, flags);
return res;
}
EXPORT_SYMBOL(of_device_is_compatible);
Expand Down Expand Up @@ -340,13 +342,14 @@ EXPORT_SYMBOL(of_device_is_available);
struct device_node *of_get_parent(const struct device_node *node)
{
struct device_node *np;
unsigned long flags;

if (!node)
return NULL;

read_lock(&devtree_lock);
raw_spin_lock_irqsave(&devtree_lock, flags);
np = of_node_get(node->parent);
read_unlock(&devtree_lock);
raw_spin_unlock_irqrestore(&devtree_lock, flags);
return np;
}
EXPORT_SYMBOL(of_get_parent);
Expand All @@ -365,14 +368,15 @@ EXPORT_SYMBOL(of_get_parent);
struct device_node *of_get_next_parent(struct device_node *node)
{
struct device_node *parent;
unsigned long flags;

if (!node)
return NULL;

read_lock(&devtree_lock);
raw_spin_lock_irqsave(&devtree_lock, flags);
parent = of_node_get(node->parent);
of_node_put(node);
read_unlock(&devtree_lock);
raw_spin_unlock_irqrestore(&devtree_lock, flags);
return parent;
}

Expand All @@ -388,14 +392,15 @@ struct device_node *of_get_next_child(const struct device_node *node,
struct device_node *prev)
{
struct device_node *next;
unsigned long flags;

read_lock(&devtree_lock);
raw_spin_lock_irqsave(&devtree_lock, flags);
next = prev ? prev->sibling : node->child;
for (; next; next = next->sibling)
if (of_node_get(next))
break;
of_node_put(prev);
read_unlock(&devtree_lock);
raw_spin_unlock_irqrestore(&devtree_lock, flags);
return next;
}
EXPORT_SYMBOL(of_get_next_child);
Expand All @@ -413,7 +418,7 @@ struct device_node *of_get_next_available_child(const struct device_node *node,
{
struct device_node *next;

read_lock(&devtree_lock);
raw_spin_lock(&devtree_lock);
next = prev ? prev->sibling : node->child;
for (; next; next = next->sibling) {
if (!of_device_is_available(next))
Expand All @@ -422,7 +427,7 @@ struct device_node *of_get_next_available_child(const struct device_node *node,
break;
}
of_node_put(prev);
read_unlock(&devtree_lock);
raw_spin_unlock(&devtree_lock);
return next;
}
EXPORT_SYMBOL(of_get_next_available_child);
Expand Down Expand Up @@ -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 *np = of_allnodes;
unsigned long flags;

read_lock(&devtree_lock);
raw_spin_lock_irqsave(&devtree_lock, flags);
for (; np; np = np->allnext) {
if (np->full_name && (of_node_cmp(np->full_name, path) == 0)
&& of_node_get(np))
break;
}
read_unlock(&devtree_lock);
raw_spin_unlock_irqrestore(&devtree_lock, flags);
return np;
}
EXPORT_SYMBOL(of_find_node_by_path);
Expand All @@ -487,15 +493,16 @@ struct device_node *of_find_node_by_name(struct device_node *from,
const char *name)
{
struct device_node *np;
unsigned long flags;

read_lock(&devtree_lock);
raw_spin_lock_irqsave(&devtree_lock, flags);
np = from ? from->allnext : of_allnodes;
for (; np; np = np->allnext)
if (np->name && (of_node_cmp(np->name, name) == 0)
&& of_node_get(np))
break;
of_node_put(from);
read_unlock(&devtree_lock);
raw_spin_unlock_irqrestore(&devtree_lock, flags);
return np;
}
EXPORT_SYMBOL(of_find_node_by_name);
Expand All @@ -516,15 +523,16 @@ struct device_node *of_find_node_by_type(struct device_node *from,
const char *type)
{
struct device_node *np;
unsigned long flags;

read_lock(&devtree_lock);
raw_spin_lock_irqsave(&devtree_lock, flags);
np = from ? from->allnext : of_allnodes;
for (; np; np = np->allnext)
if (np->type && (of_node_cmp(np->type, type) == 0)
&& of_node_get(np))
break;
of_node_put(from);
read_unlock(&devtree_lock);
raw_spin_unlock_irqrestore(&devtree_lock, flags);
return np;
}
EXPORT_SYMBOL(of_find_node_by_type);
Expand All @@ -547,8 +555,9 @@ struct device_node *of_find_compatible_node(struct device_node *from,
const char *type, const char *compatible)
{
struct device_node *np;
unsigned long flags;

read_lock(&devtree_lock);
raw_spin_lock_irqsave(&devtree_lock, flags);
np = from ? from->allnext : of_allnodes;
for (; np; np = np->allnext) {
if (type
Expand All @@ -559,7 +568,7 @@ struct device_node *of_find_compatible_node(struct device_node *from,
break;
}
of_node_put(from);
read_unlock(&devtree_lock);
raw_spin_unlock_irqrestore(&devtree_lock, flags);
return np;
}
EXPORT_SYMBOL(of_find_compatible_node);
Expand All @@ -581,8 +590,9 @@ struct device_node *of_find_node_with_property(struct device_node *from,
{
struct device_node *np;
struct property *pp;
unsigned long flags;

read_lock(&devtree_lock);
raw_spin_lock_irqsave(&devtree_lock, flags);
np = from ? from->allnext : of_allnodes;
for (; np; np = np->allnext) {
for (pp = np->properties; pp; pp = pp->next) {
Expand All @@ -594,7 +604,7 @@ struct device_node *of_find_node_with_property(struct device_node *from,
}
out:
of_node_put(from);
read_unlock(&devtree_lock);
raw_spin_unlock_irqrestore(&devtree_lock, flags);
return np;
}
EXPORT_SYMBOL(of_find_node_with_property);
Expand Down Expand Up @@ -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 of_device_id *match;
unsigned long flags;

read_lock(&devtree_lock);
raw_spin_lock_irqsave(&devtree_lock, flags);
match = __of_match_node(matches, node);
read_unlock(&devtree_lock);
raw_spin_unlock_irqrestore(&devtree_lock, flags);
return match;
}
EXPORT_SYMBOL(of_match_node);
Expand All @@ -662,11 +673,12 @@ struct device_node *of_find_matching_node_and_match(struct device_node *from,
{
struct device_node *np;
const struct of_device_id *m;
unsigned long flags;

if (match)
*match = NULL;

read_lock(&devtree_lock);
raw_spin_lock_irqsave(&devtree_lock, flags);
np = from ? from->allnext : of_allnodes;
for (; np; np = np->allnext) {
m = __of_match_node(matches, np);
Expand All @@ -677,7 +689,7 @@ struct device_node *of_find_matching_node_and_match(struct device_node *from,
}
}
of_node_put(from);
read_unlock(&devtree_lock);
raw_spin_unlock_irqrestore(&devtree_lock, flags);
return np;
}
EXPORT_SYMBOL(of_find_matching_node_and_match);
Expand Down Expand Up @@ -720,12 +732,12 @@ struct device_node *of_find_node_by_phandle(phandle handle)
{
struct device_node *np;

read_lock(&devtree_lock);
raw_spin_lock(&devtree_lock);
for (np = of_allnodes; np; np = np->allnext)
if (np->phandle == handle)
break;
of_node_get(np);
read_unlock(&devtree_lock);
raw_spin_unlock(&devtree_lock);
return np;
}
EXPORT_SYMBOL(of_find_node_by_phandle);
Expand Down Expand Up @@ -1197,18 +1209,18 @@ int of_add_property(struct device_node *np, struct property *prop)
return rc;

prop->next = NULL;
write_lock_irqsave(&devtree_lock, flags);
raw_spin_lock_irqsave(&devtree_lock, flags);
next = &np->properties;
while (*next) {
if (strcmp(prop->name, (*next)->name) == 0) {
/* duplicate ! don't insert it */
write_unlock_irqrestore(&devtree_lock, flags);
raw_spin_unlock_irqrestore(&devtree_lock, flags);
return -1;
}
next = &(*next)->next;
}
*next = prop;
write_unlock_irqrestore(&devtree_lock, flags);
raw_spin_unlock_irqrestore(&devtree_lock, flags);

#ifdef CONFIG_PROC_DEVICETREE
/* try to add to proc as well if it was initialized */
Expand Down Expand Up @@ -1238,7 +1250,7 @@ int of_remove_property(struct device_node *np, struct property *prop)
if (rc)
return rc;

write_lock_irqsave(&devtree_lock, flags);
raw_spin_lock_irqsave(&devtree_lock, flags);
next = &np->properties;
while (*next) {
if (*next == prop) {
Expand All @@ -1251,7 +1263,7 @@ int of_remove_property(struct device_node *np, struct property *prop)
}
next = &(*next)->next;
}
write_unlock_irqrestore(&devtree_lock, flags);
raw_spin_unlock_irqrestore(&devtree_lock, flags);

if (!found)
return -ENODEV;
Expand Down Expand Up @@ -1291,7 +1303,7 @@ int of_update_property(struct device_node *np, struct property *newprop)
if (!oldprop)
return of_add_property(np, newprop);

write_lock_irqsave(&devtree_lock, flags);
raw_spin_lock_irqsave(&devtree_lock, flags);
next = &np->properties;
while (*next) {
if (*next == oldprop) {
Expand All @@ -1305,7 +1317,7 @@ int of_update_property(struct device_node *np, struct property *newprop)
}
next = &(*next)->next;
}
write_unlock_irqrestore(&devtree_lock, flags);
raw_spin_unlock_irqrestore(&devtree_lock, flags);

if (!found)
return -ENODEV;
Expand Down Expand Up @@ -1378,12 +1390,12 @@ int of_attach_node(struct device_node *np)
if (rc)
return rc;

write_lock_irqsave(&devtree_lock, flags);
raw_spin_lock_irqsave(&devtree_lock, flags);
np->sibling = np->parent->child;
np->allnext = of_allnodes;
np->parent->child = np;
of_allnodes = np;
write_unlock_irqrestore(&devtree_lock, flags);
raw_spin_unlock_irqrestore(&devtree_lock, flags);

of_add_proc_dt_entry(np);
return 0;
Expand Down Expand Up @@ -1426,17 +1438,17 @@ int of_detach_node(struct device_node *np)
if (rc)
return rc;

write_lock_irqsave(&devtree_lock, flags);
raw_spin_lock_irqsave(&devtree_lock, flags);

if (of_node_check_flag(np, OF_DETACHED)) {
/* someone already detached it */
write_unlock_irqrestore(&devtree_lock, flags);
raw_spin_unlock_irqrestore(&devtree_lock, flags);
return rc;
}

parent = np->parent;
if (!parent) {
write_unlock_irqrestore(&devtree_lock, flags);
raw_spin_unlock_irqrestore(&devtree_lock, flags);
return rc;
}

Expand All @@ -1463,7 +1475,7 @@ int of_detach_node(struct device_node *np)
}

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);
return rc;
Expand Down
Loading

0 comments on commit d6d3c4e

Please sign in to comment.