[PATCH RT] update of lpptest

From: Steven Rostedt
Date: Fri Feb 16 2007 - 15:30:58 EST


Ingo and Thomas,

Here's a clean up of the lpptest. I removed the dependency to the TSC
and I now use the getnstimeofday for measuring the latency. I also added
code to request the port region.

I plan on doing more with this utility, but figured I'd send updates at
stages of progress.

-- Steve

Index: linux-2.6.20-rt7/drivers/char/lpptest.c
===================================================================
--- linux-2.6.20-rt7.orig/drivers/char/lpptest.c 2007-02-16 10:56:01.000000000 -0500
+++ linux-2.6.20-rt7/drivers/char/lpptest.c 2007-02-16 14:12:49.000000000 -0500
@@ -3,11 +3,42 @@
*
* Copyright (C) 2005 Thomas Gleixner, Ingo Molnar
*
+ * Resurrected by Steven Rostedt:
+ * - Slight code clean up.
+ * - Remove dependency on TSC (getnstimeofday is good enough)
+ *
* licensed under the GPL
*
* You need to have CONFIG_PARPORT disabled for this device, it is a
* completely self-contained device that assumes sole ownership of the
* parallel port.
+ *
+ * Notes:
+ * 1. The above is VERY important! Don't even load the parport module
+ * because once it is loaded, you might as well reboot. The parport
+ * modules (specifically parport_pc) screws up the parport and this
+ * poor simple lpptest module goes haywire. Removing the module is
+ * not even good enough. The parport code just ruins it for lpptest.
+ * So turn CONFIG_PARPORT to No.
+ *
+ * 2. This has been tested with the parallel port mode settings of both
+ * SPP(PS/2) and EPP. Both should work for both test and monitor
+ * machines.
+ *
+ * 3. If it doesn't work:
+ * a. Check to make sure none of the parport drivers were ever
+ * loaded (including lp).
+ * b. Check to make sure you have a data transfer cable.
+ * Min pin layout:
+ * 5 - 10
+ * 10 - 5
+ * GRD - GRD
+ * c. Make sure that the parallel port connector that sticks out
+ * of the chassis actually connects to the motherboard **.
+ *
+ * ** - I spent an entire day trying to figure out why it wasn't working,
+ * until I opened up the box to find that the connector wasn't plugged
+ * into the motherboard. Needless to say, I wasn't too happy - SDR
*/
#include <linux/sched.h>
#include <linux/kernel.h>
@@ -47,11 +78,24 @@
#define LPPTEST_DISABLE _IOR (LPPTEST_CHAR_MAJOR, 2, unsigned long long)
#define LPPTEST_ENABLE _IOR (LPPTEST_CHAR_MAJOR, 3, unsigned long long)

+#define LPPTEST_PORT_BASE 0x378
+
+#define LPPTEST_DATA_PORT (LPPTEST_PORT_BASE)
+#define LPPTEST_STAT_PORT (LPPTEST_PORT_BASE+1)
+#define LPPTEST_CTRL_PORT (LPPTEST_PORT_BASE+2)
+
+#define LPPTEST_PORT_SIZE 3
+
static char dev_id[] = "lpptest";

-#define INIT_PORT() outb(0x04, 0x37a)
-#define ENABLE_IRQ() outb(0x10, 0x37a)
-#define DISABLE_IRQ() outb(0, 0x37a)
+#define lpptest_data_out(x) outb(x, LPPTEST_DATA_PORT)
+#define lpptest_data_in(x) inb(LPPTEST_DATA_PORT)
+#define lpptest_stat_in() inb(LPPTEST_STAT_PORT)
+#define lpptest_ctrl_out(x) outb(x, LPPTEST_CTRL_PORT)
+
+#define INIT_PORT() lpptest_ctrl_out(0x04)
+#define ENABLE_IRQ() lpptest_ctrl_out(0x10)
+#define DISABLE_IRQ() lpptest_ctrl_out(0x00)

static unsigned char out = 0x5a;

@@ -61,37 +105,44 @@ static unsigned char out = 0x5a;
static int lpptest_irq (int irq, void *dev_id)
{
out ^= 0xff;
- outb(out, 0x378);
+ lpptest_data_out(out);

return IRQ_HANDLED;
}

-static cycles_t test_response(void)
+static u64 test_response(void)
{
- cycles_t now, end;
+ struct timespec start, end;
+ u64 startns, endns;
unsigned char in;
int timeout = 0;

local_irq_disable();
- in = inb(0x379);
- inb(0x378);
- outb(0x08, 0x378);
- now = get_cycles();
+
+ in = lpptest_stat_in();
+ lpptest_data_in();
+ lpptest_data_out(0x08);
+
+ getnstimeofday(&start);
while(1) {
if (inb(0x379) != in)
break;
if (timeout++ > 1000000) {
- outb(0x00, 0x378);
+ lpptest_data_out(0x00);
local_irq_enable();
-
return 0;
}
}
- end = get_cycles();
- outb(0x00, 0x378);
+ getnstimeofday(&end);
+ lpptest_data_out(0x00);
local_irq_enable();

- return end - now;
+ startns = (u64)start.tv_sec * 1000000000ULL;
+ startns += start.tv_nsec;
+ endns = (u64)end.tv_sec * 1000000000ULL;
+ endns += end.tv_nsec;
+
+ return endns - startns;
}

static int lpptest_open(struct inode *inode, struct file *file)
@@ -120,7 +171,7 @@ int lpptest_ioctl(struct inode *inode, s

case LPPTEST_TEST: {

- cycles_t diff = test_response();
+ unsigned long long diff = test_response();
if (copy_to_user((void *)ioctl_param, (void*) &diff, sizeof(diff)))
goto errcpy;
break;
@@ -142,17 +193,26 @@ static struct file_operations lpptest_de

static int __init lpptest_init (void)
{
+ struct resource *res;
+ int ret = -EAGAIN;
+
+ res = request_region(LPPTEST_PORT_BASE, LPPTEST_PORT_SIZE, LPPTEST_DEVICE_NAME);
+ if (!res) {
+ printk(KERN_NOTICE "Can't allocate region %x for lpp.\n",
+ LPPTEST_PORT_BASE);
+ goto out;
+ }
+
if (register_chrdev(LPPTEST_CHAR_MAJOR, LPPTEST_DEVICE_NAME, &lpptest_dev_fops))
{
printk(KERN_NOTICE "Can't allocate major number %d for lpptest.\n",
LPPTEST_CHAR_MAJOR);
- return -EAGAIN;
+ goto out1;
}

if (request_irq (LPPTEST_IRQ, lpptest_irq, 0, "lpptest", dev_id)) {
printk (KERN_WARNING "lpptest: irq %d in use. Unload parport module!\n", LPPTEST_IRQ);
- unregister_chrdev(LPPTEST_CHAR_MAJOR, LPPTEST_DEVICE_NAME);
- return -EAGAIN;
+ goto out2;
}
irq_desc[LPPTEST_IRQ].status |= IRQ_NODELAY;
irq_desc[LPPTEST_IRQ].action->flags |= IRQF_NODELAY | IRQF_DISABLED;
@@ -161,6 +221,13 @@ static int __init lpptest_init (void)
ENABLE_IRQ();

return 0;
+ out2:
+ unregister_chrdev(LPPTEST_CHAR_MAJOR, LPPTEST_DEVICE_NAME);
+ out1:
+ release_region(LPPTEST_PORT_BASE, LPPTEST_PORT_SIZE);
+ out:
+ return ret;
+
}
module_init (lpptest_init);

@@ -170,6 +237,7 @@ static void __exit lpptest_exit (void)

free_irq(LPPTEST_IRQ, dev_id);
unregister_chrdev(LPPTEST_CHAR_MAJOR, LPPTEST_DEVICE_NAME);
+ release_region(LPPTEST_PORT_BASE, LPPTEST_PORT_SIZE);
}
module_exit (lpptest_exit);

Index: linux-2.6.20-rt7/scripts/testlpp.c
===================================================================
--- linux-2.6.20-rt7.orig/scripts/testlpp.c 2007-02-16 10:46:56.000000000 -0500
+++ linux-2.6.20-rt7/scripts/testlpp.c 2007-02-16 14:02:57.000000000 -0500
@@ -4,6 +4,10 @@
*
* Copyright (C) 2005 Thomas Gleixner
*
+ * Resurrected by Steven Rostedt:
+ * - Slight code clean up.
+ * - Remove dependency on TSC (the driver returns nsecs).
+ *
* licensed under the GPL
*/
#include <unistd.h>
@@ -51,34 +55,12 @@ static void print_hist(void)
}
}

-static inline unsigned long long int rdtsc(void)
-{
- unsigned long long int x, y;
- for (;;) {
- __asm__ volatile ("rdtsc" : "=A" (x));
- __asm__ volatile ("rdtsc" : "=A" (y));
- if (y - x < 1000)
- return y;
- }
-}
-
-static unsigned long long calibrate_loop(void)
-{
- unsigned long long mytime1, mytime2;
-
- mytime1 = rdtsc();
- usleep(500000);
- mytime2 = rdtsc();
-
- return (mytime2 - mytime1) * 2;
-}
-
-#define time_to_usecs(time) ((double)time*1000000.0/(double)cycles_per_sec)
+#define time_to_usecs(time) ((double)time/1000.0)

-#define time_to_usecs_l(time) (long)(time*1000000/cycles_per_sec)
+#define time_to_usecs_l(time) (long)(time/1000)

int fd, total;
-unsigned long long tim, sum_tim, min_tim = -1ULL, max_tim, cycles_per_sec;
+unsigned long long tim, sum_tim, min_tim = -1ULL, max_tim;

void cleanup(int sig)
{
@@ -125,9 +107,6 @@ int main (int argc, char **argv)

ioctl (fd, LPPTEST_DISABLE, &tim);

- fprintf(stderr, "calibrating cycles to usecs: ");
- cycles_per_sec = calibrate_loop();
- fprintf(stderr, "%lld cycles per usec\n", cycles_per_sec/1000000);
if (nr_requests)
fprintf(stderr, "[max # of requests: %u]\n", nr_requests);
fprintf(stderr, "starting %dHz test, hit Ctrl-C to stop:\n\n", HZ);
@@ -139,7 +118,7 @@ int main (int argc, char **argv)
else {
hist_hit(time_to_usecs_l(tim));
if (tim > max_tim) {
- printf ("new max latency: %.2lf usecs (%Ld cycles)\n", time_to_usecs(tim), tim);
+ printf ("new max latency: %.2lf usecs (%Ld nsecs)\n", time_to_usecs(tim), tim);
max_tim = tim;
}
if (tim < min_tim)


-
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/