projects/linux·blob master · refs

443 lines · 12.0 KiB

1// SPDX-License-Identifier: GPL-2.0
2
3#include <kunit/fwnode.h>
4#include <kunit/platform_device.h>
5#include <kunit/resource.h>
6
7#include <linux/device.h>
8#include <linux/device/bus.h>
9#include <linux/fwnode.h>
10#include <linux/of_platform.h>
11#include <linux/platform_device.h>
12#include <linux/property.h>
13
14#define DEVICE_NAME "test"
15
16struct test_priv {
17 bool probe_done;
18 bool release_done;
19 wait_queue_head_t probe_wq;
20 wait_queue_head_t release_wq;
21 struct device *dev;
22};
23
24static int platform_device_devm_init(struct kunit *test)
25{
26 struct test_priv *priv;
27
28 priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
29 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv);
30 init_waitqueue_head(&priv->probe_wq);
31 init_waitqueue_head(&priv->release_wq);
32
33 test->priv = priv;
34
35 return 0;
36}
37
38static void devm_device_action(void *ptr)
39{
40 struct test_priv *priv = ptr;
41
42 priv->release_done = true;
43 wake_up_interruptible(&priv->release_wq);
44}
45
46static void devm_put_device_action(void *ptr)
47{
48 struct test_priv *priv = ptr;
49
50 put_device(priv->dev);
51 priv->release_done = true;
52 wake_up_interruptible(&priv->release_wq);
53}
54
55#define RELEASE_TIMEOUT_MS 100
56
57/*
58 * Tests that a platform bus, non-probed device will run its
59 * device-managed actions when unregistered.
60 */
61static void platform_device_devm_register_unregister_test(struct kunit *test)
62{
63 struct platform_device *pdev;
64 struct test_priv *priv = test->priv;
65 int ret;
66
67 pdev = platform_device_alloc(DEVICE_NAME, PLATFORM_DEVID_NONE);
68 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, pdev);
69
70 ret = platform_device_add(pdev);
71 KUNIT_ASSERT_EQ(test, ret, 0);
72
73 priv->dev = &pdev->dev;
74
75 ret = devm_add_action_or_reset(priv->dev, devm_device_action, priv);
76 KUNIT_ASSERT_EQ(test, ret, 0);
77
78 platform_device_unregister(pdev);
79
80 ret = wait_event_interruptible_timeout(priv->release_wq, priv->release_done,
81 msecs_to_jiffies(RELEASE_TIMEOUT_MS));
82 KUNIT_EXPECT_GT(test, ret, 0);
83}
84
85/*
86 * Tests that a platform bus, non-probed device will run its
87 * device-managed actions when unregistered, even if someone still holds
88 * a reference to it.
89 */
90static void platform_device_devm_register_get_unregister_with_devm_test(struct kunit *test)
91{
92 struct platform_device *pdev;
93 struct test_priv *priv = test->priv;
94 int ret;
95
96 pdev = platform_device_alloc(DEVICE_NAME, PLATFORM_DEVID_NONE);
97 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, pdev);
98
99 ret = platform_device_add(pdev);
100 KUNIT_ASSERT_EQ(test, ret, 0);
101
102 priv->dev = &pdev->dev;
103
104 get_device(priv->dev);
105
106 ret = devm_add_action_or_reset(priv->dev, devm_put_device_action, priv);
107 KUNIT_ASSERT_EQ(test, ret, 0);
108
109 platform_device_unregister(pdev);
110
111 ret = wait_event_interruptible_timeout(priv->release_wq, priv->release_done,
112 msecs_to_jiffies(RELEASE_TIMEOUT_MS));
113 KUNIT_EXPECT_GT(test, ret, 0);
114}
115
116static int fake_probe(struct platform_device *pdev)
117{
118 struct test_priv *priv = platform_get_drvdata(pdev);
119
120 priv->probe_done = true;
121 wake_up_interruptible(&priv->probe_wq);
122
123 return 0;
124}
125
126static struct platform_driver fake_driver = {
127 .probe = fake_probe,
128 .driver = {
129 .name = DEVICE_NAME,
130 },
131};
132
133/*
134 * Tests that a platform bus, probed device will run its device-managed
135 * actions when unregistered.
136 */
137static void probed_platform_device_devm_register_unregister_test(struct kunit *test)
138{
139 struct platform_device *pdev;
140 struct test_priv *priv = test->priv;
141 int ret;
142
143 ret = platform_driver_register(&fake_driver);
144 KUNIT_ASSERT_EQ(test, ret, 0);
145
146 pdev = platform_device_alloc(DEVICE_NAME, PLATFORM_DEVID_NONE);
147 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, pdev);
148
149 priv->dev = &pdev->dev;
150 platform_set_drvdata(pdev, priv);
151
152 ret = platform_device_add(pdev);
153 KUNIT_ASSERT_EQ(test, ret, 0);
154
155 ret = wait_event_interruptible_timeout(priv->probe_wq, priv->probe_done,
156 msecs_to_jiffies(RELEASE_TIMEOUT_MS));
157 KUNIT_ASSERT_GT(test, ret, 0);
158
159 ret = devm_add_action_or_reset(priv->dev, devm_device_action, priv);
160 KUNIT_ASSERT_EQ(test, ret, 0);
161
162 platform_device_unregister(pdev);
163
164 ret = wait_event_interruptible_timeout(priv->release_wq, priv->release_done,
165 msecs_to_jiffies(RELEASE_TIMEOUT_MS));
166 KUNIT_EXPECT_GT(test, ret, 0);
167
168 platform_driver_unregister(&fake_driver);
169}
170
171/*
172 * Tests that a platform bus, probed device will run its device-managed
173 * actions when unregistered, even if someone still holds a reference to
174 * it.
175 */
176static void probed_platform_device_devm_register_get_unregister_with_devm_test(struct kunit *test)
177{
178 struct platform_device *pdev;
179 struct test_priv *priv = test->priv;
180 int ret;
181
182 ret = platform_driver_register(&fake_driver);
183 KUNIT_ASSERT_EQ(test, ret, 0);
184
185 pdev = platform_device_alloc(DEVICE_NAME, PLATFORM_DEVID_NONE);
186 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, pdev);
187
188 priv->dev = &pdev->dev;
189 platform_set_drvdata(pdev, priv);
190
191 ret = platform_device_add(pdev);
192 KUNIT_ASSERT_EQ(test, ret, 0);
193
194 ret = wait_event_interruptible_timeout(priv->probe_wq, priv->probe_done,
195 msecs_to_jiffies(RELEASE_TIMEOUT_MS));
196 KUNIT_ASSERT_GT(test, ret, 0);
197
198 get_device(priv->dev);
199
200 ret = devm_add_action_or_reset(priv->dev, devm_put_device_action, priv);
201 KUNIT_ASSERT_EQ(test, ret, 0);
202
203 platform_device_unregister(pdev);
204
205 ret = wait_event_interruptible_timeout(priv->release_wq, priv->release_done,
206 msecs_to_jiffies(RELEASE_TIMEOUT_MS));
207 KUNIT_EXPECT_GT(test, ret, 0);
208
209 platform_driver_unregister(&fake_driver);
210}
211
212static struct kunit_case platform_device_devm_tests[] = {
213 KUNIT_CASE(platform_device_devm_register_unregister_test),
214 KUNIT_CASE(platform_device_devm_register_get_unregister_with_devm_test),
215 KUNIT_CASE(probed_platform_device_devm_register_unregister_test),
216 KUNIT_CASE(probed_platform_device_devm_register_get_unregister_with_devm_test),
217 {}
218};
219
220static struct kunit_suite platform_device_devm_test_suite = {
221 .name = "platform-device-devm",
222 .init = platform_device_devm_init,
223 .test_cases = platform_device_devm_tests,
224};
225
226static void platform_device_find_by_null_test(struct kunit *test)
227{
228 struct platform_device *pdev;
229 int ret;
230
231 pdev = kunit_platform_device_alloc(test, DEVICE_NAME, PLATFORM_DEVID_NONE);
232 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, pdev);
233
234 ret = kunit_platform_device_add(test, pdev);
235 KUNIT_ASSERT_EQ(test, ret, 0);
236
237 KUNIT_EXPECT_PTR_EQ(test, of_find_device_by_node(NULL), NULL);
238
239 KUNIT_EXPECT_PTR_EQ(test, bus_find_device_by_of_node(&platform_bus_type, NULL), NULL);
240 KUNIT_EXPECT_PTR_EQ(test, bus_find_device_by_fwnode(&platform_bus_type, NULL), NULL);
241 KUNIT_EXPECT_PTR_EQ(test, bus_find_device_by_acpi_dev(&platform_bus_type, NULL), NULL);
242
243 KUNIT_EXPECT_FALSE(test, device_match_of_node(&pdev->dev, NULL));
244 KUNIT_EXPECT_FALSE(test, device_match_fwnode(&pdev->dev, NULL));
245 KUNIT_EXPECT_FALSE(test, device_match_acpi_dev(&pdev->dev, NULL));
246 KUNIT_EXPECT_FALSE(test, device_match_acpi_handle(&pdev->dev, NULL));
247}
248
249static struct kunit_case platform_device_match_tests[] = {
250 KUNIT_CASE(platform_device_find_by_null_test),
251 {}
252};
253
254static struct kunit_suite platform_device_match_test_suite = {
255 .name = "platform-device-match",
256 .test_cases = platform_device_match_tests,
257};
258
259static int platform_device_swnode_test_probe(struct platform_device *pdev)
260{
261 return 0;
262}
263
264static struct platform_driver platform_swnode_test_driver = {
265 .probe = platform_device_swnode_test_probe,
266 .driver = {
267 .name = DEVICE_NAME,
268 },
269};
270
271static const struct software_node platform_device_test_swnode = { };
272
273/*
274 * Check that reusing a software node works correctly. If the call to
275 * platform_device_register_full() fails after adding the secondary firmware
276 * node, the software node must be unregistered in the device's release()
277 * callback or the subsequent call to platform_device_register_full() will fail
278 * with -EBUSY due to the software node already having been registered.
279 */
280static void platform_device_swnode_add_twice(struct kunit *test)
281{
282 struct platform_device_info pdevinfo;
283 struct platform_device *pdev;
284 struct fwnode_handle *fwnode;
285 bool bound = false;
286 int ret;
287
288 fwnode = kunit_kzalloc(test, sizeof(*fwnode), GFP_KERNEL);
289 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, fwnode);
290
291 ret = kunit_platform_driver_register(test, &platform_swnode_test_driver);
292 KUNIT_ASSERT_EQ(test, ret, 0);
293
294 fwnode_init(fwnode, NULL);
295 pdevinfo = (struct platform_device_info){
296 .name = DEVICE_NAME,
297 .id = PLATFORM_DEVID_NONE,
298 .fwnode = fwnode,
299 .swnode = &platform_device_test_swnode,
300 };
301
302 pdev = platform_device_register_full(&pdevinfo);
303 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, pdev);
304
305 wait_for_device_probe();
306 scoped_guard(device, &pdev->dev)
307 bound = device_is_bound(&pdev->dev);
308
309 KUNIT_ASSERT_TRUE(test, bound);
310
311 platform_device_unregister(pdev);
312
313 pdev = platform_device_register_full(&pdevinfo);
314 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, pdev);
315
316 wait_for_device_probe();
317 scoped_guard(device, &pdev->dev)
318 bound = device_is_bound(&pdev->dev);
319
320 KUNIT_ASSERT_TRUE(test, bound);
321
322 platform_device_unregister(pdev);
323}
324
325/*
326 * Check that passing a software node as the primary firmware node of the
327 * platform device does not result in it being unregistered by the call to
328 * device_remove_software_node() in its release path.
329 */
330static void platform_device_swnode_as_primary(struct kunit *test)
331{
332 struct platform_device_info pdevinfo;
333 struct platform_device *pdev;
334 struct fwnode_handle *fwnode;
335 bool bound = false;
336 int ret;
337
338 ret = kunit_platform_driver_register(test, &platform_swnode_test_driver);
339 KUNIT_ASSERT_EQ(test, ret, 0);
340
341 fwnode = kunit_software_node_register(test, &platform_device_test_swnode);
342 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, fwnode);
343
344 pdevinfo = (struct platform_device_info){
345 .name = DEVICE_NAME,
346 .id = PLATFORM_DEVID_NONE,
347 .fwnode = fwnode,
348 };
349
350 pdev = platform_device_register_full(&pdevinfo);
351 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, pdev);
352
353 wait_for_device_probe();
354 scoped_guard(device, &pdev->dev)
355 bound = device_is_bound(&pdev->dev);
356
357 KUNIT_ASSERT_TRUE(test, bound);
358
359 platform_device_unregister(pdev);
360
361 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, software_node_fwnode(&platform_device_test_swnode));
362}
363
364/*
365 * Check that passing two software nodes to platform_device_register_full()
366 * fails.
367 */
368static void platform_device_two_swnodes(struct kunit *test)
369{
370 static const struct property_entry properties[] = {
371 PROPERTY_ENTRY_U32("foo", 42),
372 { }
373 };
374
375 struct platform_device_info pdevinfo;
376 struct platform_device *pdev;
377 struct fwnode_handle *fwnode;
378 int ret;
379
380 ret = kunit_platform_driver_register(test, &platform_swnode_test_driver);
381 KUNIT_ASSERT_EQ(test, ret, 0);
382
383 fwnode = kunit_software_node_register(test, &platform_device_test_swnode);
384 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, fwnode);
385
386 pdevinfo = (struct platform_device_info){
387 .name = DEVICE_NAME,
388 .id = PLATFORM_DEVID_NONE,
389 .fwnode = fwnode,
390 .swnode = &platform_device_test_swnode,
391 };
392
393 pdev = platform_device_register_full(&pdevinfo);
394 KUNIT_ASSERT_TRUE(test, IS_ERR(pdev));
395 KUNIT_ASSERT_EQ_MSG(test, PTR_ERR(pdev), -EINVAL,
396 "Expected errno == -EINVAL, got: %pe", pdev);
397
398 pdevinfo = (struct platform_device_info){
399 .name = DEVICE_NAME,
400 .id = PLATFORM_DEVID_NONE,
401 .swnode = &platform_device_test_swnode,
402 .properties = properties,
403 };
404
405 pdev = platform_device_register_full(&pdevinfo);
406 KUNIT_ASSERT_TRUE(test, IS_ERR(pdev));
407 KUNIT_ASSERT_EQ_MSG(test, PTR_ERR(pdev), -EINVAL,
408 "Expected errno == -EINVAL, got: %pe", pdev);
409
410 pdevinfo = (struct platform_device_info){
411 .name = DEVICE_NAME,
412 .id = PLATFORM_DEVID_NONE,
413 .fwnode = fwnode,
414 .properties = properties,
415 };
416
417 pdev = platform_device_register_full(&pdevinfo);
418 KUNIT_ASSERT_TRUE(test, IS_ERR(pdev));
419 KUNIT_ASSERT_EQ_MSG(test, PTR_ERR(pdev), -EINVAL,
420 "Expected errno == -EINVAL, got: %pe", pdev);
421}
422
423static struct kunit_case platform_device_swnode_tests[] = {
424 KUNIT_CASE(platform_device_swnode_add_twice),
425 KUNIT_CASE(platform_device_swnode_as_primary),
426 KUNIT_CASE(platform_device_two_swnodes),
427 {}
428};
429
430static struct kunit_suite platform_device_swnode_test_suite = {
431 .name = "platform-device-swnode",
432 .test_cases = platform_device_swnode_tests,
433};
434
435kunit_test_suites(
436 &platform_device_devm_test_suite,
437 &platform_device_match_test_suite,
438 &platform_device_swnode_test_suite,
439);
440
441MODULE_DESCRIPTION("Test module for platform devices");
442MODULE_AUTHOR("Maxime Ripard <[email protected]>");
443MODULE_LICENSE("GPL");