diff options
author | Pantelis Antoniou <pantelis.antoniou@konsulko.com> | 2014-10-28 16:35:59 -0400 |
---|---|---|
committer | Grant Likely <grant.likely@linaro.org> | 2014-11-24 17:25:13 -0500 |
commit | 177d271cf3171bb6826ee5189f67dc1f7d34f1da (patch) | |
tree | 05e92739348fcd566c6a602070485766fcd0cb49 | |
parent | 7518b5890d8ac366faa2326ce2356ef6392ce63d (diff) |
of/overlay: Add overlay unittests
Add unittests for OF overlays.
It tests overlay device addition/removal and whether
the apply revert sequence is correct.
Changes since V1:
* Added local fixups entries.
Signed-off-by: Pantelis Antoniou <pantelis.antoniou@konsulko.com>
Signed-off-by: Grant Likely <grant.likely@linaro.org>
-rw-r--r-- | Documentation/devicetree/bindings/unittest.txt | 14 | ||||
-rw-r--r-- | drivers/of/unittest-data/testcases.dts | 16 | ||||
-rw-r--r-- | drivers/of/unittest-data/tests-overlay.dtsi | 180 | ||||
-rw-r--r-- | drivers/of/unittest.c | 481 |
4 files changed, 691 insertions, 0 deletions
diff --git a/Documentation/devicetree/bindings/unittest.txt b/Documentation/devicetree/bindings/unittest.txt new file mode 100644 index 000000000000..0f92a22fddfa --- /dev/null +++ b/Documentation/devicetree/bindings/unittest.txt | |||
@@ -0,0 +1,14 @@ | |||
1 | * OF selftest platform device | ||
2 | |||
3 | ** selftest | ||
4 | |||
5 | Required properties: | ||
6 | - compatible: must be "selftest" | ||
7 | |||
8 | All other properties are optional. | ||
9 | |||
10 | Example: | ||
11 | selftest { | ||
12 | compatible = "selftest"; | ||
13 | status = "okay"; | ||
14 | }; | ||
diff --git a/drivers/of/unittest-data/testcases.dts b/drivers/of/unittest-data/testcases.dts index b6bc41b2a185..12f7c3d649c8 100644 --- a/drivers/of/unittest-data/testcases.dts +++ b/drivers/of/unittest-data/testcases.dts | |||
@@ -13,6 +13,7 @@ | |||
13 | #include "tests-interrupts.dtsi" | 13 | #include "tests-interrupts.dtsi" |
14 | #include "tests-match.dtsi" | 14 | #include "tests-match.dtsi" |
15 | #include "tests-platform.dtsi" | 15 | #include "tests-platform.dtsi" |
16 | #include "tests-overlay.dtsi" | ||
16 | 17 | ||
17 | /* | 18 | /* |
18 | * phandle fixup data - generated by dtc patches that aren't upstream. | 19 | * phandle fixup data - generated by dtc patches that aren't upstream. |
@@ -59,5 +60,20 @@ | |||
59 | testcase-device2 { | 60 | testcase-device2 { |
60 | interrupt-parent = <0x00000000>; | 61 | interrupt-parent = <0x00000000>; |
61 | }; | 62 | }; |
63 | overlay2 { | ||
64 | fragment@0 { | ||
65 | target = <0x00000000>; | ||
66 | }; | ||
67 | }; | ||
68 | overlay3 { | ||
69 | fragment@0 { | ||
70 | target = <0x00000000>; | ||
71 | }; | ||
72 | }; | ||
73 | overlay4 { | ||
74 | fragment@0 { | ||
75 | target = <0x00000000>; | ||
76 | }; | ||
77 | }; | ||
62 | }; | 78 | }; |
63 | }; }; | 79 | }; }; |
diff --git a/drivers/of/unittest-data/tests-overlay.dtsi b/drivers/of/unittest-data/tests-overlay.dtsi new file mode 100644 index 000000000000..75976da22b2e --- /dev/null +++ b/drivers/of/unittest-data/tests-overlay.dtsi | |||
@@ -0,0 +1,180 @@ | |||
1 | |||
2 | / { | ||
3 | testcase-data { | ||
4 | overlay-node { | ||
5 | |||
6 | /* test bus */ | ||
7 | selftestbus: test-bus { | ||
8 | compatible = "simple-bus"; | ||
9 | #address-cells = <1>; | ||
10 | #size-cells = <0>; | ||
11 | |||
12 | selftest100: test-selftest100 { | ||
13 | compatible = "selftest"; | ||
14 | status = "okay"; | ||
15 | reg = <100>; | ||
16 | }; | ||
17 | |||
18 | selftest101: test-selftest101 { | ||
19 | compatible = "selftest"; | ||
20 | status = "disabled"; | ||
21 | reg = <101>; | ||
22 | }; | ||
23 | |||
24 | selftest0: test-selftest0 { | ||
25 | compatible = "selftest"; | ||
26 | status = "disabled"; | ||
27 | reg = <0>; | ||
28 | }; | ||
29 | |||
30 | selftest1: test-selftest1 { | ||
31 | compatible = "selftest"; | ||
32 | status = "okay"; | ||
33 | reg = <1>; | ||
34 | }; | ||
35 | |||
36 | selftest2: test-selftest2 { | ||
37 | compatible = "selftest"; | ||
38 | status = "disabled"; | ||
39 | reg = <2>; | ||
40 | }; | ||
41 | |||
42 | selftest3: test-selftest3 { | ||
43 | compatible = "selftest"; | ||
44 | status = "okay"; | ||
45 | reg = <3>; | ||
46 | }; | ||
47 | |||
48 | selftest5: test-selftest5 { | ||
49 | compatible = "selftest"; | ||
50 | status = "disabled"; | ||
51 | reg = <5>; | ||
52 | }; | ||
53 | |||
54 | selftest6: test-selftest6 { | ||
55 | compatible = "selftest"; | ||
56 | status = "disabled"; | ||
57 | reg = <6>; | ||
58 | }; | ||
59 | |||
60 | selftest7: test-selftest7 { | ||
61 | compatible = "selftest"; | ||
62 | status = "disabled"; | ||
63 | reg = <7>; | ||
64 | }; | ||
65 | |||
66 | selftest8: test-selftest8 { | ||
67 | compatible = "selftest"; | ||
68 | status = "disabled"; | ||
69 | reg = <8>; | ||
70 | }; | ||
71 | }; | ||
72 | }; | ||
73 | |||
74 | /* test enable using absolute target path */ | ||
75 | overlay0 { | ||
76 | fragment@0 { | ||
77 | target-path = "/testcase-data/overlay-node/test-bus/test-selftest0"; | ||
78 | __overlay__ { | ||
79 | status = "okay"; | ||
80 | }; | ||
81 | }; | ||
82 | }; | ||
83 | |||
84 | /* test disable using absolute target path */ | ||
85 | overlay1 { | ||
86 | fragment@0 { | ||
87 | target-path = "/testcase-data/overlay-node/test-bus/test-selftest1"; | ||
88 | __overlay__ { | ||
89 | status = "disabled"; | ||
90 | }; | ||
91 | }; | ||
92 | }; | ||
93 | |||
94 | /* test enable using label */ | ||
95 | overlay2 { | ||
96 | fragment@0 { | ||
97 | target = <&selftest2>; | ||
98 | __overlay__ { | ||
99 | status = "okay"; | ||
100 | }; | ||
101 | }; | ||
102 | }; | ||
103 | |||
104 | /* test disable using label */ | ||
105 | overlay3 { | ||
106 | fragment@0 { | ||
107 | target = <&selftest3>; | ||
108 | __overlay__ { | ||
109 | status = "disabled"; | ||
110 | }; | ||
111 | }; | ||
112 | }; | ||
113 | |||
114 | /* test insertion of a full node */ | ||
115 | overlay4 { | ||
116 | fragment@0 { | ||
117 | target = <&selftestbus>; | ||
118 | __overlay__ { | ||
119 | |||
120 | /* suppress DTC warning */ | ||
121 | #address-cells = <1>; | ||
122 | #size-cells = <0>; | ||
123 | |||
124 | test-selftest4 { | ||
125 | compatible = "selftest"; | ||
126 | status = "okay"; | ||
127 | reg = <4>; | ||
128 | }; | ||
129 | }; | ||
130 | }; | ||
131 | }; | ||
132 | |||
133 | /* test overlay apply revert */ | ||
134 | overlay5 { | ||
135 | fragment@0 { | ||
136 | target-path = "/testcase-data/overlay-node/test-bus/test-selftest5"; | ||
137 | __overlay__ { | ||
138 | status = "okay"; | ||
139 | }; | ||
140 | }; | ||
141 | }; | ||
142 | |||
143 | /* test overlays application and removal in sequence */ | ||
144 | overlay6 { | ||
145 | fragment@0 { | ||
146 | target-path = "/testcase-data/overlay-node/test-bus/test-selftest6"; | ||
147 | __overlay__ { | ||
148 | status = "okay"; | ||
149 | }; | ||
150 | }; | ||
151 | }; | ||
152 | overlay7 { | ||
153 | fragment@0 { | ||
154 | target-path = "/testcase-data/overlay-node/test-bus/test-selftest7"; | ||
155 | __overlay__ { | ||
156 | status = "okay"; | ||
157 | }; | ||
158 | }; | ||
159 | }; | ||
160 | |||
161 | /* test overlays application and removal in bad sequence */ | ||
162 | overlay8 { | ||
163 | fragment@0 { | ||
164 | target-path = "/testcase-data/overlay-node/test-bus/test-selftest8"; | ||
165 | __overlay__ { | ||
166 | status = "okay"; | ||
167 | }; | ||
168 | }; | ||
169 | }; | ||
170 | overlay9 { | ||
171 | fragment@0 { | ||
172 | target-path = "/testcase-data/overlay-node/test-bus/test-selftest8"; | ||
173 | __overlay__ { | ||
174 | property-foo = "bar"; | ||
175 | }; | ||
176 | }; | ||
177 | }; | ||
178 | |||
179 | }; | ||
180 | }; | ||
diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c index 1720b039cac7..cc0c5ec5d464 100644 --- a/drivers/of/unittest.c +++ b/drivers/of/unittest.c | |||
@@ -17,6 +17,8 @@ | |||
17 | #include <linux/mutex.h> | 17 | #include <linux/mutex.h> |
18 | #include <linux/slab.h> | 18 | #include <linux/slab.h> |
19 | #include <linux/device.h> | 19 | #include <linux/device.h> |
20 | #include <linux/platform_device.h> | ||
21 | #include <linux/of_platform.h> | ||
20 | 22 | ||
21 | #include "of_private.h" | 23 | #include "of_private.h" |
22 | 24 | ||
@@ -933,6 +935,484 @@ static void selftest_data_remove(void) | |||
933 | } | 935 | } |
934 | } | 936 | } |
935 | 937 | ||
938 | #ifdef CONFIG_OF_OVERLAY | ||
939 | |||
940 | static int selftest_probe(struct platform_device *pdev) | ||
941 | { | ||
942 | struct device *dev = &pdev->dev; | ||
943 | struct device_node *np = dev->of_node; | ||
944 | |||
945 | if (np == NULL) { | ||
946 | dev_err(dev, "No OF data for device\n"); | ||
947 | return -EINVAL; | ||
948 | |||
949 | } | ||
950 | |||
951 | dev_dbg(dev, "%s for node @%s\n", __func__, np->full_name); | ||
952 | return 0; | ||
953 | } | ||
954 | |||
955 | static int selftest_remove(struct platform_device *pdev) | ||
956 | { | ||
957 | struct device *dev = &pdev->dev; | ||
958 | struct device_node *np = dev->of_node; | ||
959 | |||
960 | dev_dbg(dev, "%s for node @%s\n", __func__, np->full_name); | ||
961 | return 0; | ||
962 | } | ||
963 | |||
964 | static struct of_device_id selftest_match[] = { | ||
965 | { .compatible = "selftest", }, | ||
966 | {}, | ||
967 | }; | ||
968 | MODULE_DEVICE_TABLE(of, altera_jtaguart_match); | ||
969 | |||
970 | static struct platform_driver selftest_driver = { | ||
971 | .probe = selftest_probe, | ||
972 | .remove = selftest_remove, | ||
973 | .driver = { | ||
974 | .name = "selftest", | ||
975 | .owner = THIS_MODULE, | ||
976 | .of_match_table = of_match_ptr(selftest_match), | ||
977 | }, | ||
978 | }; | ||
979 | |||
980 | /* get the platform device instantiated at the path */ | ||
981 | static struct platform_device *of_path_to_platform_device(const char *path) | ||
982 | { | ||
983 | struct device_node *np; | ||
984 | struct platform_device *pdev; | ||
985 | |||
986 | np = of_find_node_by_path(path); | ||
987 | if (np == NULL) | ||
988 | return NULL; | ||
989 | |||
990 | pdev = of_find_device_by_node(np); | ||
991 | of_node_put(np); | ||
992 | |||
993 | return pdev; | ||
994 | } | ||
995 | |||
996 | /* find out if a platform device exists at that path */ | ||
997 | static int of_path_platform_device_exists(const char *path) | ||
998 | { | ||
999 | struct platform_device *pdev; | ||
1000 | |||
1001 | pdev = of_path_to_platform_device(path); | ||
1002 | platform_device_put(pdev); | ||
1003 | return pdev != NULL; | ||
1004 | } | ||
1005 | |||
1006 | static const char *selftest_path(int nr) | ||
1007 | { | ||
1008 | static char buf[256]; | ||
1009 | |||
1010 | snprintf(buf, sizeof(buf) - 1, | ||
1011 | "/testcase-data/overlay-node/test-bus/test-selftest%d", nr); | ||
1012 | buf[sizeof(buf) - 1] = '\0'; | ||
1013 | |||
1014 | return buf; | ||
1015 | } | ||
1016 | |||
1017 | static const char *overlay_path(int nr) | ||
1018 | { | ||
1019 | static char buf[256]; | ||
1020 | |||
1021 | snprintf(buf, sizeof(buf) - 1, | ||
1022 | "/testcase-data/overlay%d", nr); | ||
1023 | buf[sizeof(buf) - 1] = '\0'; | ||
1024 | |||
1025 | return buf; | ||
1026 | } | ||
1027 | |||
1028 | static const char *bus_path = "/testcase-data/overlay-node/test-bus"; | ||
1029 | |||
1030 | static int of_selftest_apply_overlay(int selftest_nr, int overlay_nr, | ||
1031 | int *overlay_id) | ||
1032 | { | ||
1033 | struct device_node *np = NULL; | ||
1034 | int ret, id = -1; | ||
1035 | |||
1036 | np = of_find_node_by_path(overlay_path(overlay_nr)); | ||
1037 | if (np == NULL) { | ||
1038 | selftest(0, "could not find overlay node @\"%s\"\n", | ||
1039 | overlay_path(overlay_nr)); | ||
1040 | ret = -EINVAL; | ||
1041 | goto out; | ||
1042 | } | ||
1043 | |||
1044 | ret = of_overlay_create(np); | ||
1045 | if (ret < 0) { | ||
1046 | selftest(0, "could not create overlay from \"%s\"\n", | ||
1047 | overlay_path(overlay_nr)); | ||
1048 | goto out; | ||
1049 | } | ||
1050 | id = ret; | ||
1051 | |||
1052 | ret = 0; | ||
1053 | |||
1054 | out: | ||
1055 | of_node_put(np); | ||
1056 | |||
1057 | if (overlay_id) | ||
1058 | *overlay_id = id; | ||
1059 | |||
1060 | return ret; | ||
1061 | } | ||
1062 | |||
1063 | /* apply an overlay while checking before and after states */ | ||
1064 | static int of_selftest_apply_overlay_check(int overlay_nr, int selftest_nr, | ||
1065 | int before, int after) | ||
1066 | { | ||
1067 | int ret; | ||
1068 | |||
1069 | /* selftest device must not be in before state */ | ||
1070 | if (of_path_platform_device_exists(selftest_path(selftest_nr)) | ||
1071 | != before) { | ||
1072 | selftest(0, "overlay @\"%s\" with device @\"%s\" %s\n", | ||
1073 | overlay_path(overlay_nr), | ||
1074 | selftest_path(selftest_nr), | ||
1075 | !before ? "enabled" : "disabled"); | ||
1076 | return -EINVAL; | ||
1077 | } | ||
1078 | |||
1079 | ret = of_selftest_apply_overlay(overlay_nr, selftest_nr, NULL); | ||
1080 | if (ret != 0) { | ||
1081 | /* of_selftest_apply_overlay already called selftest() */ | ||
1082 | return ret; | ||
1083 | } | ||
1084 | |||
1085 | /* selftest device must be to set to after state */ | ||
1086 | if (of_path_platform_device_exists(selftest_path(selftest_nr)) | ||
1087 | != after) { | ||
1088 | selftest(0, "overlay @\"%s\" failed to create @\"%s\" %s\n", | ||
1089 | overlay_path(overlay_nr), | ||
1090 | selftest_path(selftest_nr), | ||
1091 | !after ? "enabled" : "disabled"); | ||
1092 | return -EINVAL; | ||
1093 | } | ||
1094 | |||
1095 | return 0; | ||
1096 | } | ||
1097 | |||
1098 | /* apply an overlay and then revert it while checking before, after states */ | ||
1099 | static int of_selftest_apply_revert_overlay_check(int overlay_nr, | ||
1100 | int selftest_nr, int before, int after) | ||
1101 | { | ||
1102 | int ret, ov_id; | ||
1103 | |||
1104 | /* selftest device must be in before state */ | ||
1105 | if (of_path_platform_device_exists(selftest_path(selftest_nr)) | ||
1106 | != before) { | ||
1107 | selftest(0, "overlay @\"%s\" with device @\"%s\" %s\n", | ||
1108 | overlay_path(overlay_nr), | ||
1109 | selftest_path(selftest_nr), | ||
1110 | !before ? "enabled" : "disabled"); | ||
1111 | return -EINVAL; | ||
1112 | } | ||
1113 | |||
1114 | /* apply the overlay */ | ||
1115 | ret = of_selftest_apply_overlay(overlay_nr, selftest_nr, &ov_id); | ||
1116 | if (ret != 0) { | ||
1117 | /* of_selftest_apply_overlay already called selftest() */ | ||
1118 | return ret; | ||
1119 | } | ||
1120 | |||
1121 | /* selftest device must be in after state */ | ||
1122 | if (of_path_platform_device_exists(selftest_path(selftest_nr)) | ||
1123 | != after) { | ||
1124 | selftest(0, "overlay @\"%s\" failed to create @\"%s\" %s\n", | ||
1125 | overlay_path(overlay_nr), | ||
1126 | selftest_path(selftest_nr), | ||
1127 | !after ? "enabled" : "disabled"); | ||
1128 | return -EINVAL; | ||
1129 | } | ||
1130 | |||
1131 | ret = of_overlay_destroy(ov_id); | ||
1132 | if (ret != 0) { | ||
1133 | selftest(0, "overlay @\"%s\" failed to be destroyed @\"%s\"\n", | ||
1134 | overlay_path(overlay_nr), | ||
1135 | selftest_path(selftest_nr)); | ||
1136 | return ret; | ||
1137 | } | ||
1138 | |||
1139 | /* selftest device must be again in before state */ | ||
1140 | if (of_path_platform_device_exists(selftest_path(selftest_nr)) | ||
1141 | != before) { | ||
1142 | selftest(0, "overlay @\"%s\" with device @\"%s\" %s\n", | ||
1143 | overlay_path(overlay_nr), | ||
1144 | selftest_path(selftest_nr), | ||
1145 | !before ? "enabled" : "disabled"); | ||
1146 | return -EINVAL; | ||
1147 | } | ||
1148 | |||
1149 | return 0; | ||
1150 | } | ||
1151 | |||
1152 | /* test activation of device */ | ||
1153 | static void of_selftest_overlay_0(void) | ||
1154 | { | ||
1155 | int ret; | ||
1156 | |||
1157 | /* device should enable */ | ||
1158 | ret = of_selftest_apply_overlay_check(0, 0, 0, 1); | ||
1159 | if (ret != 0) | ||
1160 | return; | ||
1161 | |||
1162 | selftest(1, "overlay test %d passed\n", 0); | ||
1163 | } | ||
1164 | |||
1165 | /* test deactivation of device */ | ||
1166 | static void of_selftest_overlay_1(void) | ||
1167 | { | ||
1168 | int ret; | ||
1169 | |||
1170 | /* device should disable */ | ||
1171 | ret = of_selftest_apply_overlay_check(1, 1, 1, 0); | ||
1172 | if (ret != 0) | ||
1173 | return; | ||
1174 | |||
1175 | selftest(1, "overlay test %d passed\n", 1); | ||
1176 | } | ||
1177 | |||
1178 | /* test activation of device */ | ||
1179 | static void of_selftest_overlay_2(void) | ||
1180 | { | ||
1181 | int ret; | ||
1182 | |||
1183 | /* device should enable */ | ||
1184 | ret = of_selftest_apply_overlay_check(2, 2, 0, 1); | ||
1185 | if (ret != 0) | ||
1186 | return; | ||
1187 | |||
1188 | selftest(1, "overlay test %d passed\n", 2); | ||
1189 | } | ||
1190 | |||
1191 | /* test deactivation of device */ | ||
1192 | static void of_selftest_overlay_3(void) | ||
1193 | { | ||
1194 | int ret; | ||
1195 | |||
1196 | /* device should disable */ | ||
1197 | ret = of_selftest_apply_overlay_check(3, 3, 1, 0); | ||
1198 | if (ret != 0) | ||
1199 | return; | ||
1200 | |||
1201 | selftest(1, "overlay test %d passed\n", 3); | ||
1202 | } | ||
1203 | |||
1204 | /* test activation of a full device node */ | ||
1205 | static void of_selftest_overlay_4(void) | ||
1206 | { | ||
1207 | int ret; | ||
1208 | |||
1209 | /* device should disable */ | ||
1210 | ret = of_selftest_apply_overlay_check(4, 4, 0, 1); | ||
1211 | if (ret != 0) | ||
1212 | return; | ||
1213 | |||
1214 | selftest(1, "overlay test %d passed\n", 4); | ||
1215 | } | ||
1216 | |||
1217 | /* test overlay apply/revert sequence */ | ||
1218 | static void of_selftest_overlay_5(void) | ||
1219 | { | ||
1220 | int ret; | ||
1221 | |||
1222 | /* device should disable */ | ||
1223 | ret = of_selftest_apply_revert_overlay_check(5, 5, 0, 1); | ||
1224 | if (ret != 0) | ||
1225 | return; | ||
1226 | |||
1227 | selftest(1, "overlay test %d passed\n", 5); | ||
1228 | } | ||
1229 | |||
1230 | /* test overlay application in sequence */ | ||
1231 | static void of_selftest_overlay_6(void) | ||
1232 | { | ||
1233 | struct device_node *np; | ||
1234 | int ret, i, ov_id[2]; | ||
1235 | int overlay_nr = 6, selftest_nr = 6; | ||
1236 | int before = 0, after = 1; | ||
1237 | |||
1238 | /* selftest device must be in before state */ | ||
1239 | for (i = 0; i < 2; i++) { | ||
1240 | if (of_path_platform_device_exists( | ||
1241 | selftest_path(selftest_nr + i)) | ||
1242 | != before) { | ||
1243 | selftest(0, "overlay @\"%s\" with device @\"%s\" %s\n", | ||
1244 | overlay_path(overlay_nr + i), | ||
1245 | selftest_path(selftest_nr + i), | ||
1246 | !before ? "enabled" : "disabled"); | ||
1247 | return; | ||
1248 | } | ||
1249 | } | ||
1250 | |||
1251 | /* apply the overlays */ | ||
1252 | for (i = 0; i < 2; i++) { | ||
1253 | |||
1254 | np = of_find_node_by_path(overlay_path(overlay_nr + i)); | ||
1255 | if (np == NULL) { | ||
1256 | selftest(0, "could not find overlay node @\"%s\"\n", | ||
1257 | overlay_path(overlay_nr + i)); | ||
1258 | return; | ||
1259 | } | ||
1260 | |||
1261 | ret = of_overlay_create(np); | ||
1262 | if (ret < 0) { | ||
1263 | selftest(0, "could not create overlay from \"%s\"\n", | ||
1264 | overlay_path(overlay_nr + i)); | ||
1265 | return; | ||
1266 | } | ||
1267 | ov_id[i] = ret; | ||
1268 | } | ||
1269 | |||
1270 | for (i = 0; i < 2; i++) { | ||
1271 | /* selftest device must be in after state */ | ||
1272 | if (of_path_platform_device_exists( | ||
1273 | selftest_path(selftest_nr + i)) | ||
1274 | != after) { | ||
1275 | selftest(0, "overlay @\"%s\" failed @\"%s\" %s\n", | ||
1276 | overlay_path(overlay_nr + i), | ||
1277 | selftest_path(selftest_nr + i), | ||
1278 | !after ? "enabled" : "disabled"); | ||
1279 | return; | ||
1280 | } | ||
1281 | } | ||
1282 | |||
1283 | for (i = 1; i >= 0; i--) { | ||
1284 | ret = of_overlay_destroy(ov_id[i]); | ||
1285 | if (ret != 0) { | ||
1286 | selftest(0, "overlay @\"%s\" failed destroy @\"%s\"\n", | ||
1287 | overlay_path(overlay_nr + i), | ||
1288 | selftest_path(selftest_nr + i)); | ||
1289 | return; | ||
1290 | } | ||
1291 | } | ||
1292 | |||
1293 | for (i = 0; i < 2; i++) { | ||
1294 | /* selftest device must be again in before state */ | ||
1295 | if (of_path_platform_device_exists( | ||
1296 | selftest_path(selftest_nr + i)) | ||
1297 | != before) { | ||
1298 | selftest(0, "overlay @\"%s\" with device @\"%s\" %s\n", | ||
1299 | overlay_path(overlay_nr + i), | ||
1300 | selftest_path(selftest_nr + i), | ||
1301 | !before ? "enabled" : "disabled"); | ||
1302 | return; | ||
1303 | } | ||
1304 | } | ||
1305 | |||
1306 | selftest(1, "overlay test %d passed\n", 6); | ||
1307 | } | ||
1308 | |||
1309 | /* test overlay application in sequence */ | ||
1310 | static void of_selftest_overlay_8(void) | ||
1311 | { | ||
1312 | struct device_node *np; | ||
1313 | int ret, i, ov_id[2]; | ||
1314 | int overlay_nr = 8, selftest_nr = 8; | ||
1315 | |||
1316 | /* we don't care about device state in this test */ | ||
1317 | |||
1318 | /* apply the overlays */ | ||
1319 | for (i = 0; i < 2; i++) { | ||
1320 | |||
1321 | np = of_find_node_by_path(overlay_path(overlay_nr + i)); | ||
1322 | if (np == NULL) { | ||
1323 | selftest(0, "could not find overlay node @\"%s\"\n", | ||
1324 | overlay_path(overlay_nr + i)); | ||
1325 | return; | ||
1326 | } | ||
1327 | |||
1328 | ret = of_overlay_create(np); | ||
1329 | if (ret < 0) { | ||
1330 | selftest(0, "could not create overlay from \"%s\"\n", | ||
1331 | overlay_path(overlay_nr + i)); | ||
1332 | return; | ||
1333 | } | ||
1334 | ov_id[i] = ret; | ||
1335 | } | ||
1336 | |||
1337 | /* now try to remove first overlay (it should fail) */ | ||
1338 | ret = of_overlay_destroy(ov_id[0]); | ||
1339 | if (ret == 0) { | ||
1340 | selftest(0, "overlay @\"%s\" was destroyed @\"%s\"\n", | ||
1341 | overlay_path(overlay_nr + 0), | ||
1342 | selftest_path(selftest_nr)); | ||
1343 | return; | ||
1344 | } | ||
1345 | |||
1346 | /* removing them in order should work */ | ||
1347 | for (i = 1; i >= 0; i--) { | ||
1348 | ret = of_overlay_destroy(ov_id[i]); | ||
1349 | if (ret != 0) { | ||
1350 | selftest(0, "overlay @\"%s\" not destroyed @\"%s\"\n", | ||
1351 | overlay_path(overlay_nr + i), | ||
1352 | selftest_path(selftest_nr)); | ||
1353 | return; | ||
1354 | } | ||
1355 | } | ||
1356 | |||
1357 | selftest(1, "overlay test %d passed\n", 8); | ||
1358 | } | ||
1359 | |||
1360 | static void __init of_selftest_overlay(void) | ||
1361 | { | ||
1362 | struct device_node *bus_np = NULL; | ||
1363 | int ret; | ||
1364 | |||
1365 | ret = platform_driver_register(&selftest_driver); | ||
1366 | if (ret != 0) { | ||
1367 | selftest(0, "could not register selftest driver\n"); | ||
1368 | goto out; | ||
1369 | } | ||
1370 | |||
1371 | bus_np = of_find_node_by_path(bus_path); | ||
1372 | if (bus_np == NULL) { | ||
1373 | selftest(0, "could not find bus_path \"%s\"\n", bus_path); | ||
1374 | goto out; | ||
1375 | } | ||
1376 | |||
1377 | ret = of_platform_populate(bus_np, of_default_bus_match_table, | ||
1378 | NULL, NULL); | ||
1379 | if (ret != 0) { | ||
1380 | selftest(0, "could not populate bus @ \"%s\"\n", bus_path); | ||
1381 | goto out; | ||
1382 | } | ||
1383 | |||
1384 | if (!of_path_platform_device_exists(selftest_path(100))) { | ||
1385 | selftest(0, "could not find selftest0 @ \"%s\"\n", | ||
1386 | selftest_path(100)); | ||
1387 | goto out; | ||
1388 | } | ||
1389 | |||
1390 | if (of_path_platform_device_exists(selftest_path(101))) { | ||
1391 | selftest(0, "selftest1 @ \"%s\" should not exist\n", | ||
1392 | selftest_path(101)); | ||
1393 | goto out; | ||
1394 | } | ||
1395 | |||
1396 | selftest(1, "basic infrastructure of overlays passed"); | ||
1397 | |||
1398 | /* tests in sequence */ | ||
1399 | of_selftest_overlay_0(); | ||
1400 | of_selftest_overlay_1(); | ||
1401 | of_selftest_overlay_2(); | ||
1402 | of_selftest_overlay_3(); | ||
1403 | of_selftest_overlay_4(); | ||
1404 | of_selftest_overlay_5(); | ||
1405 | of_selftest_overlay_6(); | ||
1406 | of_selftest_overlay_8(); | ||
1407 | |||
1408 | out: | ||
1409 | of_node_put(bus_np); | ||
1410 | } | ||
1411 | |||
1412 | #else | ||
1413 | static inline void __init of_selftest_overlay(void) { } | ||
1414 | #endif | ||
1415 | |||
936 | static int __init of_selftest(void) | 1416 | static int __init of_selftest(void) |
937 | { | 1417 | { |
938 | struct device_node *np; | 1418 | struct device_node *np; |
@@ -965,6 +1445,7 @@ static int __init of_selftest(void) | |||
965 | of_selftest_parse_interrupts_extended(); | 1445 | of_selftest_parse_interrupts_extended(); |
966 | of_selftest_match_node(); | 1446 | of_selftest_match_node(); |
967 | of_selftest_platform_populate(); | 1447 | of_selftest_platform_populate(); |
1448 | of_selftest_overlay(); | ||
968 | 1449 | ||
969 | /* removing selftest data from live tree */ | 1450 | /* removing selftest data from live tree */ |
970 | selftest_data_remove(); | 1451 | selftest_data_remove(); |