Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/base/test/root-device-test.c
26428 views
1
// SPDX-License-Identifier: GPL-2.0
2
// Copyright 2023 Maxime Ripard <[email protected]>
3
4
#include <kunit/resource.h>
5
6
#include <linux/device.h>
7
8
#define DEVICE_NAME "test"
9
10
struct test_priv {
11
bool probe_done;
12
bool release_done;
13
wait_queue_head_t release_wq;
14
struct device *dev;
15
};
16
17
static int root_device_devm_init(struct kunit *test)
18
{
19
struct test_priv *priv;
20
21
priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
22
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv);
23
init_waitqueue_head(&priv->release_wq);
24
25
test->priv = priv;
26
27
return 0;
28
}
29
30
static void devm_device_action(void *ptr)
31
{
32
struct test_priv *priv = ptr;
33
34
priv->release_done = true;
35
wake_up_interruptible(&priv->release_wq);
36
}
37
38
#define RELEASE_TIMEOUT_MS 100
39
40
/*
41
* Tests that a bus-less, non-probed device will run its device-managed
42
* actions when unregistered.
43
*/
44
static void root_device_devm_register_unregister_test(struct kunit *test)
45
{
46
struct test_priv *priv = test->priv;
47
int ret;
48
49
priv->dev = root_device_register(DEVICE_NAME);
50
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->dev);
51
52
ret = devm_add_action_or_reset(priv->dev, devm_device_action, priv);
53
KUNIT_ASSERT_EQ(test, ret, 0);
54
55
root_device_unregister(priv->dev);
56
57
ret = wait_event_interruptible_timeout(priv->release_wq, priv->release_done,
58
msecs_to_jiffies(RELEASE_TIMEOUT_MS));
59
KUNIT_EXPECT_GT(test, ret, 0);
60
}
61
62
static void devm_put_device_action(void *ptr)
63
{
64
struct test_priv *priv = ptr;
65
66
put_device(priv->dev);
67
priv->release_done = true;
68
wake_up_interruptible(&priv->release_wq);
69
}
70
71
/*
72
* Tests that a bus-less, non-probed device will run its device-managed
73
* actions when unregistered, even if someone still holds a reference to
74
* it.
75
*/
76
static void root_device_devm_register_get_unregister_with_devm_test(struct kunit *test)
77
{
78
struct test_priv *priv = test->priv;
79
int ret;
80
81
priv->dev = root_device_register(DEVICE_NAME);
82
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->dev);
83
84
get_device(priv->dev);
85
86
ret = devm_add_action_or_reset(priv->dev, devm_put_device_action, priv);
87
KUNIT_ASSERT_EQ(test, ret, 0);
88
89
root_device_unregister(priv->dev);
90
91
ret = wait_event_interruptible_timeout(priv->release_wq, priv->release_done,
92
msecs_to_jiffies(RELEASE_TIMEOUT_MS));
93
KUNIT_EXPECT_GT(test, ret, 0);
94
}
95
96
static struct kunit_case root_device_devm_tests[] = {
97
KUNIT_CASE(root_device_devm_register_unregister_test),
98
KUNIT_CASE(root_device_devm_register_get_unregister_with_devm_test),
99
{}
100
};
101
102
static struct kunit_suite root_device_devm_test_suite = {
103
.name = "root-device-devm",
104
.init = root_device_devm_init,
105
.test_cases = root_device_devm_tests,
106
};
107
108
kunit_test_suite(root_device_devm_test_suite);
109
110
MODULE_DESCRIPTION("Test module for root devices");
111
MODULE_AUTHOR("Maxime Ripard <[email protected]>");
112
MODULE_LICENSE("GPL");
113
114