1 // SPDX-License-Identifier: GPL-2.0+
3 * Tests for the devres (
5 * Copyright 2019 Google LLC
12 #include <dm/device-internal.h>
14 #include <dm/uclass-internal.h>
17 /* Test that devm_kmalloc() allocates memory, free when device is removed */
18 static int dm_test_devres_alloc(struct unit_test_state *uts)
20 ulong mem_start, mem_dev, mem_kmalloc;
24 mem_start = ut_check_delta(0);
25 ut_assertok(uclass_first_device_err(UCLASS_TEST, &dev));
26 mem_dev = ut_check_delta(mem_start);
27 ut_assert(mem_dev > 0);
29 /* This should increase allocated memory */
30 ptr = devm_kmalloc(dev, TEST_DEVRES_SIZE, 0);
31 ut_assert(ptr != NULL);
32 mem_kmalloc = ut_check_delta(mem_dev);
33 ut_assert(mem_kmalloc > 0);
35 /* Check that ptr is freed */
36 device_remove(dev, DM_REMOVE_NORMAL);
37 ut_asserteq(0, ut_check_delta(mem_start));
41 DM_TEST(dm_test_devres_alloc, DM_TESTF_SCAN_PDATA);
43 /* Test devm_kfree() can be used to free memory too */
44 static int dm_test_devres_free(struct unit_test_state *uts)
46 ulong mem_start, mem_dev, mem_kmalloc;
50 mem_start = ut_check_delta(0);
51 ut_assertok(uclass_first_device_err(UCLASS_TEST, &dev));
52 mem_dev = ut_check_delta(mem_start);
53 ut_assert(mem_dev > 0);
55 ptr = devm_kmalloc(dev, TEST_DEVRES_SIZE, 0);
56 ut_assert(ptr != NULL);
57 mem_kmalloc = ut_check_delta(mem_dev);
58 ut_assert(mem_kmalloc > 0);
60 /* Free the ptr and check that memory usage goes down */
62 ut_assert(ut_check_delta(mem_kmalloc) < 0);
64 device_remove(dev, DM_REMOVE_NORMAL);
65 ut_asserteq(0, ut_check_delta(mem_start));
69 DM_TEST(dm_test_devres_free, DM_TESTF_SCAN_PDATA);
72 /* Test that kzalloc() returns memory that is zeroed */
73 static int dm_test_devres_kzalloc(struct unit_test_state *uts)
79 ut_assertok(uclass_first_device_err(UCLASS_TEST, &dev));
81 ptr = devm_kzalloc(dev, TEST_DEVRES_SIZE, 0);
82 ut_assert(ptr != NULL);
83 for (val = 0, i = 0; i < TEST_DEVRES_SIZE; i++)
89 DM_TEST(dm_test_devres_kzalloc, DM_TESTF_SCAN_PDATA);
91 /* Test that devm_kmalloc_array() allocates an array that can be set */
92 static int dm_test_devres_kmalloc_array(struct unit_test_state *uts)
94 ulong mem_start, mem_dev;
98 mem_start = ut_check_delta(0);
99 ut_assertok(uclass_first_device_err(UCLASS_TEST, &dev));
100 mem_dev = ut_check_delta(mem_start);
102 ptr = devm_kmalloc_array(dev, TEST_DEVRES_COUNT, TEST_DEVRES_SIZE, 0);
103 ut_assert(ptr != NULL);
104 memset(ptr, '\xff', TEST_DEVRES_TOTAL);
105 ut_assert(ut_check_delta(mem_dev) > 0);
107 device_remove(dev, DM_REMOVE_NORMAL);
108 ut_asserteq(0, ut_check_delta(mem_start));
112 DM_TEST(dm_test_devres_kmalloc_array, DM_TESTF_SCAN_PDATA);
114 /* Test that devm_kcalloc() allocates a zeroed array */
115 static int dm_test_devres_kcalloc(struct unit_test_state *uts)
117 ulong mem_start, mem_dev;
122 mem_start = ut_check_delta(0);
123 ut_assertok(uclass_first_device_err(UCLASS_TEST, &dev));
124 mem_dev = ut_check_delta(mem_start);
125 ut_assert(mem_dev > 0);
127 /* This should increase allocated memory */
128 ptr = devm_kcalloc(dev, TEST_DEVRES_SIZE, TEST_DEVRES_COUNT, 0);
129 ut_assert(ptr != NULL);
130 ut_assert(ut_check_delta(mem_dev) > 0);
131 for (val = 0, i = 0; i < TEST_DEVRES_TOTAL; i++)
135 /* Check that ptr is freed */
136 device_remove(dev, DM_REMOVE_NORMAL);
137 ut_asserteq(0, ut_check_delta(mem_start));
141 DM_TEST(dm_test_devres_kcalloc, DM_TESTF_SCAN_PDATA);
143 static int dm_test_devres_phase(struct unit_test_state *uts)
145 struct devres_stats stats;
149 * The device is bound already, so find it and check that it has the
150 * allocation created in the bind() method.
152 ut_assertok(uclass_find_first_device(UCLASS_TEST_DEVRES, &dev));
153 devres_get_stats(dev, &stats);
154 ut_asserteq(1, stats.allocs);
155 ut_asserteq(TEST_DEVRES_SIZE, stats.total_size);
157 /* Probing the device should add one allocation */
158 ut_assertok(uclass_first_device(UCLASS_TEST_DEVRES, &dev));
159 ut_assert(dev != NULL);
160 devres_get_stats(dev, &stats);
161 ut_asserteq(2, stats.allocs);
162 ut_asserteq(TEST_DEVRES_SIZE + TEST_DEVRES_SIZE2, stats.total_size);
164 /* Removing the device should drop one allocation */
165 device_remove(dev, DM_REMOVE_NORMAL);
166 devres_get_stats(dev, &stats);
167 ut_asserteq(1, stats.allocs);
168 ut_asserteq(TEST_DEVRES_SIZE, stats.total_size);
170 /* Unbinding removes the other. Note this access a freed pointer */
172 devres_get_stats(dev, &stats);
173 ut_asserteq(0, stats.allocs);
174 ut_asserteq(0, stats.total_size);
178 DM_TEST(dm_test_devres_phase, DM_TESTF_SCAN_PDATA | DM_TESTF_SCAN_FDT);