aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorXiubo Li <Li.Xiubo@freescale.com>2014-04-17 03:48:29 -0400
committerGrant Likely <grant.likely@linaro.org>2014-05-22 19:46:30 -0400
commit947fdaad0627e277c5f3a2573203c4fab3db513b (patch)
tree6fa7dd2901226991fe0f4c34e52a448f036a79a6
parentd2d3d7cd81e90e1ffac1a6eed7b3edcbf11f4c97 (diff)
of: fix race between search and remove in of_update_property()
The of_update_property() is intented to update a property in a node and if the property does not exist, will add it. The second search of the property is possibly won't be found, that maybe removed by other thread just before the second search begain. Using the __of_find_property() and __of_add_property() instead and move them into lock operations. Signed-off-by: Xiubo Li <Li.Xiubo@freescale.com> [grant.likely: conflict with another change in same function] Signed-off-by: Grant Likely <grant.likely@linaro.org>
-rw-r--r--drivers/of/base.c26
1 files changed, 15 insertions, 11 deletions
diff --git a/drivers/of/base.c b/drivers/of/base.c
index 6d4ee22708c9..63ae00ec72ff 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -1800,7 +1800,7 @@ int of_update_property(struct device_node *np, struct property *newprop)
1800{ 1800{
1801 struct property **next, *oldprop; 1801 struct property **next, *oldprop;
1802 unsigned long flags; 1802 unsigned long flags;
1803 int rc, found = 0; 1803 int rc;
1804 1804
1805 rc = of_property_notify(OF_RECONFIG_UPDATE_PROPERTY, np, newprop); 1805 rc = of_property_notify(OF_RECONFIG_UPDATE_PROPERTY, np, newprop);
1806 if (rc) 1806 if (rc)
@@ -1809,30 +1809,34 @@ int of_update_property(struct device_node *np, struct property *newprop)
1809 if (!newprop->name) 1809 if (!newprop->name)
1810 return -EINVAL; 1810 return -EINVAL;
1811 1811
1812 oldprop = of_find_property(np, newprop->name, NULL);
1813 if (!oldprop)
1814 return of_add_property(np, newprop);
1815
1816 raw_spin_lock_irqsave(&devtree_lock, flags); 1812 raw_spin_lock_irqsave(&devtree_lock, flags);
1817 next = &np->properties; 1813 next = &np->properties;
1818 while (*next) { 1814 oldprop = __of_find_property(np, newprop->name, NULL);
1815 if (!oldprop) {
1816 /* add the new node */
1817 rc = __of_add_property(np, newprop);
1818 } else while (*next) {
1819 /* replace the node */
1819 if (*next == oldprop) { 1820 if (*next == oldprop) {
1820 /* found the node */
1821 newprop->next = oldprop->next; 1821 newprop->next = oldprop->next;
1822 *next = newprop; 1822 *next = newprop;
1823 oldprop->next = np->deadprops; 1823 oldprop->next = np->deadprops;
1824 np->deadprops = oldprop; 1824 np->deadprops = oldprop;
1825 found = 1;
1826 break; 1825 break;
1827 } 1826 }
1828 next = &(*next)->next; 1827 next = &(*next)->next;
1829 } 1828 }
1830 raw_spin_unlock_irqrestore(&devtree_lock, flags); 1829 raw_spin_unlock_irqrestore(&devtree_lock, flags);
1831 if (!found) 1830 if (rc)
1832 return -ENODEV; 1831 return rc;
1832
1833 /* At early boot, bail out and defer setup to of_init() */
1834 if (!of_kset)
1835 return 0;
1833 1836
1834 /* Update the sysfs attribute */ 1837 /* Update the sysfs attribute */
1835 sysfs_remove_bin_file(&np->kobj, &oldprop->attr); 1838 if (oldprop)
1839 sysfs_remove_bin_file(&np->kobj, &oldprop->attr);
1836 __of_add_property_sysfs(np, newprop); 1840 __of_add_property_sysfs(np, newprop);
1837 1841
1838 return 0; 1842 return 0;