|  | // SPDX-License-Identifier: GPL-2.0 | 
|  | /* | 
|  | * KUnit tests for OF APIs | 
|  | */ | 
|  | #include <linux/ioport.h> | 
|  | #include <linux/module.h> | 
|  | #include <linux/of.h> | 
|  |  | 
|  | #include <kunit/test.h> | 
|  |  | 
|  | #include "of_private.h" | 
|  |  | 
|  | /* | 
|  | * Test that the root node "/" can be found by path. | 
|  | */ | 
|  | static void of_dtb_root_node_found_by_path(struct kunit *test) | 
|  | { | 
|  | struct device_node *np; | 
|  |  | 
|  | np = of_find_node_by_path("/"); | 
|  | KUNIT_EXPECT_NOT_ERR_OR_NULL(test, np); | 
|  | of_node_put(np); | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Test that the 'of_root' global variable is always populated when DT code is | 
|  | * enabled. Remove this test once of_root is removed from global access. | 
|  | */ | 
|  | static void of_dtb_root_node_populates_of_root(struct kunit *test) | 
|  | { | 
|  | KUNIT_EXPECT_NOT_ERR_OR_NULL(test, of_root); | 
|  | } | 
|  |  | 
|  | static struct kunit_case of_dtb_test_cases[] = { | 
|  | KUNIT_CASE(of_dtb_root_node_found_by_path), | 
|  | KUNIT_CASE(of_dtb_root_node_populates_of_root), | 
|  | {} | 
|  | }; | 
|  |  | 
|  | static int of_dtb_test_init(struct kunit *test) | 
|  | { | 
|  | of_root_kunit_skip(test); | 
|  | if (!IS_ENABLED(CONFIG_OF_EARLY_FLATTREE)) | 
|  | kunit_skip(test, "requires CONFIG_OF_EARLY_FLATTREE"); | 
|  |  | 
|  | return 0; | 
|  | } | 
|  |  | 
|  | /* | 
|  | * Test suite to confirm a DTB is loaded. | 
|  | */ | 
|  | static struct kunit_suite of_dtb_suite = { | 
|  | .name = "of_dtb", | 
|  | .test_cases = of_dtb_test_cases, | 
|  | .init = of_dtb_test_init, | 
|  | }; | 
|  |  | 
|  | struct of_address_resource_bounds_case { | 
|  | u64 start; | 
|  | u64 size; | 
|  | int ret; | 
|  |  | 
|  | u64 res_start; | 
|  | u64 res_end; | 
|  | }; | 
|  |  | 
|  | static void of_address_resource_bounds_case_desc(const struct of_address_resource_bounds_case *p, | 
|  | char *name) | 
|  | { | 
|  | snprintf(name, KUNIT_PARAM_DESC_SIZE, "start=0x%016llx,size=0x%016llx", p->start, p->size); | 
|  | } | 
|  |  | 
|  | static const struct of_address_resource_bounds_case of_address_resource_bounds_cases[] = { | 
|  | { | 
|  | .start = 0, | 
|  | .size = 0, | 
|  | .ret = 0, | 
|  | .res_start = 0, | 
|  | .res_end = -1, | 
|  | }, | 
|  | { | 
|  | .start = 0, | 
|  | .size = 0x1000, | 
|  | .ret = 0, | 
|  | .res_start = 0, | 
|  | .res_end = 0xfff, | 
|  | }, | 
|  | { | 
|  | .start = 0x1000, | 
|  | .size = 0, | 
|  | .ret = 0, | 
|  | .res_start = 0x1000, | 
|  | .res_end = 0xfff, | 
|  | }, | 
|  | { | 
|  | .start = 0x1000, | 
|  | .size = 0x1000, | 
|  | .ret = 0, | 
|  | .res_start = 0x1000, | 
|  | .res_end = 0x1fff, | 
|  | }, | 
|  | { | 
|  | .start = 1, | 
|  | .size = RESOURCE_SIZE_MAX, | 
|  | .ret = 0, | 
|  | .res_start = 1, | 
|  | .res_end = RESOURCE_SIZE_MAX, | 
|  | }, | 
|  | { | 
|  | .start = RESOURCE_SIZE_MAX, | 
|  | .size = 1, | 
|  | .ret = 0, | 
|  | .res_start = RESOURCE_SIZE_MAX, | 
|  | .res_end = RESOURCE_SIZE_MAX, | 
|  | }, | 
|  | { | 
|  | .start = 2, | 
|  | .size = RESOURCE_SIZE_MAX, | 
|  | .ret = -EOVERFLOW, | 
|  | }, | 
|  | { | 
|  | .start = RESOURCE_SIZE_MAX, | 
|  | .size = 2, | 
|  | .ret = -EOVERFLOW, | 
|  | }, | 
|  | { | 
|  | .start = ULL(0x100000000), | 
|  | .size = 1, | 
|  | .ret = sizeof(resource_size_t) > sizeof(u32) ? 0 : -EOVERFLOW, | 
|  | .res_start = ULL(0x100000000), | 
|  | .res_end = ULL(0x100000000), | 
|  | }, | 
|  | { | 
|  | .start = 0x1000, | 
|  | .size = 0xffffffff, | 
|  | .ret = sizeof(resource_size_t) > sizeof(u32) ? 0 : -EOVERFLOW, | 
|  | .res_start = 0x1000, | 
|  | .res_end = ULL(0x100000ffe), | 
|  | }, | 
|  | }; | 
|  |  | 
|  | KUNIT_ARRAY_PARAM(of_address_resource_bounds, | 
|  | of_address_resource_bounds_cases, of_address_resource_bounds_case_desc); | 
|  |  | 
|  | static void of_address_resource_bounds(struct kunit *test) | 
|  | { | 
|  | const struct of_address_resource_bounds_case *param = test->param_value; | 
|  | struct resource r; /* Intentionally uninitialized */ | 
|  | int ret; | 
|  |  | 
|  | if (!IS_ENABLED(CONFIG_OF_ADDRESS)) | 
|  | kunit_skip(test, "CONFIG_OF_ADDRESS not enabled\n"); | 
|  |  | 
|  | ret = __of_address_resource_bounds(&r, param->start, param->size); | 
|  | KUNIT_EXPECT_EQ(test, param->ret, ret); | 
|  | if (ret == 0) { | 
|  | KUNIT_EXPECT_EQ(test, (resource_size_t)param->res_start, r.start); | 
|  | KUNIT_EXPECT_EQ(test, (resource_size_t)param->res_end, r.end); | 
|  | KUNIT_EXPECT_EQ(test, param->size, resource_size(&r)); | 
|  | } | 
|  | } | 
|  |  | 
|  | static struct kunit_case of_address_test_cases[] = { | 
|  | KUNIT_CASE_PARAM(of_address_resource_bounds, of_address_resource_bounds_gen_params), | 
|  | {} | 
|  | }; | 
|  |  | 
|  | static struct kunit_suite of_address_suite = { | 
|  | .name = "of_address", | 
|  | .test_cases = of_address_test_cases, | 
|  | }; | 
|  |  | 
|  | kunit_test_suites( | 
|  | &of_dtb_suite, &of_address_suite, | 
|  | ); | 
|  | MODULE_DESCRIPTION("KUnit tests for OF APIs"); | 
|  | MODULE_IMPORT_NS("EXPORTED_FOR_KUNIT_TESTING"); | 
|  | MODULE_LICENSE("GPL"); |