aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFrank Rowand <frank.rowand@sony.com>2017-10-17 19:36:25 -0400
committerRob Herring <robh@kernel.org>2017-10-17 21:46:59 -0400
commit61b4de4e0b384f4a22c55c3bada604da49cec4e1 (patch)
treebc72d1009781c110dc62c95584dbeaa761ac7bc0
parent42b2e94fe83c354b4373992c8ea28ef0ace2e633 (diff)
of: overlay: minor restructuring
Continue improving the readability of overlay.c. The previous patches renamed identifiers. This patch is split out from the previous patches to make the previous patches easier to review. Changes are: - minor code restructuring - some initialization of an overlay changeset occurred outside of init_overlay_changeset(), move that into init_overlay_changeset() - consolidate freeing an overlay changeset into free_overlay_changeset() This patch is intended to not introduce any functional change. Signed-off-by: Frank Rowand <frank.rowand@sony.com> Signed-off-by: Rob Herring <robh@kernel.org>
-rw-r--r--drivers/of/overlay.c205
1 files changed, 92 insertions, 113 deletions
diff --git a/drivers/of/overlay.c b/drivers/of/overlay.c
index bb8867cae05b..905916e17eec 100644
--- a/drivers/of/overlay.c
+++ b/drivers/of/overlay.c
@@ -55,6 +55,9 @@ static int build_changeset_next_level(struct overlay_changeset *ovcs,
55 const struct device_node *overlay_node, 55 const struct device_node *overlay_node,
56 bool is_symbols_node); 56 bool is_symbols_node);
57 57
58static LIST_HEAD(ovcs_list);
59static DEFINE_IDR(ovcs_idr);
60
58static BLOCKING_NOTIFIER_HEAD(overlay_notify_chain); 61static BLOCKING_NOTIFIER_HEAD(overlay_notify_chain);
59 62
60int of_overlay_notifier_register(struct notifier_block *nb) 63int of_overlay_notifier_register(struct notifier_block *nb)
@@ -160,8 +163,6 @@ static struct property *dup_and_fixup_symbol_prop(
160 kfree(new->value); 163 kfree(new->value);
161 kfree(new); 164 kfree(new);
162 return NULL; 165 return NULL;
163
164
165} 166}
166 167
167/** 168/**
@@ -258,13 +259,7 @@ static int add_changeset_node(struct overlay_changeset *ovcs,
258 if (!of_node_cmp(node_kbasename, kbasename(tchild->full_name))) 259 if (!of_node_cmp(node_kbasename, kbasename(tchild->full_name)))
259 break; 260 break;
260 261
261 if (tchild) { 262 if (!tchild) {
262 if (node->phandle)
263 return -EINVAL;
264
265 ret = build_changeset_next_level(ovcs, tchild, node, 0);
266 of_node_put(tchild);
267 } else {
268 tchild = __of_node_dup(node, "%pOF/%s", 263 tchild = __of_node_dup(node, "%pOF/%s",
269 target_node, node_kbasename); 264 target_node, node_kbasename);
270 if (!tchild) 265 if (!tchild)
@@ -276,11 +271,15 @@ static int add_changeset_node(struct overlay_changeset *ovcs,
276 if (ret) 271 if (ret)
277 return ret; 272 return ret;
278 273
279 ret = build_changeset_next_level(ovcs, tchild, node, 0); 274 return build_changeset_next_level(ovcs, tchild, node, 0);
280 if (ret)
281 return ret;
282 } 275 }
283 276
277 if (node->phandle)
278 return -EINVAL;
279
280 ret = build_changeset_next_level(ovcs, tchild, node, 0);
281 of_node_put(tchild);
282
284 return ret; 283 return ret;
285} 284}
286 285
@@ -394,41 +393,6 @@ static struct device_node *find_target_node(struct device_node *info_node)
394} 393}
395 394
396/** 395/**
397 * of_fill_overlay_info() - Fill an overlay info structure
398 * @ov Overlay to fill
399 * @info_node: Device node containing the overlay
400 * @ovinfo: Pointer to the overlay info structure to fill
401 *
402 * Fills an overlay info structure with the overlay information
403 * from a device node. This device node must have a target property
404 * which contains a phandle of the overlay target node, and an
405 * __overlay__ child node which has the overlay contents.
406 * Both ovinfo->target & ovinfo->overlay have their references taken.
407 *
408 * Returns 0 on success, or a negative error value.
409 */
410static int of_fill_overlay_info(struct overlay_changeset *ovcset,
411 struct device_node *info_node, struct fragment *fragment)
412{
413 fragment->overlay = of_get_child_by_name(info_node, "__overlay__");
414 if (!fragment->overlay)
415 goto err_fail;
416
417 fragment->target = find_target_node(info_node);
418 if (!fragment->target)
419 goto err_fail;
420
421 return 0;
422
423err_fail:
424 of_node_put(fragment->target);
425 of_node_put(fragment->overlay);
426
427 memset(fragment, 0, sizeof(*fragment));
428 return -EINVAL;
429}
430
431/**
432 * init_overlay_changeset() - initialize overlay changeset from overlay tree 396 * init_overlay_changeset() - initialize overlay changeset from overlay tree
433 * @ovcs Overlay changeset to build 397 * @ovcs Overlay changeset to build
434 * @tree: Contains all the overlay fragments and overlay fixup nodes 398 * @tree: Contains all the overlay fragments and overlay fixup nodes
@@ -438,32 +402,61 @@ err_fail:
438 * nodes and the __symbols__ node. Any other top level node will be ignored. 402 * nodes and the __symbols__ node. Any other top level node will be ignored.
439 * 403 *
440 * Returns 0 on success, -ENOMEM if memory allocation failure, -EINVAL if error 404 * Returns 0 on success, -ENOMEM if memory allocation failure, -EINVAL if error
441 * detected in @tree, or -ENODEV if no valid nodes found. 405 * detected in @tree, or -ENOSPC if idr_alloc() error.
442 */ 406 */
443static int init_overlay_changeset(struct overlay_changeset *ovcs, 407static int init_overlay_changeset(struct overlay_changeset *ovcs,
444 struct device_node *tree) 408 struct device_node *tree)
445{ 409{
446 struct device_node *node; 410 struct device_node *node, *overlay_node;
447 struct fragment *fragment; 411 struct fragment *fragment;
448 struct fragment *fragments; 412 struct fragment *fragments;
449 int cnt, ret; 413 int cnt, ret;
450 414
415 INIT_LIST_HEAD(&ovcs->ovcs_list);
416
417 of_changeset_init(&ovcs->cset);
418
419 ovcs->id = idr_alloc(&ovcs_idr, ovcs, 1, 0, GFP_KERNEL);
420 if (ovcs->id <= 0)
421 return ovcs->id;
422
451 cnt = 0; 423 cnt = 0;
452 for_each_child_of_node(tree, node)
453 cnt++;
454 424
455 if (of_get_child_by_name(tree, "__symbols__")) 425 /* fragment nodes */
426 for_each_child_of_node(tree, node) {
427 overlay_node = of_get_child_by_name(node, "__overlay__");
428 if (overlay_node) {
429 cnt++;
430 of_node_put(overlay_node);
431 }
432 }
433
434 node = of_get_child_by_name(tree, "__symbols__");
435 if (node) {
456 cnt++; 436 cnt++;
437 of_node_put(node);
438 }
457 439
458 fragments = kcalloc(cnt, sizeof(*fragments), GFP_KERNEL); 440 fragments = kcalloc(cnt, sizeof(*fragments), GFP_KERNEL);
459 if (!fragments) 441 if (!fragments) {
460 return -ENOMEM; 442 ret = -ENOMEM;
443 goto err_free_idr;
444 }
461 445
462 cnt = 0; 446 cnt = 0;
463 for_each_child_of_node(tree, node) { 447 for_each_child_of_node(tree, node) {
464 ret = of_fill_overlay_info(ovcs, node, &fragments[cnt]); 448 fragment = &fragments[cnt];
465 if (!ret) 449 fragment->overlay = of_get_child_by_name(node, "__overlay__");
466 cnt++; 450 if (fragment->overlay) {
451 fragment->target = find_target_node(node);
452 if (!fragment->target) {
453 of_node_put(fragment->overlay);
454 ret = -EINVAL;
455 goto err_free_fragments;
456 } else {
457 cnt++;
458 }
459 }
467 } 460 }
468 461
469 node = of_get_child_by_name(tree, "__symbols__"); 462 node = of_get_child_by_name(tree, "__symbols__");
@@ -475,44 +468,51 @@ static int init_overlay_changeset(struct overlay_changeset *ovcs,
475 468
476 if (!fragment->target) { 469 if (!fragment->target) {
477 pr_err("no symbols in root of device tree.\n"); 470 pr_err("no symbols in root of device tree.\n");
478 return -EINVAL; 471 ret = -EINVAL;
472 goto err_free_fragments;
479 } 473 }
480 474
481 cnt++; 475 cnt++;
482 } 476 }
483 477
484 if (!cnt) { 478 if (!cnt) {
485 kfree(fragments); 479 ret = -EINVAL;
486 return -ENODEV; 480 goto err_free_fragments;
487 } 481 }
488 482
489 ovcs->count = cnt; 483 ovcs->count = cnt;
490 ovcs->fragments = fragments; 484 ovcs->fragments = fragments;
491 485
492 return 0; 486 return 0;
487
488
489err_free_fragments:
490 kfree(fragments);
491err_free_idr:
492 idr_remove(&ovcs_idr, ovcs->id);
493
494 return ret;
493} 495}
494 496
495/** 497static void free_overlay_changeset(struct overlay_changeset *ovcs)
496 * free_overlay_fragments() - Free a fragments array
497 * @ovcs Overlay to free the overlay info from
498 *
499 * Frees the memory of an ovcs->fragments[] array.
500 */
501static void free_overlay_fragments(struct overlay_changeset *ovcs)
502{ 498{
503 int i; 499 int i;
504 500
505 /* do it in reverse */ 501 if (!ovcs->cset.entries.next)
506 for (i = ovcs->count - 1; i >= 0; i--) { 502 return;
503 of_changeset_destroy(&ovcs->cset);
504
505 if (ovcs->id)
506 idr_remove(&ovcs_idr, ovcs->id);
507
508 for (i = 0; i < ovcs->count; i++) {
507 of_node_put(ovcs->fragments[i].target); 509 of_node_put(ovcs->fragments[i].target);
508 of_node_put(ovcs->fragments[i].overlay); 510 of_node_put(ovcs->fragments[i].overlay);
509 } 511 }
510
511 kfree(ovcs->fragments); 512 kfree(ovcs->fragments);
512}
513 513
514static LIST_HEAD(ovcs_list); 514 kfree(ovcs);
515static DEFINE_IDR(ovcs_idr); 515}
516 516
517/** 517/**
518 * of_overlay_apply() - Create and apply an overlay changeset 518 * of_overlay_apply() - Create and apply an overlay changeset
@@ -526,47 +526,34 @@ static DEFINE_IDR(ovcs_idr);
526int of_overlay_apply(struct device_node *tree) 526int of_overlay_apply(struct device_node *tree)
527{ 527{
528 struct overlay_changeset *ovcs; 528 struct overlay_changeset *ovcs;
529 int id, ret; 529 int ret;
530 530
531 ovcs = kzalloc(sizeof(*ovcs), GFP_KERNEL); 531 ovcs = kzalloc(sizeof(*ovcs), GFP_KERNEL);
532 if (!ovcs) 532 if (!ovcs)
533 return -ENOMEM; 533 return -ENOMEM;
534 ovcs->id = -1;
535
536 INIT_LIST_HEAD(&ovcs->ovcs_list);
537
538 of_changeset_init(&ovcs->cset);
539 534
540 mutex_lock(&of_mutex); 535 mutex_lock(&of_mutex);
541 536
542 id = idr_alloc(&ovcs_idr, ovcs, 0, 0, GFP_KERNEL);
543 if (id < 0) {
544 ret = id;
545 goto err_destroy_trans;
546 }
547 ovcs->id = id;
548
549 ret = init_overlay_changeset(ovcs, tree); 537 ret = init_overlay_changeset(ovcs, tree);
550 if (ret) { 538 if (ret) {
551 pr_err("init_overlay_changeset() failed for tree@%pOF\n", 539 pr_err("init_overlay_changeset() failed, ret = %d\n", ret);
552 tree); 540 goto err_free_overlay_changeset;
553 goto err_free_idr;
554 } 541 }
555 542
556 ret = overlay_notify(ovcs, OF_OVERLAY_PRE_APPLY); 543 ret = overlay_notify(ovcs, OF_OVERLAY_PRE_APPLY);
557 if (ret < 0) { 544 if (ret < 0) {
558 pr_err("%s: Pre-apply notifier failed (ret=%d)\n", 545 pr_err("%s: Pre-apply notifier failed (ret=%d)\n",
559 __func__, ret); 546 __func__, ret);
560 goto err_free_overlay_fragments; 547 goto err_free_overlay_changeset;
561 } 548 }
562 549
563 ret = build_changeset(ovcs); 550 ret = build_changeset(ovcs);
564 if (ret) 551 if (ret)
565 goto err_free_overlay_fragments; 552 goto err_free_overlay_changeset;
566 553
567 ret = __of_changeset_apply(&ovcs->cset); 554 ret = __of_changeset_apply(&ovcs->cset);
568 if (ret) 555 if (ret)
569 goto err_free_overlay_fragments; 556 goto err_free_overlay_changeset;
570 557
571 list_add_tail(&ovcs->ovcs_list, &ovcs_list); 558 list_add_tail(&ovcs->ovcs_list, &ovcs_list);
572 559
@@ -574,15 +561,11 @@ int of_overlay_apply(struct device_node *tree)
574 561
575 mutex_unlock(&of_mutex); 562 mutex_unlock(&of_mutex);
576 563
577 return id; 564 return ovcs->id;
565
566err_free_overlay_changeset:
567 free_overlay_changeset(ovcs);
578 568
579err_free_overlay_fragments:
580 free_overlay_fragments(ovcs);
581err_free_idr:
582 idr_remove(&ovcs_idr, ovcs->id);
583err_destroy_trans:
584 of_changeset_destroy(&ovcs->cset);
585 kfree(ovcs);
586 mutex_unlock(&of_mutex); 569 mutex_unlock(&of_mutex);
587 570
588 return ret; 571 return ret;
@@ -693,13 +676,14 @@ int of_overlay_remove(int ovcs_id)
693 } 676 }
694 677
695 overlay_notify(ovcs, OF_OVERLAY_PRE_REMOVE); 678 overlay_notify(ovcs, OF_OVERLAY_PRE_REMOVE);
679
696 list_del(&ovcs->ovcs_list); 680 list_del(&ovcs->ovcs_list);
681
697 __of_changeset_revert(&ovcs->cset); 682 __of_changeset_revert(&ovcs->cset);
683
698 overlay_notify(ovcs, OF_OVERLAY_POST_REMOVE); 684 overlay_notify(ovcs, OF_OVERLAY_POST_REMOVE);
699 free_overlay_fragments(ovcs); 685
700 idr_remove(&ovcs_idr, ovcs_id); 686 free_overlay_changeset(ovcs);
701 of_changeset_destroy(&ovcs->cset);
702 kfree(ovcs);
703 687
704out: 688out:
705 mutex_unlock(&of_mutex); 689 mutex_unlock(&of_mutex);
@@ -718,20 +702,15 @@ EXPORT_SYMBOL_GPL(of_overlay_remove);
718int of_overlay_remove_all(void) 702int of_overlay_remove_all(void)
719{ 703{
720 struct overlay_changeset *ovcs, *ovcs_n; 704 struct overlay_changeset *ovcs, *ovcs_n;
721 705 int ret;
722 mutex_lock(&of_mutex);
723 706
724 /* the tail of list is guaranteed to be safe to remove */ 707 /* the tail of list is guaranteed to be safe to remove */
725 list_for_each_entry_safe_reverse(ovcs, ovcs_n, &ovcs_list, ovcs_list) { 708 list_for_each_entry_safe_reverse(ovcs, ovcs_n, &ovcs_list, ovcs_list) {
726 list_del(&ovcs->ovcs_list); 709 ret = of_overlay_remove(ovcs->id);
727 __of_changeset_revert(&ovcs->cset); 710 if (ret)
728 free_overlay_fragments(ovcs); 711 return ret;
729 idr_remove(&ovcs_idr, ovcs->id);
730 kfree(ovcs);
731 } 712 }
732 713
733 mutex_unlock(&of_mutex);
734
735 return 0; 714 return 0;
736} 715}
737EXPORT_SYMBOL_GPL(of_overlay_remove_all); 716EXPORT_SYMBOL_GPL(of_overlay_remove_all);