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