aboutsummaryrefslogtreecommitdiffstats
path: root/arch/powerpc/kernel/prom.c
diff options
context:
space:
mode:
authorDave C Boutcher <sleddog@us.ibm.com>2006-01-12 17:08:27 -0500
committerPaul Mackerras <paulus@samba.org>2006-01-13 05:02:50 -0500
commit088186ded490ced80758200cf8f906ed741df306 (patch)
tree0afbaac2b9843937c63da79dfbd91a60f606c00f /arch/powerpc/kernel/prom.c
parent898b5395e915210f41223caa30312994d64cba1d (diff)
[PATCH] powerpc: Add/remove/update properties in firmware device tree
Add support for updating and removing device tree properties. Since we hand out pointers to properties with gay abandon, we can't just free the property storage. Instead we move deleted, or the old copy of an updated property, to a "dead properties" list. Also note, its not feasable to kref device tree properties. we call get_property() all over the kernel in a wild variety of contexts. One consequence of this change is that we now take a read_lock(&devtree_lock) when doing get_property(). Signed-off-by: Dave Boutcher <sleddog@us.ibm.com> Signed-off-by: Paul Mackerras <paulus@samba.org>
Diffstat (limited to 'arch/powerpc/kernel/prom.c')
-rw-r--r--arch/powerpc/kernel/prom.c90
1 files changed, 88 insertions, 2 deletions
diff --git a/arch/powerpc/kernel/prom.c b/arch/powerpc/kernel/prom.c
index 02e2115323e4..70057b63de21 100644
--- a/arch/powerpc/kernel/prom.c
+++ b/arch/powerpc/kernel/prom.c
@@ -1627,6 +1627,11 @@ static void of_node_release(struct kref *kref)
1627 kfree(prop->value); 1627 kfree(prop->value);
1628 kfree(prop); 1628 kfree(prop);
1629 prop = next; 1629 prop = next;
1630
1631 if (!prop) {
1632 prop = node->deadprops;
1633 node->deadprops = NULL;
1634 }
1630 } 1635 }
1631 kfree(node->intrs); 1636 kfree(node->intrs);
1632 kfree(node->full_name); 1637 kfree(node->full_name);
@@ -1783,13 +1788,16 @@ unsigned char *get_property(struct device_node *np, const char *name,
1783{ 1788{
1784 struct property *pp; 1789 struct property *pp;
1785 1790
1791 read_lock(&devtree_lock);
1786 for (pp = np->properties; pp != 0; pp = pp->next) 1792 for (pp = np->properties; pp != 0; pp = pp->next)
1787 if (strcmp(pp->name, name) == 0) { 1793 if (strcmp(pp->name, name) == 0) {
1788 if (lenp != 0) 1794 if (lenp != 0)
1789 *lenp = pp->length; 1795 *lenp = pp->length;
1790 return pp->value; 1796 break;
1791 } 1797 }
1792 return NULL; 1798 read_unlock(&devtree_lock);
1799
1800 return pp ? pp->value : NULL;
1793} 1801}
1794EXPORT_SYMBOL(get_property); 1802EXPORT_SYMBOL(get_property);
1795 1803
@@ -1823,4 +1831,82 @@ int prom_add_property(struct device_node* np, struct property* prop)
1823 return 0; 1831 return 0;
1824} 1832}
1825 1833
1834/*
1835 * Remove a property from a node. Note that we don't actually
1836 * remove it, since we have given out who-knows-how-many pointers
1837 * to the data using get-property. Instead we just move the property
1838 * to the "dead properties" list, so it won't be found any more.
1839 */
1840int prom_remove_property(struct device_node *np, struct property *prop)
1841{
1842 struct property **next;
1843 int found = 0;
1844
1845 write_lock(&devtree_lock);
1846 next = &np->properties;
1847 while (*next) {
1848 if (*next == prop) {
1849 /* found the node */
1850 *next = prop->next;
1851 prop->next = np->deadprops;
1852 np->deadprops = prop;
1853 found = 1;
1854 break;
1855 }
1856 next = &(*next)->next;
1857 }
1858 write_unlock(&devtree_lock);
1859
1860 if (!found)
1861 return -ENODEV;
1862
1863#ifdef CONFIG_PROC_DEVICETREE
1864 /* try to remove the proc node as well */
1865 if (np->pde)
1866 proc_device_tree_remove_prop(np->pde, prop);
1867#endif /* CONFIG_PROC_DEVICETREE */
1868
1869 return 0;
1870}
1871
1872/*
1873 * Update a property in a node. Note that we don't actually
1874 * remove it, since we have given out who-knows-how-many pointers
1875 * to the data using get-property. Instead we just move the property
1876 * to the "dead properties" list, and add the new property to the
1877 * property list
1878 */
1879int prom_update_property(struct device_node *np,
1880 struct property *newprop,
1881 struct property *oldprop)
1882{
1883 struct property **next;
1884 int found = 0;
1885
1886 write_lock(&devtree_lock);
1887 next = &np->properties;
1888 while (*next) {
1889 if (*next == oldprop) {
1890 /* found the node */
1891 newprop->next = oldprop->next;
1892 *next = newprop;
1893 oldprop->next = np->deadprops;
1894 np->deadprops = oldprop;
1895 found = 1;
1896 break;
1897 }
1898 next = &(*next)->next;
1899 }
1900 write_unlock(&devtree_lock);
1901
1902 if (!found)
1903 return -ENODEV;
1826 1904
1905#ifdef CONFIG_PROC_DEVICETREE
1906 /* try to add to proc as well if it was initialized */
1907 if (np->pde)
1908 proc_device_tree_update_prop(np->pde, newprop, oldprop);
1909#endif /* CONFIG_PROC_DEVICETREE */
1910
1911 return 0;
1912}