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.c304
1 files changed, 203 insertions, 101 deletions
diff --git a/drivers/of/unittest.c b/drivers/of/unittest.c
index a23b54780c7d..02c5984ab09b 100644
--- a/drivers/of/unittest.c
+++ b/drivers/of/unittest.c
@@ -45,8 +45,6 @@ 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;
@@ -254,12 +252,18 @@ static void __init of_unittest_check_tree_linkage(void)
static void __init of_unittest_printf_one(struct device_node *np, const char *fmt,
const char *expected)
{
- unsigned char buf[strlen(expected)+10];
+ unsigned char *buf;
+ int buf_size;
int size, i;
+ buf_size = strlen(expected) + 10;
+ buf = kmalloc(buf_size, GFP_KERNEL);
+ if (!buf)
+ return;
+
/* Baseline; check conversion with a large size limit */
- memset(buf, 0xff, sizeof(buf));
- size = snprintf(buf, sizeof(buf) - 2, fmt, np);
+ memset(buf, 0xff, buf_size);
+ size = snprintf(buf, buf_size - 2, fmt, np);
/* use strcmp() instead of strncmp() here to be absolutely sure strings match */
unittest((strcmp(buf, expected) == 0) && (buf[size+1] == 0xff),
@@ -270,12 +274,13 @@ static void __init of_unittest_printf_one(struct device_node *np, const char *fm
size++;
for (i = 0; i < 2; i++, size--) {
/* Clear the buffer, and make sure it works correctly still */
- memset(buf, 0xff, sizeof(buf));
+ memset(buf, 0xff, buf_size);
snprintf(buf, size+1, fmt, np);
unittest(strncmp(buf, expected, size) == 0 && (buf[size+1] == 0xff),
"snprintf failed; size=%i fmt='%s' expected='%s' rslt='%s'\n",
size, fmt, expected, buf);
}
+ kfree(buf);
}
static void __init of_unittest_printf(void)
@@ -455,6 +460,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];
@@ -564,42 +688,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);
@@ -1036,6 +1190,7 @@ static int __init unittest_data_add(void)
}
#ifdef CONFIG_OF_OVERLAY
+static int __init overlay_data_apply(const char *overlay_name, int *overlay_id);
static int unittest_probe(struct platform_device *pdev)
{
@@ -1267,26 +1422,18 @@ static void of_unittest_destroy_tracked_overlays(void)
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;
overlay_name = overlay_name_from_nr(overlay_nr);
- ret = overlay_data_apply(overlay_name, overlay_id);
- if (!ret) {
+ if (!overlay_data_apply(overlay_name, overlay_id)) {
unittest(0, "could not apply overlay \"%s\"\n",
overlay_name);
- goto out;
+ return -EFAULT;
}
of_unittest_track_overlay(*overlay_id);
- ret = 0;
-
-out:
- of_node_put(np);
-
- return ret;
+ return 0;
}
/* apply an overlay while checking before and after states */
@@ -1380,11 +1527,8 @@ static int __init of_unittest_apply_revert_overlay_check(int overlay_nr,
/* test activation of device */
static void __init of_unittest_overlay_0(void)
{
- int ret;
-
/* device should enable */
- ret = of_unittest_apply_overlay_check(0, 0, 0, 1, PDEV_OVERLAY);
- if (ret != 0)
+ if (of_unittest_apply_overlay_check(0, 0, 0, 1, PDEV_OVERLAY))
return;
unittest(1, "overlay test %d passed\n", 0);
@@ -1393,11 +1537,8 @@ static void __init of_unittest_overlay_0(void)
/* test deactivation of device */
static void __init of_unittest_overlay_1(void)
{
- int ret;
-
/* device should disable */
- ret = of_unittest_apply_overlay_check(1, 1, 1, 0, PDEV_OVERLAY);
- if (ret != 0)
+ if (of_unittest_apply_overlay_check(1, 1, 1, 0, PDEV_OVERLAY))
return;
unittest(1, "overlay test %d passed\n", 1);
@@ -1406,11 +1547,8 @@ static void __init of_unittest_overlay_1(void)
/* test activation of device */
static void __init of_unittest_overlay_2(void)
{
- int ret;
-
/* device should enable */
- ret = of_unittest_apply_overlay_check(2, 2, 0, 1, PDEV_OVERLAY);
- if (ret != 0)
+ if (of_unittest_apply_overlay_check(2, 2, 0, 1, PDEV_OVERLAY))
return;
unittest(1, "overlay test %d passed\n", 2);
@@ -1419,11 +1557,8 @@ static void __init of_unittest_overlay_2(void)
/* test deactivation of device */
static void __init of_unittest_overlay_3(void)
{
- int ret;
-
/* device should disable */
- ret = of_unittest_apply_overlay_check(3, 3, 1, 0, PDEV_OVERLAY);
- if (ret != 0)
+ if (of_unittest_apply_overlay_check(3, 3, 1, 0, PDEV_OVERLAY))
return;
unittest(1, "overlay test %d passed\n", 3);
@@ -1432,11 +1567,8 @@ static void __init of_unittest_overlay_3(void)
/* test activation of a full device node */
static void __init of_unittest_overlay_4(void)
{
- int ret;
-
/* device should disable */
- ret = of_unittest_apply_overlay_check(4, 4, 0, 1, PDEV_OVERLAY);
- if (ret != 0)
+ if (of_unittest_apply_overlay_check(4, 4, 0, 1, PDEV_OVERLAY))
return;
unittest(1, "overlay test %d passed\n", 4);
@@ -1445,11 +1577,8 @@ static void __init of_unittest_overlay_4(void)
/* test overlay apply/revert sequence */
static void __init of_unittest_overlay_5(void)
{
- int ret;
-
/* device should disable */
- ret = of_unittest_apply_revert_overlay_check(5, 5, 0, 1, PDEV_OVERLAY);
- if (ret != 0)
+ if (of_unittest_apply_revert_overlay_check(5, 5, 0, 1, PDEV_OVERLAY))
return;
unittest(1, "overlay test %d passed\n", 5);
@@ -1458,7 +1587,7 @@ static void __init of_unittest_overlay_5(void)
/* test overlay application in sequence */
static void __init of_unittest_overlay_6(void)
{
- int ret, i, ov_id[2], ovcs_id;
+ int i, ov_id[2], ovcs_id;
int overlay_nr = 6, unittest_nr = 6;
int before = 0, after = 1;
const char *overlay_name;
@@ -1481,8 +1610,7 @@ static void __init of_unittest_overlay_6(void)
overlay_name = overlay_name_from_nr(overlay_nr + i);
- ret = overlay_data_apply(overlay_name, &ovcs_id);
- if (!ret) {
+ if (!overlay_data_apply(overlay_name, &ovcs_id)) {
unittest(0, "could not apply overlay \"%s\"\n",
overlay_name);
return;
@@ -1506,8 +1634,7 @@ static void __init of_unittest_overlay_6(void)
for (i = 1; i >= 0; i--) {
ovcs_id = ov_id[i];
- ret = of_overlay_remove(&ovcs_id);
- if (ret != 0) {
+ if (of_overlay_remove(&ovcs_id)) {
unittest(0, "%s failed destroy @\"%s\"\n",
overlay_name_from_nr(overlay_nr + i),
unittest_path(unittest_nr + i,
@@ -1536,7 +1663,7 @@ static void __init of_unittest_overlay_6(void)
/* test overlay application in sequence */
static void __init of_unittest_overlay_8(void)
{
- int ret, i, ov_id[2], ovcs_id;
+ int i, ov_id[2], ovcs_id;
int overlay_nr = 8, unittest_nr = 8;
const char *overlay_name;
@@ -1547,8 +1674,7 @@ static void __init of_unittest_overlay_8(void)
overlay_name = overlay_name_from_nr(overlay_nr + i);
- ret = overlay_data_apply(overlay_name, &ovcs_id);
- if (ret < 0) {
+ if (!overlay_data_apply(overlay_name, &ovcs_id)) {
unittest(0, "could not apply overlay \"%s\"\n",
overlay_name);
return;
@@ -1559,8 +1685,7 @@ static void __init of_unittest_overlay_8(void)
/* now try to remove first overlay (it should fail) */
ovcs_id = ov_id[0];
- ret = of_overlay_remove(&ovcs_id);
- if (ret == 0) {
+ if (!of_overlay_remove(&ovcs_id)) {
unittest(0, "%s was destroyed @\"%s\"\n",
overlay_name_from_nr(overlay_nr + 0),
unittest_path(unittest_nr,
@@ -1571,8 +1696,7 @@ static void __init of_unittest_overlay_8(void)
/* removing them in order should work */
for (i = 1; i >= 0; i--) {
ovcs_id = ov_id[i];
- ret = of_overlay_remove(&ovcs_id);
- if (ret != 0) {
+ if (of_overlay_remove(&ovcs_id)) {
unittest(0, "%s not destroyed @\"%s\"\n",
overlay_name_from_nr(overlay_nr + i),
unittest_path(unittest_nr,
@@ -1604,8 +1728,8 @@ static void __init of_unittest_overlay_10(void)
ret = of_path_device_type_exists(child_path, PDEV_OVERLAY);
kfree(child_path);
- if (unittest(ret, "overlay test %d failed; no child device\n", 10))
- return;
+
+ unittest(ret, "overlay test %d failed; no child device\n", 10);
}
/* test insertion of a bus with parent devices (and revert) */
@@ -1616,9 +1740,7 @@ static void __init of_unittest_overlay_11(void)
/* device should disable */
ret = of_unittest_apply_revert_overlay_check(11, 11, 0, 1,
PDEV_OVERLAY);
- if (unittest(ret == 0,
- "overlay test %d failed; overlay application\n", 11))
- return;
+ unittest(ret == 0, "overlay test %d failed; overlay apply\n", 11);
}
#if IS_BUILTIN(CONFIG_I2C) && IS_ENABLED(CONFIG_OF_OVERLAY)
@@ -1769,7 +1891,7 @@ static int unittest_i2c_mux_select_chan(struct i2c_mux_core *muxc, u32 chan)
static int unittest_i2c_mux_probe(struct i2c_client *client,
const struct i2c_device_id *id)
{
- int ret, i, nchans;
+ int i, nchans;
struct device *dev = &client->dev;
struct i2c_adapter *adap = to_i2c_adapter(dev->parent);
struct device_node *np = client->dev.of_node, *child;
@@ -1785,8 +1907,7 @@ static int unittest_i2c_mux_probe(struct i2c_client *client,
max_reg = (u32)-1;
for_each_child_of_node(np, child) {
- ret = of_property_read_u32(child, "reg", &reg);
- if (ret)
+ if (of_property_read_u32(child, "reg", &reg))
continue;
if (max_reg == (u32)-1 || reg > max_reg)
max_reg = reg;
@@ -1802,8 +1923,7 @@ static int unittest_i2c_mux_probe(struct i2c_client *client,
if (!muxc)
return -ENOMEM;
for (i = 0; i < nchans; i++) {
- ret = i2c_mux_add_adapter(muxc, 0, i, 0);
- if (ret) {
+ if (i2c_mux_add_adapter(muxc, 0, i, 0)) {
dev_err(dev, "Failed to register mux #%d\n", i);
i2c_mux_del_adapters(muxc);
return -ENODEV;
@@ -1877,11 +1997,8 @@ static void of_unittest_overlay_i2c_cleanup(void)
static void __init of_unittest_overlay_i2c_12(void)
{
- int ret;
-
/* device should enable */
- ret = of_unittest_apply_overlay_check(12, 12, 0, 1, I2C_OVERLAY);
- if (ret != 0)
+ if (of_unittest_apply_overlay_check(12, 12, 0, 1, I2C_OVERLAY))
return;
unittest(1, "overlay test %d passed\n", 12);
@@ -1890,11 +2007,8 @@ static void __init of_unittest_overlay_i2c_12(void)
/* test deactivation of device */
static void __init of_unittest_overlay_i2c_13(void)
{
- int ret;
-
/* device should disable */
- ret = of_unittest_apply_overlay_check(13, 13, 1, 0, I2C_OVERLAY);
- if (ret != 0)
+ if (of_unittest_apply_overlay_check(13, 13, 1, 0, I2C_OVERLAY))
return;
unittest(1, "overlay test %d passed\n", 13);
@@ -1907,11 +2021,8 @@ static void of_unittest_overlay_i2c_14(void)
static void __init of_unittest_overlay_i2c_15(void)
{
- int ret;
-
/* device should enable */
- ret = of_unittest_apply_overlay_check(15, 15, 0, 1, I2C_OVERLAY);
- if (ret != 0)
+ if (of_unittest_apply_overlay_check(15, 15, 0, 1, I2C_OVERLAY))
return;
unittest(1, "overlay test %d passed\n", 15);
@@ -1927,10 +2038,8 @@ static inline void of_unittest_overlay_i2c_15(void) { }
static void __init of_unittest_overlay(void)
{
struct device_node *bus_np = NULL;
- int ret;
- ret = platform_driver_register(&unittest_driver);
- if (ret != 0) {
+ if (platform_driver_register(&unittest_driver)) {
unittest(0, "could not register unittest driver\n");
goto out;
}
@@ -1941,8 +2050,7 @@ static void __init of_unittest_overlay(void)
goto out;
}
- ret = of_platform_default_populate(bus_np, NULL, NULL);
- if (ret != 0) {
+ if (of_platform_default_populate(bus_np, NULL, NULL)) {
unittest(0, "could not populate bus @ \"%s\"\n", bus_path);
goto out;
}
@@ -2156,10 +2264,8 @@ static int __init overlay_data_apply(const char *overlay_name, int *overlay_id)
}
size = info->dtb_end - info->dtb_begin;
- if (!size) {
+ if (!size)
pr_err("no overlay data for %s\n", overlay_name);
- ret = 0;
- }
ret = of_overlay_fdt_apply(info->dtb_begin, size, &info->overlay_id);
if (overlay_id)
@@ -2193,7 +2299,6 @@ static __init void of_unittest_overlay_high_level(void)
struct device_node *overlay_base_symbols;
struct device_node **pprev;
struct property *prop;
- int ret;
if (!overlay_base_root) {
unittest(0, "overlay_base_root not initialized\n");
@@ -2284,19 +2389,15 @@ static __init void of_unittest_overlay_high_level(void)
prop->name);
goto err_unlock;
}
- ret = __of_add_property(of_symbols, new_prop);
- if (ret) {
- if (!strcmp(new_prop->name, "name")) {
- /* auto-generated by unflatten */
- ret = 0;
+ if (__of_add_property(of_symbols, new_prop)) {
+ /* "name" auto-generated by unflatten */
+ if (!strcmp(new_prop->name, "name"))
continue;
- }
unittest(0, "duplicate property '%s' in overlay_base node __symbols__",
prop->name);
goto err_unlock;
}
- ret = __of_add_property_sysfs(of_symbols, new_prop);
- if (ret) {
+ if (__of_add_property_sysfs(of_symbols, new_prop)) {
unittest(0, "unable to add property '%s' in overlay_base node __symbols__ to sysfs",
prop->name);
goto err_unlock;
@@ -2355,6 +2456,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();