xref: /linux/drivers/base/test/root-device-test.c (revision a1c613ae4c322ddd58d5a8539dbfba2a0380a8c0)
106188bc8SMaxime Ripard // SPDX-License-Identifier: GPL-2.0
206188bc8SMaxime Ripard // Copyright 2023 Maxime Ripard <mripard@kernel.org>
306188bc8SMaxime Ripard 
406188bc8SMaxime Ripard #include <kunit/resource.h>
506188bc8SMaxime Ripard 
606188bc8SMaxime Ripard #include <linux/device.h>
706188bc8SMaxime Ripard 
806188bc8SMaxime Ripard #define DEVICE_NAME "test"
906188bc8SMaxime Ripard 
1006188bc8SMaxime Ripard struct test_priv {
1106188bc8SMaxime Ripard 	bool probe_done;
1206188bc8SMaxime Ripard 	bool release_done;
1306188bc8SMaxime Ripard 	wait_queue_head_t release_wq;
1406188bc8SMaxime Ripard 	struct device *dev;
1506188bc8SMaxime Ripard };
1606188bc8SMaxime Ripard 
root_device_devm_init(struct kunit * test)1706188bc8SMaxime Ripard static int root_device_devm_init(struct kunit *test)
1806188bc8SMaxime Ripard {
1906188bc8SMaxime Ripard 	struct test_priv *priv;
2006188bc8SMaxime Ripard 
2106188bc8SMaxime Ripard 	priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL);
2206188bc8SMaxime Ripard 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv);
2306188bc8SMaxime Ripard 	init_waitqueue_head(&priv->release_wq);
2406188bc8SMaxime Ripard 
2506188bc8SMaxime Ripard 	test->priv = priv;
2606188bc8SMaxime Ripard 
2706188bc8SMaxime Ripard 	return 0;
2806188bc8SMaxime Ripard }
2906188bc8SMaxime Ripard 
devm_device_action(void * ptr)3006188bc8SMaxime Ripard static void devm_device_action(void *ptr)
3106188bc8SMaxime Ripard {
3206188bc8SMaxime Ripard 	struct test_priv *priv = ptr;
3306188bc8SMaxime Ripard 
3406188bc8SMaxime Ripard 	priv->release_done = true;
3506188bc8SMaxime Ripard 	wake_up_interruptible(&priv->release_wq);
3606188bc8SMaxime Ripard }
3706188bc8SMaxime Ripard 
3806188bc8SMaxime Ripard #define RELEASE_TIMEOUT_MS	100
3906188bc8SMaxime Ripard 
4006188bc8SMaxime Ripard /*
4106188bc8SMaxime Ripard  * Tests that a bus-less, non-probed device will run its device-managed
4206188bc8SMaxime Ripard  * actions when unregistered.
4306188bc8SMaxime Ripard  */
root_device_devm_register_unregister_test(struct kunit * test)4406188bc8SMaxime Ripard static void root_device_devm_register_unregister_test(struct kunit *test)
4506188bc8SMaxime Ripard {
4606188bc8SMaxime Ripard 	struct test_priv *priv = test->priv;
4706188bc8SMaxime Ripard 	int ret;
4806188bc8SMaxime Ripard 
4906188bc8SMaxime Ripard 	priv->dev = root_device_register(DEVICE_NAME);
5006188bc8SMaxime Ripard 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->dev);
5106188bc8SMaxime Ripard 
5206188bc8SMaxime Ripard 	ret = devm_add_action_or_reset(priv->dev, devm_device_action, priv);
5306188bc8SMaxime Ripard 	KUNIT_ASSERT_EQ(test, ret, 0);
5406188bc8SMaxime Ripard 
5506188bc8SMaxime Ripard 	root_device_unregister(priv->dev);
5606188bc8SMaxime Ripard 
5706188bc8SMaxime Ripard 	ret = wait_event_interruptible_timeout(priv->release_wq, priv->release_done,
5806188bc8SMaxime Ripard 					       msecs_to_jiffies(RELEASE_TIMEOUT_MS));
5906188bc8SMaxime Ripard 	KUNIT_EXPECT_GT(test, ret, 0);
6006188bc8SMaxime Ripard }
6106188bc8SMaxime Ripard 
devm_put_device_action(void * ptr)6206188bc8SMaxime Ripard static void devm_put_device_action(void *ptr)
6306188bc8SMaxime Ripard {
6406188bc8SMaxime Ripard 	struct test_priv *priv = ptr;
6506188bc8SMaxime Ripard 
6606188bc8SMaxime Ripard 	put_device(priv->dev);
6706188bc8SMaxime Ripard 	priv->release_done = true;
6806188bc8SMaxime Ripard 	wake_up_interruptible(&priv->release_wq);
6906188bc8SMaxime Ripard }
7006188bc8SMaxime Ripard 
7106188bc8SMaxime Ripard /*
7206188bc8SMaxime Ripard  * Tests that a bus-less, non-probed device will run its device-managed
7306188bc8SMaxime Ripard  * actions when unregistered, even if someone still holds a reference to
7406188bc8SMaxime Ripard  * it.
7506188bc8SMaxime Ripard  */
root_device_devm_register_get_unregister_with_devm_test(struct kunit * test)7606188bc8SMaxime Ripard static void root_device_devm_register_get_unregister_with_devm_test(struct kunit *test)
7706188bc8SMaxime Ripard {
7806188bc8SMaxime Ripard 	struct test_priv *priv = test->priv;
7906188bc8SMaxime Ripard 	int ret;
8006188bc8SMaxime Ripard 
8106188bc8SMaxime Ripard 	priv->dev = root_device_register(DEVICE_NAME);
8206188bc8SMaxime Ripard 	KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->dev);
8306188bc8SMaxime Ripard 
8406188bc8SMaxime Ripard 	get_device(priv->dev);
8506188bc8SMaxime Ripard 
8606188bc8SMaxime Ripard 	ret = devm_add_action_or_reset(priv->dev, devm_put_device_action, priv);
8706188bc8SMaxime Ripard 	KUNIT_ASSERT_EQ(test, ret, 0);
8806188bc8SMaxime Ripard 
8906188bc8SMaxime Ripard 	root_device_unregister(priv->dev);
9006188bc8SMaxime Ripard 
9106188bc8SMaxime Ripard 	ret = wait_event_interruptible_timeout(priv->release_wq, priv->release_done,
9206188bc8SMaxime Ripard 					       msecs_to_jiffies(RELEASE_TIMEOUT_MS));
9306188bc8SMaxime Ripard 	KUNIT_EXPECT_GT(test, ret, 0);
9406188bc8SMaxime Ripard }
9506188bc8SMaxime Ripard 
9606188bc8SMaxime Ripard static struct kunit_case root_device_devm_tests[] = {
9706188bc8SMaxime Ripard 	KUNIT_CASE(root_device_devm_register_unregister_test),
9806188bc8SMaxime Ripard 	KUNIT_CASE(root_device_devm_register_get_unregister_with_devm_test),
9906188bc8SMaxime Ripard 	{}
10006188bc8SMaxime Ripard };
10106188bc8SMaxime Ripard 
10206188bc8SMaxime Ripard static struct kunit_suite root_device_devm_test_suite = {
10306188bc8SMaxime Ripard 	.name = "root-device-devm",
10406188bc8SMaxime Ripard 	.init = root_device_devm_init,
10506188bc8SMaxime Ripard 	.test_cases = root_device_devm_tests,
10606188bc8SMaxime Ripard };
10706188bc8SMaxime Ripard 
10806188bc8SMaxime Ripard kunit_test_suite(root_device_devm_test_suite);
109*f7bb2426SMaxime Ripard 
110*f7bb2426SMaxime Ripard MODULE_DESCRIPTION("Test module for root devices");
111*f7bb2426SMaxime Ripard MODULE_AUTHOR("Maxime Ripard <mripard@kernel.org>");
112*f7bb2426SMaxime Ripard MODULE_LICENSE("GPL");
113