diff options
Diffstat (limited to 'drivers/base/test')
| -rw-r--r-- | drivers/base/test/Kconfig | 9 | ||||
| -rw-r--r-- | drivers/base/test/Makefile | 1 | ||||
| -rw-r--r-- | drivers/base/test/test_async_driver_probe.c | 169 | 
3 files changed, 179 insertions, 0 deletions
diff --git a/drivers/base/test/Kconfig b/drivers/base/test/Kconfig new file mode 100644 index 000000000000..9aa0d45a60db --- /dev/null +++ b/drivers/base/test/Kconfig @@ -0,0 +1,9 @@ +config TEST_ASYNC_DRIVER_PROBE +	tristate "Build kernel module to test asynchronous driver probing" +	depends on m +	help +	  Enabling this option produces a kernel module that allows +	  testing asynchronous driver probing by the device core. +	  The module name will be test_async_driver_probe.ko + +	  If unsure say N. diff --git a/drivers/base/test/Makefile b/drivers/base/test/Makefile new file mode 100644 index 000000000000..90477c5fd9f9 --- /dev/null +++ b/drivers/base/test/Makefile @@ -0,0 +1 @@ +obj-$(CONFIG_TEST_ASYNC_DRIVER_PROBE)	+= test_async_driver_probe.o diff --git a/drivers/base/test/test_async_driver_probe.c b/drivers/base/test/test_async_driver_probe.c new file mode 100644 index 000000000000..304d5c2bd5e9 --- /dev/null +++ b/drivers/base/test/test_async_driver_probe.c @@ -0,0 +1,169 @@ +/* + * Copyright (C) 2014 Google, Inc. + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the + * GNU General Public License for more details. + */ + +#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt + +#include <linux/delay.h> +#include <linux/init.h> +#include <linux/hrtimer.h> +#include <linux/module.h> +#include <linux/platform_device.h> +#include <linux/time.h> + +#define TEST_PROBE_DELAY	(5 * 1000)	/* 5 sec */ +#define TEST_PROBE_THRESHOLD	(TEST_PROBE_DELAY / 2) + +static int test_probe(struct platform_device *pdev) +{ +	dev_info(&pdev->dev, "sleeping for %d msecs in probe\n", +		 TEST_PROBE_DELAY); +	msleep(TEST_PROBE_DELAY); +	dev_info(&pdev->dev, "done sleeping\n"); + +	return 0; +} + +static struct platform_driver async_driver = { +	.driver = { +		.name = "test_async_driver", +		.probe_type = PROBE_PREFER_ASYNCHRONOUS, +	}, +	.probe = test_probe, +}; + +static struct platform_driver sync_driver = { +	.driver = { +		.name = "test_sync_driver", +		.probe_type = PROBE_FORCE_SYNCHRONOUS, +	}, +	.probe = test_probe, +}; + +static struct platform_device *async_dev_1, *async_dev_2; +static struct platform_device *sync_dev_1; + +static int __init test_async_probe_init(void) +{ +	ktime_t calltime, delta; +	unsigned long long duration; +	int error; + +	pr_info("registering first asynchronous device...\n"); + +	async_dev_1 = platform_device_register_simple("test_async_driver", 1, +						      NULL, 0); +	if (IS_ERR(async_dev_1)) { +		error = PTR_ERR(async_dev_1); +		pr_err("failed to create async_dev_1: %d", error); +		return error; +	} + +	pr_info("registering asynchronous driver...\n"); +	calltime = ktime_get(); +	error = platform_driver_register(&async_driver); +	if (error) { +		pr_err("Failed to register async_driver: %d\n", error); +		goto err_unregister_async_dev_1; +	} + +	delta = ktime_sub(ktime_get(), calltime); +	duration = (unsigned long long) ktime_to_ms(delta); +	pr_info("registration took %lld msecs\n", duration); +	if (duration > TEST_PROBE_THRESHOLD) { +		pr_err("test failed: probe took too long\n"); +		error = -ETIMEDOUT; +		goto err_unregister_async_driver; +	} + +	pr_info("registering second asynchronous device...\n"); +	calltime = ktime_get(); +	async_dev_2 = platform_device_register_simple("test_async_driver", 2, +						      NULL, 0); +	if (IS_ERR(async_dev_2)) { +		error = PTR_ERR(async_dev_2); +		pr_err("failed to create async_dev_2: %d", error); +		goto err_unregister_async_driver; +	} + +	delta = ktime_sub(ktime_get(), calltime); +	duration = (unsigned long long) ktime_to_ms(delta); +	pr_info("registration took %lld msecs\n", duration); +	if (duration > TEST_PROBE_THRESHOLD) { +		pr_err("test failed: probe took too long\n"); +		error = -ETIMEDOUT; +		goto err_unregister_async_dev_2; +	} + +	pr_info("registering synchronous driver...\n"); + +	error = platform_driver_register(&sync_driver); +	if (error) { +		pr_err("Failed to register async_driver: %d\n", error); +		goto err_unregister_async_dev_2; +	} + +	pr_info("registering synchronous device...\n"); +	calltime = ktime_get(); +	sync_dev_1 = platform_device_register_simple("test_sync_driver", 1, +						     NULL, 0); +	if (IS_ERR(sync_dev_1)) { +		error = PTR_ERR(sync_dev_1); +		pr_err("failed to create sync_dev_1: %d", error); +		goto err_unregister_sync_driver; +	} + +	delta = ktime_sub(ktime_get(), calltime); +	duration = (unsigned long long) ktime_to_ms(delta); +	pr_info("registration took %lld msecs\n", duration); +	if (duration < TEST_PROBE_THRESHOLD) { +		pr_err("test failed: probe was too quick\n"); +		error = -ETIMEDOUT; +		goto err_unregister_sync_dev_1; +	} + +	pr_info("completed successfully"); + +	return 0; + +err_unregister_sync_dev_1: +	platform_device_unregister(sync_dev_1); + +err_unregister_sync_driver: +	platform_driver_unregister(&sync_driver); + +err_unregister_async_dev_2: +	platform_device_unregister(async_dev_2); + +err_unregister_async_driver: +	platform_driver_unregister(&async_driver); + +err_unregister_async_dev_1: +	platform_device_unregister(async_dev_1); + +	return error; +} +module_init(test_async_probe_init); + +static void __exit test_async_probe_exit(void) +{ +	platform_driver_unregister(&async_driver); +	platform_driver_unregister(&sync_driver); +	platform_device_unregister(async_dev_1); +	platform_device_unregister(async_dev_2); +	platform_device_unregister(sync_dev_1); +} +module_exit(test_async_probe_exit); + +MODULE_DESCRIPTION("Test module for asynchronous driver probing"); +MODULE_AUTHOR("Dmitry Torokhov <[email protected]>"); +MODULE_LICENSE("GPL");  |