// SPDX-License-Identifier: GPL-2.0
/*
 * 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>
#include <linux/numa.h>
#include <linux/nodemask.h>
#include <linux/topology.h>

#define TEST_PROBE_DELAY	(5 * 1000)	/* 5 sec */
#define TEST_PROBE_THRESHOLD	(TEST_PROBE_DELAY / 2)

static atomic_t warnings, errors, timeout, async_completed;

static int test_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;

	/*
	 * Determine if we have hit the "timeout" limit for the test if we
	 * have then report it as an error, otherwise we wil sleep for the
	 * required amount of time and then report completion.
	 */
	if (atomic_read(&timeout)) {
		dev_err(dev, "async probe took too long\n");
		atomic_inc(&errors);
	} else {
		dev_dbg(&pdev->dev, "sleeping for %d msecs in probe\n",
			 TEST_PROBE_DELAY);
		msleep(TEST_PROBE_DELAY);
		dev_dbg(&pdev->dev, "done sleeping\n");
	}

	/*
	 * Report NUMA mismatch if device node is set and we are not
	 * performing an async init on that node.
	 */
	if (dev->driver->probe_type == PROBE_PREFER_ASYNCHRONOUS) {
		if (IS_ENABLED(CONFIG_NUMA) &&
		    dev_to_node(dev) != numa_node_id()) {
			dev_warn(dev, "NUMA node mismatch %d != %d\n",
				 dev_to_node(dev), numa_node_id());
			atomic_inc(&warnings);
		}

		atomic_inc(&async_completed);
	}

	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[NR_CPUS * 2];
static struct platform_device *sync_dev[2];

static struct platform_device *
test_platform_device_register_node(char *name, int id, int nid)
{
	struct platform_device *pdev;
	int ret;

	pdev = platform_device_alloc(name, id);
	if (!pdev)
		return NULL;

	if (nid != NUMA_NO_NODE)
		set_dev_node(&pdev->dev, nid);

	ret = platform_device_add(pdev);
	if (ret) {
		platform_device_put(pdev);
		return ERR_PTR(ret);
	}

	return pdev;

}

static int __init test_async_probe_init(void)
{
	struct platform_device **pdev = NULL;
	int async_id = 0, sync_id = 0;
	unsigned long long duration;
	ktime_t calltime, delta;
	int err, nid, cpu;

	pr_info("registering first set of asynchronous devices...\n");

	for_each_online_cpu(cpu) {
		nid = cpu_to_node(cpu);
		pdev = &async_dev[async_id];
		*pdev =	test_platform_device_register_node("test_async_driver",
							   async_id,
							   nid);
		if (IS_ERR(*pdev)) {
			err = PTR_ERR(*pdev);
			*pdev = NULL;
			pr_err("failed to create async_dev: %d\n", err);
			goto err_unregister_async_devs;
		}

		async_id++;
	}

	pr_info("registering asynchronous driver...\n");
	calltime = ktime_get();
	err = platform_driver_register(&async_driver);
	if (err) {
		pr_err("Failed to register async_driver: %d\n", err);
		goto err_unregister_async_devs;
	}

	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");
		err = -ETIMEDOUT;
		goto err_unregister_async_driver;
	}

	pr_info("registering second set of asynchronous devices...\n");
	calltime = ktime_get();
	for_each_online_cpu(cpu) {
		nid = cpu_to_node(cpu);
		pdev = &sync_dev[sync_id];

		*pdev = test_platform_device_register_node("test_async_driver",
							   async_id,
							   nid);
		if (IS_ERR(*pdev)) {
			err = PTR_ERR(*pdev);
			*pdev = NULL;
			pr_err("failed to create async_dev: %d\n", err);
			goto err_unregister_async_driver;
		}

		async_id++;
	}

	delta = ktime_sub(ktime_get(), calltime);
	duration = (unsigned long long) ktime_to_ms(delta);
	dev_info(&(*pdev)->dev,
		 "registration took %lld msecs\n", duration);
	if (duration > TEST_PROBE_THRESHOLD) {
		dev_err(&(*pdev)->dev,
			"test failed: probe took too long\n");
		err = -ETIMEDOUT;
		goto err_unregister_async_driver;
	}


	pr_info("registering first synchronous device...\n");
	nid = cpu_to_node(cpu);
	pdev = &sync_dev[sync_id];

	*pdev = test_platform_device_register_node("test_sync_driver",
						   sync_id,
						   NUMA_NO_NODE);
	if (IS_ERR(*pdev)) {
		err = PTR_ERR(*pdev);
		*pdev = NULL;
		pr_err("failed to create sync_dev: %d\n", err);
		goto err_unregister_async_driver;
	}

	sync_id++;

	pr_info("registering synchronous driver...\n");
	calltime = ktime_get();
	err = platform_driver_register(&sync_driver);
	if (err) {
		pr_err("Failed to register async_driver: %d\n", err);
		goto err_unregister_sync_devs;
	}

	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) {
		dev_err(&(*pdev)->dev,
			"test failed: probe was too quick\n");
		err = -ETIMEDOUT;
		goto err_unregister_sync_driver;
	}

	pr_info("registering second synchronous device...\n");
	pdev = &sync_dev[sync_id];
	calltime = ktime_get();

	*pdev = test_platform_device_register_node("test_sync_driver",
						   sync_id,
						   NUMA_NO_NODE);
	if (IS_ERR(*pdev)) {
		err = PTR_ERR(*pdev);
		*pdev = NULL;
		pr_err("failed to create sync_dev: %d\n", err);
		goto err_unregister_sync_driver;
	}

	sync_id++;

	delta = ktime_sub(ktime_get(), calltime);
	duration = (unsigned long long) ktime_to_ms(delta);
	dev_info(&(*pdev)->dev,
		 "registration took %lld msecs\n", duration);
	if (duration < TEST_PROBE_THRESHOLD) {
		dev_err(&(*pdev)->dev,
			"test failed: probe was too quick\n");
		err = -ETIMEDOUT;
		goto err_unregister_sync_driver;
	}

	/*
	 * The async events should have completed while we were taking care
	 * of the synchronous events. We will now terminate any outstanding
	 * asynchronous probe calls remaining by forcing timeout and remove
	 * the driver before we return which should force the flush of the
	 * pending asynchronous probe calls.
	 *
	 * Otherwise if they completed without errors or warnings then
	 * report successful completion.
	 */
	if (atomic_read(&async_completed) != async_id) {
		pr_err("async events still pending, forcing timeout\n");
		atomic_inc(&timeout);
		err = -ETIMEDOUT;
	} else if (!atomic_read(&errors) && !atomic_read(&warnings)) {
		pr_info("completed successfully\n");
		return 0;
	}

err_unregister_sync_driver:
	platform_driver_unregister(&sync_driver);
err_unregister_sync_devs:
	while (sync_id--)
		platform_device_unregister(sync_dev[sync_id]);
err_unregister_async_driver:
	platform_driver_unregister(&async_driver);
err_unregister_async_devs:
	while (async_id--)
		platform_device_unregister(async_dev[async_id]);

	/*
	 * If err is already set then count that as an additional error for
	 * the test. Otherwise we will report an invalid argument error and
	 * not count that as we should have reached here as a result of
	 * errors or warnings being reported by the probe routine.
	 */
	if (err)
		atomic_inc(&errors);
	else
		err = -EINVAL;

	pr_err("Test failed with %d errors and %d warnings\n",
	       atomic_read(&errors), atomic_read(&warnings));

	return err;
}
module_init(test_async_probe_init);

static void __exit test_async_probe_exit(void)
{
	int id = 2;

	platform_driver_unregister(&async_driver);
	platform_driver_unregister(&sync_driver);

	while (id--)
		platform_device_unregister(sync_dev[id]);

	id = NR_CPUS * 2;
	while (id--)
		platform_device_unregister(async_dev[id]);
}
module_exit(test_async_probe_exit);

MODULE_DESCRIPTION("Test module for asynchronous driver probing");
MODULE_AUTHOR("Dmitry Torokhov <dtor@chromium.org>");
MODULE_LICENSE("GPL");
