Linux kernel mirror (for testing)
git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel
os
linux
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
13static 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. */
31static 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
65static 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
86static 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
126static 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 */
209static 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
232static 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
242static struct kunit_suite pm_runtime_test_suite = {
243 .name = "pm_runtime_test_cases",
244 .test_cases = pm_runtime_test_cases,
245};
246
247kunit_test_suite(pm_runtime_test_suite);
248MODULE_DESCRIPTION("Runtime power management unit test suite");
249MODULE_LICENSE("GPL");