aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/of
diff options
context:
space:
mode:
authorNathan Fontenot <nfont@linux.vnet.ibm.com>2012-10-02 12:57:57 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2012-11-14 20:56:41 -0500
commit1cf3d8b3d24cd383ddfd5442c83ec5c355ffc2f7 (patch)
tree0f4790e95f917c6b76d95c88b7b3d67445261893 /drivers/of
parentf59497208363f3dd9d62b79b7f7eafc95432de79 (diff)
powerpc+of: Add of node/property notification chain for adds and removes
This patch moves the notification chain for updates to the device tree from the powerpc/pseries code to the base OF code. This makes this functionality available to all architectures. Additionally the notification chain is updated to allow notifications for property add/remove/update. To make this work a pointer to a new struct (of_prop_reconfig) is passed to the routines in the notification chain. The of_prop_reconfig property contains a pointer to the node containing the property and a pointer to the property itself. In the case of property updates, the property pointer refers to the new property. Signed-off-by: Nathan Fontenot <nfont@linux.vnet.ibm.com> Acked-by: Rob Herring <rob.herring@calxeda.com> Acked-by: Grant Likely <grant.likely@secretlab.ca> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'drivers/of')
-rw-r--r--drivers/of/base.c74
1 files changed, 69 insertions, 5 deletions
diff --git a/drivers/of/base.c b/drivers/of/base.c
index bbd073f53c9f..87b63850e8dc 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -1028,6 +1028,24 @@ int of_parse_phandle_with_args(struct device_node *np, const char *list_name,
1028} 1028}
1029EXPORT_SYMBOL(of_parse_phandle_with_args); 1029EXPORT_SYMBOL(of_parse_phandle_with_args);
1030 1030
1031#if defined(CONFIG_OF_DYNAMIC)
1032static int of_property_notify(int action, struct device_node *np,
1033 struct property *prop)
1034{
1035 struct of_prop_reconfig pr;
1036
1037 pr.dn = np;
1038 pr.prop = prop;
1039 return of_reconfig_notify(action, &pr);
1040}
1041#else
1042static int of_property_notify(int action, struct device_node *np,
1043 struct property *prop)
1044{
1045 return 0;
1046}
1047#endif
1048
1031/** 1049/**
1032 * prom_add_property - Add a property to a node 1050 * prom_add_property - Add a property to a node
1033 */ 1051 */
@@ -1035,6 +1053,11 @@ int prom_add_property(struct device_node *np, struct property *prop)
1035{ 1053{
1036 struct property **next; 1054 struct property **next;
1037 unsigned long flags; 1055 unsigned long flags;
1056 int rc;
1057
1058 rc = of_property_notify(OF_RECONFIG_ADD_PROPERTY, np, prop);
1059 if (rc)
1060 return rc;
1038 1061
1039 prop->next = NULL; 1062 prop->next = NULL;
1040 write_lock_irqsave(&devtree_lock, flags); 1063 write_lock_irqsave(&devtree_lock, flags);
@@ -1072,6 +1095,11 @@ int prom_remove_property(struct device_node *np, struct property *prop)
1072 struct property **next; 1095 struct property **next;
1073 unsigned long flags; 1096 unsigned long flags;
1074 int found = 0; 1097 int found = 0;
1098 int rc;
1099
1100 rc = of_property_notify(OF_RECONFIG_REMOVE_PROPERTY, np, prop);
1101 if (rc)
1102 return rc;
1075 1103
1076 write_lock_irqsave(&devtree_lock, flags); 1104 write_lock_irqsave(&devtree_lock, flags);
1077 next = &np->properties; 1105 next = &np->properties;
@@ -1114,7 +1142,11 @@ int prom_update_property(struct device_node *np,
1114{ 1142{
1115 struct property **next, *oldprop; 1143 struct property **next, *oldprop;
1116 unsigned long flags; 1144 unsigned long flags;
1117 int found = 0; 1145 int rc, found = 0;
1146
1147 rc = of_property_notify(OF_RECONFIG_UPDATE_PROPERTY, np, newprop);
1148 if (rc)
1149 return rc;
1118 1150
1119 if (!newprop->name) 1151 if (!newprop->name)
1120 return -EINVAL; 1152 return -EINVAL;
@@ -1160,6 +1192,26 @@ int prom_update_property(struct device_node *np,
1160 * device tree nodes. 1192 * device tree nodes.
1161 */ 1193 */
1162 1194
1195static BLOCKING_NOTIFIER_HEAD(of_reconfig_chain);
1196
1197int of_reconfig_notifier_register(struct notifier_block *nb)
1198{
1199 return blocking_notifier_chain_register(&of_reconfig_chain, nb);
1200}
1201
1202int of_reconfig_notifier_unregister(struct notifier_block *nb)
1203{
1204 return blocking_notifier_chain_unregister(&of_reconfig_chain, nb);
1205}
1206
1207int of_reconfig_notify(unsigned long action, void *p)
1208{
1209 int rc;
1210
1211 rc = blocking_notifier_call_chain(&of_reconfig_chain, action, p);
1212 return notifier_to_errno(rc);
1213}
1214
1163#ifdef CONFIG_PROC_DEVICETREE 1215#ifdef CONFIG_PROC_DEVICETREE
1164static void of_add_proc_dt_entry(struct device_node *dn) 1216static void of_add_proc_dt_entry(struct device_node *dn)
1165{ 1217{
@@ -1179,9 +1231,14 @@ static void of_add_proc_dt_entry(struct device_node *dn)
1179/** 1231/**
1180 * of_attach_node - Plug a device node into the tree and global list. 1232 * of_attach_node - Plug a device node into the tree and global list.
1181 */ 1233 */
1182void of_attach_node(struct device_node *np) 1234int of_attach_node(struct device_node *np)
1183{ 1235{
1184 unsigned long flags; 1236 unsigned long flags;
1237 int rc;
1238
1239 rc = of_reconfig_notify(OF_RECONFIG_ATTACH_NODE, np);
1240 if (rc)
1241 return rc;
1185 1242
1186 write_lock_irqsave(&devtree_lock, flags); 1243 write_lock_irqsave(&devtree_lock, flags);
1187 np->sibling = np->parent->child; 1244 np->sibling = np->parent->child;
@@ -1191,6 +1248,7 @@ void of_attach_node(struct device_node *np)
1191 write_unlock_irqrestore(&devtree_lock, flags); 1248 write_unlock_irqrestore(&devtree_lock, flags);
1192 1249
1193 of_add_proc_dt_entry(np); 1250 of_add_proc_dt_entry(np);
1251 return 0;
1194} 1252}
1195 1253
1196#ifdef CONFIG_PROC_DEVICETREE 1254#ifdef CONFIG_PROC_DEVICETREE
@@ -1220,23 +1278,28 @@ static void of_remove_proc_dt_entry(struct device_node *dn)
1220 * The caller must hold a reference to the node. The memory associated with 1278 * The caller must hold a reference to the node. The memory associated with
1221 * the node is not freed until its refcount goes to zero. 1279 * the node is not freed until its refcount goes to zero.
1222 */ 1280 */
1223void of_detach_node(struct device_node *np) 1281int of_detach_node(struct device_node *np)
1224{ 1282{
1225 struct device_node *parent; 1283 struct device_node *parent;
1226 unsigned long flags; 1284 unsigned long flags;
1285 int rc = 0;
1286
1287 rc = of_reconfig_notify(OF_RECONFIG_DETACH_NODE, np);
1288 if (rc)
1289 return rc;
1227 1290
1228 write_lock_irqsave(&devtree_lock, flags); 1291 write_lock_irqsave(&devtree_lock, flags);
1229 1292
1230 if (of_node_check_flag(np, OF_DETACHED)) { 1293 if (of_node_check_flag(np, OF_DETACHED)) {
1231 /* someone already detached it */ 1294 /* someone already detached it */
1232 write_unlock_irqrestore(&devtree_lock, flags); 1295 write_unlock_irqrestore(&devtree_lock, flags);
1233 return; 1296 return rc;
1234 } 1297 }
1235 1298
1236 parent = np->parent; 1299 parent = np->parent;
1237 if (!parent) { 1300 if (!parent) {
1238 write_unlock_irqrestore(&devtree_lock, flags); 1301 write_unlock_irqrestore(&devtree_lock, flags);
1239 return; 1302 return rc;
1240 } 1303 }
1241 1304
1242 if (allnodes == np) 1305 if (allnodes == np)
@@ -1265,6 +1328,7 @@ void of_detach_node(struct device_node *np)
1265 write_unlock_irqrestore(&devtree_lock, flags); 1328 write_unlock_irqrestore(&devtree_lock, flags);
1266 1329
1267 of_remove_proc_dt_entry(np); 1330 of_remove_proc_dt_entry(np);
1331 return rc;
1268} 1332}
1269#endif /* defined(CONFIG_OF_DYNAMIC) */ 1333#endif /* defined(CONFIG_OF_DYNAMIC) */
1270 1334