1 // SPDX-License-Identifier: GPL-2.0+
3 * Tests for the devres (
5 * Copyright 2019 Google LLC
12 #include <dm/device-internal.h>
13 #include <dm/devres.h>
15 #include <dm/uclass-internal.h>
18 /* Test that devm_kmalloc() allocates memory, free when device is removed */
19 static int dm_test_devres_alloc(struct unit_test_state *uts)
21 ulong mem_start, mem_dev, mem_kmalloc;
25 mem_start = ut_check_delta(0);
26 ut_assertok(uclass_first_device_err(UCLASS_TEST, &dev));
27 mem_dev = ut_check_delta(mem_start);
28 ut_assert(mem_dev > 0);
30 /* This should increase allocated memory */
31 ptr = devm_kmalloc(dev, TEST_DEVRES_SIZE, 0);
32 ut_assert(ptr != NULL);
33 mem_kmalloc = ut_check_delta(mem_dev);
34 ut_assert(mem_kmalloc > 0);
36 /* Check that ptr is freed */
37 device_remove(dev, DM_REMOVE_NORMAL);
38 ut_asserteq(0, ut_check_delta(mem_start));
42 DM_TEST(dm_test_devres_alloc, DM_TESTF_SCAN_PDATA);
44 /* Test devm_kfree() can be used to free memory too */
45 static int dm_test_devres_free(struct unit_test_state *uts)
47 ulong mem_start, mem_dev, mem_kmalloc;
51 mem_start = ut_check_delta(0);
52 ut_assertok(uclass_first_device_err(UCLASS_TEST, &dev));
53 mem_dev = ut_check_delta(mem_start);
54 ut_assert(mem_dev > 0);
56 ptr = devm_kmalloc(dev, TEST_DEVRES_SIZE, 0);
57 ut_assert(ptr != NULL);
58 mem_kmalloc = ut_check_delta(mem_dev);
59 ut_assert(mem_kmalloc > 0);
61 /* Free the ptr and check that memory usage goes down */
63 ut_assert(ut_check_delta(mem_kmalloc) < 0);
65 device_remove(dev, DM_REMOVE_NORMAL);
66 ut_asserteq(0, ut_check_delta(mem_start));
70 DM_TEST(dm_test_devres_free, DM_TESTF_SCAN_PDATA);
73 /* Test that kzalloc() returns memory that is zeroed */
74 static int dm_test_devres_kzalloc(struct unit_test_state *uts)
80 ut_assertok(uclass_first_device_err(UCLASS_TEST, &dev));
82 ptr = devm_kzalloc(dev, TEST_DEVRES_SIZE, 0);
83 ut_assert(ptr != NULL);
84 for (val = 0, i = 0; i < TEST_DEVRES_SIZE; i++)
90 DM_TEST(dm_test_devres_kzalloc, DM_TESTF_SCAN_PDATA);
92 /* Test that devm_kmalloc_array() allocates an array that can be set */
93 static int dm_test_devres_kmalloc_array(struct unit_test_state *uts)
95 ulong mem_start, mem_dev;
99 mem_start = ut_check_delta(0);
100 ut_assertok(uclass_first_device_err(UCLASS_TEST, &dev));
101 mem_dev = ut_check_delta(mem_start);
103 ptr = devm_kmalloc_array(dev, TEST_DEVRES_COUNT, TEST_DEVRES_SIZE, 0);
104 ut_assert(ptr != NULL);
105 memset(ptr, '\xff', TEST_DEVRES_TOTAL);
106 ut_assert(ut_check_delta(mem_dev) > 0);
108 device_remove(dev, DM_REMOVE_NORMAL);
109 ut_asserteq(0, ut_check_delta(mem_start));
113 DM_TEST(dm_test_devres_kmalloc_array, DM_TESTF_SCAN_PDATA);
115 /* Test that devm_kcalloc() allocates a zeroed array */
116 static int dm_test_devres_kcalloc(struct unit_test_state *uts)
118 ulong mem_start, mem_dev;
123 mem_start = ut_check_delta(0);
124 ut_assertok(uclass_first_device_err(UCLASS_TEST, &dev));
125 mem_dev = ut_check_delta(mem_start);
126 ut_assert(mem_dev > 0);
128 /* This should increase allocated memory */
129 ptr = devm_kcalloc(dev, TEST_DEVRES_SIZE, TEST_DEVRES_COUNT, 0);
130 ut_assert(ptr != NULL);
131 ut_assert(ut_check_delta(mem_dev) > 0);
132 for (val = 0, i = 0; i < TEST_DEVRES_TOTAL; i++)
136 /* Check that ptr is freed */
137 device_remove(dev, DM_REMOVE_NORMAL);
138 ut_asserteq(0, ut_check_delta(mem_start));
142 DM_TEST(dm_test_devres_kcalloc, DM_TESTF_SCAN_PDATA);
144 /* Test devres releases resources automatically as expected */
145 static int dm_test_devres_phase(struct unit_test_state *uts)
147 struct devres_stats stats;
151 * The device is bound already, so find it and check that it has the
152 * allocation created in the bind() method.
154 ut_assertok(uclass_find_first_device(UCLASS_TEST_DEVRES, &dev));
155 devres_get_stats(dev, &stats);
156 ut_asserteq(1, stats.allocs);
157 ut_asserteq(TEST_DEVRES_SIZE, stats.total_size);
159 /* Getting platdata should add one allocation */
160 ut_assertok(device_ofdata_to_platdata(dev));
161 devres_get_stats(dev, &stats);
162 ut_asserteq(2, stats.allocs);
163 ut_asserteq(TEST_DEVRES_SIZE + TEST_DEVRES_SIZE3, stats.total_size);
165 /* Probing the device should add one allocation */
166 ut_assertok(uclass_first_device(UCLASS_TEST_DEVRES, &dev));
167 ut_assert(dev != NULL);
168 devres_get_stats(dev, &stats);
169 ut_asserteq(3, stats.allocs);
170 ut_asserteq(TEST_DEVRES_SIZE + TEST_DEVRES_SIZE2 + TEST_DEVRES_SIZE3,
173 /* Removing the device should drop both those allocations */
174 device_remove(dev, DM_REMOVE_NORMAL);
175 devres_get_stats(dev, &stats);
176 ut_asserteq(1, stats.allocs);
177 ut_asserteq(TEST_DEVRES_SIZE, stats.total_size);
179 /* Unbinding removes the other. Note this access a freed pointer */
181 devres_get_stats(dev, &stats);
182 ut_asserteq(0, stats.allocs);
183 ut_asserteq(0, stats.total_size);
187 DM_TEST(dm_test_devres_phase, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);