Linux Audio

Check our new training course

Loading...
Note: File does not exist in v3.1.
  1// SPDX-License-Identifier: GPL-2.0
  2
  3#include <kunit/resource.h>
  4
  5#include <linux/device.h>
  6#include <linux/platform_device.h>
  7
  8#define DEVICE_NAME "test"
  9
 10struct test_priv {
 11	bool probe_done;
 12	bool release_done;
 13	wait_queue_head_t probe_wq;
 14	wait_queue_head_t release_wq;
 15	struct device *dev;
 16};
 17
 18static int platform_device_devm_init(struct kunit *test)
 19{
 20	struct test_priv *priv;
 21
 22	priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
 23	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv);
 24	init_waitqueue_head(&priv->probe_wq);
 25	init_waitqueue_head(&priv->release_wq);
 26
 27	test->priv = priv;
 28
 29	return 0;
 30}
 31
 32static void devm_device_action(void *ptr)
 33{
 34	struct test_priv *priv = ptr;
 35
 36	priv->release_done = true;
 37	wake_up_interruptible(&priv->release_wq);
 38}
 39
 40static void devm_put_device_action(void *ptr)
 41{
 42	struct test_priv *priv = ptr;
 43
 44	put_device(priv->dev);
 45	priv->release_done = true;
 46	wake_up_interruptible(&priv->release_wq);
 47}
 48
 49#define RELEASE_TIMEOUT_MS	100
 50
 51/*
 52 * Tests that a platform bus, non-probed device will run its
 53 * device-managed actions when unregistered.
 54 */
 55static void platform_device_devm_register_unregister_test(struct kunit *test)
 56{
 57	struct platform_device *pdev;
 58	struct test_priv *priv = test->priv;
 59	int ret;
 60
 61	pdev = platform_device_alloc(DEVICE_NAME, PLATFORM_DEVID_NONE);
 62	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, pdev);
 63
 64	ret = platform_device_add(pdev);
 65	KUNIT_ASSERT_EQ(test, ret, 0);
 66
 67	priv->dev = &pdev->dev;
 68
 69	ret = devm_add_action_or_reset(priv->dev, devm_device_action, priv);
 70	KUNIT_ASSERT_EQ(test, ret, 0);
 71
 72	platform_device_unregister(pdev);
 73
 74	ret = wait_event_interruptible_timeout(priv->release_wq, priv->release_done,
 75					       msecs_to_jiffies(RELEASE_TIMEOUT_MS));
 76	KUNIT_EXPECT_GT(test, ret, 0);
 77}
 78
 79/*
 80 * Tests that a platform bus, non-probed device will run its
 81 * device-managed actions when unregistered, even if someone still holds
 82 * a reference to it.
 83 */
 84static void platform_device_devm_register_get_unregister_with_devm_test(struct kunit *test)
 85{
 86	struct platform_device *pdev;
 87	struct test_priv *priv = test->priv;
 88	int ret;
 89
 90	pdev = platform_device_alloc(DEVICE_NAME, PLATFORM_DEVID_NONE);
 91	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, pdev);
 92
 93	ret = platform_device_add(pdev);
 94	KUNIT_ASSERT_EQ(test, ret, 0);
 95
 96	priv->dev = &pdev->dev;
 97
 98	get_device(priv->dev);
 99
100	ret = devm_add_action_or_reset(priv->dev, devm_put_device_action, priv);
101	KUNIT_ASSERT_EQ(test, ret, 0);
102
103	platform_device_unregister(pdev);
104
105	ret = wait_event_interruptible_timeout(priv->release_wq, priv->release_done,
106					       msecs_to_jiffies(RELEASE_TIMEOUT_MS));
107	KUNIT_EXPECT_GT(test, ret, 0);
108}
109
110static int fake_probe(struct platform_device *pdev)
111{
112	struct test_priv *priv = platform_get_drvdata(pdev);
113
114	priv->probe_done = true;
115	wake_up_interruptible(&priv->probe_wq);
116
117	return 0;
118}
119
120static struct platform_driver fake_driver = {
121	.probe	= fake_probe,
122	.driver = {
123		.name = DEVICE_NAME,
124	},
125};
126
127/*
128 * Tests that a platform bus, probed device will run its device-managed
129 * actions when unregistered.
130 */
131static void probed_platform_device_devm_register_unregister_test(struct kunit *test)
132{
133	struct platform_device *pdev;
134	struct test_priv *priv = test->priv;
135	int ret;
136
137	ret = platform_driver_register(&fake_driver);
138	KUNIT_ASSERT_EQ(test, ret, 0);
139
140	pdev = platform_device_alloc(DEVICE_NAME, PLATFORM_DEVID_NONE);
141	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, pdev);
142
143	priv->dev = &pdev->dev;
144	platform_set_drvdata(pdev, priv);
145
146	ret = platform_device_add(pdev);
147	KUNIT_ASSERT_EQ(test, ret, 0);
148
149	ret = wait_event_interruptible_timeout(priv->probe_wq, priv->probe_done,
150					       msecs_to_jiffies(RELEASE_TIMEOUT_MS));
151	KUNIT_ASSERT_GT(test, ret, 0);
152
153	ret = devm_add_action_or_reset(priv->dev, devm_device_action, priv);
154	KUNIT_ASSERT_EQ(test, ret, 0);
155
156	platform_device_unregister(pdev);
157
158	ret = wait_event_interruptible_timeout(priv->release_wq, priv->release_done,
159					       msecs_to_jiffies(RELEASE_TIMEOUT_MS));
160	KUNIT_EXPECT_GT(test, ret, 0);
161
162	platform_driver_unregister(&fake_driver);
163}
164
165/*
166 * Tests that a platform bus, probed device will run its device-managed
167 * actions when unregistered, even if someone still holds a reference to
168 * it.
169 */
170static void probed_platform_device_devm_register_get_unregister_with_devm_test(struct kunit *test)
171{
172	struct platform_device *pdev;
173	struct test_priv *priv = test->priv;
174	int ret;
175
176	ret = platform_driver_register(&fake_driver);
177	KUNIT_ASSERT_EQ(test, ret, 0);
178
179	pdev = platform_device_alloc(DEVICE_NAME, PLATFORM_DEVID_NONE);
180	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, pdev);
181
182	priv->dev = &pdev->dev;
183	platform_set_drvdata(pdev, priv);
184
185	ret = platform_device_add(pdev);
186	KUNIT_ASSERT_EQ(test, ret, 0);
187
188	ret = wait_event_interruptible_timeout(priv->probe_wq, priv->probe_done,
189					       msecs_to_jiffies(RELEASE_TIMEOUT_MS));
190	KUNIT_ASSERT_GT(test, ret, 0);
191
192	get_device(priv->dev);
193
194	ret = devm_add_action_or_reset(priv->dev, devm_put_device_action, priv);
195	KUNIT_ASSERT_EQ(test, ret, 0);
196
197	platform_device_unregister(pdev);
198
199	ret = wait_event_interruptible_timeout(priv->release_wq, priv->release_done,
200					       msecs_to_jiffies(RELEASE_TIMEOUT_MS));
201	KUNIT_EXPECT_GT(test, ret, 0);
202
203	platform_driver_unregister(&fake_driver);
204}
205
206static struct kunit_case platform_device_devm_tests[] = {
207	KUNIT_CASE(platform_device_devm_register_unregister_test),
208	KUNIT_CASE(platform_device_devm_register_get_unregister_with_devm_test),
209	KUNIT_CASE(probed_platform_device_devm_register_unregister_test),
210	KUNIT_CASE(probed_platform_device_devm_register_get_unregister_with_devm_test),
211	{}
212};
213
214static struct kunit_suite platform_device_devm_test_suite = {
215	.name = "platform-device-devm",
216	.init = platform_device_devm_init,
217	.test_cases = platform_device_devm_tests,
218};
219
220kunit_test_suite(platform_device_devm_test_suite);
221
222MODULE_DESCRIPTION("Test module for platform devices");
223MODULE_AUTHOR("Maxime Ripard <mripard@kernel.org>");
224MODULE_LICENSE("GPL");