aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/of/overlay.c47
-rw-r--r--include/linux/of.h25
2 files changed, 71 insertions, 1 deletions
diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
index 318dbb51e7a2..0d4cda7050e0 100644
--- a/drivers/of/overlay.c
+++ b/drivers/of/overlay.c
@@ -58,6 +58,41 @@ struct of_overlay {
58static int of_overlay_apply_one(struct of_overlay *ov, 58static int of_overlay_apply_one(struct of_overlay *ov,
59 struct device_node *target, const struct device_node *overlay); 59 struct device_node *target, const struct device_node *overlay);
60 60
61static BLOCKING_NOTIFIER_HEAD(of_overlay_chain);
62
63int of_overlay_notifier_register(struct notifier_block *nb)
64{
65 return blocking_notifier_chain_register(&of_overlay_chain, nb);
66}
67EXPORT_SYMBOL_GPL(of_overlay_notifier_register);
68
69int of_overlay_notifier_unregister(struct notifier_block *nb)
70{
71 return blocking_notifier_chain_unregister(&of_overlay_chain, nb);
72}
73EXPORT_SYMBOL_GPL(of_overlay_notifier_unregister);
74
75static int of_overlay_notify(struct of_overlay *ov,
76 enum of_overlay_notify_action action)
77{
78 struct of_overlay_notify_data nd;
79 int i, ret;
80
81 for (i = 0; i < ov->count; i++) {
82 struct of_overlay_info *ovinfo = &ov->ovinfo_tab[i];
83
84 nd.target = ovinfo->target;
85 nd.overlay = ovinfo->overlay;
86
87 ret = blocking_notifier_call_chain(&of_overlay_chain,
88 action, &nd);
89 if (ret)
90 return notifier_to_errno(ret);
91 }
92
93 return 0;
94}
95
61static int of_overlay_apply_single_property(struct of_overlay *ov, 96static int of_overlay_apply_single_property(struct of_overlay *ov,
62 struct device_node *target, struct property *prop) 97 struct device_node *target, struct property *prop)
63{ 98{
@@ -368,6 +403,13 @@ int of_overlay_create(struct device_node *tree)
368 goto err_free_idr; 403 goto err_free_idr;
369 } 404 }
370 405
406 err = of_overlay_notify(ov, OF_OVERLAY_PRE_APPLY);
407 if (err < 0) {
408 pr_err("%s: Pre-apply notifier failed (err=%d)\n",
409 __func__, err);
410 goto err_free_idr;
411 }
412
371 /* apply the overlay */ 413 /* apply the overlay */
372 err = of_overlay_apply(ov); 414 err = of_overlay_apply(ov);
373 if (err) 415 if (err)
@@ -382,6 +424,8 @@ int of_overlay_create(struct device_node *tree)
382 /* add to the tail of the overlay list */ 424 /* add to the tail of the overlay list */
383 list_add_tail(&ov->node, &ov_list); 425 list_add_tail(&ov->node, &ov_list);
384 426
427 of_overlay_notify(ov, OF_OVERLAY_POST_APPLY);
428
385 mutex_unlock(&of_mutex); 429 mutex_unlock(&of_mutex);
386 430
387 return id; 431 return id;
@@ -498,9 +542,10 @@ int of_overlay_destroy(int id)
498 goto out; 542 goto out;
499 } 543 }
500 544
501 545 of_overlay_notify(ov, OF_OVERLAY_PRE_REMOVE);
502 list_del(&ov->node); 546 list_del(&ov->node);
503 __of_changeset_revert(&ov->cset); 547 __of_changeset_revert(&ov->cset);
548 of_overlay_notify(ov, OF_OVERLAY_POST_REMOVE);
504 of_free_overlay_info(ov); 549 of_free_overlay_info(ov);
505 idr_remove(&ov_idr, id); 550 idr_remove(&ov_idr, id);
506 of_changeset_destroy(&ov->cset); 551 of_changeset_destroy(&ov->cset);
diff --git a/include/linux/of.h b/include/linux/of.h
index 299aeb192727..d72f01009297 100644
--- a/include/linux/of.h
+++ b/include/linux/of.h
@@ -1266,6 +1266,18 @@ static inline bool of_device_is_system_power_controller(const struct device_node
1266 * Overlay support 1266 * Overlay support
1267 */ 1267 */
1268 1268
1269enum of_overlay_notify_action {
1270 OF_OVERLAY_PRE_APPLY,
1271 OF_OVERLAY_POST_APPLY,
1272 OF_OVERLAY_PRE_REMOVE,
1273 OF_OVERLAY_POST_REMOVE,
1274};
1275
1276struct of_overlay_notify_data {
1277 struct device_node *overlay;
1278 struct device_node *target;
1279};
1280
1269#ifdef CONFIG_OF_OVERLAY 1281#ifdef CONFIG_OF_OVERLAY
1270 1282
1271/* ID based overlays; the API for external users */ 1283/* ID based overlays; the API for external users */
@@ -1273,6 +1285,9 @@ int of_overlay_create(struct device_node *tree);
1273int of_overlay_destroy(int id); 1285int of_overlay_destroy(int id);
1274int of_overlay_destroy_all(void); 1286int of_overlay_destroy_all(void);
1275 1287
1288int of_overlay_notifier_register(struct notifier_block *nb);
1289int of_overlay_notifier_unregister(struct notifier_block *nb);
1290
1276#else 1291#else
1277 1292
1278static inline int of_overlay_create(struct device_node *tree) 1293static inline int of_overlay_create(struct device_node *tree)
@@ -1290,6 +1305,16 @@ static inline int of_overlay_destroy_all(void)
1290 return -ENOTSUPP; 1305 return -ENOTSUPP;
1291} 1306}
1292 1307
1308static inline int of_overlay_notifier_register(struct notifier_block *nb)
1309{
1310 return 0;
1311}
1312
1313static inline int of_overlay_notifier_unregister(struct notifier_block *nb)
1314{
1315 return 0;
1316}
1317
1293#endif 1318#endif
1294 1319
1295#endif /* _LINUX_OF_H */ 1320#endif /* _LINUX_OF_H */