Kees requested that this test module be renamed for consistency sake, so this patch renames the udelay_test.c file (recently added to tip/timers/core for 3.17) to test_udelay.c Cc: Kees Cook <keescook@xxxxxxxxxxxx> Cc: Greg KH <greg@xxxxxxxxx> Cc: Stephen Rothwell <sfr@xxxxxxxxxxxxxxxx> Cc: Thomas Gleixner <tglx@xxxxxxxxxxxxx> Cc: Ingo Molnar <mingo@xxxxxxx> Cc: Linux-Next <linux-next@xxxxxxxxxxxxxxx> Cc: David Riley <davidriley@xxxxxxxxxxxx> Signed-off-by: John Stultz <john.stultz@xxxxxxxxxx> --- kernel/time/Makefile | 2 +- kernel/time/test_udelay.c | 168 ++++++++++++++++++++++++++++++++++++++++++++++ kernel/time/udelay_test.c | 168 ---------------------------------------------- 3 files changed, 169 insertions(+), 169 deletions(-) create mode 100644 kernel/time/test_udelay.c delete mode 100644 kernel/time/udelay_test.c diff --git a/kernel/time/Makefile b/kernel/time/Makefile index 7347426..f622cf2 100644 --- a/kernel/time/Makefile +++ b/kernel/time/Makefile @@ -13,7 +13,7 @@ obj-$(CONFIG_TICK_ONESHOT) += tick-oneshot.o obj-$(CONFIG_TICK_ONESHOT) += tick-sched.o obj-$(CONFIG_TIMER_STATS) += timer_stats.o obj-$(CONFIG_DEBUG_FS) += timekeeping_debug.o -obj-$(CONFIG_TEST_UDELAY) += udelay_test.o +obj-$(CONFIG_TEST_UDELAY) += test_udelay.o $(obj)/time.o: $(obj)/timeconst.h diff --git a/kernel/time/test_udelay.c b/kernel/time/test_udelay.c new file mode 100644 index 0000000..e622ba3 --- /dev/null +++ b/kernel/time/test_udelay.c @@ -0,0 +1,168 @@ +/* + * udelay() test kernel module + * + * Test is executed by writing and reading to /sys/kernel/debug/udelay_test + * Tests are configured by writing: USECS ITERATIONS + * Tests are executed by reading from the same file. + * Specifying usecs of 0 or negative values will run multiples tests. + * + * Copyright (C) 2014 Google, Inc. + * + * This software is licensed under the terms of the GNU General Public + * License version 2, as published by the Free Software Foundation, and + * may be copied, distributed, and modified under those terms. + * + * 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. + */ + +#include <linux/debugfs.h> +#include <linux/delay.h> +#include <linux/ktime.h> +#include <linux/module.h> +#include <linux/uaccess.h> + +#define DEFAULT_ITERATIONS 100 + +#define DEBUGFS_FILENAME "udelay_test" + +static DEFINE_MUTEX(udelay_test_lock); +static struct dentry *udelay_test_debugfs_file; +static int udelay_test_usecs; +static int udelay_test_iterations = DEFAULT_ITERATIONS; + +static int udelay_test_single(struct seq_file *s, int usecs, uint32_t iters) +{ + int min = 0, max = 0, fail_count = 0; + uint64_t sum = 0; + uint64_t avg; + int i; + /* Allow udelay to be up to 0.5% fast */ + int allowed_error_ns = usecs * 5; + + for (i = 0; i < iters; ++i) { + struct timespec ts1, ts2; + int time_passed; + + ktime_get_ts(&ts1); + udelay(usecs); + ktime_get_ts(&ts2); + time_passed = timespec_to_ns(&ts2) - timespec_to_ns(&ts1); + + if (i == 0 || time_passed < min) + min = time_passed; + if (i == 0 || time_passed > max) + max = time_passed; + if ((time_passed + allowed_error_ns) / 1000 < usecs) + ++fail_count; + WARN_ON(time_passed < 0); + sum += time_passed; + } + + avg = sum; + do_div(avg, iters); + seq_printf(s, "%d usecs x %d: exp=%d allowed=%d min=%d avg=%lld max=%d", + usecs, iters, usecs * 1000, + (usecs * 1000) - allowed_error_ns, min, avg, max); + if (fail_count) + seq_printf(s, " FAIL=%d", fail_count); + seq_puts(s, "\n"); + + return 0; +} + +static int udelay_test_show(struct seq_file *s, void *v) +{ + int usecs; + int iters; + int ret = 0; + + mutex_lock(&udelay_test_lock); + usecs = udelay_test_usecs; + iters = udelay_test_iterations; + mutex_unlock(&udelay_test_lock); + + if (usecs > 0 && iters > 0) { + return udelay_test_single(s, usecs, iters); + } else if (usecs == 0) { + struct timespec ts; + + ktime_get_ts(&ts); + seq_printf(s, "udelay() test (lpj=%ld kt=%ld.%09ld)\n", + loops_per_jiffy, ts.tv_sec, ts.tv_nsec); + seq_puts(s, "usage:\n"); + seq_puts(s, "echo USECS [ITERS] > " DEBUGFS_FILENAME "\n"); + seq_puts(s, "cat " DEBUGFS_FILENAME "\n"); + } + + return ret; +} + +static int udelay_test_open(struct inode *inode, struct file *file) +{ + return single_open(file, udelay_test_show, inode->i_private); +} + +static ssize_t udelay_test_write(struct file *file, const char __user *buf, + size_t count, loff_t *pos) +{ + char lbuf[32]; + int ret; + int usecs; + int iters; + + if (count >= sizeof(lbuf)) + return -EINVAL; + + if (copy_from_user(lbuf, buf, count)) + return -EFAULT; + lbuf[count] = '\0'; + + ret = sscanf(lbuf, "%d %d", &usecs, &iters); + if (ret < 1) + return -EINVAL; + else if (ret < 2) + iters = DEFAULT_ITERATIONS; + + mutex_lock(&udelay_test_lock); + udelay_test_usecs = usecs; + udelay_test_iterations = iters; + mutex_unlock(&udelay_test_lock); + + return count; +} + +static const struct file_operations udelay_test_debugfs_ops = { + .owner = THIS_MODULE, + .open = udelay_test_open, + .read = seq_read, + .write = udelay_test_write, + .llseek = seq_lseek, + .release = single_release, +}; + +static int __init udelay_test_init(void) +{ + mutex_lock(&udelay_test_lock); + udelay_test_debugfs_file = debugfs_create_file(DEBUGFS_FILENAME, + S_IRUSR, NULL, NULL, &udelay_test_debugfs_ops); + mutex_unlock(&udelay_test_lock); + + return 0; +} + +module_init(udelay_test_init); + +static void __exit udelay_test_exit(void) +{ + mutex_lock(&udelay_test_lock); + debugfs_remove(udelay_test_debugfs_file); + mutex_unlock(&udelay_test_lock); +} + +module_exit(udelay_test_exit); + +MODULE_AUTHOR("David Riley <davidriley@xxxxxxxxxxxx>"); +MODULE_LICENSE("GPL"); diff --git a/kernel/time/udelay_test.c b/kernel/time/udelay_test.c deleted file mode 100644 index e622ba3..0000000 --- a/kernel/time/udelay_test.c +++ /dev/null @@ -1,168 +0,0 @@ -/* - * udelay() test kernel module - * - * Test is executed by writing and reading to /sys/kernel/debug/udelay_test - * Tests are configured by writing: USECS ITERATIONS - * Tests are executed by reading from the same file. - * Specifying usecs of 0 or negative values will run multiples tests. - * - * Copyright (C) 2014 Google, Inc. - * - * This software is licensed under the terms of the GNU General Public - * License version 2, as published by the Free Software Foundation, and - * may be copied, distributed, and modified under those terms. - * - * 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. - */ - -#include <linux/debugfs.h> -#include <linux/delay.h> -#include <linux/ktime.h> -#include <linux/module.h> -#include <linux/uaccess.h> - -#define DEFAULT_ITERATIONS 100 - -#define DEBUGFS_FILENAME "udelay_test" - -static DEFINE_MUTEX(udelay_test_lock); -static struct dentry *udelay_test_debugfs_file; -static int udelay_test_usecs; -static int udelay_test_iterations = DEFAULT_ITERATIONS; - -static int udelay_test_single(struct seq_file *s, int usecs, uint32_t iters) -{ - int min = 0, max = 0, fail_count = 0; - uint64_t sum = 0; - uint64_t avg; - int i; - /* Allow udelay to be up to 0.5% fast */ - int allowed_error_ns = usecs * 5; - - for (i = 0; i < iters; ++i) { - struct timespec ts1, ts2; - int time_passed; - - ktime_get_ts(&ts1); - udelay(usecs); - ktime_get_ts(&ts2); - time_passed = timespec_to_ns(&ts2) - timespec_to_ns(&ts1); - - if (i == 0 || time_passed < min) - min = time_passed; - if (i == 0 || time_passed > max) - max = time_passed; - if ((time_passed + allowed_error_ns) / 1000 < usecs) - ++fail_count; - WARN_ON(time_passed < 0); - sum += time_passed; - } - - avg = sum; - do_div(avg, iters); - seq_printf(s, "%d usecs x %d: exp=%d allowed=%d min=%d avg=%lld max=%d", - usecs, iters, usecs * 1000, - (usecs * 1000) - allowed_error_ns, min, avg, max); - if (fail_count) - seq_printf(s, " FAIL=%d", fail_count); - seq_puts(s, "\n"); - - return 0; -} - -static int udelay_test_show(struct seq_file *s, void *v) -{ - int usecs; - int iters; - int ret = 0; - - mutex_lock(&udelay_test_lock); - usecs = udelay_test_usecs; - iters = udelay_test_iterations; - mutex_unlock(&udelay_test_lock); - - if (usecs > 0 && iters > 0) { - return udelay_test_single(s, usecs, iters); - } else if (usecs == 0) { - struct timespec ts; - - ktime_get_ts(&ts); - seq_printf(s, "udelay() test (lpj=%ld kt=%ld.%09ld)\n", - loops_per_jiffy, ts.tv_sec, ts.tv_nsec); - seq_puts(s, "usage:\n"); - seq_puts(s, "echo USECS [ITERS] > " DEBUGFS_FILENAME "\n"); - seq_puts(s, "cat " DEBUGFS_FILENAME "\n"); - } - - return ret; -} - -static int udelay_test_open(struct inode *inode, struct file *file) -{ - return single_open(file, udelay_test_show, inode->i_private); -} - -static ssize_t udelay_test_write(struct file *file, const char __user *buf, - size_t count, loff_t *pos) -{ - char lbuf[32]; - int ret; - int usecs; - int iters; - - if (count >= sizeof(lbuf)) - return -EINVAL; - - if (copy_from_user(lbuf, buf, count)) - return -EFAULT; - lbuf[count] = '\0'; - - ret = sscanf(lbuf, "%d %d", &usecs, &iters); - if (ret < 1) - return -EINVAL; - else if (ret < 2) - iters = DEFAULT_ITERATIONS; - - mutex_lock(&udelay_test_lock); - udelay_test_usecs = usecs; - udelay_test_iterations = iters; - mutex_unlock(&udelay_test_lock); - - return count; -} - -static const struct file_operations udelay_test_debugfs_ops = { - .owner = THIS_MODULE, - .open = udelay_test_open, - .read = seq_read, - .write = udelay_test_write, - .llseek = seq_lseek, - .release = single_release, -}; - -static int __init udelay_test_init(void) -{ - mutex_lock(&udelay_test_lock); - udelay_test_debugfs_file = debugfs_create_file(DEBUGFS_FILENAME, - S_IRUSR, NULL, NULL, &udelay_test_debugfs_ops); - mutex_unlock(&udelay_test_lock); - - return 0; -} - -module_init(udelay_test_init); - -static void __exit udelay_test_exit(void) -{ - mutex_lock(&udelay_test_lock); - debugfs_remove(udelay_test_debugfs_file); - mutex_unlock(&udelay_test_lock); -} - -module_exit(udelay_test_exit); - -MODULE_AUTHOR("David Riley <davidriley@xxxxxxxxxxxx>"); -MODULE_LICENSE("GPL"); -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe linux-next" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html