summaryrefslogtreecommitdiff
path: root/drivers/input/gameport/gameport.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/input/gameport/gameport.c')
-rw-r--r--drivers/input/gameport/gameport.c41
1 files changed, 40 insertions, 1 deletions
diff --git a/drivers/input/gameport/gameport.c b/drivers/input/gameport/gameport.c
index 24c41ba7d4e0..e29c04e2aff4 100644
--- a/drivers/input/gameport/gameport.c
+++ b/drivers/input/gameport/gameport.c
@@ -23,6 +23,7 @@
#include <linux/workqueue.h>
#include <linux/sched.h> /* HZ */
#include <linux/mutex.h>
+#include <linux/timekeeping.h>
/*#include <asm/io.h>*/
@@ -30,6 +31,10 @@ MODULE_AUTHOR("Vojtech Pavlik <vojtech@ucw.cz>");
MODULE_DESCRIPTION("Generic gameport layer");
MODULE_LICENSE("GPL");
+static bool use_ktime = true;
+module_param(use_ktime, bool, 0400);
+MODULE_PARM_DESC(use_ktime, "Use ktime for measuring I/O speed");
+
/*
* gameport_mutex protects entire gameport subsystem and is taken
* every time gameport port or driver registrered or unregistered.
@@ -76,6 +81,38 @@ static unsigned int get_time_pit(void)
static int gameport_measure_speed(struct gameport *gameport)
{
+ unsigned int i, t, tx;
+ u64 t1, t2, t3;
+ unsigned long flags;
+
+ if (gameport_open(gameport, NULL, GAMEPORT_MODE_RAW))
+ return 0;
+
+ tx = ~0;
+
+ for (i = 0; i < 50; i++) {
+ local_irq_save(flags);
+ t1 = ktime_get_ns();
+ for (t = 0; t < 50; t++)
+ gameport_read(gameport);
+ t2 = ktime_get_ns();
+ t3 = ktime_get_ns();
+ local_irq_restore(flags);
+ udelay(i * 10);
+ t = (t2 - t1) - (t3 - t2);
+ if (t < tx)
+ tx = t;
+ }
+
+ gameport_close(gameport);
+ t = 1000000 * 50;
+ if (tx)
+ t /= tx;
+ return t;
+}
+
+static int old_gameport_measure_speed(struct gameport *gameport)
+{
#if defined(__i386__)
unsigned int i, t, t1, t2, t3, tx;
@@ -521,7 +558,9 @@ static void gameport_add_port(struct gameport *gameport)
if (gameport->parent)
gameport->parent->child = gameport;
- gameport->speed = gameport_measure_speed(gameport);
+ gameport->speed = use_ktime ?
+ gameport_measure_speed(gameport) :
+ old_gameport_measure_speed(gameport);
list_add_tail(&gameport->node, &gameport_list);