blob: 95a470b9f1c128a94b4cae0fdd54175d78c67cc1 [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 Glass974dccd2020-07-28 19:41:12 -060042DM_TEST(dm_test_devres_alloc, UT_TESTF_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 Glass974dccd2020-07-28 19:41:12 -060070DM_TEST(dm_test_devres_free, UT_TESTF_SCAN_PDATA);
Simon Glass323ff9f2019-12-29 21:19:26 -070071
72
73/* Test that kzalloc() returns memory that is zeroed */
74static 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}
Simon Glass974dccd2020-07-28 19:41:12 -060090DM_TEST(dm_test_devres_kzalloc, UT_TESTF_SCAN_PDATA);
Simon Glass323ff9f2019-12-29 21:19:26 -070091
92/* Test that devm_kmalloc_array() allocates an array that can be set */
93static 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}
Simon Glass974dccd2020-07-28 19:41:12 -0600113DM_TEST(dm_test_devres_kmalloc_array, UT_TESTF_SCAN_PDATA);
Simon Glass323ff9f2019-12-29 21:19:26 -0700114
115/* Test that devm_kcalloc() allocates a zeroed array */
116static 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}
Simon Glass974dccd2020-07-28 19:41:12 -0600142DM_TEST(dm_test_devres_kcalloc, UT_TESTF_SCAN_PDATA);
Simon Glass323ff9f2019-12-29 21:19:26 -0700143
Simon Glass0fe15372019-12-29 21:19:28 -0700144/* Test devres releases resources automatically as expected */
Simon Glass323ff9f2019-12-29 21:19:26 -0700145static 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));
Heinrich Schuchardt6c2a8712020-07-17 00:20:14 +0200155 ut_assertnonnull(dev);
Simon Glass323ff9f2019-12-29 21:19:26 -0700156 devres_get_stats(dev, &stats);
157 ut_asserteq(1, stats.allocs);
158 ut_asserteq(TEST_DEVRES_SIZE, stats.total_size);
159
Simon Glass71fa5b42020-12-03 16:55:18 -0700160 /* Getting plat should add one allocation */
Simon Glassaad29ae2020-12-03 16:55:21 -0700161 ut_assertok(device_of_to_plat(dev));
Simon Glass0fe15372019-12-29 21:19:28 -0700162 devres_get_stats(dev, &stats);
163 ut_asserteq(2, stats.allocs);
164 ut_asserteq(TEST_DEVRES_SIZE + TEST_DEVRES_SIZE3, stats.total_size);
165
Simon Glass323ff9f2019-12-29 21:19:26 -0700166 /* Probing the device should add one allocation */
Michal Suchanekac12a2f2022-10-12 21:57:59 +0200167 ut_assertok(uclass_first_device_err(UCLASS_TEST_DEVRES, &dev));
168 ut_assertnonnull(dev);
Simon Glass323ff9f2019-12-29 21:19:26 -0700169 devres_get_stats(dev, &stats);
Simon Glass0fe15372019-12-29 21:19:28 -0700170 ut_asserteq(3, stats.allocs);
171 ut_asserteq(TEST_DEVRES_SIZE + TEST_DEVRES_SIZE2 + TEST_DEVRES_SIZE3,
172 stats.total_size);
Simon Glass323ff9f2019-12-29 21:19:26 -0700173
Simon Glass0fe15372019-12-29 21:19:28 -0700174 /* Removing the device should drop both those allocations */
Simon Glass323ff9f2019-12-29 21:19:26 -0700175 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
Andrew Scull6e0abff2022-04-03 10:39:15 +0000180 /* Unbinding removes the other. */
Simon Glass323ff9f2019-12-29 21:19:26 -0700181 device_unbind(dev);
Simon Glass323ff9f2019-12-29 21:19:26 -0700182
183 return 0;
184}
Simon Glass974dccd2020-07-28 19:41:12 -0600185DM_TEST(dm_test_devres_phase, UT_TESTF_SCAN_PDATA | UT_TESTF_SCAN_FDT);