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