blob: dc91a1b4c78ccffcbbada33797b4989676c0d3aa [file] [log] [blame]
Grant Likely6afc0dc2014-06-26 15:40:48 +01001/*
2 * Support for dynamic device trees.
3 *
4 * On some platforms, the device tree can be manipulated at runtime.
5 * The routines in this section support adding, removing and changing
6 * device tree nodes.
7 */
8
Rob Herring606ad422016-06-15 08:32:18 -05009#define pr_fmt(fmt) "OF: " fmt
10
Grant Likely6afc0dc2014-06-26 15:40:48 +010011#include <linux/of.h>
12#include <linux/spinlock.h>
13#include <linux/slab.h>
14#include <linux/string.h>
15#include <linux/proc_fs.h>
16
17#include "of_private.h"
18
Rob Herring1b21d322017-10-04 19:30:53 -050019static struct device_node *kobj_to_device_node(struct kobject *kobj)
20{
21 return container_of(kobj, struct device_node, kobj);
22}
23
Grant Likely6afc0dc2014-06-26 15:40:48 +010024/**
25 * of_node_get() - Increment refcount of a node
26 * @node: Node to inc refcount, NULL is supported to simplify writing of
27 * callers
28 *
29 * Returns node.
30 */
31struct device_node *of_node_get(struct device_node *node)
32{
33 if (node)
34 kobject_get(&node->kobj);
35 return node;
36}
37EXPORT_SYMBOL(of_node_get);
38
39/**
40 * of_node_put() - Decrement refcount of a node
41 * @node: Node to dec refcount, NULL is supported to simplify writing of
42 * callers
43 */
44void of_node_put(struct device_node *node)
45{
46 if (node)
47 kobject_put(&node->kobj);
48}
49EXPORT_SYMBOL(of_node_put);
50
Grant Likely8a2b22a2014-07-23 17:05:06 -060051void __of_detach_node_sysfs(struct device_node *np)
Grant Likely6afc0dc2014-06-26 15:40:48 +010052{
53 struct property *pp;
54
Gaurav Minochaef69d742014-09-05 09:56:13 -070055 if (!IS_ENABLED(CONFIG_SYSFS))
56 return;
57
Grant Likely6afc0dc2014-06-26 15:40:48 +010058 BUG_ON(!of_node_is_initialized(np));
Grant Likely8a2b22a2014-07-23 17:05:06 -060059 if (!of_kset)
60 return;
Grant Likely6afc0dc2014-06-26 15:40:48 +010061
62 /* only remove properties if on sysfs */
63 if (of_node_is_attached(np)) {
64 for_each_property_of_node(np, pp)
Frank Rowandd9fc8802016-06-16 10:51:46 -070065 __of_sysfs_remove_bin_file(np, pp);
Grant Likely6afc0dc2014-06-26 15:40:48 +010066 kobject_del(&np->kobj);
67 }
68
69 /* finally remove the kobj_init ref */
70 of_node_put(np);
71}
72
73static BLOCKING_NOTIFIER_HEAD(of_reconfig_chain);
74
75int of_reconfig_notifier_register(struct notifier_block *nb)
76{
77 return blocking_notifier_chain_register(&of_reconfig_chain, nb);
78}
79EXPORT_SYMBOL_GPL(of_reconfig_notifier_register);
80
81int of_reconfig_notifier_unregister(struct notifier_block *nb)
82{
83 return blocking_notifier_chain_unregister(&of_reconfig_chain, nb);
84}
85EXPORT_SYMBOL_GPL(of_reconfig_notifier_unregister);
86
Grant Likely00aa3722014-11-14 14:34:55 +000087#ifdef DEBUG
88const char *action_names[] = {
89 [OF_RECONFIG_ATTACH_NODE] = "ATTACH_NODE",
90 [OF_RECONFIG_DETACH_NODE] = "DETACH_NODE",
91 [OF_RECONFIG_ADD_PROPERTY] = "ADD_PROPERTY",
92 [OF_RECONFIG_REMOVE_PROPERTY] = "REMOVE_PROPERTY",
93 [OF_RECONFIG_UPDATE_PROPERTY] = "UPDATE_PROPERTY",
94};
95#endif
96
Grant Likelyf5242e52014-11-24 17:58:01 +000097int of_reconfig_notify(unsigned long action, struct of_reconfig_data *p)
Grant Likely6afc0dc2014-06-26 15:40:48 +010098{
99 int rc;
Grant Likely00aa3722014-11-14 14:34:55 +0000100#ifdef DEBUG
Grant Likelyf5242e52014-11-24 17:58:01 +0000101 struct of_reconfig_data *pr = p;
Grant Likely6afc0dc2014-06-26 15:40:48 +0100102
Grant Likely00aa3722014-11-14 14:34:55 +0000103 switch (action) {
104 case OF_RECONFIG_ATTACH_NODE:
105 case OF_RECONFIG_DETACH_NODE:
Rob Herring606ad422016-06-15 08:32:18 -0500106 pr_debug("notify %-15s %s\n", action_names[action],
Grant Likelyf5242e52014-11-24 17:58:01 +0000107 pr->dn->full_name);
Grant Likely00aa3722014-11-14 14:34:55 +0000108 break;
109 case OF_RECONFIG_ADD_PROPERTY:
110 case OF_RECONFIG_REMOVE_PROPERTY:
111 case OF_RECONFIG_UPDATE_PROPERTY:
Rob Herring606ad422016-06-15 08:32:18 -0500112 pr_debug("notify %-15s %s:%s\n", action_names[action],
Grant Likely00aa3722014-11-14 14:34:55 +0000113 pr->dn->full_name, pr->prop->name);
114 break;
115
116 }
117#endif
Grant Likely6afc0dc2014-06-26 15:40:48 +0100118 rc = blocking_notifier_call_chain(&of_reconfig_chain, action, p);
119 return notifier_to_errno(rc);
120}
121
Pantelis Antonioub53a2342014-10-28 22:33:53 +0200122/*
123 * of_reconfig_get_state_change() - Returns new state of device
124 * @action - action of the of notifier
125 * @arg - argument of the of notifier
126 *
127 * Returns the new state of a device based on the notifier used.
128 * Returns 0 on device going from enabled to disabled, 1 on device
129 * going from disabled to enabled and -1 on no change.
130 */
Grant Likelyf5242e52014-11-24 17:58:01 +0000131int of_reconfig_get_state_change(unsigned long action, struct of_reconfig_data *pr)
Pantelis Antonioub53a2342014-10-28 22:33:53 +0200132{
Grant Likelyf5242e52014-11-24 17:58:01 +0000133 struct property *prop, *old_prop = NULL;
Pantelis Antonioub53a2342014-10-28 22:33:53 +0200134 int is_status, status_state, old_status_state, prev_state, new_state;
135
136 /* figure out if a device should be created or destroyed */
Pantelis Antonioub53a2342014-10-28 22:33:53 +0200137 switch (action) {
138 case OF_RECONFIG_ATTACH_NODE:
139 case OF_RECONFIG_DETACH_NODE:
Grant Likelyf5242e52014-11-24 17:58:01 +0000140 prop = of_find_property(pr->dn, "status", NULL);
Pantelis Antonioub53a2342014-10-28 22:33:53 +0200141 break;
142 case OF_RECONFIG_ADD_PROPERTY:
143 case OF_RECONFIG_REMOVE_PROPERTY:
Pantelis Antonioub53a2342014-10-28 22:33:53 +0200144 prop = pr->prop;
145 break;
146 case OF_RECONFIG_UPDATE_PROPERTY:
Pantelis Antonioub53a2342014-10-28 22:33:53 +0200147 prop = pr->prop;
148 old_prop = pr->old_prop;
149 break;
150 default:
151 return OF_RECONFIG_NO_CHANGE;
152 }
153
154 is_status = 0;
155 status_state = -1;
156 old_status_state = -1;
157 prev_state = -1;
158 new_state = -1;
159
160 if (prop && !strcmp(prop->name, "status")) {
161 is_status = 1;
162 status_state = !strcmp(prop->value, "okay") ||
163 !strcmp(prop->value, "ok");
164 if (old_prop)
165 old_status_state = !strcmp(old_prop->value, "okay") ||
166 !strcmp(old_prop->value, "ok");
167 }
168
169 switch (action) {
170 case OF_RECONFIG_ATTACH_NODE:
171 prev_state = 0;
172 /* -1 & 0 status either missing or okay */
173 new_state = status_state != 0;
174 break;
175 case OF_RECONFIG_DETACH_NODE:
176 /* -1 & 0 status either missing or okay */
177 prev_state = status_state != 0;
178 new_state = 0;
179 break;
180 case OF_RECONFIG_ADD_PROPERTY:
181 if (is_status) {
182 /* no status property -> enabled (legacy) */
183 prev_state = 1;
184 new_state = status_state;
185 }
186 break;
187 case OF_RECONFIG_REMOVE_PROPERTY:
188 if (is_status) {
189 prev_state = status_state;
190 /* no status property -> enabled (legacy) */
191 new_state = 1;
192 }
193 break;
194 case OF_RECONFIG_UPDATE_PROPERTY:
195 if (is_status) {
196 prev_state = old_status_state != 0;
197 new_state = status_state != 0;
198 }
199 break;
200 }
201
202 if (prev_state == new_state)
203 return OF_RECONFIG_NO_CHANGE;
204
205 return new_state ? OF_RECONFIG_CHANGE_ADD : OF_RECONFIG_CHANGE_REMOVE;
206}
207EXPORT_SYMBOL_GPL(of_reconfig_get_state_change);
208
Grant Likely6afc0dc2014-06-26 15:40:48 +0100209int of_property_notify(int action, struct device_node *np,
Grant Likely259092a2014-07-16 12:48:23 -0600210 struct property *prop, struct property *oldprop)
Grant Likely6afc0dc2014-06-26 15:40:48 +0100211{
Grant Likelyf5242e52014-11-24 17:58:01 +0000212 struct of_reconfig_data pr;
Grant Likely6afc0dc2014-06-26 15:40:48 +0100213
214 /* only call notifiers if the node is attached */
215 if (!of_node_is_attached(np))
216 return 0;
217
218 pr.dn = np;
219 pr.prop = prop;
Grant Likely259092a2014-07-16 12:48:23 -0600220 pr.old_prop = oldprop;
Grant Likely6afc0dc2014-06-26 15:40:48 +0100221 return of_reconfig_notify(action, &pr);
222}
223
Pantelis Antonioud8c50082014-07-04 19:58:46 +0300224void __of_attach_node(struct device_node *np)
225{
Grant Likelya25095d2014-07-15 23:25:43 -0600226 const __be32 *phandle;
227 int sz;
228
229 np->name = __of_get_property(np, "name", NULL) ? : "<NULL>";
230 np->type = __of_get_property(np, "device_type", NULL) ? : "<NULL>";
231
232 phandle = __of_get_property(np, "phandle", &sz);
233 if (!phandle)
234 phandle = __of_get_property(np, "linux,phandle", &sz);
Geert Uytterhoevenf76502a2015-06-04 11:34:41 +0200235 if (IS_ENABLED(CONFIG_PPC_PSERIES) && !phandle)
Grant Likelya25095d2014-07-15 23:25:43 -0600236 phandle = __of_get_property(np, "ibm,phandle", &sz);
237 np->phandle = (phandle && (sz >= 4)) ? be32_to_cpup(phandle) : 0;
238
Grant Likely6162dbe2014-07-16 08:48:46 -0600239 np->child = NULL;
Pantelis Antonioud8c50082014-07-04 19:58:46 +0300240 np->sibling = np->parent->child;
Pantelis Antonioud8c50082014-07-04 19:58:46 +0300241 np->parent->child = np;
242 of_node_clear_flag(np, OF_DETACHED);
243}
244
Grant Likely6afc0dc2014-06-26 15:40:48 +0100245/**
246 * of_attach_node() - Plug a device node into the tree and global list.
247 */
248int of_attach_node(struct device_node *np)
249{
Grant Likelyf5242e52014-11-24 17:58:01 +0000250 struct of_reconfig_data rd;
Grant Likely6afc0dc2014-06-26 15:40:48 +0100251 unsigned long flags;
Grant Likely6afc0dc2014-06-26 15:40:48 +0100252
Grant Likelyf5242e52014-11-24 17:58:01 +0000253 memset(&rd, 0, sizeof(rd));
254 rd.dn = np;
255
Grant Likely8a2b22a2014-07-23 17:05:06 -0600256 mutex_lock(&of_mutex);
Grant Likely6afc0dc2014-06-26 15:40:48 +0100257 raw_spin_lock_irqsave(&devtree_lock, flags);
Pantelis Antonioud8c50082014-07-04 19:58:46 +0300258 __of_attach_node(np);
Grant Likely6afc0dc2014-06-26 15:40:48 +0100259 raw_spin_unlock_irqrestore(&devtree_lock, flags);
260
Grant Likely8a2b22a2014-07-23 17:05:06 -0600261 __of_attach_node_sysfs(np);
262 mutex_unlock(&of_mutex);
Grant Likely259092a2014-07-16 12:48:23 -0600263
Grant Likelyf5242e52014-11-24 17:58:01 +0000264 of_reconfig_notify(OF_RECONFIG_ATTACH_NODE, &rd);
Grant Likely259092a2014-07-16 12:48:23 -0600265
Grant Likely6afc0dc2014-06-26 15:40:48 +0100266 return 0;
267}
268
Pantelis Antonioud8c50082014-07-04 19:58:46 +0300269void __of_detach_node(struct device_node *np)
Grant Likely6afc0dc2014-06-26 15:40:48 +0100270{
271 struct device_node *parent;
Grant Likely6afc0dc2014-06-26 15:40:48 +0100272
Pantelis Antonioud8c50082014-07-04 19:58:46 +0300273 if (WARN_ON(of_node_check_flag(np, OF_DETACHED)))
274 return;
Grant Likely6afc0dc2014-06-26 15:40:48 +0100275
276 parent = np->parent;
Pantelis Antonioud8c50082014-07-04 19:58:46 +0300277 if (WARN_ON(!parent))
278 return;
Grant Likely6afc0dc2014-06-26 15:40:48 +0100279
Grant Likely6afc0dc2014-06-26 15:40:48 +0100280 if (parent->child == np)
281 parent->child = np->sibling;
282 else {
283 struct device_node *prevsib;
284 for (prevsib = np->parent->child;
285 prevsib->sibling != np;
286 prevsib = prevsib->sibling)
287 ;
288 prevsib->sibling = np->sibling;
289 }
290
291 of_node_set_flag(np, OF_DETACHED);
Pantelis Antonioud8c50082014-07-04 19:58:46 +0300292}
293
294/**
295 * of_detach_node() - "Unplug" a node from the device tree.
296 *
297 * The caller must hold a reference to the node. The memory associated with
298 * the node is not freed until its refcount goes to zero.
299 */
300int of_detach_node(struct device_node *np)
301{
Grant Likelyf5242e52014-11-24 17:58:01 +0000302 struct of_reconfig_data rd;
Pantelis Antonioud8c50082014-07-04 19:58:46 +0300303 unsigned long flags;
304 int rc = 0;
305
Grant Likelyf5242e52014-11-24 17:58:01 +0000306 memset(&rd, 0, sizeof(rd));
307 rd.dn = np;
308
Grant Likely8a2b22a2014-07-23 17:05:06 -0600309 mutex_lock(&of_mutex);
Pantelis Antonioud8c50082014-07-04 19:58:46 +0300310 raw_spin_lock_irqsave(&devtree_lock, flags);
311 __of_detach_node(np);
Grant Likely6afc0dc2014-06-26 15:40:48 +0100312 raw_spin_unlock_irqrestore(&devtree_lock, flags);
313
Grant Likely8a2b22a2014-07-23 17:05:06 -0600314 __of_detach_node_sysfs(np);
315 mutex_unlock(&of_mutex);
Grant Likely259092a2014-07-16 12:48:23 -0600316
Grant Likelyf5242e52014-11-24 17:58:01 +0000317 of_reconfig_notify(OF_RECONFIG_DETACH_NODE, &rd);
Grant Likely259092a2014-07-16 12:48:23 -0600318
Grant Likely6afc0dc2014-06-26 15:40:48 +0100319 return rc;
320}
Gavin Shanbb91f922016-05-03 23:22:52 +1000321EXPORT_SYMBOL_GPL(of_detach_node);
Grant Likely6afc0dc2014-06-26 15:40:48 +0100322
323/**
324 * of_node_release() - release a dynamically allocated node
325 * @kref: kref element of the node to be released
326 *
327 * In of_node_put() this function is passed to kref_put() as the destructor.
328 */
329void of_node_release(struct kobject *kobj)
330{
331 struct device_node *node = kobj_to_device_node(kobj);
332 struct property *prop = node->properties;
333
334 /* We should never be releasing nodes that haven't been detached. */
335 if (!of_node_check_flag(node, OF_DETACHED)) {
336 pr_err("ERROR: Bad of_node_put() on %s\n", node->full_name);
337 dump_stack();
338 return;
339 }
340
341 if (!of_node_check_flag(node, OF_DYNAMIC))
342 return;
343
344 while (prop) {
345 struct property *next = prop->next;
346 kfree(prop->name);
347 kfree(prop->value);
348 kfree(prop);
349 prop = next;
350
351 if (!prop) {
352 prop = node->deadprops;
353 node->deadprops = NULL;
354 }
355 }
356 kfree(node->full_name);
357 kfree(node->data);
358 kfree(node);
359}
Pantelis Antoniou69843392014-07-04 19:58:47 +0300360
361/**
362 * __of_prop_dup - Copy a property dynamically.
363 * @prop: Property to copy
364 * @allocflags: Allocation flags (typically pass GFP_KERNEL)
365 *
366 * Copy a property by dynamically allocating the memory of both the
Geert Uytterhoeven27b33832014-10-22 11:49:01 +0200367 * property structure and the property name & contents. The property's
Pantelis Antoniou69843392014-07-04 19:58:47 +0300368 * flags have the OF_DYNAMIC bit set so that we can differentiate between
369 * dynamically allocated properties and not.
370 * Returns the newly allocated property or NULL on out of memory error.
371 */
372struct property *__of_prop_dup(const struct property *prop, gfp_t allocflags)
373{
374 struct property *new;
375
376 new = kzalloc(sizeof(*new), allocflags);
377 if (!new)
378 return NULL;
379
380 /*
381 * NOTE: There is no check for zero length value.
Grant Likelyb6ae5dc2014-07-26 10:58:43 -0600382 * In case of a boolean property, this will allocate a value
Pantelis Antoniou69843392014-07-04 19:58:47 +0300383 * of zero bytes. We do this to work around the use
384 * of of_get_property() calls on boolean values.
385 */
386 new->name = kstrdup(prop->name, allocflags);
387 new->value = kmemdup(prop->value, prop->length, allocflags);
388 new->length = prop->length;
389 if (!new->name || !new->value)
390 goto err_free;
391
392 /* mark the property as dynamic */
393 of_property_set_flag(new, OF_DYNAMIC);
394
395 return new;
396
397 err_free:
398 kfree(new->name);
399 kfree(new->value);
400 kfree(new);
401 return NULL;
402}
403
404/**
Grant Likelye5179582014-11-17 22:31:32 +0000405 * __of_node_dup() - Duplicate or create an empty device node dynamically.
406 * @fmt: Format string (plus vargs) for new full name of the device node
Pantelis Antoniou69843392014-07-04 19:58:47 +0300407 *
Grant Likelye5179582014-11-17 22:31:32 +0000408 * Create an device tree node, either by duplicating an empty node or by allocating
409 * an empty one suitable for further modification. The node data are
410 * dynamically allocated and all the node flags have the OF_DYNAMIC &
411 * OF_DETACHED bits set. Returns the newly allocated node or NULL on out of
412 * memory error.
Pantelis Antoniou69843392014-07-04 19:58:47 +0300413 */
Grant Likelye5179582014-11-17 22:31:32 +0000414struct device_node *__of_node_dup(const struct device_node *np, const char *fmt, ...)
Pantelis Antoniou69843392014-07-04 19:58:47 +0300415{
Grant Likelyef8bbd72014-11-14 15:33:07 +0000416 va_list vargs;
Pantelis Antoniou69843392014-07-04 19:58:47 +0300417 struct device_node *node;
418
Grant Likelyef8bbd72014-11-14 15:33:07 +0000419 node = kzalloc(sizeof(*node), GFP_KERNEL);
Pantelis Antoniou69843392014-07-04 19:58:47 +0300420 if (!node)
421 return NULL;
Grant Likelyef8bbd72014-11-14 15:33:07 +0000422 va_start(vargs, fmt);
423 node->full_name = kvasprintf(GFP_KERNEL, fmt, vargs);
424 va_end(vargs);
Grant Likelye5179582014-11-17 22:31:32 +0000425 if (!node->full_name) {
426 kfree(node);
427 return NULL;
428 }
Pantelis Antoniou69843392014-07-04 19:58:47 +0300429
Grant Likelyef8bbd72014-11-14 15:33:07 +0000430 of_node_set_flag(node, OF_DYNAMIC);
431 of_node_set_flag(node, OF_DETACHED);
Pantelis Antoniou69843392014-07-04 19:58:47 +0300432 of_node_init(node);
433
Grant Likelye5179582014-11-17 22:31:32 +0000434 /* Iterate over and duplicate all properties */
435 if (np) {
436 struct property *pp, *new_pp;
437 for_each_property_of_node(np, pp) {
438 new_pp = __of_prop_dup(pp, GFP_KERNEL);
439 if (!new_pp)
440 goto err_prop;
441 if (__of_add_property(node, new_pp)) {
442 kfree(new_pp->name);
443 kfree(new_pp->value);
444 kfree(new_pp);
445 goto err_prop;
446 }
447 }
448 }
Pantelis Antoniou69843392014-07-04 19:58:47 +0300449 return node;
450
Grant Likelye5179582014-11-17 22:31:32 +0000451 err_prop:
452 of_node_put(node); /* Frees the node and properties */
Pantelis Antoniou69843392014-07-04 19:58:47 +0300453 return NULL;
454}
Pantelis Antoniou201c9102014-07-04 19:58:49 +0300455
456static void __of_changeset_entry_destroy(struct of_changeset_entry *ce)
457{
458 of_node_put(ce->np);
459 list_del(&ce->node);
460 kfree(ce);
461}
462
463#ifdef DEBUG
464static void __of_changeset_entry_dump(struct of_changeset_entry *ce)
465{
466 switch (ce->action) {
467 case OF_RECONFIG_ADD_PROPERTY:
Pantelis Antoniou201c9102014-07-04 19:58:49 +0300468 case OF_RECONFIG_REMOVE_PROPERTY:
Pantelis Antoniou201c9102014-07-04 19:58:49 +0300469 case OF_RECONFIG_UPDATE_PROPERTY:
Rob Herring606ad422016-06-15 08:32:18 -0500470 pr_debug("cset<%p> %-15s %s/%s\n", ce, action_names[ce->action],
Grant Likely00aa3722014-11-14 14:34:55 +0000471 ce->np->full_name, ce->prop->name);
Pantelis Antoniou201c9102014-07-04 19:58:49 +0300472 break;
473 case OF_RECONFIG_ATTACH_NODE:
Pantelis Antoniou201c9102014-07-04 19:58:49 +0300474 case OF_RECONFIG_DETACH_NODE:
Rob Herring606ad422016-06-15 08:32:18 -0500475 pr_debug("cset<%p> %-15s %s\n", ce, action_names[ce->action],
Grant Likely00aa3722014-11-14 14:34:55 +0000476 ce->np->full_name);
Pantelis Antoniou201c9102014-07-04 19:58:49 +0300477 break;
478 }
479}
480#else
481static inline void __of_changeset_entry_dump(struct of_changeset_entry *ce)
482{
483 /* empty */
484}
485#endif
486
487static void __of_changeset_entry_invert(struct of_changeset_entry *ce,
488 struct of_changeset_entry *rce)
489{
490 memcpy(rce, ce, sizeof(*rce));
491
492 switch (ce->action) {
493 case OF_RECONFIG_ATTACH_NODE:
494 rce->action = OF_RECONFIG_DETACH_NODE;
495 break;
496 case OF_RECONFIG_DETACH_NODE:
497 rce->action = OF_RECONFIG_ATTACH_NODE;
498 break;
499 case OF_RECONFIG_ADD_PROPERTY:
500 rce->action = OF_RECONFIG_REMOVE_PROPERTY;
501 break;
502 case OF_RECONFIG_REMOVE_PROPERTY:
503 rce->action = OF_RECONFIG_ADD_PROPERTY;
504 break;
505 case OF_RECONFIG_UPDATE_PROPERTY:
506 rce->old_prop = ce->prop;
507 rce->prop = ce->old_prop;
Pantelis Antonioub9c43852016-05-09 16:20:42 +0300508 /* update was used but original property did not exist */
509 if (!rce->prop) {
510 rce->action = OF_RECONFIG_REMOVE_PROPERTY;
511 rce->prop = ce->prop;
512 }
Pantelis Antoniou201c9102014-07-04 19:58:49 +0300513 break;
514 }
515}
516
517static void __of_changeset_entry_notify(struct of_changeset_entry *ce, bool revert)
518{
Grant Likelyf5242e52014-11-24 17:58:01 +0000519 struct of_reconfig_data rd;
Pantelis Antoniou201c9102014-07-04 19:58:49 +0300520 struct of_changeset_entry ce_inverted;
521 int ret;
522
523 if (revert) {
524 __of_changeset_entry_invert(ce, &ce_inverted);
525 ce = &ce_inverted;
526 }
527
528 switch (ce->action) {
529 case OF_RECONFIG_ATTACH_NODE:
530 case OF_RECONFIG_DETACH_NODE:
Grant Likelyf5242e52014-11-24 17:58:01 +0000531 memset(&rd, 0, sizeof(rd));
532 rd.dn = ce->np;
533 ret = of_reconfig_notify(ce->action, &rd);
Pantelis Antoniou201c9102014-07-04 19:58:49 +0300534 break;
535 case OF_RECONFIG_ADD_PROPERTY:
536 case OF_RECONFIG_REMOVE_PROPERTY:
537 case OF_RECONFIG_UPDATE_PROPERTY:
538 ret = of_property_notify(ce->action, ce->np, ce->prop, ce->old_prop);
539 break;
540 default:
Rob Herring606ad422016-06-15 08:32:18 -0500541 pr_err("invalid devicetree changeset action: %i\n",
Pantelis Antoniou201c9102014-07-04 19:58:49 +0300542 (int)ce->action);
543 return;
544 }
545
546 if (ret)
Rob Herring606ad422016-06-15 08:32:18 -0500547 pr_err("changeset notifier error @%s\n", ce->np->full_name);
Pantelis Antoniou201c9102014-07-04 19:58:49 +0300548}
549
550static int __of_changeset_entry_apply(struct of_changeset_entry *ce)
551{
552 struct property *old_prop, **propp;
553 unsigned long flags;
554 int ret = 0;
555
556 __of_changeset_entry_dump(ce);
557
558 raw_spin_lock_irqsave(&devtree_lock, flags);
559 switch (ce->action) {
560 case OF_RECONFIG_ATTACH_NODE:
561 __of_attach_node(ce->np);
562 break;
563 case OF_RECONFIG_DETACH_NODE:
564 __of_detach_node(ce->np);
565 break;
566 case OF_RECONFIG_ADD_PROPERTY:
567 /* If the property is in deadprops then it must be removed */
568 for (propp = &ce->np->deadprops; *propp; propp = &(*propp)->next) {
569 if (*propp == ce->prop) {
570 *propp = ce->prop->next;
571 ce->prop->next = NULL;
572 break;
573 }
574 }
575
576 ret = __of_add_property(ce->np, ce->prop);
577 if (ret) {
Rob Herring606ad422016-06-15 08:32:18 -0500578 pr_err("changeset: add_property failed @%s/%s\n",
579 ce->np->full_name,
Pantelis Antoniou201c9102014-07-04 19:58:49 +0300580 ce->prop->name);
581 break;
582 }
583 break;
584 case OF_RECONFIG_REMOVE_PROPERTY:
585 ret = __of_remove_property(ce->np, ce->prop);
586 if (ret) {
Rob Herring606ad422016-06-15 08:32:18 -0500587 pr_err("changeset: remove_property failed @%s/%s\n",
588 ce->np->full_name,
Pantelis Antoniou201c9102014-07-04 19:58:49 +0300589 ce->prop->name);
590 break;
591 }
592 break;
593
594 case OF_RECONFIG_UPDATE_PROPERTY:
595 /* If the property is in deadprops then it must be removed */
596 for (propp = &ce->np->deadprops; *propp; propp = &(*propp)->next) {
597 if (*propp == ce->prop) {
598 *propp = ce->prop->next;
599 ce->prop->next = NULL;
600 break;
601 }
602 }
603
604 ret = __of_update_property(ce->np, ce->prop, &old_prop);
605 if (ret) {
Rob Herring606ad422016-06-15 08:32:18 -0500606 pr_err("changeset: update_property failed @%s/%s\n",
607 ce->np->full_name,
Pantelis Antoniou201c9102014-07-04 19:58:49 +0300608 ce->prop->name);
609 break;
610 }
611 break;
612 default:
613 ret = -EINVAL;
614 }
615 raw_spin_unlock_irqrestore(&devtree_lock, flags);
616
617 if (ret)
618 return ret;
619
620 switch (ce->action) {
621 case OF_RECONFIG_ATTACH_NODE:
622 __of_attach_node_sysfs(ce->np);
623 break;
624 case OF_RECONFIG_DETACH_NODE:
625 __of_detach_node_sysfs(ce->np);
626 break;
627 case OF_RECONFIG_ADD_PROPERTY:
628 /* ignore duplicate names */
629 __of_add_property_sysfs(ce->np, ce->prop);
630 break;
631 case OF_RECONFIG_REMOVE_PROPERTY:
632 __of_remove_property_sysfs(ce->np, ce->prop);
633 break;
634 case OF_RECONFIG_UPDATE_PROPERTY:
635 __of_update_property_sysfs(ce->np, ce->prop, ce->old_prop);
636 break;
637 }
638
639 return 0;
640}
641
642static inline int __of_changeset_entry_revert(struct of_changeset_entry *ce)
643{
644 struct of_changeset_entry ce_inverted;
645
646 __of_changeset_entry_invert(ce, &ce_inverted);
647 return __of_changeset_entry_apply(&ce_inverted);
648}
649
650/**
651 * of_changeset_init - Initialize a changeset for use
652 *
653 * @ocs: changeset pointer
654 *
655 * Initialize a changeset structure
656 */
657void of_changeset_init(struct of_changeset *ocs)
658{
659 memset(ocs, 0, sizeof(*ocs));
660 INIT_LIST_HEAD(&ocs->entries);
661}
Gavin Shan18322372015-11-05 00:12:49 +1100662EXPORT_SYMBOL_GPL(of_changeset_init);
Pantelis Antoniou201c9102014-07-04 19:58:49 +0300663
664/**
665 * of_changeset_destroy - Destroy a changeset
666 *
667 * @ocs: changeset pointer
668 *
669 * Destroys a changeset. Note that if a changeset is applied,
670 * its changes to the tree cannot be reverted.
671 */
672void of_changeset_destroy(struct of_changeset *ocs)
673{
674 struct of_changeset_entry *ce, *cen;
675
676 list_for_each_entry_safe_reverse(ce, cen, &ocs->entries, node)
677 __of_changeset_entry_destroy(ce);
678}
Gavin Shan18322372015-11-05 00:12:49 +1100679EXPORT_SYMBOL_GPL(of_changeset_destroy);
Pantelis Antoniou201c9102014-07-04 19:58:49 +0300680
Gavin Shan18322372015-11-05 00:12:49 +1100681int __of_changeset_apply(struct of_changeset *ocs)
Pantelis Antoniou201c9102014-07-04 19:58:49 +0300682{
683 struct of_changeset_entry *ce;
684 int ret;
685
686 /* perform the rest of the work */
Rob Herring606ad422016-06-15 08:32:18 -0500687 pr_debug("changeset: applying...\n");
Pantelis Antoniou201c9102014-07-04 19:58:49 +0300688 list_for_each_entry(ce, &ocs->entries, node) {
689 ret = __of_changeset_entry_apply(ce);
690 if (ret) {
Rob Herring606ad422016-06-15 08:32:18 -0500691 pr_err("Error applying changeset (%d)\n", ret);
Pantelis Antoniou201c9102014-07-04 19:58:49 +0300692 list_for_each_entry_continue_reverse(ce, &ocs->entries, node)
693 __of_changeset_entry_revert(ce);
694 return ret;
695 }
696 }
Rob Herring606ad422016-06-15 08:32:18 -0500697 pr_debug("changeset: applied, emitting notifiers.\n");
Pantelis Antoniou201c9102014-07-04 19:58:49 +0300698
699 /* drop the global lock while emitting notifiers */
700 mutex_unlock(&of_mutex);
701 list_for_each_entry(ce, &ocs->entries, node)
702 __of_changeset_entry_notify(ce, 0);
703 mutex_lock(&of_mutex);
Rob Herring606ad422016-06-15 08:32:18 -0500704 pr_debug("changeset: notifiers sent.\n");
Pantelis Antoniou201c9102014-07-04 19:58:49 +0300705
706 return 0;
707}
708
709/**
Gavin Shan18322372015-11-05 00:12:49 +1100710 * of_changeset_apply - Applies a changeset
Pantelis Antoniou201c9102014-07-04 19:58:49 +0300711 *
712 * @ocs: changeset pointer
713 *
Gavin Shan18322372015-11-05 00:12:49 +1100714 * Applies a changeset to the live tree.
715 * Any side-effects of live tree state changes are applied here on
716 * success, like creation/destruction of devices and side-effects
717 * like creation of sysfs properties and directories.
Pantelis Antoniou201c9102014-07-04 19:58:49 +0300718 * Returns 0 on success, a negative error value in case of an error.
Gavin Shan18322372015-11-05 00:12:49 +1100719 * On error the partially applied effects are reverted.
Pantelis Antoniou201c9102014-07-04 19:58:49 +0300720 */
Gavin Shan18322372015-11-05 00:12:49 +1100721int of_changeset_apply(struct of_changeset *ocs)
722{
723 int ret;
724
725 mutex_lock(&of_mutex);
726 ret = __of_changeset_apply(ocs);
727 mutex_unlock(&of_mutex);
728
729 return ret;
730}
731EXPORT_SYMBOL_GPL(of_changeset_apply);
732
733int __of_changeset_revert(struct of_changeset *ocs)
Pantelis Antoniou201c9102014-07-04 19:58:49 +0300734{
735 struct of_changeset_entry *ce;
736 int ret;
737
Rob Herring606ad422016-06-15 08:32:18 -0500738 pr_debug("changeset: reverting...\n");
Pantelis Antoniou201c9102014-07-04 19:58:49 +0300739 list_for_each_entry_reverse(ce, &ocs->entries, node) {
740 ret = __of_changeset_entry_revert(ce);
741 if (ret) {
Rob Herring606ad422016-06-15 08:32:18 -0500742 pr_err("Error reverting changeset (%d)\n", ret);
Pantelis Antoniou201c9102014-07-04 19:58:49 +0300743 list_for_each_entry_continue(ce, &ocs->entries, node)
744 __of_changeset_entry_apply(ce);
745 return ret;
746 }
747 }
Rob Herring606ad422016-06-15 08:32:18 -0500748 pr_debug("changeset: reverted, emitting notifiers.\n");
Pantelis Antoniou201c9102014-07-04 19:58:49 +0300749
750 /* drop the global lock while emitting notifiers */
751 mutex_unlock(&of_mutex);
752 list_for_each_entry_reverse(ce, &ocs->entries, node)
753 __of_changeset_entry_notify(ce, 1);
754 mutex_lock(&of_mutex);
Rob Herring606ad422016-06-15 08:32:18 -0500755 pr_debug("changeset: notifiers sent.\n");
Pantelis Antoniou201c9102014-07-04 19:58:49 +0300756
757 return 0;
758}
759
760/**
Gavin Shan18322372015-11-05 00:12:49 +1100761 * of_changeset_revert - Reverts an applied changeset
762 *
763 * @ocs: changeset pointer
764 *
765 * Reverts a changeset returning the state of the tree to what it
766 * was before the application.
767 * Any side-effects like creation/destruction of devices and
768 * removal of sysfs properties and directories are applied.
769 * Returns 0 on success, a negative error value in case of an error.
770 */
771int of_changeset_revert(struct of_changeset *ocs)
772{
773 int ret;
774
775 mutex_lock(&of_mutex);
776 ret = __of_changeset_revert(ocs);
777 mutex_unlock(&of_mutex);
778
779 return ret;
780}
781EXPORT_SYMBOL_GPL(of_changeset_revert);
782
783/**
Pantelis Antoniou201c9102014-07-04 19:58:49 +0300784 * of_changeset_action - Perform a changeset action
785 *
786 * @ocs: changeset pointer
787 * @action: action to perform
788 * @np: Pointer to device node
789 * @prop: Pointer to property
790 *
791 * On action being one of:
792 * + OF_RECONFIG_ATTACH_NODE
793 * + OF_RECONFIG_DETACH_NODE,
794 * + OF_RECONFIG_ADD_PROPERTY
795 * + OF_RECONFIG_REMOVE_PROPERTY,
796 * + OF_RECONFIG_UPDATE_PROPERTY
797 * Returns 0 on success, a negative error value in case of an error.
798 */
799int of_changeset_action(struct of_changeset *ocs, unsigned long action,
800 struct device_node *np, struct property *prop)
801{
802 struct of_changeset_entry *ce;
803
804 ce = kzalloc(sizeof(*ce), GFP_KERNEL);
Rob Herring606ad422016-06-15 08:32:18 -0500805 if (!ce)
Pantelis Antoniou201c9102014-07-04 19:58:49 +0300806 return -ENOMEM;
Rob Herring606ad422016-06-15 08:32:18 -0500807
Pantelis Antoniou201c9102014-07-04 19:58:49 +0300808 /* get a reference to the node */
809 ce->action = action;
810 ce->np = of_node_get(np);
811 ce->prop = prop;
812
813 if (action == OF_RECONFIG_UPDATE_PROPERTY && prop)
814 ce->old_prop = of_find_property(np, prop->name, NULL);
815
816 /* add it to the list */
817 list_add_tail(&ce->node, &ocs->entries);
818 return 0;
819}
Gavin Shan18322372015-11-05 00:12:49 +1100820EXPORT_SYMBOL_GPL(of_changeset_action);