1 // SPDX-License-Identifier: GPL-2.0+
3 * Tests for the devres (
5 * Copyright 2019 Google LLC
13 #include <dm/device-internal.h>
14 #include <dm/devres.h>
16 #include <dm/uclass-internal.h>
19 /* Test that devm_kmalloc() allocates memory, free when device is removed */
20 static int dm_test_devres_alloc(struct unit_test_state *uts)
22 ulong mem_start, mem_dev, mem_kmalloc;
26 mem_start = ut_check_delta(0);
27 ut_assertok(uclass_first_device_err(UCLASS_TEST, &dev));
28 mem_dev = ut_check_delta(mem_start);
29 ut_assert(mem_dev > 0);
31 /* This should increase allocated memory */
32 ptr = devm_kmalloc(dev, TEST_DEVRES_SIZE, 0);
33 ut_assert(ptr != NULL);
34 mem_kmalloc = ut_check_delta(mem_dev);
35 ut_assert(mem_kmalloc > 0);
37 /* Check that ptr is freed */
38 device_remove(dev, DM_REMOVE_NORMAL);
39 ut_asserteq(0, ut_check_delta(mem_start));
43 DM_TEST(dm_test_devres_alloc, UT_TESTF_SCAN_PDATA);
45 /* Test devm_kfree() can be used to free memory too */
46 static int dm_test_devres_free(struct unit_test_state *uts)
48 ulong mem_start, mem_dev, mem_kmalloc;
52 mem_start = ut_check_delta(0);
53 ut_assertok(uclass_first_device_err(UCLASS_TEST, &dev));
54 mem_dev = ut_check_delta(mem_start);
55 ut_assert(mem_dev > 0);
57 ptr = devm_kmalloc(dev, TEST_DEVRES_SIZE, 0);
58 ut_assert(ptr != NULL);
59 mem_kmalloc = ut_check_delta(mem_dev);
60 ut_assert(mem_kmalloc > 0);
62 /* Free the ptr and check that memory usage goes down */
64 ut_assert(ut_check_delta(mem_kmalloc) < 0);
66 device_remove(dev, DM_REMOVE_NORMAL);
67 ut_asserteq(0, ut_check_delta(mem_start));
71 DM_TEST(dm_test_devres_free, UT_TESTF_SCAN_PDATA);
74 /* Test that kzalloc() returns memory that is zeroed */
75 static int dm_test_devres_kzalloc(struct unit_test_state *uts)
81 ut_assertok(uclass_first_device_err(UCLASS_TEST, &dev));
83 ptr = devm_kzalloc(dev, TEST_DEVRES_SIZE, 0);
84 ut_assert(ptr != NULL);
85 for (val = 0, i = 0; i < TEST_DEVRES_SIZE; i++)
91 DM_TEST(dm_test_devres_kzalloc, UT_TESTF_SCAN_PDATA);
93 /* Test that devm_kmalloc_array() allocates an array that can be set */
94 static int dm_test_devres_kmalloc_array(struct unit_test_state *uts)
96 ulong mem_start, mem_dev;
100 mem_start = ut_check_delta(0);
101 ut_assertok(uclass_first_device_err(UCLASS_TEST, &dev));
102 mem_dev = ut_check_delta(mem_start);
104 ptr = devm_kmalloc_array(dev, TEST_DEVRES_COUNT, TEST_DEVRES_SIZE, 0);
105 ut_assert(ptr != NULL);
106 memset(ptr, '\xff', TEST_DEVRES_TOTAL);
107 ut_assert(ut_check_delta(mem_dev) > 0);
109 device_remove(dev, DM_REMOVE_NORMAL);
110 ut_asserteq(0, ut_check_delta(mem_start));
114 DM_TEST(dm_test_devres_kmalloc_array, UT_TESTF_SCAN_PDATA);
116 /* Test that devm_kcalloc() allocates a zeroed array */
117 static int dm_test_devres_kcalloc(struct unit_test_state *uts)
119 ulong mem_start, mem_dev;
124 mem_start = ut_check_delta(0);
125 ut_assertok(uclass_first_device_err(UCLASS_TEST, &dev));
126 mem_dev = ut_check_delta(mem_start);
127 ut_assert(mem_dev > 0);
129 /* This should increase allocated memory */
130 ptr = devm_kcalloc(dev, TEST_DEVRES_SIZE, TEST_DEVRES_COUNT, 0);
131 ut_assert(ptr != NULL);
132 ut_assert(ut_check_delta(mem_dev) > 0);
133 for (val = 0, i = 0; i < TEST_DEVRES_TOTAL; i++)
137 /* Check that ptr is freed */
138 device_remove(dev, DM_REMOVE_NORMAL);
139 ut_asserteq(0, ut_check_delta(mem_start));
143 DM_TEST(dm_test_devres_kcalloc, UT_TESTF_SCAN_PDATA);
145 /* Test devres releases resources automatically as expected */
146 static int dm_test_devres_phase(struct unit_test_state *uts)
148 struct devres_stats stats;
152 * The device is bound already, so find it and check that it has the
153 * allocation created in the bind() method.
155 ut_assertok(uclass_find_first_device(UCLASS_TEST_DEVRES, &dev));
156 ut_assertnonnull(dev);
157 devres_get_stats(dev, &stats);
158 ut_asserteq(1, stats.allocs);
159 ut_asserteq(TEST_DEVRES_SIZE, stats.total_size);
161 /* Getting plat should add one allocation */
162 ut_assertok(device_ofdata_to_platdata(dev));
163 devres_get_stats(dev, &stats);
164 ut_asserteq(2, stats.allocs);
165 ut_asserteq(TEST_DEVRES_SIZE + TEST_DEVRES_SIZE3, stats.total_size);
167 /* Probing the device should add one allocation */
168 ut_assertok(uclass_first_device(UCLASS_TEST_DEVRES, &dev));
169 ut_assert(dev != NULL);
170 devres_get_stats(dev, &stats);
171 ut_asserteq(3, stats.allocs);
172 ut_asserteq(TEST_DEVRES_SIZE + TEST_DEVRES_SIZE2 + TEST_DEVRES_SIZE3,
175 /* Removing the device should drop both those allocations */
176 device_remove(dev, DM_REMOVE_NORMAL);
177 devres_get_stats(dev, &stats);
178 ut_asserteq(1, stats.allocs);
179 ut_asserteq(TEST_DEVRES_SIZE, stats.total_size);
181 /* Unbinding removes the other. Note this access a freed pointer */
183 devres_get_stats(dev, &stats);
184 ut_asserteq(0, stats.allocs);
185 ut_asserteq(0, stats.total_size);
189 DM_TEST(dm_test_devres_phase, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);