2017-11-07 17:30:07 +01:00
// SPDX-License-Identifier: GPL-2.0
2016-09-29 17:13:14 +02:00
/*
* Copyright ( C ) 2014 Google , Inc .
*/
# 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 ) ;
2017-09-25 12:55:28 +05:30
pr_err ( " failed to create async_dev_1: %d \n " , error ) ;
2016-09-29 17:13:14 +02:00
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 ) ;
2017-09-25 12:55:28 +05:30
pr_err ( " failed to create async_dev_2: %d \n " , error ) ;
2016-09-29 17:13:14 +02:00
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 ) ;
2016-11-29 22:06:42 +01:00
if ( IS_ERR ( sync_dev_1 ) ) {
2016-09-29 17:13:14 +02:00
error = PTR_ERR ( sync_dev_1 ) ;
2017-09-25 12:55:28 +05:30
pr_err ( " failed to create sync_dev_1: %d \n " , error ) ;
2016-09-29 17:13:14 +02:00
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 <dtor@chromium.org> " ) ;
MODULE_LICENSE ( " GPL " ) ;