of: Reorder device tree changes and notifiers
authorGrant Likely <grant.likely@linaro.org>
Wed, 16 Jul 2014 18:48:23 +0000 (12:48 -0600)
committerMark Brown <broonie@kernel.org>
Mon, 16 Feb 2015 05:53:23 +0000 (14:53 +0900)
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>
(cherry picked from commit 259092a35c7e11f1d4616b0f5b3ba7b851fe4fa6)
Signed-off-by: Mark Brown <broonie@kernel.org>
arch/powerpc/platforms/pseries/hotplug-memory.c
drivers/crypto/nx/nx-842.c
drivers/of/base.c
drivers/of/dynamic.c
drivers/of/of_private.h
include/linux/of.h

index 9a432de363b8d081d0663f8795f28ff7354ce378..06d6e5bdde70fd1af6949d1327d234a66962c7cd 100644 (file)
@@ -210,7 +210,7 @@ static int pseries_update_drconf_memory(struct of_prop_reconfig *pr)
        if (!memblock_size)
                return -EINVAL;
 
-       p = (u32 *)of_get_property(pr->dn, "ibm,dynamic-memory", NULL);
+       p = (u32 *) pr->old_prop->value;
        if (!p)
                return -EINVAL;
 
index 6c4c000671c50d88885bb39618c5ae9e4ceabe42..142533fbce39a50dfb3dc13e7a6f2834cdceb7cc 100644 (file)
@@ -927,28 +927,14 @@ static int nx842_OF_upd(struct property *new_prop)
                goto error_out;
        }
 
-       /* Set ptr to new property if provided */
-       if (new_prop) {
-               /* Single property */
-               if (!strncmp(new_prop->name, "status", new_prop->length)) {
-                       status = new_prop;
-
-               } else if (!strncmp(new_prop->name, "ibm,max-sg-len",
-                                       new_prop->length)) {
-                       maxsglen = new_prop;
-
-               } else if (!strncmp(new_prop->name, "ibm,max-sync-cop",
-                                       new_prop->length)) {
-                       maxsyncop = new_prop;
-
-               } else {
-                       /*
-                        * Skip the update, the property being updated
-                        * has no impact.
-                        */
-                       goto out;
-               }
-       }
+       /*
+        * If this is a property update, there are only certain properties that
+        * we care about. Bail if it isn't in the below list
+        */
+       if (new_prop && (strncmp(new_prop->name, "status", new_prop->length) ||
+                        strncmp(new_prop->name, "ibm,max-sg-len", new_prop->length) ||
+                        strncmp(new_prop->name, "ibm,max-sync-cop", new_prop->length)))
+               goto out;
 
        /* Perform property updates */
        ret = nx842_OF_upd_status(new_devdata, status);
index 842184a8f92245757a84b89f1c23a512cd1de03f..4a2cf4f70f4796de9928db02d841bccc7e497349 100644 (file)
@@ -1437,10 +1437,6 @@ int of_add_property(struct device_node *np, struct property *prop)
        unsigned long flags;
        int rc;
 
-       rc = of_property_notify(OF_RECONFIG_ADD_PROPERTY, np, prop);
-       if (rc)
-               return rc;
-
        mutex_lock(&of_mutex);
 
        raw_spin_lock_irqsave(&devtree_lock, flags);
@@ -1452,6 +1448,9 @@ int of_add_property(struct device_node *np, struct property *prop)
 
        mutex_unlock(&of_mutex);
 
+       if (!rc)
+               of_property_notify(OF_RECONFIG_ADD_PROPERTY, np, prop, NULL);
+
        return rc;
 }
 
@@ -1494,10 +1493,6 @@ int of_remove_property(struct device_node *np, struct property *prop)
        unsigned long flags;
        int rc;
 
-       rc = of_property_notify(OF_RECONFIG_REMOVE_PROPERTY, np, prop);
-       if (rc)
-               return rc;
-
        mutex_lock(&of_mutex);
 
        raw_spin_lock_irqsave(&devtree_lock, flags);
@@ -1509,6 +1504,9 @@ int of_remove_property(struct device_node *np, struct property *prop)
 
        mutex_unlock(&of_mutex);
 
+       if (!rc)
+               of_property_notify(OF_RECONFIG_REMOVE_PROPERTY, np, prop, NULL);
+
        return rc;
 }
 
@@ -1568,10 +1566,6 @@ int of_update_property(struct device_node *np, struct property *newprop)
        if (!newprop->name)
                return -EINVAL;
 
-       rc = of_property_notify(OF_RECONFIG_UPDATE_PROPERTY, np, newprop);
-       if (rc)
-               return rc;
-
        mutex_lock(&of_mutex);
 
        raw_spin_lock_irqsave(&devtree_lock, flags);
@@ -1583,6 +1577,9 @@ int of_update_property(struct device_node *np, struct property *newprop)
 
        mutex_unlock(&of_mutex);
 
+       if (!rc)
+               of_property_notify(OF_RECONFIG_UPDATE_PROPERTY, np, newprop, oldprop);
+
        return rc;
 }
 
index 7c020b9a3317b518d2bebbaa324cfb219cdf1fe7..7bd5501736a6a06da9b39088526ee214b656567d 100644 (file)
@@ -83,7 +83,7 @@ int of_reconfig_notify(unsigned long action, void *p)
 }
 
 int of_property_notify(int action, struct device_node *np,
-                      struct property *prop)
+                      struct property *prop, struct property *oldprop)
 {
        struct of_prop_reconfig pr;
 
@@ -93,6 +93,7 @@ int of_property_notify(int action, struct device_node *np,
 
        pr.dn = np;
        pr.prop = prop;
+       pr.old_prop = oldprop;
        return of_reconfig_notify(action, &pr);
 }
 
@@ -125,11 +126,6 @@ void __of_attach_node(struct device_node *np)
 int of_attach_node(struct device_node *np)
 {
        unsigned long flags;
-       int rc;
-
-       rc = of_reconfig_notify(OF_RECONFIG_ATTACH_NODE, np);
-       if (rc)
-               return rc;
 
        mutex_lock(&of_mutex);
        raw_spin_lock_irqsave(&devtree_lock, flags);
@@ -138,6 +134,9 @@ int of_attach_node(struct device_node *np)
 
        __of_attach_node_sysfs(np);
        mutex_unlock(&of_mutex);
+
+       of_reconfig_notify(OF_RECONFIG_ATTACH_NODE, np);
+
        return 0;
 }
 
@@ -188,10 +187,6 @@ int of_detach_node(struct device_node *np)
        unsigned long flags;
        int rc = 0;
 
-       rc = of_reconfig_notify(OF_RECONFIG_DETACH_NODE, np);
-       if (rc)
-               return rc;
-
        mutex_lock(&of_mutex);
        raw_spin_lock_irqsave(&devtree_lock, flags);
        __of_detach_node(np);
@@ -199,6 +194,9 @@ int of_detach_node(struct device_node *np)
 
        __of_detach_node_sysfs(np);
        mutex_unlock(&of_mutex);
+
+       of_reconfig_notify(OF_RECONFIG_DETACH_NODE, np);
+
        return rc;
 }
 
index 8129c0e58d701e3a0ca86b6265bf6b95e9869dc6..f69ccb1fa3085c315a20f1bd185d6743a46d9993 100644 (file)
@@ -43,11 +43,11 @@ static inline struct device_node *kobj_to_device_node(struct kobject *kobj)
 
 #if defined(CONFIG_OF_DYNAMIC)
 extern int of_property_notify(int action, struct device_node *np,
-                             struct property *prop);
+                             struct property *prop, struct property *old_prop);
 extern void of_node_release(struct kobject *kobj);
 #else /* CONFIG_OF_DYNAMIC */
 static inline int of_property_notify(int action, struct device_node *np,
-                                    struct property *prop)
+                                    struct property *prop, struct property *old_prop)
 {
        return 0;
 }
index 27cc048b85b3ee27d3a161c8a5f1133684f76511..3a8515ef45c0f667fa15ae4ecbde8ff95c020750 100644 (file)
@@ -348,6 +348,7 @@ extern int of_update_property(struct device_node *np, struct property *newprop);
 struct of_prop_reconfig {
        struct device_node      *dn;
        struct property         *prop;
+       struct property         *old_prop;
 };
 
 extern int of_reconfig_notifier_register(struct notifier_block *);