File Index
Files and directories
Sign in
FILE

runtime-test.c

File preview with syntax highlighting.

linux-6.19.14/drivers/base/power/runtime-test.c C
  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");
~/ Read-only file preview.