blob: efc5c72ae2a8a67f3e323462ed92c4c7583bf6bb [file] [log] [blame]
Simon Glass323ff9f2019-12-29 21:19:26 -07001// SPDX-License-Identifier: GPL-2.0+
2/*
3 * Tests for the devres (
4 *
5 * Copyright 2019 Google LLC
6 */
7
Simon Glass323ff9f2019-12-29 21:19:26 -07008#include <errno.h>
9#include <dm.h>
Simon Glass0f2af882020-05-10 11:40:05 -060010#include <log.h>
Simon Glass323ff9f2019-12-29 21:19:26 -070011#include <malloc.h>
12#include <dm/device-internal.h>
Simon Glassd66c5f72020-02-03 07:36:15 -070013#include <dm/devres.h>
Simon Glass323ff9f2019-12-29 21:19:26 -070014#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 */
19static 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}
Simon Glass1a92f832024-08-22 07:57:48 -060042DM_TEST(dm_test_devres_alloc, UTF_SCAN_PDATA);
Simon Glass323ff9f2019-12-29 21:19:26 -070043
44/* Test devm_kfree() can be used to free memory too */
45static 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}
Simon Glass1a92f832024-08-22 07:57:48 -060070DM_TEST(dm_test_devres_free, UTF_SCAN_PDATA);
Simon Glass323ff9f2019-12-29 21:19:26 -070071
Simon Glass323ff9f2019-12-29 21:19:26 -070072/* Test that kzalloc() returns memory that is zeroed */
73static int dm_test_devres_kzalloc(struct unit_test_state *uts)
74{
75 struct udevice *dev;
76 u8 *ptr, val;
77 int i;
78
79 ut_assertok(uclass_first_device_err(UCLASS_TEST, &dev));
80
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++)
84 val |= *ptr;
85 ut_asserteq(0, val);
86
87 return 0;
88}
Simon Glass1a92f832024-08-22 07:57:48 -060089DM_TEST(dm_test_devres_kzalloc, UTF_SCAN_PDATA);
Simon Glass323ff9f2019-12-29 21:19:26 -070090
91/* Test that devm_kmalloc_array() allocates an array that can be set */
92static int dm_test_devres_kmalloc_array(struct unit_test_state *uts)
93{
94 ulong mem_start, mem_dev;
95 struct udevice *dev;
96 u8 *ptr;
97
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);
101
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);
106
107 device_remove(dev, DM_REMOVE_NORMAL);
108 ut_asserteq(0, ut_check_delta(mem_start));
109
110 return 0;
111}
Simon Glass1a92f832024-08-22 07:57:48 -0600112DM_TEST(dm_test_devres_kmalloc_array, UTF_SCAN_PDATA);
Simon Glass323ff9f2019-12-29 21:19:26 -0700113
114/* Test that devm_kcalloc() allocates a zeroed array */
115static int dm_test_devres_kcalloc(struct unit_test_state *uts)
116{
117 ulong mem_start, mem_dev;
118 struct udevice *dev;
119 u8 *ptr, val;
120 int i;
121
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);
126
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++)
132 val |= *ptr;
133 ut_asserteq(0, val);
134
135 /* Check that ptr is freed */
136 device_remove(dev, DM_REMOVE_NORMAL);
137 ut_asserteq(0, ut_check_delta(mem_start));
138
139 return 0;
140}
Simon Glass1a92f832024-08-22 07:57:48 -0600141DM_TEST(dm_test_devres_kcalloc, UTF_SCAN_PDATA);
Simon Glass323ff9f2019-12-29 21:19:26 -0700142
Simon Glass0fe15372019-12-29 21:19:28 -0700143/* Test devres releases resources automatically as expected */
Simon Glass323ff9f2019-12-29 21:19:26 -0700144static int dm_test_devres_phase(struct unit_test_state *uts)
145{
146 struct devres_stats stats;
147 struct udevice *dev;
148
149 /*
150 * The device is bound already, so find it and check that it has the
151 * allocation created in the bind() method.
152 */
153 ut_assertok(uclass_find_first_device(UCLASS_TEST_DEVRES, &dev));
Heinrich Schuchardt6c2a8712020-07-17 00:20:14 +0200154 ut_assertnonnull(dev);
Simon Glass323ff9f2019-12-29 21:19:26 -0700155 devres_get_stats(dev, &stats);
156 ut_asserteq(1, stats.allocs);
157 ut_asserteq(TEST_DEVRES_SIZE, stats.total_size);
158
Simon Glass71fa5b42020-12-03 16:55:18 -0700159 /* Getting plat should add one allocation */
Simon Glassaad29ae2020-12-03 16:55:21 -0700160 ut_assertok(device_of_to_plat(dev));
Simon Glass0fe15372019-12-29 21:19:28 -0700161 devres_get_stats(dev, &stats);
162 ut_asserteq(2, stats.allocs);
163 ut_asserteq(TEST_DEVRES_SIZE + TEST_DEVRES_SIZE3, stats.total_size);
164
Simon Glass323ff9f2019-12-29 21:19:26 -0700165 /* Probing the device should add one allocation */
Michal Suchanekac12a2f2022-10-12 21:57:59 +0200166 ut_assertok(uclass_first_device_err(UCLASS_TEST_DEVRES, &dev));
167 ut_assertnonnull(dev);
Simon Glass323ff9f2019-12-29 21:19:26 -0700168 devres_get_stats(dev, &stats);
Simon Glass0fe15372019-12-29 21:19:28 -0700169 ut_asserteq(3, stats.allocs);
170 ut_asserteq(TEST_DEVRES_SIZE + TEST_DEVRES_SIZE2 + TEST_DEVRES_SIZE3,
171 stats.total_size);
Simon Glass323ff9f2019-12-29 21:19:26 -0700172
Simon Glass0fe15372019-12-29 21:19:28 -0700173 /* Removing the device should drop both those allocations */
Simon Glass323ff9f2019-12-29 21:19:26 -0700174 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);
178
Andrew Scull6e0abff2022-04-03 10:39:15 +0000179 /* Unbinding removes the other. */
Simon Glass323ff9f2019-12-29 21:19:26 -0700180 device_unbind(dev);
Simon Glass323ff9f2019-12-29 21:19:26 -0700181
182 return 0;
183}
Simon Glass1a92f832024-08-22 07:57:48 -0600184DM_TEST(dm_test_devres_phase, UTF_SCAN_PDATA | UTF_SCAN_FDT);