/*
 * 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\n", 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\n", 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\n", 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 <dtor@chromium.org>");
MODULE_LICENSE("GPL");
