Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

of: Reorder device tree changes and notifiers

Currently, devicetree reconfig notifiers get emitted before the change
is applied to the tree, but that behaviour is problematic if the
receiver wants the determine the new state of the tree. The current
users don't care, but the changeset code to follow will be making
multiple changes at once. Reorder notifiers to get emitted after the
change has been applied to the tree so that callbacks see the new tree
state.

At the same time, fixup the existing callbacks to expect the new order.
There are a few callbacks that compare the old and new values of a
changed property. Put both property pointers into the of_prop_reconfig
structure.

The current notifiers also allow the notifier callback to fail and
cancel the change to the tree, but that feature isn't actually used.
It really isn't valid to ignore a tree modification provided by firmware
anyway, so remove the ability to cancel a change to the tree.

Signed-off-by: Grant Likely <grant.likely@linaro.org>
Cc: Nathan Fontenot <nfont@austin.ibm.com>

+29 -47
+1 -1
arch/powerpc/platforms/pseries/hotplug-memory.c
··· 194 194 if (!memblock_size) 195 195 return -EINVAL; 196 196 197 - p = (u32 *)of_get_property(pr->dn, "ibm,dynamic-memory", NULL); 197 + p = (u32 *) pr->old_prop->value; 198 198 if (!p) 199 199 return -EINVAL; 200 200
+8 -22
drivers/crypto/nx/nx-842.c
··· 936 936 goto error_out; 937 937 } 938 938 939 - /* Set ptr to new property if provided */ 940 - if (new_prop) { 941 - /* Single property */ 942 - if (!strncmp(new_prop->name, "status", new_prop->length)) { 943 - status = new_prop; 944 - 945 - } else if (!strncmp(new_prop->name, "ibm,max-sg-len", 946 - new_prop->length)) { 947 - maxsglen = new_prop; 948 - 949 - } else if (!strncmp(new_prop->name, "ibm,max-sync-cop", 950 - new_prop->length)) { 951 - maxsyncop = new_prop; 952 - 953 - } else { 954 - /* 955 - * Skip the update, the property being updated 956 - * has no impact. 957 - */ 958 - goto out; 959 - } 960 - } 939 + /* 940 + * If this is a property update, there are only certain properties that 941 + * we care about. Bail if it isn't in the below list 942 + */ 943 + if (new_prop && (strncmp(new_prop->name, "status", new_prop->length) || 944 + strncmp(new_prop->name, "ibm,max-sg-len", new_prop->length) || 945 + strncmp(new_prop->name, "ibm,max-sync-cop", new_prop->length))) 946 + goto out; 961 947 962 948 /* Perform property updates */ 963 949 ret = nx842_OF_upd_status(new_devdata, status);
+9 -12
drivers/of/base.c
··· 1674 1674 unsigned long flags; 1675 1675 int rc; 1676 1676 1677 - rc = of_property_notify(OF_RECONFIG_ADD_PROPERTY, np, prop); 1678 - if (rc) 1679 - return rc; 1680 - 1681 1677 mutex_lock(&of_mutex); 1682 1678 1683 1679 raw_spin_lock_irqsave(&devtree_lock, flags); ··· 1684 1688 __of_add_property_sysfs(np, prop); 1685 1689 1686 1690 mutex_unlock(&of_mutex); 1691 + 1692 + if (!rc) 1693 + of_property_notify(OF_RECONFIG_ADD_PROPERTY, np, prop, NULL); 1687 1694 1688 1695 return rc; 1689 1696 } ··· 1730 1731 unsigned long flags; 1731 1732 int rc; 1732 1733 1733 - rc = of_property_notify(OF_RECONFIG_REMOVE_PROPERTY, np, prop); 1734 - if (rc) 1735 - return rc; 1736 - 1737 1734 mutex_lock(&of_mutex); 1738 1735 1739 1736 raw_spin_lock_irqsave(&devtree_lock, flags); ··· 1740 1745 __of_remove_property_sysfs(np, prop); 1741 1746 1742 1747 mutex_unlock(&of_mutex); 1748 + 1749 + if (!rc) 1750 + of_property_notify(OF_RECONFIG_REMOVE_PROPERTY, np, prop, NULL); 1743 1751 1744 1752 return rc; 1745 1753 } ··· 1803 1805 if (!newprop->name) 1804 1806 return -EINVAL; 1805 1807 1806 - rc = of_property_notify(OF_RECONFIG_UPDATE_PROPERTY, np, newprop); 1807 - if (rc) 1808 - return rc; 1809 - 1810 1808 mutex_lock(&of_mutex); 1811 1809 1812 1810 raw_spin_lock_irqsave(&devtree_lock, flags); ··· 1813 1819 __of_update_property_sysfs(np, newprop, oldprop); 1814 1820 1815 1821 mutex_unlock(&of_mutex); 1822 + 1823 + if (!rc) 1824 + of_property_notify(OF_RECONFIG_UPDATE_PROPERTY, np, newprop, oldprop); 1816 1825 1817 1826 return rc; 1818 1827 }
+8 -10
drivers/of/dynamic.c
··· 83 83 } 84 84 85 85 int of_property_notify(int action, struct device_node *np, 86 - struct property *prop) 86 + struct property *prop, struct property *oldprop) 87 87 { 88 88 struct of_prop_reconfig pr; 89 89 ··· 93 93 94 94 pr.dn = np; 95 95 pr.prop = prop; 96 + pr.old_prop = oldprop; 96 97 return of_reconfig_notify(action, &pr); 97 98 } 98 99 ··· 126 125 int of_attach_node(struct device_node *np) 127 126 { 128 127 unsigned long flags; 129 - int rc; 130 - 131 - rc = of_reconfig_notify(OF_RECONFIG_ATTACH_NODE, np); 132 - if (rc) 133 - return rc; 134 128 135 129 mutex_lock(&of_mutex); 136 130 raw_spin_lock_irqsave(&devtree_lock, flags); ··· 134 138 135 139 __of_attach_node_sysfs(np); 136 140 mutex_unlock(&of_mutex); 141 + 142 + of_reconfig_notify(OF_RECONFIG_ATTACH_NODE, np); 143 + 137 144 return 0; 138 145 } 139 146 ··· 187 188 unsigned long flags; 188 189 int rc = 0; 189 190 190 - rc = of_reconfig_notify(OF_RECONFIG_DETACH_NODE, np); 191 - if (rc) 192 - return rc; 193 - 194 191 mutex_lock(&of_mutex); 195 192 raw_spin_lock_irqsave(&devtree_lock, flags); 196 193 __of_detach_node(np); ··· 194 199 195 200 __of_detach_node_sysfs(np); 196 201 mutex_unlock(&of_mutex); 202 + 203 + of_reconfig_notify(OF_RECONFIG_DETACH_NODE, np); 204 + 197 205 return rc; 198 206 } 199 207
+2 -2
drivers/of/of_private.h
··· 43 43 44 44 #if defined(CONFIG_OF_DYNAMIC) 45 45 extern int of_property_notify(int action, struct device_node *np, 46 - struct property *prop); 46 + struct property *prop, struct property *old_prop); 47 47 extern void of_node_release(struct kobject *kobj); 48 48 #else /* CONFIG_OF_DYNAMIC */ 49 49 static inline int of_property_notify(int action, struct device_node *np, 50 - struct property *prop) 50 + struct property *prop, struct property *old_prop) 51 51 { 52 52 return 0; 53 53 }
+1
include/linux/of.h
··· 321 321 struct of_prop_reconfig { 322 322 struct device_node *dn; 323 323 struct property *prop; 324 + struct property *old_prop; 324 325 }; 325 326 326 327 extern int of_reconfig_notifier_register(struct notifier_block *);