Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
torvalds
GitHub Repository: torvalds/linux
Path: blob/master/drivers/base/power/runtime-test.c
49129 views
1
// SPDX-License-Identifier: GPL-2.0
2
/*
3
* Copyright 2025 Google, Inc.
4
*/
5
6
#include <linux/cleanup.h>
7
#include <linux/pm_runtime.h>
8
#include <kunit/device.h>
9
#include <kunit/test.h>
10
11
#define DEVICE_NAME "pm_runtime_test_device"
12
13
static void pm_runtime_depth_test(struct kunit *test)
14
{
15
struct device *dev = kunit_device_register(test, DEVICE_NAME);
16
17
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
18
19
pm_runtime_enable(dev);
20
21
KUNIT_EXPECT_TRUE(test, pm_runtime_suspended(dev));
22
KUNIT_EXPECT_EQ(test, 0, pm_runtime_get_sync(dev));
23
KUNIT_EXPECT_TRUE(test, pm_runtime_active(dev));
24
KUNIT_EXPECT_EQ(test, 1, pm_runtime_get_sync(dev)); /* "already active" */
25
KUNIT_EXPECT_EQ(test, 0, pm_runtime_put_sync(dev));
26
KUNIT_EXPECT_EQ(test, 0, pm_runtime_put_sync(dev));
27
KUNIT_EXPECT_TRUE(test, pm_runtime_suspended(dev));
28
}
29
30
/* Test pm_runtime_put() and friends when already suspended. */
31
static void pm_runtime_already_suspended_test(struct kunit *test)
32
{
33
struct device *dev = kunit_device_register(test, DEVICE_NAME);
34
35
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
36
37
pm_runtime_enable(dev);
38
KUNIT_EXPECT_TRUE(test, pm_runtime_suspended(dev));
39
40
pm_runtime_get_noresume(dev);
41
KUNIT_EXPECT_EQ(test, 1, pm_runtime_put_sync(dev));
42
43
KUNIT_EXPECT_EQ(test, 1, pm_runtime_suspend(dev));
44
KUNIT_EXPECT_EQ(test, 1, pm_runtime_autosuspend(dev));
45
KUNIT_EXPECT_EQ(test, 1, pm_request_autosuspend(dev));
46
47
pm_runtime_get_noresume(dev);
48
KUNIT_EXPECT_EQ(test, 1, pm_runtime_put_sync_autosuspend(dev));
49
50
pm_runtime_get_noresume(dev);
51
pm_runtime_put_autosuspend(dev);
52
53
/* Grab 2 refcounts */
54
pm_runtime_get_noresume(dev);
55
pm_runtime_get_noresume(dev);
56
/* The first put() sees usage_count 1 */
57
KUNIT_EXPECT_EQ(test, 0, pm_runtime_put_sync_autosuspend(dev));
58
/* The second put() sees usage_count 0 but tells us "already suspended". */
59
KUNIT_EXPECT_EQ(test, 1, pm_runtime_put_sync_autosuspend(dev));
60
61
/* Should have remained suspended the whole time. */
62
KUNIT_EXPECT_TRUE(test, pm_runtime_suspended(dev));
63
}
64
65
static void pm_runtime_idle_test(struct kunit *test)
66
{
67
struct device *dev = kunit_device_register(test, DEVICE_NAME);
68
69
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
70
71
pm_runtime_enable(dev);
72
73
KUNIT_EXPECT_TRUE(test, pm_runtime_suspended(dev));
74
KUNIT_EXPECT_EQ(test, 0, pm_runtime_get_sync(dev));
75
KUNIT_EXPECT_TRUE(test, pm_runtime_active(dev));
76
KUNIT_EXPECT_EQ(test, -EAGAIN, pm_runtime_idle(dev));
77
KUNIT_EXPECT_TRUE(test, pm_runtime_active(dev));
78
pm_runtime_put_noidle(dev);
79
KUNIT_EXPECT_TRUE(test, pm_runtime_active(dev));
80
KUNIT_EXPECT_EQ(test, 0, pm_runtime_idle(dev));
81
KUNIT_EXPECT_TRUE(test, pm_runtime_suspended(dev));
82
KUNIT_EXPECT_EQ(test, -EAGAIN, pm_runtime_idle(dev));
83
KUNIT_EXPECT_EQ(test, -EAGAIN, pm_request_idle(dev));
84
}
85
86
static void pm_runtime_disabled_test(struct kunit *test)
87
{
88
struct device *dev = kunit_device_register(test, DEVICE_NAME);
89
90
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
91
92
/* Never called pm_runtime_enable() */
93
KUNIT_EXPECT_FALSE(test, pm_runtime_enabled(dev));
94
95
/* "disabled" is treated as "active" */
96
KUNIT_EXPECT_TRUE(test, pm_runtime_active(dev));
97
KUNIT_EXPECT_FALSE(test, pm_runtime_suspended(dev));
98
99
/*
100
* Note: these "fail", but they still acquire/release refcounts, so
101
* keep them balanced.
102
*/
103
KUNIT_EXPECT_EQ(test, -EACCES, pm_runtime_get(dev));
104
pm_runtime_put(dev);
105
106
KUNIT_EXPECT_EQ(test, -EACCES, pm_runtime_get_sync(dev));
107
KUNIT_EXPECT_EQ(test, -EACCES, pm_runtime_put_sync(dev));
108
109
KUNIT_EXPECT_EQ(test, -EACCES, pm_runtime_get(dev));
110
pm_runtime_put_autosuspend(dev);
111
112
KUNIT_EXPECT_EQ(test, -EACCES, pm_runtime_resume_and_get(dev));
113
KUNIT_EXPECT_EQ(test, -EACCES, pm_runtime_idle(dev));
114
KUNIT_EXPECT_EQ(test, -EACCES, pm_request_idle(dev));
115
KUNIT_EXPECT_EQ(test, -EACCES, pm_request_resume(dev));
116
KUNIT_EXPECT_EQ(test, -EACCES, pm_request_autosuspend(dev));
117
KUNIT_EXPECT_EQ(test, -EACCES, pm_runtime_suspend(dev));
118
KUNIT_EXPECT_EQ(test, -EACCES, pm_runtime_resume(dev));
119
KUNIT_EXPECT_EQ(test, -EACCES, pm_runtime_autosuspend(dev));
120
121
/* Still disabled */
122
KUNIT_EXPECT_TRUE(test, pm_runtime_active(dev));
123
KUNIT_EXPECT_FALSE(test, pm_runtime_enabled(dev));
124
}
125
126
static void pm_runtime_error_test(struct kunit *test)
127
{
128
struct device *dev = kunit_device_register(test, DEVICE_NAME);
129
130
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
131
132
pm_runtime_enable(dev);
133
KUNIT_EXPECT_TRUE(test, pm_runtime_suspended(dev));
134
135
/* Fake a .runtime_resume() error */
136
dev->power.runtime_error = -EIO;
137
138
/*
139
* Note: these "fail", but they still acquire/release refcounts, so
140
* keep them balanced.
141
*/
142
KUNIT_EXPECT_EQ(test, -EINVAL, pm_runtime_get(dev));
143
pm_runtime_put(dev);
144
145
KUNIT_EXPECT_EQ(test, -EINVAL, pm_runtime_get_sync(dev));
146
KUNIT_EXPECT_EQ(test, -EINVAL, pm_runtime_put_sync(dev));
147
148
KUNIT_EXPECT_EQ(test, -EINVAL, pm_runtime_get(dev));
149
pm_runtime_put_autosuspend(dev);
150
151
KUNIT_EXPECT_EQ(test, -EINVAL, pm_runtime_get(dev));
152
KUNIT_EXPECT_EQ(test, -EINVAL, pm_runtime_put_sync_autosuspend(dev));
153
154
KUNIT_EXPECT_EQ(test, -EINVAL, pm_runtime_resume_and_get(dev));
155
KUNIT_EXPECT_EQ(test, -EINVAL, pm_runtime_idle(dev));
156
KUNIT_EXPECT_EQ(test, -EINVAL, pm_request_idle(dev));
157
KUNIT_EXPECT_EQ(test, -EINVAL, pm_request_resume(dev));
158
KUNIT_EXPECT_EQ(test, -EINVAL, pm_request_autosuspend(dev));
159
KUNIT_EXPECT_EQ(test, -EINVAL, pm_runtime_suspend(dev));
160
KUNIT_EXPECT_EQ(test, -EINVAL, pm_runtime_resume(dev));
161
KUNIT_EXPECT_EQ(test, -EINVAL, pm_runtime_autosuspend(dev));
162
163
/* Error is still pending */
164
KUNIT_EXPECT_TRUE(test, pm_runtime_suspended(dev));
165
KUNIT_EXPECT_EQ(test, -EIO, dev->power.runtime_error);
166
/* Clear error */
167
KUNIT_EXPECT_EQ(test, 0, pm_runtime_set_suspended(dev));
168
KUNIT_EXPECT_EQ(test, 0, dev->power.runtime_error);
169
/* Still suspended */
170
KUNIT_EXPECT_TRUE(test, pm_runtime_suspended(dev));
171
172
KUNIT_EXPECT_EQ(test, 0, pm_runtime_get(dev));
173
pm_runtime_barrier(dev);
174
pm_runtime_put(dev);
175
pm_runtime_suspend(dev); /* flush the put(), to suspend */
176
KUNIT_EXPECT_TRUE(test, pm_runtime_suspended(dev));
177
178
KUNIT_EXPECT_EQ(test, 0, pm_runtime_get_sync(dev));
179
KUNIT_EXPECT_EQ(test, 0, pm_runtime_put_sync(dev));
180
181
KUNIT_EXPECT_EQ(test, 0, pm_runtime_get_sync(dev));
182
pm_runtime_put_autosuspend(dev);
183
184
KUNIT_EXPECT_EQ(test, 0, pm_runtime_resume_and_get(dev));
185
186
/*
187
* The following should all return -EAGAIN (usage is non-zero) or 1
188
* (already resumed).
189
*/
190
KUNIT_EXPECT_EQ(test, -EAGAIN, pm_runtime_idle(dev));
191
KUNIT_EXPECT_EQ(test, -EAGAIN, pm_request_idle(dev));
192
KUNIT_EXPECT_EQ(test, 1, pm_request_resume(dev));
193
KUNIT_EXPECT_EQ(test, -EAGAIN, pm_request_autosuspend(dev));
194
KUNIT_EXPECT_EQ(test, -EAGAIN, pm_runtime_suspend(dev));
195
KUNIT_EXPECT_EQ(test, 1, pm_runtime_resume(dev));
196
KUNIT_EXPECT_EQ(test, -EAGAIN, pm_runtime_autosuspend(dev));
197
198
KUNIT_EXPECT_EQ(test, 0, pm_runtime_put_sync(dev));
199
200
/* Suspended again */
201
KUNIT_EXPECT_TRUE(test, pm_runtime_suspended(dev));
202
}
203
204
/*
205
* Explore a typical probe() sequence in which a device marks itself powered,
206
* but doesn't hold any runtime PM reference, so it suspends as soon as it goes
207
* idle.
208
*/
209
static void pm_runtime_probe_active_test(struct kunit *test)
210
{
211
struct device *dev = kunit_device_register(test, DEVICE_NAME);
212
213
KUNIT_ASSERT_NOT_ERR_OR_NULL(test, dev);
214
215
KUNIT_EXPECT_TRUE(test, pm_runtime_status_suspended(dev));
216
217
KUNIT_EXPECT_EQ(test, 0, pm_runtime_set_active(dev));
218
KUNIT_EXPECT_TRUE(test, pm_runtime_active(dev));
219
220
pm_runtime_enable(dev);
221
KUNIT_EXPECT_TRUE(test, pm_runtime_active(dev));
222
223
/* Nothing to flush. We stay active. */
224
pm_runtime_barrier(dev);
225
KUNIT_EXPECT_TRUE(test, pm_runtime_active(dev));
226
227
/* Ask for idle? Now we suspend. */
228
KUNIT_EXPECT_EQ(test, 0, pm_runtime_idle(dev));
229
KUNIT_EXPECT_TRUE(test, pm_runtime_suspended(dev));
230
}
231
232
static struct kunit_case pm_runtime_test_cases[] = {
233
KUNIT_CASE(pm_runtime_depth_test),
234
KUNIT_CASE(pm_runtime_already_suspended_test),
235
KUNIT_CASE(pm_runtime_idle_test),
236
KUNIT_CASE(pm_runtime_disabled_test),
237
KUNIT_CASE(pm_runtime_error_test),
238
KUNIT_CASE(pm_runtime_probe_active_test),
239
{}
240
};
241
242
static struct kunit_suite pm_runtime_test_suite = {
243
.name = "pm_runtime_test_cases",
244
.test_cases = pm_runtime_test_cases,
245
};
246
247
kunit_test_suite(pm_runtime_test_suite);
248
MODULE_DESCRIPTION("Runtime power management unit test suite");
249
MODULE_LICENSE("GPL");
250
251