]>
Commit | Line | Data |
---|---|---|
8d6320cc SG |
1 | // SPDX-License-Identifier: GPL-2.0+ |
2 | /* | |
3 | * Tests for the devres ( | |
4 | * | |
5 | * Copyright 2019 Google LLC | |
6 | */ | |
7 | ||
8d6320cc SG |
8 | #include <errno.h> |
9 | #include <dm.h> | |
f7ae49fc | 10 | #include <log.h> |
8d6320cc SG |
11 | #include <malloc.h> |
12 | #include <dm/device-internal.h> | |
61b29b82 | 13 | #include <dm/devres.h> |
8d6320cc SG |
14 | #include <dm/test.h> |
15 | #include <dm/uclass-internal.h> | |
16 | #include <test/ut.h> | |
17 | ||
18 | /* Test that devm_kmalloc() allocates memory, free when device is removed */ | |
19 | static int dm_test_devres_alloc(struct unit_test_state *uts) | |
20 | { | |
21 | ulong mem_start, mem_dev, mem_kmalloc; | |
22 | struct udevice *dev; | |
23 | void *ptr; | |
24 | ||
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); | |
29 | ||
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); | |
35 | ||
36 | /* Check that ptr is freed */ | |
37 | device_remove(dev, DM_REMOVE_NORMAL); | |
38 | ut_asserteq(0, ut_check_delta(mem_start)); | |
39 | ||
40 | return 0; | |
41 | } | |
e180c2b1 | 42 | DM_TEST(dm_test_devres_alloc, UT_TESTF_SCAN_PDATA); |
8d6320cc SG |
43 | |
44 | /* Test devm_kfree() can be used to free memory too */ | |
45 | static int dm_test_devres_free(struct unit_test_state *uts) | |
46 | { | |
47 | ulong mem_start, mem_dev, mem_kmalloc; | |
48 | struct udevice *dev; | |
49 | void *ptr; | |
50 | ||
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); | |
55 | ||
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); | |
60 | ||
61 | /* Free the ptr and check that memory usage goes down */ | |
62 | devm_kfree(dev, ptr); | |
63 | ut_assert(ut_check_delta(mem_kmalloc) < 0); | |
64 | ||
65 | device_remove(dev, DM_REMOVE_NORMAL); | |
66 | ut_asserteq(0, ut_check_delta(mem_start)); | |
67 | ||
68 | return 0; | |
69 | } | |
e180c2b1 | 70 | DM_TEST(dm_test_devres_free, UT_TESTF_SCAN_PDATA); |
8d6320cc SG |
71 | |
72 | ||
73 | /* Test that kzalloc() returns memory that is zeroed */ | |
74 | static int dm_test_devres_kzalloc(struct unit_test_state *uts) | |
75 | { | |
76 | struct udevice *dev; | |
77 | u8 *ptr, val; | |
78 | int i; | |
79 | ||
80 | ut_assertok(uclass_first_device_err(UCLASS_TEST, &dev)); | |
81 | ||
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++) | |
85 | val |= *ptr; | |
86 | ut_asserteq(0, val); | |
87 | ||
88 | return 0; | |
89 | } | |
e180c2b1 | 90 | DM_TEST(dm_test_devres_kzalloc, UT_TESTF_SCAN_PDATA); |
8d6320cc SG |
91 | |
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) | |
94 | { | |
95 | ulong mem_start, mem_dev; | |
96 | struct udevice *dev; | |
97 | u8 *ptr; | |
98 | ||
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); | |
102 | ||
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); | |
107 | ||
108 | device_remove(dev, DM_REMOVE_NORMAL); | |
109 | ut_asserteq(0, ut_check_delta(mem_start)); | |
110 | ||
111 | return 0; | |
112 | } | |
e180c2b1 | 113 | DM_TEST(dm_test_devres_kmalloc_array, UT_TESTF_SCAN_PDATA); |
8d6320cc SG |
114 | |
115 | /* Test that devm_kcalloc() allocates a zeroed array */ | |
116 | static int dm_test_devres_kcalloc(struct unit_test_state *uts) | |
117 | { | |
118 | ulong mem_start, mem_dev; | |
119 | struct udevice *dev; | |
120 | u8 *ptr, val; | |
121 | int i; | |
122 | ||
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); | |
127 | ||
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++) | |
133 | val |= *ptr; | |
134 | ut_asserteq(0, val); | |
135 | ||
136 | /* Check that ptr is freed */ | |
137 | device_remove(dev, DM_REMOVE_NORMAL); | |
138 | ut_asserteq(0, ut_check_delta(mem_start)); | |
139 | ||
140 | return 0; | |
141 | } | |
e180c2b1 | 142 | DM_TEST(dm_test_devres_kcalloc, UT_TESTF_SCAN_PDATA); |
8d6320cc | 143 | |
42a0ce57 | 144 | /* Test devres releases resources automatically as expected */ |
8d6320cc SG |
145 | static int dm_test_devres_phase(struct unit_test_state *uts) |
146 | { | |
147 | struct devres_stats stats; | |
148 | struct udevice *dev; | |
149 | ||
150 | /* | |
151 | * The device is bound already, so find it and check that it has the | |
152 | * allocation created in the bind() method. | |
153 | */ | |
154 | ut_assertok(uclass_find_first_device(UCLASS_TEST_DEVRES, &dev)); | |
331caeaf | 155 | ut_assertnonnull(dev); |
8d6320cc SG |
156 | devres_get_stats(dev, &stats); |
157 | ut_asserteq(1, stats.allocs); | |
158 | ut_asserteq(TEST_DEVRES_SIZE, stats.total_size); | |
159 | ||
caa4daa2 | 160 | /* Getting plat should add one allocation */ |
d1998a9f | 161 | ut_assertok(device_of_to_plat(dev)); |
42a0ce57 SG |
162 | devres_get_stats(dev, &stats); |
163 | ut_asserteq(2, stats.allocs); | |
164 | ut_asserteq(TEST_DEVRES_SIZE + TEST_DEVRES_SIZE3, stats.total_size); | |
165 | ||
8d6320cc | 166 | /* Probing the device should add one allocation */ |
c726fc01 MS |
167 | ut_assertok(uclass_first_device_err(UCLASS_TEST_DEVRES, &dev)); |
168 | ut_assertnonnull(dev); | |
8d6320cc | 169 | devres_get_stats(dev, &stats); |
42a0ce57 SG |
170 | ut_asserteq(3, stats.allocs); |
171 | ut_asserteq(TEST_DEVRES_SIZE + TEST_DEVRES_SIZE2 + TEST_DEVRES_SIZE3, | |
172 | stats.total_size); | |
8d6320cc | 173 | |
42a0ce57 | 174 | /* Removing the device should drop both those allocations */ |
8d6320cc SG |
175 | device_remove(dev, DM_REMOVE_NORMAL); |
176 | devres_get_stats(dev, &stats); | |
177 | ut_asserteq(1, stats.allocs); | |
178 | ut_asserteq(TEST_DEVRES_SIZE, stats.total_size); | |
179 | ||
d69616e5 | 180 | /* Unbinding removes the other. */ |
8d6320cc | 181 | device_unbind(dev); |
8d6320cc SG |
182 | |
183 | return 0; | |
184 | } | |
e180c2b1 | 185 | DM_TEST(dm_test_devres_phase, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT); |