Patches to speed up SLIP and PPP

Theodore Y. Ts'o (tytso@MIT.EDU)
Sat, 26 Apr 1997 10:44:55 -0400


Enclosed please find patches to speed up SLIP and PPP by decreasing the
latency between when a SLIP and PPP packet comes in, and when it is
actually processed by the networking stack.

- Ted

Patch generated: on Sat Apr 26 10:36:06 EDT 1997 by tytso@rsts-11
against Linux version 2.1.36

===================================================================
RCS file: drivers/char/RCS/serial.c,v
retrieving revision 1.1
diff -u -r1.1 drivers/char/serial.c
--- drivers/char/serial.c 1997/04/25 02:57:49 1.1
+++ drivers/char/serial.c 1997/04/26 04:41:51
@@ -53,9 +53,10 @@
#include <asm/bitops.h>

static char *serial_name = "Serial driver";
-static char *serial_version = "4.24";
+static char *serial_version = "4.25";

static DECLARE_TASK_QUEUE(tq_serial);
+static DECLARE_TASK_QUEUE(tq_expedite);

static struct tty_driver serial_driver, callout_driver;
static int serial_refcount;
@@ -464,7 +465,7 @@
}

static _INLINE_ void receive_chars(struct async_struct *info,
- int *status)
+ int *status)
{
struct tty_struct *tty = info->tty;
unsigned char ch;
@@ -478,7 +479,9 @@
break;
*tty->flip.char_buf_ptr = ch;
icount->rx++;
-
+ if (info->expedite_char && ch == info->expedite_char)
+ queue_task(&info->tqueue_expedite, &tq_expedite);
+
#ifdef SERIAL_DEBUG_INTR
printk("DR%02x:%02x...", ch, *status);
#endif
@@ -715,6 +718,12 @@
#endif
break; /* Prevent infinite loops */
}
+ if (tq_expedite) {
+ sti();
+ run_task_queue(&tq_expedite);
+ end_mark = 0;
+ cli();
+ }
continue;
}
} while (end_mark != info);
@@ -774,6 +783,11 @@
#endif
break;
}
+ if (tq_expedite) {
+ sti();
+ run_task_queue(&tq_expedite);
+ cli();
+ }
} while (!(serial_in(info, UART_IIR) & UART_IIR_NO_INT));
info->last_active = jiffies;
#ifdef CONFIG_SERIAL_MULTIPORT
@@ -844,6 +858,11 @@
#endif
break; /* Prevent infinite loops */
}
+ if (tq_expedite) {
+ sti();
+ run_task_queue(&tq_expedite);
+ cli();
+ }
if (multi->port_monitor)
printk("rs port monitor irq %d: 0x%x, 0x%x\n",
info->state->irq, first_multi,
@@ -1140,7 +1159,13 @@
#endif
handler = rs_interrupt;
#else
- retval = -EBUSY;
+ if (suser()) {
+ if (info->tty)
+ set_bit(TTY_IO_ERROR,
+ &info->tty->flags);
+ retval = 0;
+ } else
+ retval = -EBUSY;
goto errout;
#endif /* CONFIG_SERIAL_SHARE_IRQ */
} else
@@ -2369,6 +2394,34 @@
}

/*
+ * rs_set_ldisc()
+ *
+ * Called by the high-level tty routines to notify the driver of a
+ * line discpline change.
+ */
+static void rs_set_ldisc(struct tty_struct *tty)
+{
+ struct async_struct * info = (struct async_struct *)tty->driver_data;
+
+ if (!info || serial_paranoia_check(info, tty->device, "rs_set_ldisc"))
+ return;
+
+ switch (tty->ldisc.num) {
+ case N_SLIP:
+ info->expedite_char = 0xC0;
+ break;
+ case N_PPP:
+ info->expedite_char = 0x7E;
+ break;
+ case N_STRIP:
+ info->expedite_char = 0x0D;
+ break;
+ default:
+ info->expedite_char = 0;
+ }
+}
+
+/*
* ------------------------------------------------------------
* rs_close()
*
@@ -2750,6 +2803,8 @@
return retval;
if (serial_paranoia_check(info, tty->device, "rs_open"))
return -ENODEV;
+ info->tqueue_expedite.routine = tty->flip.tqueue.routine;
+ info->tqueue_expedite.data = tty->flip.tqueue.data;

#ifdef SERIAL_DEBUG_OPEN
printk("rs_open %s%d, count = %d\n", tty->driver.name, info->line,
@@ -2774,6 +2829,7 @@
retval = startup(info);
if (retval)
return retval;
+ rs_set_ldisc(tty);

MOD_INC_USE_COUNT;
retval = block_til_ready(tty, filp, info);
@@ -3161,7 +3217,6 @@
scratch = serial_in(info, UART_IIR) >> 5;
if (scratch == 7) {
serial_outp(info, UART_LCR, 0);
- serial_outp(info, UART_FCR, UART_FCR_ENABLE_FIFO);
scratch = serial_in(info, UART_IIR) >> 5;
if (scratch == 6)
state->type = PORT_16750;
@@ -3273,6 +3328,7 @@
serial_driver.unthrottle = rs_unthrottle;
serial_driver.send_xchar = rs_send_xchar;
serial_driver.set_termios = rs_set_termios;
+ serial_driver.set_ldisc = rs_set_ldisc;
serial_driver.stop = rs_stop;
serial_driver.start = rs_start;
serial_driver.hangup = rs_hangup;
===================================================================
RCS file: drivers/char/RCS/tty_io.c,v
retrieving revision 1.1
diff -u -r1.1 drivers/char/tty_io.c
--- drivers/char/tty_io.c 1997/04/26 03:08:57 1.1
+++ drivers/char/tty_io.c 1997/04/26 03:09:52
@@ -1535,7 +1535,9 @@
unsigned char *cp;
char *fp;
int count;
+ unsigned long flags;

+ save_flags(flags);
if (tty->flip.buf_num) {
cp = tty->flip.char_buf + TTY_FLIPBUF_SIZE;
fp = tty->flip.flag_buf + TTY_FLIPBUF_SIZE;
@@ -1555,7 +1557,7 @@
}
count = tty->flip.count;
tty->flip.count = 0;
- sti();
+ restore_flags(flags);

#if 0
if (count > tty->max_flip_cnt)
===================================================================
RCS file: include/linux/RCS/serial.h,v
retrieving revision 1.1
diff -u -r1.1 include/linux/serial.h
--- include/linux/serial.h 1997/04/26 03:11:22 1.1
+++ include/linux/serial.h 1997/04/26 03:55:54
@@ -200,8 +200,10 @@
int xmit_head;
int xmit_tail;
int xmit_cnt;
+ char expedite_char;
struct tq_struct tqueue;
struct tq_struct tqueue_hangup;
+ struct tq_struct tqueue_expedite;
struct wait_queue *open_wait;
struct wait_queue *close_wait;
struct wait_queue *delta_msr_wait;