1 // SPDX-License-Identifier: GPL-2.0 2 // Copyright 2023 Maxime Ripard <mripard@kernel.org> 3 4 #include <kunit/resource.h> 5 6 #include <linux/device.h> 7 8 #define DEVICE_NAME "test" 9 10 struct test_priv { 11 bool probe_done; 12 bool release_done; 13 wait_queue_head_t release_wq; 14 struct device *dev; 15 }; 16 17 static int root_device_devm_init(struct kunit *test) 18 { 19 struct test_priv *priv; 20 21 priv = kunit_kzalloc(test, sizeof(*priv), GFP_KERNEL); 22 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv); 23 init_waitqueue_head(&priv->release_wq); 24 25 test->priv = priv; 26 27 return 0; 28 } 29 30 static void devm_device_action(void *ptr) 31 { 32 struct test_priv *priv = ptr; 33 34 priv->release_done = true; 35 wake_up_interruptible(&priv->release_wq); 36 } 37 38 #define RELEASE_TIMEOUT_MS 100 39 40 /* 41 * Tests that a bus-less, non-probed device will run its device-managed 42 * actions when unregistered. 43 */ 44 static void root_device_devm_register_unregister_test(struct kunit *test) 45 { 46 struct test_priv *priv = test->priv; 47 int ret; 48 49 priv->dev = root_device_register(DEVICE_NAME); 50 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->dev); 51 52 ret = devm_add_action_or_reset(priv->dev, devm_device_action, priv); 53 KUNIT_ASSERT_EQ(test, ret, 0); 54 55 root_device_unregister(priv->dev); 56 57 ret = wait_event_interruptible_timeout(priv->release_wq, priv->release_done, 58 msecs_to_jiffies(RELEASE_TIMEOUT_MS)); 59 KUNIT_EXPECT_GT(test, ret, 0); 60 } 61 62 static void devm_put_device_action(void *ptr) 63 { 64 struct test_priv *priv = ptr; 65 66 put_device(priv->dev); 67 priv->release_done = true; 68 wake_up_interruptible(&priv->release_wq); 69 } 70 71 /* 72 * Tests that a bus-less, non-probed device will run its device-managed 73 * actions when unregistered, even if someone still holds a reference to 74 * it. 75 */ 76 static void root_device_devm_register_get_unregister_with_devm_test(struct kunit *test) 77 { 78 struct test_priv *priv = test->priv; 79 int ret; 80 81 priv->dev = root_device_register(DEVICE_NAME); 82 KUNIT_ASSERT_NOT_ERR_OR_NULL(test, priv->dev); 83 84 get_device(priv->dev); 85 86 ret = devm_add_action_or_reset(priv->dev, devm_put_device_action, priv); 87 KUNIT_ASSERT_EQ(test, ret, 0); 88 89 root_device_unregister(priv->dev); 90 91 ret = wait_event_interruptible_timeout(priv->release_wq, priv->release_done, 92 msecs_to_jiffies(RELEASE_TIMEOUT_MS)); 93 KUNIT_EXPECT_GT(test, ret, 0); 94 } 95 96 static struct kunit_case root_device_devm_tests[] = { 97 KUNIT_CASE(root_device_devm_register_unregister_test), 98 KUNIT_CASE(root_device_devm_register_get_unregister_with_devm_test), 99 {} 100 }; 101 102 static struct kunit_suite root_device_devm_test_suite = { 103 .name = "root-device-devm", 104 .init = root_device_devm_init, 105 .test_cases = root_device_devm_tests, 106 }; 107 108 kunit_test_suite(root_device_devm_test_suite); 109 110 MODULE_DESCRIPTION("Test module for root devices"); 111 MODULE_AUTHOR("Maxime Ripard <mripard@kernel.org>"); 112 MODULE_LICENSE("GPL"); 113