Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

driver-core: add test module for asynchronous probing

This test module tries to test asynchronous driver probing by having a
driver that sleeps for an extended period of time (5 secs) in its
probe() method. It measures the time needed to register this driver
(with device already registered) and a new device (with driver already
registered). The module will fail to load if the time spent in register
call is more than half the probing sleep time.

As a sanity check the driver will then try to synchronously register
driver and device and fail if registration takes less than half of the
probing sleep time.

Signed-off-by: Dmitry Torokhov <dtor@chromium.org>
Reviewed-by: Olof Johansson <olofj@chromium.org>
Signed-off-by: Guenter Roeck <groeck@chromium.org>
Signed-off-by: Thierry Escande <thierry.escande@collabora.com>
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>

authored by

Dmitry Torokhov and committed by
Greg Kroah-Hartman
79543cf2 6751667a

+185
+2
drivers/base/Kconfig
··· 224 224 unusable. You should say N here unless you are explicitly looking to 225 225 test this functionality. 226 226 227 + source "drivers/base/test/Kconfig" 228 + 227 229 config SYS_HYPERVISOR 228 230 bool 229 231 default n
+2
drivers/base/Makefile
··· 24 24 obj-$(CONFIG_DEV_COREDUMP) += devcoredump.o 25 25 obj-$(CONFIG_GENERIC_MSI_IRQ_DOMAIN) += platform-msi.o 26 26 27 + obj-y += test/ 28 + 27 29 ccflags-$(CONFIG_DEBUG_DRIVER) := -DDEBUG 28 30
+9
drivers/base/test/Kconfig
··· 1 + config TEST_ASYNC_DRIVER_PROBE 2 + tristate "Build kernel module to test asynchronous driver probing" 3 + depends on m 4 + help 5 + Enabling this option produces a kernel module that allows 6 + testing asynchronous driver probing by the device core. 7 + The module name will be test_async_driver_probe.ko 8 + 9 + If unsure say N.
+1
drivers/base/test/Makefile
··· 1 + obj-$(CONFIG_TEST_ASYNC_DRIVER_PROBE) += test_async_driver_probe.o
+171
drivers/base/test/test_async_driver_probe.c
··· 1 + /* 2 + * Copyright (C) 2014 Google, Inc. 3 + * 4 + * This program is free software; you can redistribute it and/or modify 5 + * it under the terms of the GNU General Public License version 2 as 6 + * published by the Free Software Foundation. 7 + * 8 + * This program is distributed in the hope that it will be useful, 9 + * but WITHOUT ANY WARRANTY; without even the implied warranty of 10 + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 11 + * GNU General Public License for more details. 12 + */ 13 + 14 + #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 15 + 16 + #include <linux/delay.h> 17 + #include <linux/init.h> 18 + #include <linux/hrtimer.h> 19 + #include <linux/module.h> 20 + #include <linux/platform_device.h> 21 + #include <linux/time.h> 22 + 23 + #define TEST_PROBE_DELAY (5 * 1000) /* 5 sec */ 24 + #define TEST_PROBE_THRESHOLD (TEST_PROBE_DELAY / 2) 25 + 26 + static int test_probe(struct platform_device *pdev) 27 + { 28 + dev_info(&pdev->dev, "sleeping for %d msecs in probe\n", 29 + TEST_PROBE_DELAY); 30 + msleep(TEST_PROBE_DELAY); 31 + dev_info(&pdev->dev, "done sleeping\n"); 32 + 33 + return 0; 34 + } 35 + 36 + static struct platform_driver async_driver = { 37 + .driver = { 38 + .name = "test_async_driver", 39 + .owner = THIS_MODULE, 40 + .probe_type = PROBE_PREFER_ASYNCHRONOUS, 41 + }, 42 + .probe = test_probe, 43 + }; 44 + 45 + static struct platform_driver sync_driver = { 46 + .driver = { 47 + .name = "test_sync_driver", 48 + .owner = THIS_MODULE, 49 + .probe_type = PROBE_FORCE_SYNCHRONOUS, 50 + }, 51 + .probe = test_probe, 52 + }; 53 + 54 + static struct platform_device *async_dev_1, *async_dev_2; 55 + static struct platform_device *sync_dev_1; 56 + 57 + static int __init test_async_probe_init(void) 58 + { 59 + ktime_t calltime, delta; 60 + unsigned long long duration; 61 + int error; 62 + 63 + pr_info("registering first asynchronous device...\n"); 64 + 65 + async_dev_1 = platform_device_register_simple("test_async_driver", 1, 66 + NULL, 0); 67 + if (IS_ERR(async_dev_1)) { 68 + error = PTR_ERR(async_dev_1); 69 + pr_err("failed to create async_dev_1: %d", error); 70 + return error; 71 + } 72 + 73 + pr_info("registering asynchronous driver...\n"); 74 + calltime = ktime_get(); 75 + error = platform_driver_register(&async_driver); 76 + if (error) { 77 + pr_err("Failed to register async_driver: %d\n", error); 78 + goto err_unregister_async_dev_1; 79 + } 80 + 81 + delta = ktime_sub(ktime_get(), calltime); 82 + duration = (unsigned long long) ktime_to_ms(delta); 83 + pr_info("registration took %lld msecs\n", duration); 84 + if (duration > TEST_PROBE_THRESHOLD) { 85 + pr_err("test failed: probe took too long\n"); 86 + error = -ETIMEDOUT; 87 + goto err_unregister_async_driver; 88 + } 89 + 90 + pr_info("registering second asynchronous device...\n"); 91 + calltime = ktime_get(); 92 + async_dev_2 = platform_device_register_simple("test_async_driver", 2, 93 + NULL, 0); 94 + if (IS_ERR(async_dev_2)) { 95 + error = PTR_ERR(async_dev_2); 96 + pr_err("failed to create async_dev_2: %d", error); 97 + goto err_unregister_async_driver; 98 + } 99 + 100 + delta = ktime_sub(ktime_get(), calltime); 101 + duration = (unsigned long long) ktime_to_ms(delta); 102 + pr_info("registration took %lld msecs\n", duration); 103 + if (duration > TEST_PROBE_THRESHOLD) { 104 + pr_err("test failed: probe took too long\n"); 105 + error = -ETIMEDOUT; 106 + goto err_unregister_async_dev_2; 107 + } 108 + 109 + pr_info("registering synchronous driver...\n"); 110 + 111 + error = platform_driver_register(&sync_driver); 112 + if (error) { 113 + pr_err("Failed to register async_driver: %d\n", error); 114 + goto err_unregister_async_dev_2; 115 + } 116 + 117 + pr_info("registering synchronous device...\n"); 118 + calltime = ktime_get(); 119 + sync_dev_1 = platform_device_register_simple("test_sync_driver", 1, 120 + NULL, 0); 121 + if (IS_ERR(async_dev_1)) { 122 + error = PTR_ERR(sync_dev_1); 123 + pr_err("failed to create sync_dev_1: %d", error); 124 + goto err_unregister_sync_driver; 125 + } 126 + 127 + delta = ktime_sub(ktime_get(), calltime); 128 + duration = (unsigned long long) ktime_to_ms(delta); 129 + pr_info("registration took %lld msecs\n", duration); 130 + if (duration < TEST_PROBE_THRESHOLD) { 131 + pr_err("test failed: probe was too quick\n"); 132 + error = -ETIMEDOUT; 133 + goto err_unregister_sync_dev_1; 134 + } 135 + 136 + pr_info("completed successfully"); 137 + 138 + return 0; 139 + 140 + err_unregister_sync_dev_1: 141 + platform_device_unregister(sync_dev_1); 142 + 143 + err_unregister_sync_driver: 144 + platform_driver_unregister(&sync_driver); 145 + 146 + err_unregister_async_dev_2: 147 + platform_device_unregister(async_dev_2); 148 + 149 + err_unregister_async_driver: 150 + platform_driver_unregister(&async_driver); 151 + 152 + err_unregister_async_dev_1: 153 + platform_device_unregister(async_dev_1); 154 + 155 + return error; 156 + } 157 + module_init(test_async_probe_init); 158 + 159 + static void __exit test_async_probe_exit(void) 160 + { 161 + platform_driver_unregister(&async_driver); 162 + platform_driver_unregister(&sync_driver); 163 + platform_device_unregister(async_dev_1); 164 + platform_device_unregister(async_dev_2); 165 + platform_device_unregister(sync_dev_1); 166 + } 167 + module_exit(test_async_probe_exit); 168 + 169 + MODULE_DESCRIPTION("Test module for asynchronous driver probing"); 170 + MODULE_AUTHOR("Dmitry Torokhov <dtor@chromium.org>"); 171 + MODULE_LICENSE("GPL");