99#include <linux/errno.h>
1010#include <linux/module.h>
1111#include <linux/of.h>
12+ #include <linux/of_fdt.h>
1213#include <linux/of_irq.h>
1314#include <linux/of_platform.h>
1415#include <linux/list.h>
@@ -21,6 +22,10 @@ static struct selftest_results {
2122 int failed ;
2223} selftest_results ;
2324
25+ #define NO_OF_NODES 2
26+ static struct device_node * nodes [NO_OF_NODES ];
27+ static int last_node_index ;
28+
2429#define selftest (result , fmt , ...) { \
2530 if (!(result)) { \
2631 selftest_results.failed++; \
@@ -517,9 +522,156 @@ static void __init of_selftest_platform_populate(void)
517522 }
518523}
519524
525+ /**
526+ * update_node_properties - adds the properties
527+ * of np into dup node (present in live tree) and
528+ * updates parent of children of np to dup.
529+ *
530+ * @np: node already present in live tree
531+ * @dup: node present in live tree to be updated
532+ */
533+ static void update_node_properties (struct device_node * np ,
534+ struct device_node * dup )
535+ {
536+ struct property * prop ;
537+ struct device_node * child ;
538+
539+ for_each_property_of_node (np , prop )
540+ of_add_property (dup , prop );
541+
542+ for_each_child_of_node (np , child )
543+ child -> parent = dup ;
544+ }
545+
546+ /**
547+ * attach_node_and_children - attaches nodes
548+ * and its children to live tree
549+ *
550+ * @np: Node to attach to live tree
551+ */
552+ static int attach_node_and_children (struct device_node * np )
553+ {
554+ struct device_node * next , * root = np , * dup ;
555+
556+ if (!np ) {
557+ pr_warn ("%s: No tree to attach; not running tests\n" ,
558+ __func__ );
559+ return - ENODATA ;
560+ }
561+
562+
563+ /* skip root node */
564+ np = np -> child ;
565+ /* storing a copy in temporary node */
566+ dup = np ;
567+
568+ while (dup ) {
569+ nodes [last_node_index ++ ] = dup ;
570+ dup = dup -> sibling ;
571+ }
572+ dup = NULL ;
573+
574+ while (np ) {
575+ next = np -> allnext ;
576+ dup = of_find_node_by_path (np -> full_name );
577+ if (dup )
578+ update_node_properties (np , dup );
579+ else {
580+ np -> child = NULL ;
581+ if (np -> parent == root )
582+ np -> parent = of_allnodes ;
583+ of_attach_node (np );
584+ }
585+ np = next ;
586+ }
587+
588+ return 0 ;
589+ }
590+
591+ /**
592+ * selftest_data_add - Reads, copies data from
593+ * linked tree and attaches it to the live tree
594+ */
595+ static int __init selftest_data_add (void )
596+ {
597+ void * selftest_data ;
598+ struct device_node * selftest_data_node ;
599+ extern uint8_t __dtb_testcases_begin [];
600+ extern uint8_t __dtb_testcases_end [];
601+ const int size = __dtb_testcases_end - __dtb_testcases_begin ;
602+
603+ if (!size || !of_allnodes ) {
604+ pr_warn ("%s: No testcase data to attach; not running tests\n" ,
605+ __func__ );
606+ return - ENODATA ;
607+ }
608+
609+ /* creating copy */
610+ selftest_data = kmemdup (__dtb_testcases_begin , size , GFP_KERNEL );
611+
612+ if (!selftest_data ) {
613+ pr_warn ("%s: Failed to allocate memory for selftest_data; "
614+ "not running tests\n" , __func__ );
615+ return - ENOMEM ;
616+ }
617+ of_fdt_unflatten_tree (selftest_data , & selftest_data_node );
618+
619+ /* attach the sub-tree to live tree */
620+ return attach_node_and_children (selftest_data_node );
621+ }
622+
623+ /**
624+ * detach_node_and_children - detaches node
625+ * and its children from live tree
626+ *
627+ * @np: Node to detach from live tree
628+ */
629+ static void detach_node_and_children (struct device_node * np )
630+ {
631+ while (np -> child )
632+ detach_node_and_children (np -> child );
633+
634+ while (np -> sibling )
635+ detach_node_and_children (np -> sibling );
636+
637+ of_detach_node (np );
638+ }
639+
640+ /**
641+ * selftest_data_remove - removes the selftest data
642+ * nodes from the live tree
643+ */
644+ static void selftest_data_remove (void )
645+ {
646+ struct device_node * np ;
647+ struct property * prop ;
648+
649+ while (last_node_index >= 0 ) {
650+ if (nodes [last_node_index ]) {
651+ np = of_find_node_by_path (nodes [last_node_index ]-> full_name );
652+ if (strcmp (np -> full_name , "/aliases" ) != 0 ) {
653+ detach_node_and_children (np -> child );
654+ of_detach_node (np );
655+ } else {
656+ for_each_property_of_node (np , prop ) {
657+ if (strcmp (prop -> name , "testcase-alias" ) == 0 )
658+ of_remove_property (np , prop );
659+ }
660+ }
661+ }
662+ last_node_index -- ;
663+ }
664+ }
665+
520666static int __init of_selftest (void )
521667{
522668 struct device_node * np ;
669+ int res ;
670+
671+ /* adding data for selftest */
672+ res = selftest_data_add ();
673+ if (res )
674+ return res ;
523675
524676 np = of_find_node_by_path ("/testcase-data/phandle-tests/consumer-a" );
525677 if (!np ) {
@@ -539,6 +691,10 @@ static int __init of_selftest(void)
539691 of_selftest_platform_populate ();
540692 pr_info ("end of selftest - %i passed, %i failed\n" ,
541693 selftest_results .passed , selftest_results .failed );
694+
695+ /* removing selftest data from live tree */
696+ selftest_data_remove ();
697+
542698 return 0 ;
543699}
544700late_initcall (of_selftest );
0 commit comments