aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/powerpc/kernel/prom.c90
-rw-r--r--include/asm-powerpc/prom.h5
2 files changed, 93 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}
diff --git a/include/asm-powerpc/prom.h b/include/asm-powerpc/prom.h
index 329e9bf62260..25d8d5974d19 100644
--- a/include/asm-powerpc/prom.h
+++ b/include/asm-powerpc/prom.h
@@ -87,6 +87,7 @@ struct device_node {
87 char *full_name; 87 char *full_name;
88 88
89 struct property *properties; 89 struct property *properties;
90 struct property *deadprops; /* removed properties */
90 struct device_node *parent; 91 struct device_node *parent;
91 struct device_node *child; 92 struct device_node *child;
92 struct device_node *sibling; 93 struct device_node *sibling;
@@ -164,6 +165,10 @@ extern int prom_n_size_cells(struct device_node* np);
164extern int prom_n_intr_cells(struct device_node* np); 165extern int prom_n_intr_cells(struct device_node* np);
165extern void prom_get_irq_senses(unsigned char *senses, int off, int max); 166extern void prom_get_irq_senses(unsigned char *senses, int off, int max);
166extern int prom_add_property(struct device_node* np, struct property* prop); 167extern int prom_add_property(struct device_node* np, struct property* prop);
168extern int prom_remove_property(struct device_node *np, struct property *prop);
169extern int prom_update_property(struct device_node *np,
170 struct property *newprop,
171 struct property *oldprop);
167 172
168#ifdef CONFIG_PPC32 173#ifdef CONFIG_PPC32
169/* 174/*