summaryrefslogtreecommitdiff
path: root/drivers/of/unittest.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/of/unittest.c')
-rw-r--r--drivers/of/unittest.c469
1 files changed, 307 insertions, 162 deletions
diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c
index 7a9abaae874d..20ffbedac524 100644
--- a/drivers/of/unittest.c
+++ b/drivers/of/unittest.c
@@ -45,6 +45,8 @@ static struct unittest_results {
failed; \
})
+static int __init overlay_data_apply(const char *overlay_name, int *overlay_id);
+
static void __init of_unittest_find_node_by_name(void)
{
struct device_node *np;
@@ -453,6 +455,125 @@ static void __init of_unittest_parse_phandle_with_args(void)
unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc);
}
+static void __init of_unittest_parse_phandle_with_args_map(void)
+{
+ struct device_node *np, *p0, *p1, *p2, *p3;
+ struct of_phandle_args args;
+ int i, rc;
+
+ np = of_find_node_by_path("/testcase-data/phandle-tests/consumer-b");
+ if (!np) {
+ pr_err("missing testcase data\n");
+ return;
+ }
+
+ p0 = of_find_node_by_path("/testcase-data/phandle-tests/provider0");
+ if (!p0) {
+ pr_err("missing testcase data\n");
+ return;
+ }
+
+ p1 = of_find_node_by_path("/testcase-data/phandle-tests/provider1");
+ if (!p1) {
+ pr_err("missing testcase data\n");
+ return;
+ }
+
+ p2 = of_find_node_by_path("/testcase-data/phandle-tests/provider2");
+ if (!p2) {
+ pr_err("missing testcase data\n");
+ return;
+ }
+
+ p3 = of_find_node_by_path("/testcase-data/phandle-tests/provider3");
+ if (!p3) {
+ pr_err("missing testcase data\n");
+ return;
+ }
+
+ rc = of_count_phandle_with_args(np, "phandle-list", "#phandle-cells");
+ unittest(rc == 7, "of_count_phandle_with_args() returned %i, expected 7\n", rc);
+
+ for (i = 0; i < 8; i++) {
+ bool passed = true;
+
+ rc = of_parse_phandle_with_args_map(np, "phandle-list",
+ "phandle", i, &args);
+
+ /* Test the values from tests-phandle.dtsi */
+ switch (i) {
+ case 0:
+ passed &= !rc;
+ passed &= (args.np == p1);
+ passed &= (args.args_count == 1);
+ passed &= (args.args[0] == 1);
+ break;
+ case 1:
+ passed &= !rc;
+ passed &= (args.np == p3);
+ passed &= (args.args_count == 3);
+ passed &= (args.args[0] == 2);
+ passed &= (args.args[1] == 5);
+ passed &= (args.args[2] == 3);
+ break;
+ case 2:
+ passed &= (rc == -ENOENT);
+ break;
+ case 3:
+ passed &= !rc;
+ passed &= (args.np == p0);
+ passed &= (args.args_count == 0);
+ break;
+ case 4:
+ passed &= !rc;
+ passed &= (args.np == p1);
+ passed &= (args.args_count == 1);
+ passed &= (args.args[0] == 3);
+ break;
+ case 5:
+ passed &= !rc;
+ passed &= (args.np == p0);
+ passed &= (args.args_count == 0);
+ break;
+ case 6:
+ passed &= !rc;
+ passed &= (args.np == p2);
+ passed &= (args.args_count == 2);
+ passed &= (args.args[0] == 15);
+ passed &= (args.args[1] == 0x20);
+ break;
+ case 7:
+ passed &= (rc == -ENOENT);
+ break;
+ default:
+ passed = false;
+ }
+
+ unittest(passed, "index %i - data error on node %s rc=%i\n",
+ i, args.np->full_name, rc);
+ }
+
+ /* Check for missing list property */
+ rc = of_parse_phandle_with_args_map(np, "phandle-list-missing",
+ "phandle", 0, &args);
+ unittest(rc == -ENOENT, "expected:%i got:%i\n", -ENOENT, rc);
+
+ /* Check for missing cells,map,mask property */
+ rc = of_parse_phandle_with_args_map(np, "phandle-list",
+ "phandle-missing", 0, &args);
+ unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc);
+
+ /* Check for bad phandle in list */
+ rc = of_parse_phandle_with_args_map(np, "phandle-list-bad-phandle",
+ "phandle", 0, &args);
+ unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc);
+
+ /* Check for incorrectly formed argument list */
+ rc = of_parse_phandle_with_args_map(np, "phandle-list-bad-args",
+ "phandle", 1, &args);
+ unittest(rc == -EINVAL, "expected:%i got:%i\n", -EINVAL, rc);
+}
+
static void __init of_unittest_property_string(void)
{
const char *strings[4];
@@ -562,42 +683,72 @@ static void __init of_unittest_property_copy(void)
static void __init of_unittest_changeset(void)
{
#ifdef CONFIG_OF_DYNAMIC
- struct property *ppadd, padd = { .name = "prop-add", .length = 0, .value = "" };
+ struct property *ppadd, padd = { .name = "prop-add", .length = 1, .value = "" };
+ struct property *ppname_n1, pname_n1 = { .name = "name", .length = 3, .value = "n1" };
+ struct property *ppname_n2, pname_n2 = { .name = "name", .length = 3, .value = "n2" };
+ struct property *ppname_n21, pname_n21 = { .name = "name", .length = 3, .value = "n21" };
struct property *ppupdate, pupdate = { .name = "prop-update", .length = 5, .value = "abcd" };
struct property *ppremove;
- struct device_node *n1, *n2, *n21, *nremove, *parent, *np;
+ struct device_node *n1, *n2, *n21, *nchangeset, *nremove, *parent, *np;
struct of_changeset chgset;
- n1 = __of_node_dup(NULL, "/testcase-data/changeset/n1");
+ n1 = __of_node_dup(NULL, "n1");
unittest(n1, "testcase setup failure\n");
- n2 = __of_node_dup(NULL, "/testcase-data/changeset/n2");
+
+ n2 = __of_node_dup(NULL, "n2");
unittest(n2, "testcase setup failure\n");
- n21 = __of_node_dup(NULL, "%s/%s", "/testcase-data/changeset/n2", "n21");
+
+ n21 = __of_node_dup(NULL, "n21");
unittest(n21, "testcase setup failure %p\n", n21);
- nremove = of_find_node_by_path("/testcase-data/changeset/node-remove");
+
+ nchangeset = of_find_node_by_path("/testcase-data/changeset");
+ nremove = of_get_child_by_name(nchangeset, "node-remove");
unittest(nremove, "testcase setup failure\n");
+
ppadd = __of_prop_dup(&padd, GFP_KERNEL);
unittest(ppadd, "testcase setup failure\n");
+
+ ppname_n1 = __of_prop_dup(&pname_n1, GFP_KERNEL);
+ unittest(ppname_n1, "testcase setup failure\n");
+
+ ppname_n2 = __of_prop_dup(&pname_n2, GFP_KERNEL);
+ unittest(ppname_n2, "testcase setup failure\n");
+
+ ppname_n21 = __of_prop_dup(&pname_n21, GFP_KERNEL);
+ unittest(ppname_n21, "testcase setup failure\n");
+
ppupdate = __of_prop_dup(&pupdate, GFP_KERNEL);
unittest(ppupdate, "testcase setup failure\n");
- parent = nremove->parent;
+
+ parent = nchangeset;
n1->parent = parent;
n2->parent = parent;
n21->parent = n2;
- n2->child = n21;
+
ppremove = of_find_property(parent, "prop-remove", NULL);
unittest(ppremove, "failed to find removal prop");
of_changeset_init(&chgset);
+
unittest(!of_changeset_attach_node(&chgset, n1), "fail attach n1\n");
+ unittest(!of_changeset_add_property(&chgset, n1, ppname_n1), "fail add prop name\n");
+
unittest(!of_changeset_attach_node(&chgset, n2), "fail attach n2\n");
+ unittest(!of_changeset_add_property(&chgset, n2, ppname_n2), "fail add prop name\n");
+
unittest(!of_changeset_detach_node(&chgset, nremove), "fail remove node\n");
+ unittest(!of_changeset_add_property(&chgset, n21, ppname_n21), "fail add prop name\n");
+
unittest(!of_changeset_attach_node(&chgset, n21), "fail attach n21\n");
- unittest(!of_changeset_add_property(&chgset, parent, ppadd), "fail add prop\n");
+
+ unittest(!of_changeset_add_property(&chgset, parent, ppadd), "fail add prop prop-add\n");
unittest(!of_changeset_update_property(&chgset, parent, ppupdate), "fail update prop\n");
unittest(!of_changeset_remove_property(&chgset, parent, ppremove), "fail remove prop\n");
+
unittest(!of_changeset_apply(&chgset), "apply failed\n");
+ of_node_put(nchangeset);
+
/* Make sure node names are constructed correctly */
unittest((np = of_find_node_by_path("/testcase-data/changeset/n2/n21")),
"'%pOF' not added\n", n21);
@@ -997,8 +1148,7 @@ static int __init unittest_data_add(void)
}
/*
- * This lock normally encloses of_overlay_apply() as well as
- * of_resolve_phandles().
+ * This lock normally encloses of_resolve_phandles()
*/
of_overlay_mutex_lock();
@@ -1191,12 +1341,12 @@ static int of_unittest_device_exists(int unittest_nr, enum overlay_type ovtype)
return 0;
}
-static const char *overlay_path(int nr)
+static const char *overlay_name_from_nr(int nr)
{
static char buf[256];
snprintf(buf, sizeof(buf) - 1,
- "/testcase-data/overlay%d", nr);
+ "overlay_%d", nr);
buf[sizeof(buf) - 1] = '\0';
return buf;
@@ -1263,25 +1413,19 @@ static void of_unittest_destroy_tracked_overlays(void)
} while (defers > 0);
}
-static int of_unittest_apply_overlay(int overlay_nr, int unittest_nr,
+static int __init of_unittest_apply_overlay(int overlay_nr, int unittest_nr,
int *overlay_id)
{
struct device_node *np = NULL;
+ const char *overlay_name;
int ret;
- np = of_find_node_by_path(overlay_path(overlay_nr));
- if (np == NULL) {
- unittest(0, "could not find overlay node @\"%s\"\n",
- overlay_path(overlay_nr));
- ret = -EINVAL;
- goto out;
- }
+ overlay_name = overlay_name_from_nr(overlay_nr);
- *overlay_id = 0;
- ret = of_overlay_apply(np, overlay_id);
- if (ret < 0) {
- unittest(0, "could not create overlay from \"%s\"\n",
- overlay_path(overlay_nr));
+ ret = overlay_data_apply(overlay_name, overlay_id);
+ if (!ret) {
+ unittest(0, "could not apply overlay \"%s\"\n",
+ overlay_name);
goto out;
}
of_unittest_track_overlay(*overlay_id);
@@ -1295,15 +1439,16 @@ out:
}
/* apply an overlay while checking before and after states */
-static int of_unittest_apply_overlay_check(int overlay_nr, int unittest_nr,
- int before, int after, enum overlay_type ovtype)
+static int __init of_unittest_apply_overlay_check(int overlay_nr,
+ int unittest_nr, int before, int after,
+ enum overlay_type ovtype)
{
int ret, ovcs_id;
/* unittest device must not be in before state */
if (of_unittest_device_exists(unittest_nr, ovtype) != before) {
- unittest(0, "overlay @\"%s\" with device @\"%s\" %s\n",
- overlay_path(overlay_nr),
+ unittest(0, "%s with device @\"%s\" %s\n",
+ overlay_name_from_nr(overlay_nr),
unittest_path(unittest_nr, ovtype),
!before ? "enabled" : "disabled");
return -EINVAL;
@@ -1318,8 +1463,8 @@ static int of_unittest_apply_overlay_check(int overlay_nr, int unittest_nr,
/* unittest device must be to set to after state */
if (of_unittest_device_exists(unittest_nr, ovtype) != after) {
- unittest(0, "overlay @\"%s\" failed to create @\"%s\" %s\n",
- overlay_path(overlay_nr),
+ unittest(0, "%s failed to create @\"%s\" %s\n",
+ overlay_name_from_nr(overlay_nr),
unittest_path(unittest_nr, ovtype),
!after ? "enabled" : "disabled");
return -EINVAL;
@@ -1329,7 +1474,7 @@ static int of_unittest_apply_overlay_check(int overlay_nr, int unittest_nr,
}
/* apply an overlay and then revert it while checking before, after states */
-static int of_unittest_apply_revert_overlay_check(int overlay_nr,
+static int __init of_unittest_apply_revert_overlay_check(int overlay_nr,
int unittest_nr, int before, int after,
enum overlay_type ovtype)
{
@@ -1337,8 +1482,8 @@ static int of_unittest_apply_revert_overlay_check(int overlay_nr,
/* unittest device must be in before state */
if (of_unittest_device_exists(unittest_nr, ovtype) != before) {
- unittest(0, "overlay @\"%s\" with device @\"%s\" %s\n",
- overlay_path(overlay_nr),
+ unittest(0, "%s with device @\"%s\" %s\n",
+ overlay_name_from_nr(overlay_nr),
unittest_path(unittest_nr, ovtype),
!before ? "enabled" : "disabled");
return -EINVAL;
@@ -1354,8 +1499,8 @@ static int of_unittest_apply_revert_overlay_check(int overlay_nr,
/* unittest device must be in after state */
if (of_unittest_device_exists(unittest_nr, ovtype) != after) {
- unittest(0, "overlay @\"%s\" failed to create @\"%s\" %s\n",
- overlay_path(overlay_nr),
+ unittest(0, "%s failed to create @\"%s\" %s\n",
+ overlay_name_from_nr(overlay_nr),
unittest_path(unittest_nr, ovtype),
!after ? "enabled" : "disabled");
return -EINVAL;
@@ -1363,16 +1508,16 @@ static int of_unittest_apply_revert_overlay_check(int overlay_nr,
ret = of_overlay_remove(&ovcs_id);
if (ret != 0) {
- unittest(0, "overlay @\"%s\" failed to be destroyed @\"%s\"\n",
- overlay_path(overlay_nr),
+ unittest(0, "%s failed to be destroyed @\"%s\"\n",
+ overlay_name_from_nr(overlay_nr),
unittest_path(unittest_nr, ovtype));
return ret;
}
/* unittest device must be again in before state */
if (of_unittest_device_exists(unittest_nr, PDEV_OVERLAY) != before) {
- unittest(0, "overlay @\"%s\" with device @\"%s\" %s\n",
- overlay_path(overlay_nr),
+ unittest(0, "%s with device @\"%s\" %s\n",
+ overlay_name_from_nr(overlay_nr),
unittest_path(unittest_nr, ovtype),
!before ? "enabled" : "disabled");
return -EINVAL;
@@ -1382,7 +1527,7 @@ static int of_unittest_apply_revert_overlay_check(int overlay_nr,
}
/* test activation of device */
-static void of_unittest_overlay_0(void)
+static void __init of_unittest_overlay_0(void)
{
int ret;
@@ -1395,7 +1540,7 @@ static void of_unittest_overlay_0(void)
}
/* test deactivation of device */
-static void of_unittest_overlay_1(void)
+static void __init of_unittest_overlay_1(void)
{
int ret;
@@ -1408,7 +1553,7 @@ static void of_unittest_overlay_1(void)
}
/* test activation of device */
-static void of_unittest_overlay_2(void)
+static void __init of_unittest_overlay_2(void)
{
int ret;
@@ -1421,7 +1566,7 @@ static void of_unittest_overlay_2(void)
}
/* test deactivation of device */
-static void of_unittest_overlay_3(void)
+static void __init of_unittest_overlay_3(void)
{
int ret;
@@ -1434,7 +1579,7 @@ static void of_unittest_overlay_3(void)
}
/* test activation of a full device node */
-static void of_unittest_overlay_4(void)
+static void __init of_unittest_overlay_4(void)
{
int ret;
@@ -1447,7 +1592,7 @@ static void of_unittest_overlay_4(void)
}
/* test overlay apply/revert sequence */
-static void of_unittest_overlay_5(void)
+static void __init of_unittest_overlay_5(void)
{
int ret;
@@ -1460,19 +1605,19 @@ static void of_unittest_overlay_5(void)
}
/* test overlay application in sequence */
-static void of_unittest_overlay_6(void)
+static void __init of_unittest_overlay_6(void)
{
- struct device_node *np;
int ret, i, ov_id[2], ovcs_id;
int overlay_nr = 6, unittest_nr = 6;
int before = 0, after = 1;
+ const char *overlay_name;
/* unittest device must be in before state */
for (i = 0; i < 2; i++) {
if (of_unittest_device_exists(unittest_nr + i, PDEV_OVERLAY)
!= before) {
- unittest(0, "overlay @\"%s\" with device @\"%s\" %s\n",
- overlay_path(overlay_nr + i),
+ unittest(0, "%s with device @\"%s\" %s\n",
+ overlay_name_from_nr(overlay_nr + i),
unittest_path(unittest_nr + i,
PDEV_OVERLAY),
!before ? "enabled" : "disabled");
@@ -1483,18 +1628,12 @@ static void of_unittest_overlay_6(void)
/* apply the overlays */
for (i = 0; i < 2; i++) {
- np = of_find_node_by_path(overlay_path(overlay_nr + i));
- if (np == NULL) {
- unittest(0, "could not find overlay node @\"%s\"\n",
- overlay_path(overlay_nr + i));
- return;
- }
+ overlay_name = overlay_name_from_nr(overlay_nr + i);
- ovcs_id = 0;
- ret = of_overlay_apply(np, &ovcs_id);
- if (ret < 0) {
- unittest(0, "could not create overlay from \"%s\"\n",
- overlay_path(overlay_nr + i));
+ ret = overlay_data_apply(overlay_name, &ovcs_id);
+ if (!ret) {
+ unittest(0, "could not apply overlay \"%s\"\n",
+ overlay_name);
return;
}
ov_id[i] = ovcs_id;
@@ -1506,7 +1645,7 @@ static void of_unittest_overlay_6(void)
if (of_unittest_device_exists(unittest_nr + i, PDEV_OVERLAY)
!= after) {
unittest(0, "overlay @\"%s\" failed @\"%s\" %s\n",
- overlay_path(overlay_nr + i),
+ overlay_name_from_nr(overlay_nr + i),
unittest_path(unittest_nr + i,
PDEV_OVERLAY),
!after ? "enabled" : "disabled");
@@ -1518,8 +1657,8 @@ static void of_unittest_overlay_6(void)
ovcs_id = ov_id[i];
ret = of_overlay_remove(&ovcs_id);
if (ret != 0) {
- unittest(0, "overlay @\"%s\" failed destroy @\"%s\"\n",
- overlay_path(overlay_nr + i),
+ unittest(0, "%s failed destroy @\"%s\"\n",
+ overlay_name_from_nr(overlay_nr + i),
unittest_path(unittest_nr + i,
PDEV_OVERLAY));
return;
@@ -1531,8 +1670,8 @@ static void of_unittest_overlay_6(void)
/* unittest device must be again in before state */
if (of_unittest_device_exists(unittest_nr + i, PDEV_OVERLAY)
!= before) {
- unittest(0, "overlay @\"%s\" with device @\"%s\" %s\n",
- overlay_path(overlay_nr + i),
+ unittest(0, "%s with device @\"%s\" %s\n",
+ overlay_name_from_nr(overlay_nr + i),
unittest_path(unittest_nr + i,
PDEV_OVERLAY),
!before ? "enabled" : "disabled");
@@ -1544,29 +1683,22 @@ static void of_unittest_overlay_6(void)
}
/* test overlay application in sequence */
-static void of_unittest_overlay_8(void)
+static void __init of_unittest_overlay_8(void)
{
- struct device_node *np;
int ret, i, ov_id[2], ovcs_id;
int overlay_nr = 8, unittest_nr = 8;
+ const char *overlay_name;
/* we don't care about device state in this test */
/* apply the overlays */
for (i = 0; i < 2; i++) {
- np = of_find_node_by_path(overlay_path(overlay_nr + i));
- if (np == NULL) {
- unittest(0, "could not find overlay node @\"%s\"\n",
- overlay_path(overlay_nr + i));
- return;
- }
+ overlay_name = overlay_name_from_nr(overlay_nr + i);
- ovcs_id = 0;
- ret = of_overlay_apply(np, &ovcs_id);
- if (ret < 0) {
- unittest(0, "could not create overlay from \"%s\"\n",
- overlay_path(overlay_nr + i));
+ if (!overlay_data_apply(overlay_name, &ovcs_id)) {
+ unittest(0, "could not apply overlay \"%s\"\n",
+ overlay_name);
return;
}
ov_id[i] = ovcs_id;
@@ -1577,8 +1709,8 @@ static void of_unittest_overlay_8(void)
ovcs_id = ov_id[0];
ret = of_overlay_remove(&ovcs_id);
if (ret == 0) {
- unittest(0, "overlay @\"%s\" was destroyed @\"%s\"\n",
- overlay_path(overlay_nr + 0),
+ unittest(0, "%s was destroyed @\"%s\"\n",
+ overlay_name_from_nr(overlay_nr + 0),
unittest_path(unittest_nr,
PDEV_OVERLAY));
return;
@@ -1589,8 +1721,8 @@ static void of_unittest_overlay_8(void)
ovcs_id = ov_id[i];
ret = of_overlay_remove(&ovcs_id);
if (ret != 0) {
- unittest(0, "overlay @\"%s\" not destroyed @\"%s\"\n",
- overlay_path(overlay_nr + i),
+ unittest(0, "%s not destroyed @\"%s\"\n",
+ overlay_name_from_nr(overlay_nr + i),
unittest_path(unittest_nr,
PDEV_OVERLAY));
return;
@@ -1602,7 +1734,7 @@ static void of_unittest_overlay_8(void)
}
/* test insertion of a bus with parent devices */
-static void of_unittest_overlay_10(void)
+static void __init of_unittest_overlay_10(void)
{
int ret;
char *child_path;
@@ -1625,7 +1757,7 @@ static void of_unittest_overlay_10(void)
}
/* test insertion of a bus with parent devices (and revert) */
-static void of_unittest_overlay_11(void)
+static void __init of_unittest_overlay_11(void)
{
int ret;
@@ -1891,7 +2023,7 @@ static void of_unittest_overlay_i2c_cleanup(void)
i2c_del_driver(&unittest_i2c_dev_driver);
}
-static void of_unittest_overlay_i2c_12(void)
+static void __init of_unittest_overlay_i2c_12(void)
{
int ret;
@@ -1904,7 +2036,7 @@ static void of_unittest_overlay_i2c_12(void)
}
/* test deactivation of device */
-static void of_unittest_overlay_i2c_13(void)
+static void __init of_unittest_overlay_i2c_13(void)
{
int ret;
@@ -1921,7 +2053,7 @@ static void of_unittest_overlay_i2c_14(void)
{
}
-static void of_unittest_overlay_i2c_15(void)
+static void __init of_unittest_overlay_i2c_15(void)
{
int ret;
@@ -2023,23 +2155,38 @@ static inline void __init of_unittest_overlay(void) { }
extern uint8_t __dtb_##name##_begin[]; \
extern uint8_t __dtb_##name##_end[]
-#define OVERLAY_INFO(name, expected) \
-{ .dtb_begin = __dtb_##name##_begin, \
- .dtb_end = __dtb_##name##_end, \
- .expected_result = expected, \
+#define OVERLAY_INFO(overlay_name, expected) \
+{ .dtb_begin = __dtb_##overlay_name##_begin, \
+ .dtb_end = __dtb_##overlay_name##_end, \
+ .expected_result = expected, \
+ .name = #overlay_name, \
}
struct overlay_info {
- uint8_t *dtb_begin;
- uint8_t *dtb_end;
- void *data;
- struct device_node *np_overlay;
- int expected_result;
- int overlay_id;
+ uint8_t *dtb_begin;
+ uint8_t *dtb_end;
+ int expected_result;
+ int overlay_id;
+ char *name;
};
OVERLAY_INFO_EXTERN(overlay_base);
OVERLAY_INFO_EXTERN(overlay);
+OVERLAY_INFO_EXTERN(overlay_0);
+OVERLAY_INFO_EXTERN(overlay_1);
+OVERLAY_INFO_EXTERN(overlay_2);
+OVERLAY_INFO_EXTERN(overlay_3);
+OVERLAY_INFO_EXTERN(overlay_4);
+OVERLAY_INFO_EXTERN(overlay_5);
+OVERLAY_INFO_EXTERN(overlay_6);
+OVERLAY_INFO_EXTERN(overlay_7);
+OVERLAY_INFO_EXTERN(overlay_8);
+OVERLAY_INFO_EXTERN(overlay_9);
+OVERLAY_INFO_EXTERN(overlay_10);
+OVERLAY_INFO_EXTERN(overlay_11);
+OVERLAY_INFO_EXTERN(overlay_12);
+OVERLAY_INFO_EXTERN(overlay_13);
+OVERLAY_INFO_EXTERN(overlay_15);
OVERLAY_INFO_EXTERN(overlay_bad_phandle);
OVERLAY_INFO_EXTERN(overlay_bad_symbol);
@@ -2047,6 +2194,21 @@ OVERLAY_INFO_EXTERN(overlay_bad_symbol);
static struct overlay_info overlays[] = {
OVERLAY_INFO(overlay_base, -9999),
OVERLAY_INFO(overlay, 0),
+ OVERLAY_INFO(overlay_0, 0),
+ OVERLAY_INFO(overlay_1, 0),
+ OVERLAY_INFO(overlay_2, 0),
+ OVERLAY_INFO(overlay_3, 0),
+ OVERLAY_INFO(overlay_4, 0),
+ OVERLAY_INFO(overlay_5, 0),
+ OVERLAY_INFO(overlay_6, 0),
+ OVERLAY_INFO(overlay_7, 0),
+ OVERLAY_INFO(overlay_8, 0),
+ OVERLAY_INFO(overlay_9, 0),
+ OVERLAY_INFO(overlay_10, 0),
+ OVERLAY_INFO(overlay_11, 0),
+ OVERLAY_INFO(overlay_12, 0),
+ OVERLAY_INFO(overlay_13, 0),
+ OVERLAY_INFO(overlay_15, 0),
OVERLAY_INFO(overlay_bad_phandle, -EINVAL),
OVERLAY_INFO(overlay_bad_symbol, -EINVAL),
{}
@@ -2077,6 +2239,7 @@ void __init unittest_unflatten_overlay_base(void)
{
struct overlay_info *info;
u32 data_size;
+ void *new_fdt;
u32 size;
info = &overlays[0];
@@ -2098,17 +2261,16 @@ void __init unittest_unflatten_overlay_base(void)
return;
}
- info->data = dt_alloc_memory(size, roundup_pow_of_two(FDT_V17_SIZE));
- if (!info->data) {
+ new_fdt = dt_alloc_memory(size, roundup_pow_of_two(FDT_V17_SIZE));
+ if (!new_fdt) {
pr_err("alloc for dtb 'overlay_base' failed");
return;
}
- memcpy(info->data, info->dtb_begin, size);
+ memcpy(new_fdt, info->dtb_begin, size);
- __unflatten_device_tree(info->data, NULL, &info->np_overlay,
+ __unflatten_device_tree(new_fdt, NULL, &overlay_base_root,
dt_alloc_memory, true);
- overlay_base_root = info->np_overlay;
}
/*
@@ -2122,73 +2284,44 @@ void __init unittest_unflatten_overlay_base(void)
*
* Return 0 on unexpected error.
*/
-static int __init overlay_data_add(int onum)
+static int __init overlay_data_apply(const char *overlay_name, int *overlay_id)
{
struct overlay_info *info;
+ int found = 0;
int k;
int ret;
u32 size;
- u32 size_from_header;
- for (k = 0, info = overlays; info; info++, k++) {
- if (k == onum)
+ for (k = 0, info = overlays; info && info->name; info++, k++) {
+ if (!strcmp(overlay_name, info->name)) {
+ found = 1;
break;
+ }
}
- if (onum > k)
+ if (!found) {
+ pr_err("no overlay data for %s\n", overlay_name);
return 0;
+ }
size = info->dtb_end - info->dtb_begin;
if (!size) {
- pr_err("no overlay to attach, %d\n", onum);
+ pr_err("no overlay data for %s\n", overlay_name);
ret = 0;
}
- size_from_header = fdt_totalsize(info->dtb_begin);
- if (size_from_header != size) {
- pr_err("overlay header totalsize != actual size, %d", onum);
- return 0;
- }
-
- /*
- * Must create permanent copy of FDT because of_fdt_unflatten_tree()
- * will create pointers to the passed in FDT in the EDT.
- */
- info->data = kmemdup(info->dtb_begin, size, GFP_KERNEL);
- if (!info->data) {
- pr_err("unable to allocate memory for data, %d\n", onum);
- return 0;
- }
-
- of_fdt_unflatten_tree(info->data, NULL, &info->np_overlay);
- if (!info->np_overlay) {
- pr_err("unable to unflatten overlay, %d\n", onum);
- ret = 0;
- goto out_free_data;
- }
-
- info->overlay_id = 0;
- ret = of_overlay_apply(info->np_overlay, &info->overlay_id);
- if (ret < 0) {
- pr_err("of_overlay_apply() (ret=%d), %d\n", ret, onum);
- goto out_free_np_overlay;
- }
-
- pr_debug("__dtb_overlay_begin applied, overlay id %d\n", ret);
-
- goto out;
-
-out_free_np_overlay:
- /*
- * info->np_overlay is the unflattened device tree
- * It has not been spliced into the live tree.
- */
-
- /* todo: function to free unflattened device tree */
+ ret = of_overlay_fdt_apply(info->dtb_begin, size, &info->overlay_id);
+ if (overlay_id)
+ *overlay_id = info->overlay_id;
+ if (ret < 0)
+ goto out;
-out_free_data:
- kfree(info->data);
+ pr_debug("%s applied\n", overlay_name);
out:
+ if (ret != info->expected_result)
+ pr_err("of_overlay_fdt_apply() expected %d, ret=%d, %s\n",
+ info->expected_result, ret, overlay_name);
+
return (ret == info->expected_result);
}
@@ -2290,18 +2423,29 @@ static __init void of_unittest_overlay_high_level(void)
__of_attach_node_sysfs(np);
if (of_symbols) {
+ struct property *new_prop;
for_each_property_of_node(overlay_base_symbols, prop) {
- ret = __of_add_property(of_symbols, prop);
+
+ new_prop = __of_prop_dup(prop, GFP_KERNEL);
+ if (!new_prop) {
+ unittest(0, "__of_prop_dup() of '%s' from overlay_base node __symbols__",
+ prop->name);
+ goto err_unlock;
+ }
+ ret = __of_add_property(of_symbols, new_prop);
if (ret) {
- unittest(0,
- "duplicate property '%s' in overlay_base node __symbols__",
+ if (!strcmp(new_prop->name, "name")) {
+ /* auto-generated by unflatten */
+ ret = 0;
+ continue;
+ }
+ unittest(0, "duplicate property '%s' in overlay_base node __symbols__",
prop->name);
goto err_unlock;
}
- ret = __of_add_property_sysfs(of_symbols, prop);
+ ret = __of_add_property_sysfs(of_symbols, new_prop);
if (ret) {
- unittest(0,
- "unable to add property '%s' in overlay_base node __symbols__ to sysfs",
+ unittest(0, "unable to add property '%s' in overlay_base node __symbols__ to sysfs",
prop->name);
goto err_unlock;
}
@@ -2313,13 +2457,13 @@ static __init void of_unittest_overlay_high_level(void)
/* now do the normal overlay usage test */
- unittest(overlay_data_add(1),
+ unittest(overlay_data_apply("overlay", NULL),
"Adding overlay 'overlay' failed\n");
- unittest(overlay_data_add(2),
+ unittest(overlay_data_apply("overlay_bad_phandle", NULL),
"Adding overlay 'overlay_bad_phandle' failed\n");
- unittest(overlay_data_add(3),
+ unittest(overlay_data_apply("overlay_bad_symbol", NULL),
"Adding overlay 'overlay_bad_symbol' failed\n");
return;
@@ -2359,6 +2503,7 @@ static int __init of_unittest(void)
of_unittest_find_node_by_name();
of_unittest_dynamic();
of_unittest_parse_phandle_with_args();
+ of_unittest_parse_phandle_with_args_map();
of_unittest_printf();
of_unittest_property_string();
of_unittest_property_copy();