From: "Ilpo Järvinen" <ilpo.jarvinen@linux.intel.com>
To: linux-pci@vger.kernel.org, Bjorn Helgaas <bhelgaas@google.com>,
Geert Uytterhoeven <geert@linux-m68k.org>,
Kai-Heng Feng <kaihengf@nvidia.com>,
Rob Herring <robh@kernel.org>,
linux-kernel@vger.kernel.org
Cc: "Andy Shevchenko" <andriy.shevchenko@linux.intel.com>,
"Krzysztof Wilczyński" <kw@linux.com>,
Linux-Renesas <linux-renesas-soc@vger.kernel.org>,
"Ilpo Järvinen" <ilpo.jarvinen@linux.intel.com>
Subject: [PATCH 3/3] resource, kunit: add test case for resource_coalesce()
Date: Fri, 10 Oct 2025 17:42:31 +0300 [thread overview]
Message-ID: <20251010144231.15773-4-ilpo.jarvinen@linux.intel.com> (raw)
In-Reply-To: <20251010144231.15773-1-ilpo.jarvinen@linux.intel.com>
Add a test case for resource_coalesce() which has both parent and
children resources to adjust.
Add framework to build resource trees in a human-readable way and to
verify them which could be used to kunit test also other resource tree
manipulation functions.
Signed-off-by: Ilpo Järvinen <ilpo.jarvinen@linux.intel.com>
---
include/linux/ioport.h | 5 ++
kernel/resource.c | 8 ++-
kernel/resource_kunit.c | 121 ++++++++++++++++++++++++++++++++++++++++
3 files changed, 132 insertions(+), 2 deletions(-)
diff --git a/include/linux/ioport.h b/include/linux/ioport.h
index e8b2d6aa4013..56f4d1cfde29 100644
--- a/include/linux/ioport.h
+++ b/include/linux/ioport.h
@@ -426,5 +426,10 @@ static inline void irqresource_disabled(struct resource *res, u32 irq)
extern struct address_space *iomem_get_mapping(void);
+#if IS_ENABLED(CONFIG_KUNIT)
+int resource_coalesce(struct resource *res, struct resource *next_res,
+ struct resource *new_res);
+#endif
+
#endif /* __ASSEMBLY__ */
#endif /* _LINUX_IOPORT_H */
diff --git a/kernel/resource.c b/kernel/resource.c
index c6e1872abb78..f7e7b49dc9a4 100644
--- a/kernel/resource.c
+++ b/kernel/resource.c
@@ -10,6 +10,8 @@
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
+#include <kunit/visibility.h>
+
#include <linux/cleanup.h>
#include <linux/export.h>
#include <linux/errno.h>
@@ -299,8 +301,9 @@ static bool resource_mergeable(struct resource *r1, struct resource *r2)
return false;
}
-static int resource_coalesce(struct resource *res, struct resource *next_res,
- struct resource *new_res)
+VISIBLE_IF_KUNIT int resource_coalesce(struct resource *res,
+ struct resource *next_res,
+ struct resource *new_res)
{
struct resource *parent, *tmp;
struct resource **p, **c;
@@ -367,6 +370,7 @@ static int resource_coalesce(struct resource *res, struct resource *next_res,
return 0;
}
+EXPORT_SYMBOL_IF_KUNIT(resource_coalesce);
/**
* request_resource_conflict - request and reserve an I/O or memory resource
diff --git a/kernel/resource_kunit.c b/kernel/resource_kunit.c
index b8ef75b99eb2..3b5d09bb612a 100644
--- a/kernel/resource_kunit.c
+++ b/kernel/resource_kunit.c
@@ -4,6 +4,8 @@
*/
#include <kunit/test.h>
+
+#include <linux/array_size.h>
#include <linux/ioport.h>
#include <linux/kernel.h>
#include <linux/string.h>
@@ -20,6 +22,16 @@
#define R3_END 0x789a
#define R4_START 0x2000
#define R4_END 0x7000
+#define R4A_START 0x2000
+#define R4A_END 0x3000
+#define R4B_START 0x3001
+#define R4B_END 0x4000
+#define R5_START 0x7001
+#define R5_END 0x8000
+#define R5A_START 0x7001
+#define R5A_END 0x7800
+#define R5B_START 0x7801
+#define R5B_END 0x7c00
static struct resource r0 = { .start = R0_START, .end = R0_END };
static struct resource r1 = { .start = R1_START, .end = R1_END };
@@ -34,6 +46,11 @@ struct result {
bool ret;
};
+struct resource_tree_def {
+ struct resource r;
+ unsigned int parent, child, sibling;
+};
+
static struct result results_for_union[] = {
{
.r1 = &r1, .r2 = &r0, .r.start = R0_START, .r.end = R0_END, .ret = true,
@@ -139,6 +156,107 @@ static void resource_test_intersection(struct kunit *test)
} while (++i < ARRAY_SIZE(results_for_intersection));
}
+static struct resource *copy_resource_tree(struct kunit *test,
+ struct resource_tree_def *def,
+ size_t len, size_t extra)
+{
+ struct resource *tree;
+ unsigned int i;
+
+ tree = kunit_kcalloc(test, len + extra, sizeof(*tree), GFP_KERNEL);
+ KUNIT_EXPECT_NOT_NULL(test, tree);
+
+ for (i = 0; i < len; i++) {
+ tree[i] = def[i].r;
+
+ if (def[i].parent)
+ tree[i].parent = &tree[def[i].parent];
+ if (def[i].child)
+ tree[i].child = &tree[def[i].child];
+ if (def[i].sibling)
+ tree[i].sibling = &tree[def[i].sibling];
+ }
+
+ return tree;
+}
+
+static void resource_do_test_tree(struct kunit *test, struct resource *tree,
+ struct resource_tree_def *exp_tree,
+ size_t len)
+{
+ unsigned int link, i;
+
+ for (i = 0; i < len; i++) {
+ KUNIT_EXPECT_EQ_MSG(test, tree[i].start, exp_tree[i].r.start,
+ "Start elements for resource %u are not equal", i);
+ KUNIT_EXPECT_EQ_MSG(test, tree[i].end, exp_tree[i].r.end,
+ "End elements for resource %u are not equal", i);
+
+ link = tree[i].parent ? tree[i].parent - &tree[0] : 0;
+ KUNIT_EXPECT_EQ_MSG(test, link, exp_tree[i].parent,
+ "Parent link for resource %u is not equal", i);
+
+ link = tree[i].child ? tree[i].child - &tree[0] : 0;
+ KUNIT_EXPECT_EQ_MSG(test, link, exp_tree[i].child,
+ "Child link for resource %u is not equal", i);
+
+ link = tree[i].sibling ? tree[i].sibling - &tree[0] : 0;
+ KUNIT_EXPECT_EQ_MSG(test, link, exp_tree[i].sibling,
+ "Sibling link for resource %u is not equal", i);
+ }
+}
+
+struct resource_tree_def resource_test_tree[8] = {
+ /* [0] is empty intentionally. */
+ [1] = { .r.start = R0_START, .r.end = R0_END, .child = 2 },
+ [2] = { .r.start = R4_START, .r.end = R4_END, .parent = 1, .sibling = 3, .child = 4 },
+ [3] = { .r.start = R5_START, .r.end = R5_END, .parent = 1, .child = 6 },
+ [4] = { .r.start = R4A_START, .r.end = R4A_END, .parent = 2, .sibling = 5 },
+ [5] = { .r.start = R4B_START, .r.end = R4B_END, .parent = 2 },
+ [6] = { .r.start = R5A_START, .r.end = R5A_END, .parent = 3, .sibling = 7 },
+ [7] = { .r.start = R5B_START, .r.end = R5B_END, .parent = 3 },
+};
+
+struct resource_tree_def result_for_coalesce_2_and_3[9] = {
+ /* [0] is empty intentionally. */
+ [1] = { .r.start = R0_START, .r.end = R0_END, .child = 8 },
+ [2] = { .r.start = R4_START, .r.end = R4_END },
+ [3] = { .r.start = R5_START, .r.end = R5_END },
+ [4] = { .r.start = R4A_START, .r.end = R4A_END, .parent = 8, .sibling = 5 },
+ [5] = { .r.start = R4B_START, .r.end = R4B_END, .parent = 8, .sibling = 6 },
+ [6] = { .r.start = R5A_START, .r.end = R5A_END, .parent = 8, .sibling = 7 },
+ [7] = { .r.start = R5B_START, .r.end = R5B_END, .parent = 8 },
+ [8] = { .r.start = R4_START, .r.end = R5_END, .parent = 1, .child = 4 },
+};
+
+static void resource_test_tree_test_harness(struct kunit *test)
+{
+ struct resource *tree;
+
+ tree = copy_resource_tree(test, resource_test_tree,
+ ARRAY_SIZE(resource_test_tree), 0);
+
+ /* Sanity-check test harness with identity check */
+ resource_do_test_tree(test, tree, resource_test_tree,
+ ARRAY_SIZE(resource_test_tree));
+}
+
+static void resource_test_coalesce(struct kunit *test)
+{
+ struct resource *tree, *result;
+ int ret;
+
+ tree = copy_resource_tree(test, resource_test_tree,
+ ARRAY_SIZE(resource_test_tree), 1);
+
+ result = &tree[ARRAY_SIZE(resource_test_tree)];
+
+ ret = resource_coalesce(&tree[2], &tree[3], result);
+ KUNIT_EXPECT_EQ(test, ret, 0);
+ resource_do_test_tree(test, tree, result_for_coalesce_2_and_3,
+ ARRAY_SIZE(result_for_coalesce_2_and_3));
+}
+
/*
* The test resource tree for region_intersects() test:
*
@@ -292,6 +410,8 @@ static void resource_test_region_intersects(struct kunit *test)
static struct kunit_case resource_test_cases[] = {
KUNIT_CASE(resource_test_union),
KUNIT_CASE(resource_test_intersection),
+ KUNIT_CASE(resource_test_tree_test_harness),
+ KUNIT_CASE(resource_test_coalesce),
KUNIT_CASE(resource_test_region_intersects),
{}
};
@@ -304,3 +424,4 @@ kunit_test_suite(resource_test_suite);
MODULE_DESCRIPTION("I/O Port & Memory Resource manager unit tests");
MODULE_LICENSE("GPL");
+MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING");
--
2.39.5
next prev parent reply other threads:[~2025-10-10 14:43 UTC|newest]
Thread overview: 21+ messages / expand[flat|nested] mbox.gz Atom feed top
2025-10-10 14:42 [PATCH 0/3] PCI & resource: Make coalescing host bridge windows safer Ilpo Järvinen
2025-10-10 14:42 ` [PATCH 1/3] PCI: Refactor host bridge window coalescing loop to use prev Ilpo Järvinen
2025-10-10 14:42 ` [PATCH 2/3] PCI: Do not coalesce host bridge resource structs in place Ilpo Järvinen
2025-10-15 14:29 ` Andy Shevchenko
2025-10-20 17:21 ` Ilpo Järvinen
2025-10-20 17:44 ` Andy Shevchenko
2025-10-20 18:15 ` Ilpo Järvinen
2025-10-20 18:30 ` Andy Shevchenko
2025-10-10 14:42 ` Ilpo Järvinen [this message]
2025-10-20 13:42 ` [PATCH 0/3] PCI & resource: Make coalescing host bridge windows safer Geert Uytterhoeven
2025-10-20 16:20 ` Ilpo Järvinen
2025-10-21 7:44 ` Geert Uytterhoeven
2025-10-21 11:54 ` Ilpo Järvinen
2025-10-21 15:49 ` Andy Shevchenko
2025-10-21 16:09 ` Ilpo Järvinen
2025-10-22 7:19 ` Geert Uytterhoeven
2025-10-22 7:45 ` Geert Uytterhoeven
2025-10-22 11:13 ` Ilpo Järvinen
2025-10-22 12:14 ` Ilpo Järvinen
2025-10-22 12:51 ` Rob Herring
2025-10-23 23:02 ` Bjorn Helgaas
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20251010144231.15773-4-ilpo.jarvinen@linux.intel.com \
--to=ilpo.jarvinen@linux.intel.com \
--cc=andriy.shevchenko@linux.intel.com \
--cc=bhelgaas@google.com \
--cc=geert@linux-m68k.org \
--cc=kaihengf@nvidia.com \
--cc=kw@linux.com \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-pci@vger.kernel.org \
--cc=linux-renesas-soc@vger.kernel.org \
--cc=robh@kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox