2024-07-18 21:05:03 +00:00
|
|
|
// SPDX-License-Identifier: GPL-2.0
|
|
|
|
/*
|
|
|
|
* KUnit tests for device tree overlays
|
|
|
|
*/
|
|
|
|
#include <linux/device/bus.h>
|
|
|
|
#include <linux/kconfig.h>
|
|
|
|
#include <linux/of.h>
|
|
|
|
#include <linux/of_platform.h>
|
|
|
|
#include <linux/platform_device.h>
|
|
|
|
|
|
|
|
#include <kunit/of.h>
|
|
|
|
#include <kunit/test.h>
|
|
|
|
|
2024-10-09 20:41:31 +00:00
|
|
|
#include "of_private.h"
|
|
|
|
|
2024-07-18 21:05:03 +00:00
|
|
|
static const char * const kunit_node_name = "kunit-test";
|
|
|
|
static const char * const kunit_compatible = "test,empty";
|
|
|
|
|
|
|
|
/* Test that of_overlay_apply_kunit() adds a node to the live tree */
|
|
|
|
static void of_overlay_apply_kunit_apply(struct kunit *test)
|
|
|
|
{
|
|
|
|
struct device_node *np;
|
|
|
|
|
|
|
|
KUNIT_ASSERT_EQ(test, 0,
|
|
|
|
of_overlay_apply_kunit(test, kunit_overlay_test));
|
|
|
|
|
|
|
|
np = of_find_node_by_name(NULL, kunit_node_name);
|
|
|
|
KUNIT_EXPECT_NOT_ERR_OR_NULL(test, np);
|
|
|
|
of_node_put(np);
|
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Test that of_overlay_apply_kunit() creates platform devices with the
|
|
|
|
* expected device_node
|
|
|
|
*/
|
|
|
|
static void of_overlay_apply_kunit_platform_device(struct kunit *test)
|
|
|
|
{
|
|
|
|
struct platform_device *pdev;
|
|
|
|
struct device_node *np;
|
|
|
|
|
|
|
|
KUNIT_ASSERT_EQ(test, 0,
|
|
|
|
of_overlay_apply_kunit(test, kunit_overlay_test));
|
|
|
|
|
|
|
|
np = of_find_node_by_name(NULL, kunit_node_name);
|
|
|
|
of_node_put_kunit(test, np);
|
|
|
|
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, np);
|
|
|
|
|
|
|
|
pdev = of_find_device_by_node(np);
|
|
|
|
KUNIT_EXPECT_NOT_ERR_OR_NULL(test, pdev);
|
|
|
|
if (pdev)
|
|
|
|
put_device(&pdev->dev);
|
|
|
|
}
|
|
|
|
|
|
|
|
static int of_overlay_bus_match_compatible(struct device *dev, const void *data)
|
|
|
|
{
|
|
|
|
return of_device_is_compatible(dev->of_node, data);
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Test that of_overlay_apply_kunit() cleans up after the test is finished */
|
|
|
|
static void of_overlay_apply_kunit_cleanup(struct kunit *test)
|
|
|
|
{
|
|
|
|
struct kunit fake;
|
|
|
|
struct platform_device *pdev;
|
|
|
|
struct device *dev;
|
|
|
|
struct device_node *np;
|
|
|
|
|
2024-10-09 20:41:31 +00:00
|
|
|
of_root_kunit_skip(test);
|
2024-10-16 21:20:15 +00:00
|
|
|
if (!IS_ENABLED(CONFIG_OF_OVERLAY))
|
|
|
|
kunit_skip(test, "requires CONFIG_OF_OVERLAY to apply overlay");
|
2024-07-18 21:05:03 +00:00
|
|
|
if (!IS_ENABLED(CONFIG_OF_EARLY_FLATTREE))
|
|
|
|
kunit_skip(test, "requires CONFIG_OF_EARLY_FLATTREE for root node");
|
|
|
|
|
|
|
|
kunit_init_test(&fake, "fake test", NULL);
|
|
|
|
KUNIT_ASSERT_EQ(test, fake.status, KUNIT_SUCCESS);
|
|
|
|
|
|
|
|
KUNIT_ASSERT_EQ(test, 0,
|
|
|
|
of_overlay_apply_kunit(&fake, kunit_overlay_test));
|
|
|
|
|
|
|
|
np = of_find_node_by_name(NULL, kunit_node_name);
|
|
|
|
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, np);
|
of: Fix unbalanced of node refcount and memory leaks
Got following report when doing overlay_test:
OF: ERROR: memory leak, expected refcount 1 instead of 2,
of_node_get()/of_node_put() unbalanced - destroy cset entry:
attach overlay node /kunit-test
OF: ERROR: memory leak before free overlay changeset, /kunit-test
In of_overlay_apply_kunit_cleanup(), the "np" should be associated with
fake instead of test to call of_node_put(), so the node is put before
the overlay is removed.
It also fix the following memory leaks:
unreferenced object 0xffffff80c7d22800 (size 256):
comm "kunit_try_catch", pid 236, jiffies 4294894764
hex dump (first 32 bytes):
d0 26 d4 c2 80 ff ff ff 00 00 00 00 00 00 00 00 .&..............
60 19 75 c1 80 ff ff ff 00 00 00 00 00 00 00 00 `.u.............
backtrace (crc ee0a471c):
[<0000000058ea1340>] kmemleak_alloc+0x34/0x40
[<00000000c538ac7e>] __kmalloc_cache_noprof+0x26c/0x2f4
[<00000000119f34f3>] __of_node_dup+0x4c/0x328
[<00000000b212ca39>] build_changeset_next_level+0x2cc/0x4c0
[<00000000eb208e87>] of_overlay_fdt_apply+0x930/0x1334
[<000000005bdc53a3>] of_overlay_fdt_apply_kunit+0x54/0x10c
[<00000000143acd5d>] of_overlay_apply_kunit_cleanup+0x12c/0x524
[<00000000a813abc8>] kunit_try_run_case+0x13c/0x3ac
[<00000000d77ab00c>] kunit_generic_run_threadfn_adapter+0x80/0xec
[<000000000b296be1>] kthread+0x2e8/0x374
[<0000000007bd1c51>] ret_from_fork+0x10/0x20
unreferenced object 0xffffff80c1751960 (size 16):
comm "kunit_try_catch", pid 236, jiffies 4294894764
hex dump (first 16 bytes):
6b 75 6e 69 74 2d 74 65 73 74 00 c1 80 ff ff ff kunit-test......
backtrace (crc 18196259):
[<0000000058ea1340>] kmemleak_alloc+0x34/0x40
[<0000000071006e2c>] __kmalloc_node_track_caller_noprof+0x300/0x3e0
[<00000000b16ac6cb>] kstrdup+0x48/0x84
[<0000000050e3373b>] __of_node_dup+0x60/0x328
[<00000000b212ca39>] build_changeset_next_level+0x2cc/0x4c0
[<00000000eb208e87>] of_overlay_fdt_apply+0x930/0x1334
[<000000005bdc53a3>] of_overlay_fdt_apply_kunit+0x54/0x10c
[<00000000143acd5d>] of_overlay_apply_kunit_cleanup+0x12c/0x524
[<00000000a813abc8>] kunit_try_run_case+0x13c/0x3ac
[<00000000d77ab00c>] kunit_generic_run_threadfn_adapter+0x80/0xec
[<000000000b296be1>] kthread+0x2e8/0x374
[<0000000007bd1c51>] ret_from_fork+0x10/0x20
unreferenced object 0xffffff80c2e96e00 (size 192):
comm "kunit_try_catch", pid 236, jiffies 4294894764
hex dump (first 32 bytes):
80 19 75 c1 80 ff ff ff 0b 00 00 00 00 00 00 00 ..u.............
a0 19 75 c1 80 ff ff ff 00 6f e9 c2 80 ff ff ff ..u......o......
backtrace (crc 1924cba4):
[<0000000058ea1340>] kmemleak_alloc+0x34/0x40
[<00000000c538ac7e>] __kmalloc_cache_noprof+0x26c/0x2f4
[<000000009fdd35ad>] __of_prop_dup+0x7c/0x2ec
[<00000000aa4e0111>] add_changeset_property+0x548/0x9e0
[<000000004777e25b>] build_changeset_next_level+0xd4/0x4c0
[<00000000a9c93f8a>] build_changeset_next_level+0x3a8/0x4c0
[<00000000eb208e87>] of_overlay_fdt_apply+0x930/0x1334
[<000000005bdc53a3>] of_overlay_fdt_apply_kunit+0x54/0x10c
[<00000000143acd5d>] of_overlay_apply_kunit_cleanup+0x12c/0x524
[<00000000a813abc8>] kunit_try_run_case+0x13c/0x3ac
[<00000000d77ab00c>] kunit_generic_run_threadfn_adapter+0x80/0xec
[<000000000b296be1>] kthread+0x2e8/0x374
[<0000000007bd1c51>] ret_from_fork+0x10/0x20
unreferenced object 0xffffff80c1751980 (size 16):
comm "kunit_try_catch", pid 236, jiffies 4294894764
hex dump (first 16 bytes):
63 6f 6d 70 61 74 69 62 6c 65 00 c1 80 ff ff ff compatible......
backtrace (crc 42df3c87):
[<0000000058ea1340>] kmemleak_alloc+0x34/0x40
[<0000000071006e2c>] __kmalloc_node_track_caller_noprof+0x300/0x3e0
[<00000000b16ac6cb>] kstrdup+0x48/0x84
[<00000000a8888fd8>] __of_prop_dup+0xb0/0x2ec
[<00000000aa4e0111>] add_changeset_property+0x548/0x9e0
[<000000004777e25b>] build_changeset_next_level+0xd4/0x4c0
[<00000000a9c93f8a>] build_changeset_next_level+0x3a8/0x4c0
[<00000000eb208e87>] of_overlay_fdt_apply+0x930/0x1334
[<000000005bdc53a3>] of_overlay_fdt_apply_kunit+0x54/0x10c
[<00000000143acd5d>] of_overlay_apply_kunit_cleanup+0x12c/0x524
[<00000000a813abc8>] kunit_try_run_case+0x13c/0x3ac
[<00000000d77ab00c>] kunit_generic_run_threadfn_adapter+0x80/0xec
[<000000000b296be1>] kthread+0x2e8/0x374
unreferenced object 0xffffff80c2e96f00 (size 192):
comm "kunit_try_catch", pid 236, jiffies 4294894764
hex dump (first 32 bytes):
40 f7 bb c6 80 ff ff ff 0b 00 00 00 00 00 00 00 @...............
c0 19 75 c1 80 ff ff ff 00 00 00 00 00 00 00 00 ..u.............
backtrace (crc f2f57ea7):
[<0000000058ea1340>] kmemleak_alloc+0x34/0x40
[<00000000c538ac7e>] __kmalloc_cache_noprof+0x26c/0x2f4
[<000000009fdd35ad>] __of_prop_dup+0x7c/0x2ec
[<00000000aa4e0111>] add_changeset_property+0x548/0x9e0
[<000000004777e25b>] build_changeset_next_level+0xd4/0x4c0
[<00000000a9c93f8a>] build_changeset_next_level+0x3a8/0x4c0
[<00000000eb208e87>] of_overlay_fdt_apply+0x930/0x1334
[<000000005bdc53a3>] of_overlay_fdt_apply_kunit+0x54/0x10c
[<00000000143acd5d>] of_overlay_apply_kunit_cleanup+0x12c/0x524
[<00000000a813abc8>] kunit_try_run_case+0x13c/0x3ac
[<00000000d77ab00c>] kunit_generic_run_threadfn_adapter+0x80/0xec
[<000000000b296be1>] kthread+0x2e8/0x374
[<0000000007bd1c51>] ret_from_fork+0x10/0x20
......
How to reproduce:
CONFIG_OF_OVERLAY_KUNIT_TEST=y, CONFIG_DEBUG_KMEMLEAK=y
and CONFIG_DEBUG_KMEMLEAK_AUTO_SCAN=y, launch the kernel.
Fixes: 5c9dd72d8385 ("of: Add a KUnit test for overlays and test managed APIs")
Reviewed-by: Stephen Boyd <sboyd@kernel.org>
Signed-off-by: Jinjie Ruan <ruanjinjie@huawei.com>
Link: https://lore.kernel.org/r/20241010034416.2324196-1-ruanjinjie@huawei.com
Signed-off-by: Rob Herring (Arm) <robh@kernel.org>
2024-10-10 03:44:16 +00:00
|
|
|
of_node_put_kunit(&fake, np);
|
2024-07-18 21:05:03 +00:00
|
|
|
|
|
|
|
pdev = of_find_device_by_node(np);
|
|
|
|
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, pdev);
|
|
|
|
put_device(&pdev->dev); /* Not derefing 'pdev' after this */
|
|
|
|
|
|
|
|
/* Remove overlay */
|
|
|
|
kunit_cleanup(&fake);
|
|
|
|
|
|
|
|
/* The node and device should be removed */
|
|
|
|
np = of_find_node_by_name(NULL, kunit_node_name);
|
|
|
|
KUNIT_EXPECT_PTR_EQ(test, NULL, np);
|
|
|
|
of_node_put(np);
|
|
|
|
|
|
|
|
dev = bus_find_device(&platform_bus_type, NULL, kunit_compatible,
|
|
|
|
of_overlay_bus_match_compatible);
|
|
|
|
KUNIT_EXPECT_PTR_EQ(test, NULL, dev);
|
|
|
|
put_device(dev);
|
|
|
|
}
|
|
|
|
|
|
|
|
static struct kunit_case of_overlay_apply_kunit_test_cases[] = {
|
|
|
|
KUNIT_CASE(of_overlay_apply_kunit_apply),
|
|
|
|
KUNIT_CASE(of_overlay_apply_kunit_platform_device),
|
|
|
|
KUNIT_CASE(of_overlay_apply_kunit_cleanup),
|
|
|
|
{}
|
|
|
|
};
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Test suite for test managed device tree overlays.
|
|
|
|
*/
|
|
|
|
static struct kunit_suite of_overlay_apply_kunit_suite = {
|
|
|
|
.name = "of_overlay_apply_kunit",
|
|
|
|
.test_cases = of_overlay_apply_kunit_test_cases,
|
|
|
|
};
|
|
|
|
|
|
|
|
kunit_test_suites(
|
|
|
|
&of_overlay_apply_kunit_suite,
|
|
|
|
);
|
|
|
|
MODULE_LICENSE("GPL");
|
|
|
|
MODULE_DESCRIPTION("KUnit tests for device tree overlays");
|