xref: /linux/drivers/base/power/runtime-test.c (revision 7b8e9264f55a9c320f398e337d215e68cca50131)
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