aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/of/base.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/of/base.c')
-rw-r--r--drivers/of/base.c142
1 files changed, 127 insertions, 15 deletions
diff --git a/drivers/of/base.c b/drivers/of/base.c
index be846408dbc1..db8d211a0d05 100644
--- a/drivers/of/base.c
+++ b/drivers/of/base.c
@@ -1114,13 +1114,36 @@ int of_parse_phandle_with_args(const struct device_node *np, const char *list_na
1114} 1114}
1115EXPORT_SYMBOL(of_parse_phandle_with_args); 1115EXPORT_SYMBOL(of_parse_phandle_with_args);
1116 1116
1117#if defined(CONFIG_OF_DYNAMIC)
1118static int of_property_notify(int action, struct device_node *np,
1119 struct property *prop)
1120{
1121 struct of_prop_reconfig pr;
1122
1123 pr.dn = np;
1124 pr.prop = prop;
1125 return of_reconfig_notify(action, &pr);
1126}
1127#else
1128static int of_property_notify(int action, struct device_node *np,
1129 struct property *prop)
1130{
1131 return 0;
1132}
1133#endif
1134
1117/** 1135/**
1118 * prom_add_property - Add a property to a node 1136 * of_add_property - Add a property to a node
1119 */ 1137 */
1120int prom_add_property(struct device_node *np, struct property *prop) 1138int of_add_property(struct device_node *np, struct property *prop)
1121{ 1139{
1122 struct property **next; 1140 struct property **next;
1123 unsigned long flags; 1141 unsigned long flags;
1142 int rc;
1143
1144 rc = of_property_notify(OF_RECONFIG_ADD_PROPERTY, np, prop);
1145 if (rc)
1146 return rc;
1124 1147
1125 prop->next = NULL; 1148 prop->next = NULL;
1126 write_lock_irqsave(&devtree_lock, flags); 1149 write_lock_irqsave(&devtree_lock, flags);
@@ -1146,18 +1169,23 @@ int prom_add_property(struct device_node *np, struct property *prop)
1146} 1169}
1147 1170
1148/** 1171/**
1149 * prom_remove_property - Remove a property from a node. 1172 * of_remove_property - Remove a property from a node.
1150 * 1173 *
1151 * Note that we don't actually remove it, since we have given out 1174 * Note that we don't actually remove it, since we have given out
1152 * who-knows-how-many pointers to the data using get-property. 1175 * who-knows-how-many pointers to the data using get-property.
1153 * Instead we just move the property to the "dead properties" 1176 * Instead we just move the property to the "dead properties"
1154 * list, so it won't be found any more. 1177 * list, so it won't be found any more.
1155 */ 1178 */
1156int prom_remove_property(struct device_node *np, struct property *prop) 1179int of_remove_property(struct device_node *np, struct property *prop)
1157{ 1180{
1158 struct property **next; 1181 struct property **next;
1159 unsigned long flags; 1182 unsigned long flags;
1160 int found = 0; 1183 int found = 0;
1184 int rc;
1185
1186 rc = of_property_notify(OF_RECONFIG_REMOVE_PROPERTY, np, prop);
1187 if (rc)
1188 return rc;
1161 1189
1162 write_lock_irqsave(&devtree_lock, flags); 1190 write_lock_irqsave(&devtree_lock, flags);
1163 next = &np->properties; 1191 next = &np->properties;
@@ -1187,7 +1215,7 @@ int prom_remove_property(struct device_node *np, struct property *prop)
1187} 1215}
1188 1216
1189/* 1217/*
1190 * prom_update_property - Update a property in a node, if the property does 1218 * of_update_property - Update a property in a node, if the property does
1191 * not exist, add it. 1219 * not exist, add it.
1192 * 1220 *
1193 * Note that we don't actually remove it, since we have given out 1221 * Note that we don't actually remove it, since we have given out
@@ -1195,19 +1223,22 @@ int prom_remove_property(struct device_node *np, struct property *prop)
1195 * Instead we just move the property to the "dead properties" list, 1223 * Instead we just move the property to the "dead properties" list,
1196 * and add the new property to the property list 1224 * and add the new property to the property list
1197 */ 1225 */
1198int prom_update_property(struct device_node *np, 1226int of_update_property(struct device_node *np, struct property *newprop)
1199 struct property *newprop)
1200{ 1227{
1201 struct property **next, *oldprop; 1228 struct property **next, *oldprop;
1202 unsigned long flags; 1229 unsigned long flags;
1203 int found = 0; 1230 int rc, found = 0;
1231
1232 rc = of_property_notify(OF_RECONFIG_UPDATE_PROPERTY, np, newprop);
1233 if (rc)
1234 return rc;
1204 1235
1205 if (!newprop->name) 1236 if (!newprop->name)
1206 return -EINVAL; 1237 return -EINVAL;
1207 1238
1208 oldprop = of_find_property(np, newprop->name, NULL); 1239 oldprop = of_find_property(np, newprop->name, NULL);
1209 if (!oldprop) 1240 if (!oldprop)
1210 return prom_add_property(np, newprop); 1241 return of_add_property(np, newprop);
1211 1242
1212 write_lock_irqsave(&devtree_lock, flags); 1243 write_lock_irqsave(&devtree_lock, flags);
1213 next = &np->properties; 1244 next = &np->properties;
@@ -1246,12 +1277,55 @@ int prom_update_property(struct device_node *np,
1246 * device tree nodes. 1277 * device tree nodes.
1247 */ 1278 */
1248 1279
1280static BLOCKING_NOTIFIER_HEAD(of_reconfig_chain);
1281
1282int of_reconfig_notifier_register(struct notifier_block *nb)
1283{
1284 return blocking_notifier_chain_register(&of_reconfig_chain, nb);
1285}
1286EXPORT_SYMBOL_GPL(of_reconfig_notifier_register);
1287
1288int of_reconfig_notifier_unregister(struct notifier_block *nb)
1289{
1290 return blocking_notifier_chain_unregister(&of_reconfig_chain, nb);
1291}
1292EXPORT_SYMBOL_GPL(of_reconfig_notifier_unregister);
1293
1294int of_reconfig_notify(unsigned long action, void *p)
1295{
1296 int rc;
1297
1298 rc = blocking_notifier_call_chain(&of_reconfig_chain, action, p);
1299 return notifier_to_errno(rc);
1300}
1301
1302#ifdef CONFIG_PROC_DEVICETREE
1303static void of_add_proc_dt_entry(struct device_node *dn)
1304{
1305 struct proc_dir_entry *ent;
1306
1307 ent = proc_mkdir(strrchr(dn->full_name, '/') + 1, dn->parent->pde);
1308 if (ent)
1309 proc_device_tree_add_node(dn, ent);
1310}
1311#else
1312static void of_add_proc_dt_entry(struct device_node *dn)
1313{
1314 return;
1315}
1316#endif
1317
1249/** 1318/**
1250 * of_attach_node - Plug a device node into the tree and global list. 1319 * of_attach_node - Plug a device node into the tree and global list.
1251 */ 1320 */
1252void of_attach_node(struct device_node *np) 1321int of_attach_node(struct device_node *np)
1253{ 1322{
1254 unsigned long flags; 1323 unsigned long flags;
1324 int rc;
1325
1326 rc = of_reconfig_notify(OF_RECONFIG_ATTACH_NODE, np);
1327 if (rc)
1328 return rc;
1255 1329
1256 write_lock_irqsave(&devtree_lock, flags); 1330 write_lock_irqsave(&devtree_lock, flags);
1257 np->sibling = np->parent->child; 1331 np->sibling = np->parent->child;
@@ -1259,24 +1333,61 @@ void of_attach_node(struct device_node *np)
1259 np->parent->child = np; 1333 np->parent->child = np;
1260 of_allnodes = np; 1334 of_allnodes = np;
1261 write_unlock_irqrestore(&devtree_lock, flags); 1335 write_unlock_irqrestore(&devtree_lock, flags);
1336
1337 of_add_proc_dt_entry(np);
1338 return 0;
1262} 1339}
1263 1340
1341#ifdef CONFIG_PROC_DEVICETREE
1342static void of_remove_proc_dt_entry(struct device_node *dn)
1343{
1344 struct device_node *parent = dn->parent;
1345 struct property *prop = dn->properties;
1346
1347 while (prop) {
1348 remove_proc_entry(prop->name, dn->pde);
1349 prop = prop->next;
1350 }
1351
1352 if (dn->pde)
1353 remove_proc_entry(dn->pde->name, parent->pde);
1354}
1355#else
1356static void of_remove_proc_dt_entry(struct device_node *dn)
1357{
1358 return;
1359}
1360#endif
1361
1264/** 1362/**
1265 * of_detach_node - "Unplug" a node from the device tree. 1363 * of_detach_node - "Unplug" a node from the device tree.
1266 * 1364 *
1267 * The caller must hold a reference to the node. The memory associated with 1365 * The caller must hold a reference to the node. The memory associated with
1268 * the node is not freed until its refcount goes to zero. 1366 * the node is not freed until its refcount goes to zero.
1269 */ 1367 */
1270void of_detach_node(struct device_node *np) 1368int of_detach_node(struct device_node *np)
1271{ 1369{
1272 struct device_node *parent; 1370 struct device_node *parent;
1273 unsigned long flags; 1371 unsigned long flags;
1372 int rc = 0;
1373
1374 rc = of_reconfig_notify(OF_RECONFIG_DETACH_NODE, np);
1375 if (rc)
1376 return rc;
1274 1377
1275 write_lock_irqsave(&devtree_lock, flags); 1378 write_lock_irqsave(&devtree_lock, flags);
1276 1379
1380 if (of_node_check_flag(np, OF_DETACHED)) {
1381 /* someone already detached it */
1382 write_unlock_irqrestore(&devtree_lock, flags);
1383 return rc;
1384 }
1385
1277 parent = np->parent; 1386 parent = np->parent;
1278 if (!parent) 1387 if (!parent) {
1279 goto out_unlock; 1388 write_unlock_irqrestore(&devtree_lock, flags);
1389 return rc;
1390 }
1280 1391
1281 if (of_allnodes == np) 1392 if (of_allnodes == np)
1282 of_allnodes = np->allnext; 1393 of_allnodes = np->allnext;
@@ -1301,9 +1412,10 @@ void of_detach_node(struct device_node *np)
1301 } 1412 }
1302 1413
1303 of_node_set_flag(np, OF_DETACHED); 1414 of_node_set_flag(np, OF_DETACHED);
1304
1305out_unlock:
1306 write_unlock_irqrestore(&devtree_lock, flags); 1415 write_unlock_irqrestore(&devtree_lock, flags);
1416
1417 of_remove_proc_dt_entry(np);
1418 return rc;
1307} 1419}
1308#endif /* defined(CONFIG_OF_DYNAMIC) */ 1420#endif /* defined(CONFIG_OF_DYNAMIC) */
1309 1421