Merge to Fedora kernel-2.6.18-1.2224_FC5 patched with stable patch-2.6.18.1-vs2.0...
[linux-2.6.git] / drivers / char / stallion.c
index 90018ce..3beb220 100644 (file)
@@ -26,7 +26,6 @@
 
 /*****************************************************************************/
 
-#include <linux/config.h>
 #include <linux/module.h>
 #include <linux/slab.h>
 #include <linux/interrupt.h>
@@ -40,8 +39,8 @@
 #include <linux/ioport.h>
 #include <linux/init.h>
 #include <linux/smp_lock.h>
-#include <linux/devfs_fs_kernel.h>
 #include <linux/device.h>
+#include <linux/delay.h>
 
 #include <asm/io.h>
 #include <asm/uaccess.h>
@@ -102,7 +101,7 @@ static stlconf_t    stl_brdconf[] = {
        /*{ BRD_EASYIO, 0x2a0, 0, 0, 10, 0 },*/
 };
 
-static int     stl_nrbrds = sizeof(stl_brdconf) / sizeof(stlconf_t);
+static int     stl_nrbrds = ARRAY_SIZE(stl_brdconf);
 
 /*****************************************************************************/
 
@@ -139,16 +138,6 @@ static char        *stl_drvversion = "5.6.0";
 
 static struct tty_driver       *stl_serial;
 
-/*
- *     We will need to allocate a temporary write buffer for chars that
- *     come direct from user space. The problem is that a copy from user
- *     space might cause a page fault (typically on a system that is
- *     swapping!). All ports will share one buffer - since if the system
- *     is already swapping a shared buffer won't make things any worse.
- */
-static char                    *stl_tmpwritebuf;
-static DECLARE_MUTEX(stl_tmpwritesem);
-
 /*
  *     Define a local default termios struct. All ports will be created
  *     with this termios initially. Basically all it defines is a raw port
@@ -173,14 +162,6 @@ static stlport_t   stl_dummyport;
  */
 static char            stl_unwanted[SC26198_RXFIFOSIZE];
 
-/*
- *     Keep track of what interrupts we have requested for us.
- *     We don't need to request an interrupt twice if it is being
- *     shared with another Stallion board.
- */
-static int     stl_gotintrs[STL_MAXBRDS];
-static int     stl_numintrs;
-
 /*****************************************************************************/
 
 static stlbrd_t                *stl_brds[STL_MAXBRDS];
@@ -239,13 +220,12 @@ static char       *stl_brdnames[] = {
 
 /*****************************************************************************/
 
-#ifdef MODULE
 /*
  *     Define some string labels for arguments passed from the module
  *     load line. These allow for easy board definitions, and easy
  *     modification of the io, memory and irq resoucres.
  */
-
+static int     stl_nargs = 0;
 static char    *board0[4];
 static char    *board1[4];
 static char    *board2[4];
@@ -306,17 +286,15 @@ MODULE_AUTHOR("Greg Ungerer");
 MODULE_DESCRIPTION("Stallion Multiport Serial Driver");
 MODULE_LICENSE("GPL");
 
-MODULE_PARM(board0, "1-4s");
+module_param_array(board0, charp, &stl_nargs, 0);
 MODULE_PARM_DESC(board0, "Board 0 config -> name[,ioaddr[,ioaddr2][,irq]]");
-MODULE_PARM(board1, "1-4s");
+module_param_array(board1, charp, &stl_nargs, 0);
 MODULE_PARM_DESC(board1, "Board 1 config -> name[,ioaddr[,ioaddr2][,irq]]");
-MODULE_PARM(board2, "1-4s");
+module_param_array(board2, charp, &stl_nargs, 0);
 MODULE_PARM_DESC(board2, "Board 2 config -> name[,ioaddr[,ioaddr2][,irq]]");
-MODULE_PARM(board3, "1-4s");
+module_param_array(board3, charp, &stl_nargs, 0);
 MODULE_PARM_DESC(board3, "Board 3 config -> name[,ioaddr[,ioaddr2][,irq]]");
 
-#endif
-
 /*****************************************************************************/
 
 /*
@@ -373,6 +351,14 @@ static unsigned char       stl_vecmap[] = {
        0xff, 0xff, 0x00, 0x02, 0x01, 0xff, 0xff, 0x03
 };
 
+/*
+ *     Lock ordering is that you may not take stallion_lock holding
+ *     brd_lock.
+ */
+
+static spinlock_t brd_lock;            /* Guard the board mapping */
+static spinlock_t stallion_lock;       /* Guard the tty driver */
+
 /*
  *     Set up enable and disable macros for the ECH boards. They require
  *     the secondary io address space to be activated and deactivated.
@@ -434,7 +420,7 @@ static stlpcibrd_t  stl_pcibrds[] = {
        { PCI_VENDOR_ID_NS, PCI_DEVICE_ID_NS_87410, BRD_ECHPCI },
 };
 
-static int     stl_nrpcibrds = sizeof(stl_pcibrds) / sizeof(stlpcibrd_t);
+static int     stl_nrpcibrds = ARRAY_SIZE(stl_pcibrds);
 
 #endif
 
@@ -471,17 +457,15 @@ static unsigned int       stl_baudrates[] = {
  *     Declare all those functions in this driver!
  */
 
-#ifdef MODULE
 static void    stl_argbrds(void);
 static int     stl_parsebrd(stlconf_t *confp, char **argp);
 
 static unsigned long stl_atol(char *str);
-#endif
 
-int            stl_init(void);
+static int     stl_init(void);
 static int     stl_open(struct tty_struct *tty, struct file *filp);
 static void    stl_close(struct tty_struct *tty, struct file *filp);
-static int     stl_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count);
+static int     stl_write(struct tty_struct *tty, const unsigned char *buf, int count);
 static void    stl_putchar(struct tty_struct *tty, unsigned char ch);
 static void    stl_flushchars(struct tty_struct *tty);
 static int     stl_writeroom(struct tty_struct *tty);
@@ -503,7 +487,6 @@ static int  stl_readproc(char *page, char **start, off_t off, int count, int *eof
 
 static int     stl_brdinit(stlbrd_t *brdp);
 static int     stl_initports(stlbrd_t *brdp, stlpanel_t *panelp);
-static int     stl_mapirq(int irq, char *name);
 static int     stl_getserial(stlport_t *portp, struct serial_struct __user *sp);
 static int     stl_setserial(stlport_t *portp, struct serial_struct __user *sp);
 static int     stl_getbrdstats(combrd_t __user *bp);
@@ -512,14 +495,12 @@ static int        stl_clrportstats(stlport_t *portp, comstats_t __user *cp);
 static int     stl_getportstruct(stlport_t __user *arg);
 static int     stl_getbrdstruct(stlbrd_t __user *arg);
 static int     stl_waitcarrier(stlport_t *portp, struct file *filp);
-static void    stl_delay(int len);
-static void    stl_eiointr(stlbrd_t *brdp);
-static void    stl_echatintr(stlbrd_t *brdp);
-static void    stl_echmcaintr(stlbrd_t *brdp);
-static void    stl_echpciintr(stlbrd_t *brdp);
-static void    stl_echpci64intr(stlbrd_t *brdp);
+static int     stl_eiointr(stlbrd_t *brdp);
+static int     stl_echatintr(stlbrd_t *brdp);
+static int     stl_echmcaintr(stlbrd_t *brdp);
+static int     stl_echpciintr(stlbrd_t *brdp);
+static int     stl_echpci64intr(stlbrd_t *brdp);
 static void    stl_offintr(void *private);
-static void    *stl_memalloc(int len);
 static stlbrd_t *stl_allocbrd(void);
 static stlport_t *stl_getport(int brdnr, int panelnr, int portnr);
 
@@ -718,7 +699,7 @@ static unsigned int sc26198_baudtable[] = {
        230400, 460800, 921600
 };
 
-#define        SC26198_NRBAUDS         (sizeof(sc26198_baudtable) / sizeof(unsigned int))
+#define        SC26198_NRBAUDS         ARRAY_SIZE(sc26198_baudtable)
 
 /*****************************************************************************/
 
@@ -726,16 +707,14 @@ static unsigned int       sc26198_baudtable[] = {
  *     Define the driver info for a user level control device. Used mainly
  *     to get at port stats - only not using the port device itself.
  */
-static struct file_operations  stl_fsiomem = {
+static const struct file_operations    stl_fsiomem = {
        .owner          = THIS_MODULE,
        .ioctl          = stl_memioctl,
 };
 
 /*****************************************************************************/
 
-static struct class_simple *stallion_class;
-
-#ifdef MODULE
+static struct class *stallion_class;
 
 /*
  *     Loadable module initialization stuff.
@@ -743,18 +722,8 @@ static struct class_simple *stallion_class;
 
 static int __init stallion_module_init(void)
 {
-       unsigned long   flags;
-
-#ifdef DEBUG
-       printk("init_module()\n");
-#endif
-
-       save_flags(flags);
-       cli();
        stl_init();
-       restore_flags(flags);
-
-       return(0);
+       return 0;
 }
 
 /*****************************************************************************/
@@ -764,7 +733,6 @@ static void __exit stallion_module_exit(void)
        stlbrd_t        *brdp;
        stlpanel_t      *panelp;
        stlport_t       *portp;
-       unsigned long   flags;
        int             i, j, k;
 
 #ifdef DEBUG
@@ -774,9 +742,6 @@ static void __exit stallion_module_exit(void)
        printk(KERN_INFO "Unloading %s: version %s\n", stl_drvtitle,
                stl_drvversion);
 
-       save_flags(flags);
-       cli();
-
 /*
  *     Free up all allocated resources used by the ports. This includes
  *     memory and interrupts. As part of this process we will also do
@@ -788,25 +753,21 @@ static void __exit stallion_module_exit(void)
        if (i) {
                printk("STALLION: failed to un-register tty driver, "
                        "errno=%d\n", -i);
-               restore_flags(flags);
                return;
        }
-       for (i = 0; i < 4; i++) {
-               devfs_remove("staliomem/%d", i);
-               class_simple_device_remove(MKDEV(STL_SIOMEMMAJOR, i));
-       }
-       devfs_remove("staliomem");
+       for (i = 0; i < 4; i++)
+               class_device_destroy(stallion_class, MKDEV(STL_SIOMEMMAJOR, i));
        if ((i = unregister_chrdev(STL_SIOMEMMAJOR, "staliomem")))
                printk("STALLION: failed to un-register serial memory device, "
                        "errno=%d\n", -i);
-       class_simple_destroy(stallion_class);
-
-       if (stl_tmpwritebuf != (char *) NULL)
-               kfree(stl_tmpwritebuf);
+       class_destroy(stallion_class);
 
        for (i = 0; (i < stl_nrbrds); i++) {
                if ((brdp = stl_brds[i]) == (stlbrd_t *) NULL)
                        continue;
+
+               free_irq(brdp->irq, brdp);
+
                for (j = 0; (j < STL_MAXPANELS); j++) {
                        panelp = brdp->panels[j];
                        if (panelp == (stlpanel_t *) NULL)
@@ -817,8 +778,7 @@ static void __exit stallion_module_exit(void)
                                        continue;
                                if (portp->tty != (struct tty_struct *) NULL)
                                        stl_hangup(portp->tty);
-                               if (portp->tx.buf != (char *) NULL)
-                                       kfree(portp->tx.buf);
+                               kfree(portp->tx.buf);
                                kfree(portp);
                        }
                        kfree(panelp);
@@ -831,11 +791,6 @@ static void __exit stallion_module_exit(void)
                kfree(brdp);
                stl_brds[i] = (stlbrd_t *) NULL;
        }
-
-       for (i = 0; (i < stl_numintrs); i++)
-               free_irq(stl_gotintrs[i], NULL);
-
-       restore_flags(flags);
 }
 
 module_init(stallion_module_init);
@@ -851,15 +806,13 @@ static void stl_argbrds(void)
 {
        stlconf_t       conf;
        stlbrd_t        *brdp;
-       int             nrargs, i;
+       int             i;
 
 #ifdef DEBUG
        printk("stl_argbrds()\n");
 #endif
 
-       nrargs = sizeof(stl_brdsp) / sizeof(char **);
-
-       for (i = stl_nrbrds; (i < nrargs); i++) {
+       for (i = stl_nrbrds; (i < stl_nargs); i++) {
                memset(&conf, 0, sizeof(conf));
                if (stl_parsebrd(&conf, stl_brdsp[i]) == 0)
                        continue;
@@ -909,7 +862,7 @@ static unsigned long stl_atol(char *str)
                }
                val = (val * base) + c;
        }
-       return(val);
+       return val;
 }
 
 /*****************************************************************************/
@@ -921,26 +874,25 @@ static unsigned long stl_atol(char *str)
 static int stl_parsebrd(stlconf_t *confp, char **argp)
 {
        char    *sp;
-       int     nrbrdnames, i;
+       int     i;
 
 #ifdef DEBUG
        printk("stl_parsebrd(confp=%x,argp=%x)\n", (int) confp, (int) argp);
 #endif
 
        if ((argp[0] == (char *) NULL) || (*argp[0] == 0))
-               return(0);
+               return 0;
 
        for (sp = argp[0], i = 0; ((*sp != 0) && (i < 25)); sp++, i++)
                *sp = TOLOWER(*sp);
 
-       nrbrdnames = sizeof(stl_brdstr) / sizeof(stlbrdtype_t);
-       for (i = 0; (i < nrbrdnames); i++) {
+       for (i = 0; i < ARRAY_SIZE(stl_brdstr); i++) {
                if (strcmp(stl_brdstr[i].name, argp[0]) == 0)
                        break;
        }
-       if (i >= nrbrdnames) {
+       if (i == ARRAY_SIZE(stl_brdstr)) {
                printk("STALLION: unknown board name, %s?\n", argp[0]);
-               return(0);
+               return 0;
        }
 
        confp->brdtype = stl_brdstr[i].type;
@@ -956,20 +908,7 @@ static int stl_parsebrd(stlconf_t *confp, char **argp)
        }
        if ((argp[i] != (char *) NULL) && (*argp[i] != 0))
                confp->irq = stl_atol(argp[i]);
-       return(1);
-}
-
-#endif
-
-/*****************************************************************************/
-
-/*
- *     Local driver kernel memory allocation routine.
- */
-
-static void *stl_memalloc(int len)
-{
-       return((void *) kmalloc(len, GFP_KERNEL));
+       return 1;
 }
 
 /*****************************************************************************/
@@ -982,16 +921,15 @@ static stlbrd_t *stl_allocbrd(void)
 {
        stlbrd_t        *brdp;
 
-       brdp = (stlbrd_t *) stl_memalloc(sizeof(stlbrd_t));
-       if (brdp == (stlbrd_t *) NULL) {
-               printk("STALLION: failed to allocate memory (size=%d)\n",
+       brdp = kzalloc(sizeof(stlbrd_t), GFP_KERNEL);
+       if (!brdp) {
+               printk("STALLION: failed to allocate memory (size=%Zd)\n",
                        sizeof(stlbrd_t));
-               return((stlbrd_t *) NULL);
+               return NULL;
        }
 
-       memset(brdp, 0, sizeof(stlbrd_t));
        brdp->magic = STL_BOARDMAGIC;
-       return(brdp);
+       return brdp;
 }
 
 /*****************************************************************************/
@@ -1011,10 +949,10 @@ static int stl_open(struct tty_struct *tty, struct file *filp)
        minordev = tty->index;
        brdnr = MINOR2BRD(minordev);
        if (brdnr >= stl_nrbrds)
-               return(-ENODEV);
+               return -ENODEV;
        brdp = stl_brds[brdnr];
        if (brdp == (stlbrd_t *) NULL)
-               return(-ENODEV);
+               return -ENODEV;
        minordev = MINOR2PORT(minordev);
        for (portnr = -1, panelnr = 0; (panelnr < STL_MAXPANELS); panelnr++) {
                if (brdp->panels[panelnr] == (stlpanel_t *) NULL)
@@ -1026,11 +964,11 @@ static int stl_open(struct tty_struct *tty, struct file *filp)
                minordev -= brdp->panels[panelnr]->nrports;
        }
        if (portnr < 0)
-               return(-ENODEV);
+               return -ENODEV;
 
        portp = brdp->panels[panelnr]->ports[portnr];
        if (portp == (stlport_t *) NULL)
-               return(-ENODEV);
+               return -ENODEV;
 
 /*
  *     On the first open of the device setup the port hardware, and
@@ -1041,10 +979,10 @@ static int stl_open(struct tty_struct *tty, struct file *filp)
        portp->refcount++;
 
        if ((portp->flags & ASYNC_INITIALIZED) == 0) {
-               if (portp->tx.buf == (char *) NULL) {
-                       portp->tx.buf = (char *) stl_memalloc(STL_TXBUFSIZE);
-                       if (portp->tx.buf == (char *) NULL)
-                               return(-ENOMEM);
+               if (!portp->tx.buf) {
+                       portp->tx.buf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL);
+                       if (!portp->tx.buf)
+                               return -ENOMEM;
                        portp->tx.head = portp->tx.buf;
                        portp->tx.tail = portp->tx.buf;
                }
@@ -1066,8 +1004,8 @@ static int stl_open(struct tty_struct *tty, struct file *filp)
        if (portp->flags & ASYNC_CLOSING) {
                interruptible_sleep_on(&portp->close_wait);
                if (portp->flags & ASYNC_HUP_NOTIFY)
-                       return(-EAGAIN);
-               return(-ERESTARTSYS);
+                       return -EAGAIN;
+               return -ERESTARTSYS;
        }
 
 /*
@@ -1077,11 +1015,11 @@ static int stl_open(struct tty_struct *tty, struct file *filp)
  */
        if (!(filp->f_flags & O_NONBLOCK)) {
                if ((rc = stl_waitcarrier(portp, filp)) != 0)
-                       return(rc);
+                       return rc;
        }
        portp->flags |= ASYNC_NORMAL_ACTIVE;
 
-       return(0);
+       return 0;
 }
 
 /*****************************************************************************/
@@ -1103,16 +1041,17 @@ static int stl_waitcarrier(stlport_t *portp, struct file *filp)
        rc = 0;
        doclocal = 0;
 
+       spin_lock_irqsave(&stallion_lock, flags);
+
        if (portp->tty->termios->c_cflag & CLOCAL)
                doclocal++;
 
-       save_flags(flags);
-       cli();
        portp->openwaitcnt++;
        if (! tty_hung_up_p(filp))
                portp->refcount--;
 
        for (;;) {
+               /* Takes brd_lock internally */
                stl_setsignals(portp, 1, 1);
                if (tty_hung_up_p(filp) ||
                    ((portp->flags & ASYNC_INITIALIZED) == 0)) {
@@ -1130,15 +1069,16 @@ static int stl_waitcarrier(stlport_t *portp, struct file *filp)
                        rc = -ERESTARTSYS;
                        break;
                }
+               /* FIXME */
                interruptible_sleep_on(&portp->open_wait);
        }
 
        if (! tty_hung_up_p(filp))
                portp->refcount++;
        portp->openwaitcnt--;
-       restore_flags(flags);
+       spin_unlock_irqrestore(&stallion_lock, flags);
 
-       return(rc);
+       return rc;
 }
 
 /*****************************************************************************/
@@ -1156,16 +1096,15 @@ static void stl_close(struct tty_struct *tty, struct file *filp)
        if (portp == (stlport_t *) NULL)
                return;
 
-       save_flags(flags);
-       cli();
+       spin_lock_irqsave(&stallion_lock, flags);
        if (tty_hung_up_p(filp)) {
-               restore_flags(flags);
+               spin_unlock_irqrestore(&stallion_lock, flags);
                return;
        }
        if ((tty->count == 1) && (portp->refcount != 1))
                portp->refcount = 1;
        if (portp->refcount-- > 1) {
-               restore_flags(flags);
+               spin_unlock_irqrestore(&stallion_lock, flags);
                return;
        }
 
@@ -1179,11 +1118,18 @@ static void stl_close(struct tty_struct *tty, struct file *filp)
  *     (The sc26198 has no "end-of-data" interrupt only empty FIFO)
  */
        tty->closing = 1;
+
+       spin_unlock_irqrestore(&stallion_lock, flags);
+
        if (portp->closing_wait != ASYNC_CLOSING_WAIT_NONE)
                tty_wait_until_sent(tty, portp->closing_wait);
        stl_waituntilsent(tty, (HZ / 2));
 
+
+       spin_lock_irqsave(&stallion_lock, flags);
        portp->flags &= ~ASYNC_INITIALIZED;
+       spin_unlock_irqrestore(&stallion_lock, flags);
+
        stl_disableintrs(portp);
        if (tty->termios->c_cflag & HUPCL)
                stl_setsignals(portp, 0, 0);
@@ -1204,32 +1150,12 @@ static void stl_close(struct tty_struct *tty, struct file *filp)
 
        if (portp->openwaitcnt) {
                if (portp->close_delay)
-                       stl_delay(portp->close_delay);
+                       msleep_interruptible(jiffies_to_msecs(portp->close_delay));
                wake_up_interruptible(&portp->open_wait);
        }
 
        portp->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
        wake_up_interruptible(&portp->close_wait);
-       restore_flags(flags);
-}
-
-/*****************************************************************************/
-
-/*
- *     Wait for a specified delay period, this is not a busy-loop. It will
- *     give up the processor while waiting. Unfortunately this has some
- *     rather intimate knowledge of the process management stuff.
- */
-
-static void stl_delay(int len)
-{
-#ifdef DEBUG
-       printk("stl_delay(len=%d)\n", len);
-#endif
-       if (len > 0) {
-               current->state = TASK_INTERRUPTIBLE;
-               schedule_timeout(len);
-       }
 }
 
 /*****************************************************************************/
@@ -1239,7 +1165,7 @@ static void stl_delay(int len)
  *     If transmit interrupts are not running then start them.
  */
 
-static int stl_write(struct tty_struct *tty, int from_user, const unsigned char *buf, int count)
+static int stl_write(struct tty_struct *tty, const unsigned char *buf, int count)
 {
        stlport_t       *portp;
        unsigned int    len, stlen;
@@ -1247,18 +1173,15 @@ static int stl_write(struct tty_struct *tty, int from_user, const unsigned char
        char            *head, *tail;
 
 #ifdef DEBUG
-       printk("stl_write(tty=%x,from_user=%d,buf=%x,count=%d)\n",
-               (int) tty, from_user, (int) buf, count);
+       printk("stl_write(tty=%x,buf=%x,count=%d)\n",
+               (int) tty, (int) buf, count);
 #endif
 
-       if ((tty == (struct tty_struct *) NULL) ||
-           (stl_tmpwritebuf == (char *) NULL))
-               return(0);
        portp = tty->driver_data;
        if (portp == (stlport_t *) NULL)
-               return(0);
+               return 0;
        if (portp->tx.buf == (char *) NULL)
-               return(0);
+               return 0;
 
 /*
  *     If copying direct from user space we must cater for page faults,
@@ -1267,18 +1190,6 @@ static int stl_write(struct tty_struct *tty, int from_user, const unsigned char
  *     copy it into the TX buffer.
  */
        chbuf = (unsigned char *) buf;
-       if (from_user) {
-               head = portp->tx.head;
-               tail = portp->tx.tail;
-               len = (head >= tail) ? (STL_TXBUFSIZE - (head - tail) - 1) :
-                       (tail - head - 1);
-               count = MIN(len, count);
-               
-               down(&stl_tmpwritesem);
-               if (copy_from_user(stl_tmpwritebuf, chbuf, count)) 
-                       return -EFAULT;
-               chbuf = &stl_tmpwritebuf[0];
-       }
 
        head = portp->tx.head;
        tail = portp->tx.tail;
@@ -1309,10 +1220,7 @@ static int stl_write(struct tty_struct *tty, int from_user, const unsigned char
        clear_bit(ASYI_TXLOW, &portp->istate);
        stl_startrxtx(portp, -1, 1);
 
-       if (from_user)
-               up(&stl_tmpwritesem);
-
-       return(count);
+       return count;
 }
 
 /*****************************************************************************/
@@ -1373,11 +1281,6 @@ static void stl_flushchars(struct tty_struct *tty)
        if (portp->tx.buf == (char *) NULL)
                return;
 
-#if 0
-       if (tty->stopped || tty->hw_stopped ||
-           (portp->tx.head == portp->tx.tail))
-               return;
-#endif
        stl_startrxtx(portp, -1, 1);
 }
 
@@ -1393,16 +1296,16 @@ static int stl_writeroom(struct tty_struct *tty)
 #endif
 
        if (tty == (struct tty_struct *) NULL)
-               return(0);
+               return 0;
        portp = tty->driver_data;
        if (portp == (stlport_t *) NULL)
-               return(0);
+               return 0;
        if (portp->tx.buf == (char *) NULL)
-               return(0);
+               return 0;
 
        head = portp->tx.head;
        tail = portp->tx.tail;
-       return((head >= tail) ? (STL_TXBUFSIZE - (head - tail) - 1) : (tail - head - 1));
+       return ((head >= tail) ? (STL_TXBUFSIZE - (head - tail) - 1) : (tail - head - 1));
 }
 
 /*****************************************************************************/
@@ -1427,19 +1330,19 @@ static int stl_charsinbuffer(struct tty_struct *tty)
 #endif
 
        if (tty == (struct tty_struct *) NULL)
-               return(0);
+               return 0;
        portp = tty->driver_data;
        if (portp == (stlport_t *) NULL)
-               return(0);
+               return 0;
        if (portp->tx.buf == (char *) NULL)
-               return(0);
+               return 0;
 
        head = portp->tx.head;
        tail = portp->tx.tail;
        size = (head >= tail) ? (head - tail) : (STL_TXBUFSIZE - (tail - head));
        if ((size == 0) && test_bit(ASYI_TXBUSY, &portp->istate))
                size = 1;
-       return(size);
+       return size;
 }
 
 /*****************************************************************************/
@@ -1504,7 +1407,7 @@ static int stl_setserial(stlport_t *portp, struct serial_struct __user *sp)
                    (sio.close_delay != portp->close_delay) ||
                    ((sio.flags & ~ASYNC_USR_MASK) !=
                    (portp->flags & ~ASYNC_USR_MASK)))
-                       return(-EPERM);
+                       return -EPERM;
        } 
 
        portp->flags = (portp->flags & ~ASYNC_USR_MASK) |
@@ -1514,7 +1417,7 @@ static int stl_setserial(stlport_t *portp, struct serial_struct __user *sp)
        portp->closing_wait = sio.closing_wait;
        portp->custom_divisor = sio.custom_divisor;
        stl_setport(portp, portp->tty->termios);
-       return(0);
+       return 0;
 }
 
 /*****************************************************************************/
@@ -1524,12 +1427,12 @@ static int stl_tiocmget(struct tty_struct *tty, struct file *file)
        stlport_t       *portp;
 
        if (tty == (struct tty_struct *) NULL)
-               return(-ENODEV);
+               return -ENODEV;
        portp = tty->driver_data;
        if (portp == (stlport_t *) NULL)
-               return(-ENODEV);
+               return -ENODEV;
        if (tty->flags & (1 << TTY_IO_ERROR))
-               return(-EIO);
+               return -EIO;
 
        return stl_getsignals(portp);
 }
@@ -1541,12 +1444,12 @@ static int stl_tiocmset(struct tty_struct *tty, struct file *file,
        int rts = -1, dtr = -1;
 
        if (tty == (struct tty_struct *) NULL)
-               return(-ENODEV);
+               return -ENODEV;
        portp = tty->driver_data;
        if (portp == (stlport_t *) NULL)
-               return(-ENODEV);
+               return -ENODEV;
        if (tty->flags & (1 << TTY_IO_ERROR))
-               return(-EIO);
+               return -EIO;
 
        if (set & TIOCM_RTS)
                rts = 1;
@@ -1574,15 +1477,15 @@ static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd
 #endif
 
        if (tty == (struct tty_struct *) NULL)
-               return(-ENODEV);
+               return -ENODEV;
        portp = tty->driver_data;
        if (portp == (stlport_t *) NULL)
-               return(-ENODEV);
+               return -ENODEV;
 
        if ((cmd != TIOCGSERIAL) && (cmd != TIOCSSERIAL) &&
            (cmd != COM_GETPORTSTATS) && (cmd != COM_CLRPORTSTATS)) {
                if (tty->flags & (1 << TTY_IO_ERROR))
-                       return(-EIO);
+                       return -EIO;
        }
 
        rc = 0;
@@ -1623,7 +1526,7 @@ static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd
                break;
        }
 
-       return(rc);
+       return rc;
 }
 
 /*****************************************************************************/
@@ -1854,7 +1757,7 @@ static void stl_waituntilsent(struct tty_struct *tty, int timeout)
        while (stl_datastate(portp)) {
                if (signal_pending(current))
                        break;
-               stl_delay(2);
+               msleep_interruptible(20);
                if (time_after_eq(jiffies, tend))
                        break;
        }
@@ -1929,7 +1832,7 @@ static int stl_portinfo(stlport_t *portp, int portnr, char *pos)
                pos[(MAXLINE - 2)] = '+';
        pos[(MAXLINE - 1)] = '\n';
 
-       return(MAXLINE);
+       return MAXLINE;
 }
 
 /*****************************************************************************/
@@ -2014,7 +1917,7 @@ static int stl_readproc(char *page, char **start, off_t off, int count, int *eof
 
 stl_readdone:
        *start = page;
-       return(pos - page);
+       return (pos - page);
 }
 
 /*****************************************************************************/
@@ -2026,23 +1929,14 @@ stl_readdone:
 
 static irqreturn_t stl_intr(int irq, void *dev_id, struct pt_regs *regs)
 {
-       stlbrd_t        *brdp;
-       int             i;
-       int handled = 0;
+       stlbrd_t        *brdp = (stlbrd_t *) dev_id;
 
 #ifdef DEBUG
-       printk("stl_intr(irq=%d,regs=%x)\n", irq, (int) regs);
+       printk("stl_intr(brdp=%x,irq=%d,regs=%x)\n", (int) brdp, irq,
+           (int) regs);
 #endif
 
-       for (i = 0; (i < stl_nrbrds); i++) {
-               if ((brdp = stl_brds[i]) == (stlbrd_t *) NULL)
-                       continue;
-               if (brdp->state == 0)
-                       continue;
-               handled = 1;
-               (* brdp->isr)(brdp);
-       }
-       return IRQ_RETVAL(handled);
+       return IRQ_RETVAL((* brdp->isr)(brdp));
 }
 
 /*****************************************************************************/
@@ -2051,15 +1945,21 @@ static irqreturn_t stl_intr(int irq, void *dev_id, struct pt_regs *regs)
  *     Interrupt service routine for EasyIO board types.
  */
 
-static void stl_eiointr(stlbrd_t *brdp)
+static int stl_eiointr(stlbrd_t *brdp)
 {
        stlpanel_t      *panelp;
        unsigned int    iobase;
+       int             handled = 0;
 
+       spin_lock(&brd_lock);
        panelp = brdp->panels[0];
        iobase = panelp->iobase;
-       while (inb(brdp->iostatus) & EIO_INTRPEND)
+       while (inb(brdp->iostatus) & EIO_INTRPEND) {
+               handled = 1;
                (* panelp->isr)(panelp, iobase);
+       }
+       spin_unlock(&brd_lock);
+       return handled;
 }
 
 /*****************************************************************************/
@@ -2068,15 +1968,17 @@ static void stl_eiointr(stlbrd_t *brdp)
  *     Interrupt service routine for ECH-AT board types.
  */
 
-static void stl_echatintr(stlbrd_t *brdp)
+static int stl_echatintr(stlbrd_t *brdp)
 {
        stlpanel_t      *panelp;
        unsigned int    ioaddr;
        int             bnknr;
+       int             handled = 0;
 
        outb((brdp->ioctrlval | ECH_BRDENABLE), brdp->ioctrl);
 
        while (inb(brdp->iostatus) & ECH_INTRPEND) {
+               handled = 1;
                for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
                        ioaddr = brdp->bnkstataddr[bnknr];
                        if (inb(ioaddr) & ECH_PNLINTRPEND) {
@@ -2087,6 +1989,8 @@ static void stl_echatintr(stlbrd_t *brdp)
        }
 
        outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
+
+       return handled;
 }
 
 /*****************************************************************************/
@@ -2095,13 +1999,15 @@ static void stl_echatintr(stlbrd_t *brdp)
  *     Interrupt service routine for ECH-MCA board types.
  */
 
-static void stl_echmcaintr(stlbrd_t *brdp)
+static int stl_echmcaintr(stlbrd_t *brdp)
 {
        stlpanel_t      *panelp;
        unsigned int    ioaddr;
        int             bnknr;
+       int             handled = 0;
 
        while (inb(brdp->iostatus) & ECH_INTRPEND) {
+               handled = 1;
                for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
                        ioaddr = brdp->bnkstataddr[bnknr];
                        if (inb(ioaddr) & ECH_PNLINTRPEND) {
@@ -2110,6 +2016,7 @@ static void stl_echmcaintr(stlbrd_t *brdp)
                        }
                }
        }
+       return handled;
 }
 
 /*****************************************************************************/
@@ -2118,11 +2025,12 @@ static void stl_echmcaintr(stlbrd_t *brdp)
  *     Interrupt service routine for ECH-PCI board types.
  */
 
-static void stl_echpciintr(stlbrd_t *brdp)
+static int stl_echpciintr(stlbrd_t *brdp)
 {
        stlpanel_t      *panelp;
        unsigned int    ioaddr;
        int             bnknr, recheck;
+       int             handled = 0;
 
        while (1) {
                recheck = 0;
@@ -2133,11 +2041,13 @@ static void stl_echpciintr(stlbrd_t *brdp)
                                panelp = brdp->bnk2panel[bnknr];
                                (* panelp->isr)(panelp, (ioaddr & 0xfffc));
                                recheck++;
+                               handled = 1;
                        }
                }
                if (! recheck)
                        break;
        }
+       return handled;
 }
 
 /*****************************************************************************/
@@ -2146,13 +2056,15 @@ static void stl_echpciintr(stlbrd_t *brdp)
  *     Interrupt service routine for ECH-8/64-PCI board types.
  */
 
-static void stl_echpci64intr(stlbrd_t *brdp)
+static int stl_echpci64intr(stlbrd_t *brdp)
 {
        stlpanel_t      *panelp;
        unsigned int    ioaddr;
        int             bnknr;
+       int             handled = 0;
 
        while (inb(brdp->ioctrl) & 0x1) {
+               handled = 1;
                for (bnknr = 0; (bnknr < brdp->nrbnks); bnknr++) {
                        ioaddr = brdp->bnkstataddr[bnknr];
                        if (inb(ioaddr) & ECH_PNLINTRPEND) {
@@ -2161,6 +2073,8 @@ static void stl_echpci64intr(stlbrd_t *brdp)
                        }
                }
        }
+
+       return handled;
 }
 
 /*****************************************************************************/
@@ -2207,39 +2121,6 @@ static void stl_offintr(void *private)
 
 /*****************************************************************************/
 
-/*
- *     Map in interrupt vector to this driver. Check that we don't
- *     already have this vector mapped, we might be sharing this
- *     interrupt across multiple boards.
- */
-
-static int __init stl_mapirq(int irq, char *name)
-{
-       int     rc, i;
-
-#ifdef DEBUG
-       printk("stl_mapirq(irq=%d,name=%s)\n", irq, name);
-#endif
-
-       rc = 0;
-       for (i = 0; (i < stl_numintrs); i++) {
-               if (stl_gotintrs[i] == irq)
-                       break;
-       }
-       if (i >= stl_numintrs) {
-               if (request_irq(irq, stl_intr, SA_SHIRQ, name, NULL) != 0) {
-                       printk("STALLION: failed to register interrupt "
-                               "routine for %s irq=%d\n", name, irq);
-                       rc = -ENODEV;
-               } else {
-                       stl_gotintrs[stl_numintrs++] = irq;
-               }
-       }
-       return(rc);
-}
-
-/*****************************************************************************/
-
 /*
  *     Initialize all the ports on a panel.
  */
@@ -2260,13 +2141,12 @@ static int __init stl_initports(stlbrd_t *brdp, stlpanel_t *panelp)
  *     each ports data structures.
  */
        for (i = 0; (i < panelp->nrports); i++) {
-               portp = (stlport_t *) stl_memalloc(sizeof(stlport_t));
-               if (portp == (stlport_t *) NULL) {
+               portp = kzalloc(sizeof(stlport_t), GFP_KERNEL);
+               if (!portp) {
                        printk("STALLION: failed to allocate memory "
-                               "(size=%d)\n", sizeof(stlport_t));
+                               "(size=%Zd)\n", sizeof(stlport_t));
                        break;
                }
-               memset(portp, 0, sizeof(stlport_t));
 
                portp->magic = STL_PORTMAGIC;
                portp->portnr = i;
@@ -2397,13 +2277,12 @@ static inline int stl_initeio(stlbrd_t *brdp)
  *     can complete the setup.
  */
 
-       panelp = (stlpanel_t *) stl_memalloc(sizeof(stlpanel_t));
-       if (panelp == (stlpanel_t *) NULL) {
+       panelp = kzalloc(sizeof(stlpanel_t), GFP_KERNEL);
+       if (!panelp) {
                printk(KERN_WARNING "STALLION: failed to allocate memory "
-                       "(size=%d)\n", sizeof(stlpanel_t));
-               return(-ENOMEM);
+                       "(size=%Zd)\n", sizeof(stlpanel_t));
+               return -ENOMEM;
        }
-       memset(panelp, 0, sizeof(stlpanel_t));
 
        panelp->magic = STL_PANELMAGIC;
        panelp->brdnr = brdp->brdnr;
@@ -2423,8 +2302,14 @@ static inline int stl_initeio(stlbrd_t *brdp)
        brdp->nrpanels = 1;
        brdp->state |= BRD_FOUND;
        brdp->hwid = status;
-       rc = stl_mapirq(brdp->irq, name);
-       return(rc);
+       if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
+               printk("STALLION: failed to register interrupt "
+                   "routine for %s irq=%d\n", name, brdp->irq);
+               rc = -ENODEV;
+       } else {
+               rc = 0;
+       }
+       return rc;
 }
 
 /*****************************************************************************/
@@ -2566,13 +2451,12 @@ static inline int stl_initech(stlbrd_t *brdp)
                status = inb(ioaddr + ECH_PNLSTATUS);
                if ((status & ECH_PNLIDMASK) != nxtid)
                        break;
-               panelp = (stlpanel_t *) stl_memalloc(sizeof(stlpanel_t));
-               if (panelp == (stlpanel_t *) NULL) {
+               panelp = kzalloc(sizeof(stlpanel_t), GFP_KERNEL);
+               if (!panelp) {
                        printk("STALLION: failed to allocate memory "
-                               "(size=%d)\n", sizeof(stlpanel_t));
+                               "(size=%Zd)\n", sizeof(stlpanel_t));
                        break;
                }
-               memset(panelp, 0, sizeof(stlpanel_t));
                panelp->magic = STL_PANELMAGIC;
                panelp->brdnr = brdp->brdnr;
                panelp->panelnr = panelnr;
@@ -2628,7 +2512,14 @@ static inline int stl_initech(stlbrd_t *brdp)
                outb((brdp->ioctrlval | ECH_BRDDISABLE), brdp->ioctrl);
 
        brdp->state |= BRD_FOUND;
-       i = stl_mapirq(brdp->irq, name);
+       if (request_irq(brdp->irq, stl_intr, IRQF_SHARED, name, brdp) != 0) {
+               printk("STALLION: failed to register interrupt "
+                   "routine for %s irq=%d\n", name, brdp->irq);
+               i = -ENODEV;
+       } else {
+               i = 0;
+       }
+
        return(i);
 }
 
@@ -2841,9 +2732,7 @@ static inline int stl_initbrds(void)
  */
        for (i = 0; (i < stl_nrbrds); i++) {
                confp = &stl_brdconf[i];
-#ifdef MODULE
                stl_parsebrd(confp, stl_brdsp[i]);
-#endif
                if ((brdp = stl_allocbrd()) == (stlbrd_t *) NULL)
                        return(-ENOMEM);
                brdp->brdnr = i;
@@ -2859,9 +2748,7 @@ static inline int stl_initbrds(void)
  *     Find any dynamically supported boards. That is via module load
  *     line options or auto-detected on the PCI bus.
  */
-#ifdef MODULE
        stl_argbrds();
-#endif
 #ifdef CONFIG_PCI
        stl_findpcibrds();
 #endif
@@ -2968,12 +2855,12 @@ static int stl_getportstats(stlport_t *portp, comstats_t __user *cp)
        portp->stats.lflags = 0;
        portp->stats.rxbuffered = 0;
 
-       save_flags(flags);
-       cli();
+       spin_lock_irqsave(&stallion_lock, flags);
        if (portp->tty != (struct tty_struct *) NULL) {
                if (portp->tty->driver_data == portp) {
                        portp->stats.ttystate = portp->tty->flags;
-                       portp->stats.rxbuffered = portp->tty->flip.count;
+                       /* No longer available as a statistic */
+                       portp->stats.rxbuffered = 1; /*portp->tty->flip.count; */
                        if (portp->tty->termios != (struct termios *) NULL) {
                                portp->stats.cflags = portp->tty->termios->c_cflag;
                                portp->stats.iflags = portp->tty->termios->c_iflag;
@@ -2982,7 +2869,7 @@ static int stl_getportstats(stlport_t *portp, comstats_t __user *cp)
                        }
                }
        }
-       restore_flags(flags);
+       spin_unlock_irqrestore(&stallion_lock, flags);
 
        head = portp->tx.head;
        tail = portp->tx.tail;
@@ -3132,45 +3019,36 @@ static struct tty_operations stl_ops = {
 
 /*****************************************************************************/
 
-int __init stl_init(void)
+static int __init stl_init(void)
 {
        int i;
        printk(KERN_INFO "%s: version %s\n", stl_drvtitle, stl_drvversion);
 
+       spin_lock_init(&stallion_lock);
+       spin_lock_init(&brd_lock);
+
        stl_initbrds();
 
        stl_serial = alloc_tty_driver(STL_MAXBRDS * STL_MAXPORTS);
        if (!stl_serial)
                return -1;
 
-/*
- *     Allocate a temporary write buffer.
- */
-       stl_tmpwritebuf = (char *) stl_memalloc(STL_TXBUFSIZE);
-       if (stl_tmpwritebuf == (char *) NULL)
-               printk("STALLION: failed to allocate memory (size=%d)\n",
-                       STL_TXBUFSIZE);
-
 /*
  *     Set up a character driver for per board stuff. This is mainly used
  *     to do stats ioctls on the ports.
  */
        if (register_chrdev(STL_SIOMEMMAJOR, "staliomem", &stl_fsiomem))
                printk("STALLION: failed to register serial board device\n");
-       devfs_mk_dir("staliomem");
-
-       stallion_class = class_simple_create(THIS_MODULE, "staliomem");
-       for (i = 0; i < 4; i++) {
-               devfs_mk_cdev(MKDEV(STL_SIOMEMMAJOR, i),
-                               S_IFCHR|S_IRUSR|S_IWUSR,
-                               "staliomem/%d", i);
-               class_simple_device_add(stallion_class, MKDEV(STL_SIOMEMMAJOR, i), NULL, "staliomem%d", i);
-       }
+
+       stallion_class = class_create(THIS_MODULE, "staliomem");
+       for (i = 0; i < 4; i++)
+               class_device_create(stallion_class, NULL,
+                                   MKDEV(STL_SIOMEMMAJOR, i), NULL,
+                                   "staliomem%d", i);
 
        stl_serial->owner = THIS_MODULE;
        stl_serial->driver_name = stl_drvname;
        stl_serial->name = "ttyE";
-       stl_serial->devfs_name = "tts/E";
        stl_serial->major = STL_SERIALMAJOR;
        stl_serial->minor_start = 0;
        stl_serial->type = TTY_DRIVER_TYPE_SERIAL;
@@ -3185,7 +3063,7 @@ int __init stl_init(void)
                return -1;
        }
 
-       return(0);
+       return 0;
 }
 
 /*****************************************************************************/
@@ -3201,7 +3079,7 @@ int __init stl_init(void)
 static int stl_cd1400getreg(stlport_t *portp, int regnr)
 {
        outb((regnr + portp->uartaddr), portp->ioaddr);
-       return(inb(portp->ioaddr + EREG_DATA));
+       return inb(portp->ioaddr + EREG_DATA);
 }
 
 static void stl_cd1400setreg(stlport_t *portp, int regnr, int value)
@@ -3215,9 +3093,9 @@ static int stl_cd1400updatereg(stlport_t *portp, int regnr, int value)
        outb((regnr + portp->uartaddr), portp->ioaddr);
        if (inb(portp->ioaddr + EREG_DATA) != value) {
                outb(value, portp->ioaddr + EREG_DATA);
-               return(1);
+               return 1;
        }
-       return(0);
+       return 0;
 }
 
 /*****************************************************************************/
@@ -3233,11 +3111,13 @@ static int stl_cd1400panelinit(stlbrd_t *brdp, stlpanel_t *panelp)
        unsigned int    gfrcr;
        int             chipmask, i, j;
        int             nrchips, uartaddr, ioaddr;
+       unsigned long   flags;
 
 #ifdef DEBUG
        printk("stl_panelinit(brdp=%x,panelp=%x)\n", (int) brdp, (int) panelp);
 #endif
 
+       spin_lock_irqsave(&brd_lock, flags);
        BRDENABLE(panelp->brdnr, panelp->pagenr);
 
 /*
@@ -3275,7 +3155,8 @@ static int stl_cd1400panelinit(stlbrd_t *brdp, stlpanel_t *panelp)
        }
 
        BRDDISABLE(panelp->brdnr);
-       return(chipmask);
+       spin_unlock_irqrestore(&brd_lock, flags);
+       return chipmask;
 }
 
 /*****************************************************************************/
@@ -3286,6 +3167,7 @@ static int stl_cd1400panelinit(stlbrd_t *brdp, stlpanel_t *panelp)
 
 static void stl_cd1400portinit(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *portp)
 {
+       unsigned long flags;
 #ifdef DEBUG
        printk("stl_cd1400portinit(brdp=%x,panelp=%x,portp=%x)\n",
                (int) brdp, (int) panelp, (int) portp);
@@ -3295,6 +3177,7 @@ static void stl_cd1400portinit(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *po
            (portp == (stlport_t *) NULL))
                return;
 
+       spin_lock_irqsave(&brd_lock, flags);
        portp->ioaddr = panelp->iobase + (((brdp->brdtype == BRD_ECHPCI) ||
                (portp->portnr < 8)) ? 0 : EREG_BANKSIZE);
        portp->uartaddr = (portp->portnr & 0x04) << 5;
@@ -3305,6 +3188,7 @@ static void stl_cd1400portinit(stlbrd_t *brdp, stlpanel_t *panelp, stlport_t *po
        stl_cd1400setreg(portp, LIVR, (portp->portnr << 3));
        portp->hwid = stl_cd1400getreg(portp, GFRCR);
        BRDDISABLE(portp->brdnr);
+       spin_unlock_irqrestore(&brd_lock, flags);
 }
 
 /*****************************************************************************/
@@ -3514,8 +3398,7 @@ static void stl_cd1400setport(stlport_t *portp, struct termios *tiosp)
                tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
 #endif
 
-       save_flags(flags);
-       cli();
+       spin_lock_irqsave(&brd_lock, flags);
        BRDENABLE(portp->brdnr, portp->pagenr);
        stl_cd1400setreg(portp, CAR, (portp->portnr & 0x3));
        srer = stl_cd1400getreg(portp, SRER);
@@ -3552,7 +3435,7 @@ static void stl_cd1400setport(stlport_t *portp, struct termios *tiosp)
                portp->sigs &= ~TIOCM_CD;
        stl_cd1400setreg(portp, SRER, ((srer & ~sreroff) | sreron));
        BRDDISABLE(portp->brdnr);
-       restore_flags(flags);
+       spin_unlock_irqrestore(&brd_lock, flags);
 }
 
 /*****************************************************************************/
@@ -3578,8 +3461,7 @@ static void stl_cd1400setsignals(stlport_t *portp, int dtr, int rts)
        if (rts > 0)
                msvr2 = MSVR2_RTS;
 
-       save_flags(flags);
-       cli();
+       spin_lock_irqsave(&brd_lock, flags);
        BRDENABLE(portp->brdnr, portp->pagenr);
        stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
        if (rts >= 0)
@@ -3587,7 +3469,7 @@ static void stl_cd1400setsignals(stlport_t *portp, int dtr, int rts)
        if (dtr >= 0)
                stl_cd1400setreg(portp, MSVR1, msvr1);
        BRDDISABLE(portp->brdnr);
-       restore_flags(flags);
+       spin_unlock_irqrestore(&brd_lock, flags);
 }
 
 /*****************************************************************************/
@@ -3606,14 +3488,13 @@ static int stl_cd1400getsignals(stlport_t *portp)
        printk("stl_cd1400getsignals(portp=%x)\n", (int) portp);
 #endif
 
-       save_flags(flags);
-       cli();
+       spin_lock_irqsave(&brd_lock, flags);
        BRDENABLE(portp->brdnr, portp->pagenr);
        stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
        msvr1 = stl_cd1400getreg(portp, MSVR1);
        msvr2 = stl_cd1400getreg(portp, MSVR2);
        BRDDISABLE(portp->brdnr);
-       restore_flags(flags);
+       spin_unlock_irqrestore(&brd_lock, flags);
 
        sigs = 0;
        sigs |= (msvr1 & MSVR1_DCD) ? TIOCM_CD : 0;
@@ -3626,7 +3507,7 @@ static int stl_cd1400getsignals(stlport_t *portp)
 #else
        sigs |= TIOCM_DSR;
 #endif
-       return(sigs);
+       return sigs;
 }
 
 /*****************************************************************************/
@@ -3655,15 +3536,14 @@ static void stl_cd1400enablerxtx(stlport_t *portp, int rx, int tx)
        else if (rx > 0)
                ccr |= CCR_RXENABLE;
 
-       save_flags(flags);
-       cli();
+       spin_lock_irqsave(&brd_lock, flags);
        BRDENABLE(portp->brdnr, portp->pagenr);
        stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
        stl_cd1400ccrwait(portp);
        stl_cd1400setreg(portp, CCR, ccr);
        stl_cd1400ccrwait(portp);
        BRDDISABLE(portp->brdnr);
-       restore_flags(flags);
+       spin_unlock_irqrestore(&brd_lock, flags);
 }
 
 /*****************************************************************************/
@@ -3695,8 +3575,7 @@ static void stl_cd1400startrxtx(stlport_t *portp, int rx, int tx)
        else if (rx > 0)
                sreron |= SRER_RXDATA;
 
-       save_flags(flags);
-       cli();
+       spin_lock_irqsave(&brd_lock, flags);
        BRDENABLE(portp->brdnr, portp->pagenr);
        stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
        stl_cd1400setreg(portp, SRER,
@@ -3704,7 +3583,7 @@ static void stl_cd1400startrxtx(stlport_t *portp, int rx, int tx)
        BRDDISABLE(portp->brdnr);
        if (tx > 0)
                set_bit(ASYI_TXBUSY, &portp->istate);
-       restore_flags(flags);
+       spin_unlock_irqrestore(&brd_lock, flags);
 }
 
 /*****************************************************************************/
@@ -3720,13 +3599,12 @@ static void stl_cd1400disableintrs(stlport_t *portp)
 #ifdef DEBUG
        printk("stl_cd1400disableintrs(portp=%x)\n", (int) portp);
 #endif
-       save_flags(flags);
-       cli();
+       spin_lock_irqsave(&brd_lock, flags);
        BRDENABLE(portp->brdnr, portp->pagenr);
        stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
        stl_cd1400setreg(portp, SRER, 0);
        BRDDISABLE(portp->brdnr);
-       restore_flags(flags);
+       spin_unlock_irqrestore(&brd_lock, flags);
 }
 
 /*****************************************************************************/
@@ -3739,8 +3617,7 @@ static void stl_cd1400sendbreak(stlport_t *portp, int len)
        printk("stl_cd1400sendbreak(portp=%x,len=%d)\n", (int) portp, len);
 #endif
 
-       save_flags(flags);
-       cli();
+       spin_lock_irqsave(&brd_lock, flags);
        BRDENABLE(portp->brdnr, portp->pagenr);
        stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
        stl_cd1400setreg(portp, SRER,
@@ -3750,7 +3627,7 @@ static void stl_cd1400sendbreak(stlport_t *portp, int len)
        portp->brklen = len;
        if (len == 1)
                portp->stats.txbreaks++;
-       restore_flags(flags);
+       spin_unlock_irqrestore(&brd_lock, flags);
 }
 
 /*****************************************************************************/
@@ -3774,8 +3651,7 @@ static void stl_cd1400flowctrl(stlport_t *portp, int state)
        if (tty == (struct tty_struct *) NULL)
                return;
 
-       save_flags(flags);
-       cli();
+       spin_lock_irqsave(&brd_lock, flags);
        BRDENABLE(portp->brdnr, portp->pagenr);
        stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
 
@@ -3815,7 +3691,7 @@ static void stl_cd1400flowctrl(stlport_t *portp, int state)
        }
 
        BRDDISABLE(portp->brdnr);
-       restore_flags(flags);
+       spin_unlock_irqrestore(&brd_lock, flags);
 }
 
 /*****************************************************************************/
@@ -3839,8 +3715,7 @@ static void stl_cd1400sendflow(stlport_t *portp, int state)
        if (tty == (struct tty_struct *) NULL)
                return;
 
-       save_flags(flags);
-       cli();
+       spin_lock_irqsave(&brd_lock, flags);
        BRDENABLE(portp->brdnr, portp->pagenr);
        stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
        if (state) {
@@ -3855,7 +3730,7 @@ static void stl_cd1400sendflow(stlport_t *portp, int state)
                stl_cd1400ccrwait(portp);
        }
        BRDDISABLE(portp->brdnr);
-       restore_flags(flags);
+       spin_unlock_irqrestore(&brd_lock, flags);
 }
 
 /*****************************************************************************/
@@ -3871,8 +3746,7 @@ static void stl_cd1400flush(stlport_t *portp)
        if (portp == (stlport_t *) NULL)
                return;
 
-       save_flags(flags);
-       cli();
+       spin_lock_irqsave(&brd_lock, flags);
        BRDENABLE(portp->brdnr, portp->pagenr);
        stl_cd1400setreg(portp, CAR, (portp->portnr & 0x03));
        stl_cd1400ccrwait(portp);
@@ -3880,7 +3754,7 @@ static void stl_cd1400flush(stlport_t *portp)
        stl_cd1400ccrwait(portp);
        portp->tx.tail = portp->tx.head;
        BRDDISABLE(portp->brdnr);
-       restore_flags(flags);
+       spin_unlock_irqrestore(&brd_lock, flags);
 }
 
 /*****************************************************************************/
@@ -3899,9 +3773,9 @@ static int stl_cd1400datastate(stlport_t *portp)
 #endif
 
        if (portp == (stlport_t *) NULL)
-               return(0);
+               return 0;
 
-       return(test_bit(ASYI_TXBUSY, &portp->istate) ? 1 : 0);
+       return test_bit(ASYI_TXBUSY, &portp->istate) ? 1 : 0;
 }
 
 /*****************************************************************************/
@@ -3919,6 +3793,7 @@ static void stl_cd1400eiointr(stlpanel_t *panelp, unsigned int iobase)
                (int) panelp, iobase);
 #endif
 
+       spin_lock(&brd_lock);
        outb(SVRR, iobase);
        svrtype = inb(iobase + EREG_DATA);
        if (panelp->nrports > 4) {
@@ -3932,6 +3807,8 @@ static void stl_cd1400eiointr(stlpanel_t *panelp, unsigned int iobase)
                stl_cd1400txisr(panelp, iobase);
        else if (svrtype & SVRR_MDM)
                stl_cd1400mdmisr(panelp, iobase);
+
+       spin_unlock(&brd_lock);
 }
 
 /*****************************************************************************/
@@ -3981,20 +3858,20 @@ static inline int stl_cd1400breakisr(stlport_t *portp, int ioaddr)
                outb((SRER + portp->uartaddr), ioaddr);
                outb((inb(ioaddr + EREG_DATA) & ~(SRER_TXDATA | SRER_TXEMPTY)),
                        (ioaddr + EREG_DATA));
-               return(1);
+               return 1;
        } else if (portp->brklen > 1) {
                outb((TDR + portp->uartaddr), ioaddr);
                outb(ETC_CMD, (ioaddr + EREG_DATA));
                outb(ETC_STOPBREAK, (ioaddr + EREG_DATA));
                portp->brklen = -1;
-               return(1);
+               return 1;
        } else {
                outb((COR2 + portp->uartaddr), ioaddr);
                outb((inb(ioaddr + EREG_DATA) & ~COR2_ETC),
                        (ioaddr + EREG_DATA));
                portp->brklen = 0;
        }
-       return(0);
+       return 0;
 }
 
 /*****************************************************************************/
@@ -4115,9 +3992,7 @@ static void stl_cd1400rxisr(stlpanel_t *panelp, int ioaddr)
        if ((ioack & ACK_TYPMASK) == ACK_TYPRXGOOD) {
                outb((RDCR + portp->uartaddr), ioaddr);
                len = inb(ioaddr + EREG_DATA);
-               if ((tty == (struct tty_struct *) NULL) ||
-                   (tty->flip.char_buf_ptr == (char *) NULL) ||
-                   ((buflen = TTY_FLIPBUF_SIZE - tty->flip.count) == 0)) {
+               if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
                        len = MIN(len, sizeof(stl_unwanted));
                        outb((RDSR + portp->uartaddr), ioaddr);
                        insb((ioaddr + EREG_DATA), &stl_unwanted[0], len);
@@ -4126,12 +4001,10 @@ static void stl_cd1400rxisr(stlpanel_t *panelp, int ioaddr)
                } else {
                        len = MIN(len, buflen);
                        if (len > 0) {
+                               unsigned char *ptr;
                                outb((RDSR + portp->uartaddr), ioaddr);
-                               insb((ioaddr + EREG_DATA), tty->flip.char_buf_ptr, len);
-                               memset(tty->flip.flag_buf_ptr, 0, len);
-                               tty->flip.flag_buf_ptr += len;
-                               tty->flip.char_buf_ptr += len;
-                               tty->flip.count += len;
+                               tty_prepare_flip_string(tty, &ptr, len);
+                               insb((ioaddr + EREG_DATA), ptr, len);
                                tty_schedule_flip(tty);
                                portp->stats.rxtotal += len;
                        }
@@ -4155,8 +4028,7 @@ static void stl_cd1400rxisr(stlpanel_t *panelp, int ioaddr)
                                portp->stats.txxoff++;
                        goto stl_rxalldone;
                }
-               if ((tty != (struct tty_struct *) NULL) &&
-                   ((portp->rxignoremsk & status) == 0)) {
+               if (tty != NULL && (portp->rxignoremsk & status) == 0) {
                        if (portp->rxmarkmsk & status) {
                                if (status & ST_BREAK) {
                                        status = TTY_BREAK;
@@ -4176,14 +4048,8 @@ static void stl_cd1400rxisr(stlpanel_t *panelp, int ioaddr)
                        } else {
                                status = 0;
                        }
-                       if (tty->flip.char_buf_ptr != (char *) NULL) {
-                               if (tty->flip.count < TTY_FLIPBUF_SIZE) {
-                                       *tty->flip.flag_buf_ptr++ = status;
-                                       *tty->flip.char_buf_ptr++ = ch;
-                                       tty->flip.count++;
-                               }
-                               tty_schedule_flip(tty);
-                       }
+                       tty_insert_flip_char(tty, ch, status);
+                       tty_schedule_flip(tty);
                }
        } else {
                printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
@@ -4246,7 +4112,7 @@ static void stl_cd1400mdmisr(stlpanel_t *panelp, int ioaddr)
 static int stl_sc26198getreg(stlport_t *portp, int regnr)
 {
        outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
-       return(inb(portp->ioaddr + XP_DATA));
+       return inb(portp->ioaddr + XP_DATA);
 }
 
 static void stl_sc26198setreg(stlport_t *portp, int regnr, int value)
@@ -4260,9 +4126,9 @@ static int stl_sc26198updatereg(stlport_t *portp, int regnr, int value)
        outb((regnr | portp->uartaddr), (portp->ioaddr + XP_ADDR));
        if (inb(portp->ioaddr + XP_DATA) != value) {
                outb(value, (portp->ioaddr + XP_DATA));
-               return(1);
+               return 1;
        }
-       return(0);
+       return 0;
 }
 
 /*****************************************************************************/
@@ -4274,7 +4140,7 @@ static int stl_sc26198updatereg(stlport_t *portp, int regnr, int value)
 static int stl_sc26198getglobreg(stlport_t *portp, int regnr)
 {
        outb(regnr, (portp->ioaddr + XP_ADDR));
-       return(inb(portp->ioaddr + XP_DATA));
+       return inb(portp->ioaddr + XP_DATA);
 }
 
 #if 0
@@ -4332,7 +4198,7 @@ static int stl_sc26198panelinit(stlbrd_t *brdp, stlpanel_t *panelp)
        }
 
        BRDDISABLE(panelp->brdnr);
-       return(chipmask);
+       return chipmask;
 }
 
 /*****************************************************************************/
@@ -4530,8 +4396,7 @@ static void stl_sc26198setport(stlport_t *portp, struct termios *tiosp)
                tiosp->c_cc[VSTART], tiosp->c_cc[VSTOP]);
 #endif
 
-       save_flags(flags);
-       cli();
+       spin_lock_irqsave(&brd_lock, flags);
        BRDENABLE(portp->brdnr, portp->pagenr);
        stl_sc26198setreg(portp, IMR, 0);
        stl_sc26198updatereg(portp, MR0, mr0);
@@ -4558,7 +4423,7 @@ static void stl_sc26198setport(stlport_t *portp, struct termios *tiosp)
        portp->imr = (portp->imr & ~imroff) | imron;
        stl_sc26198setreg(portp, IMR, portp->imr);
        BRDDISABLE(portp->brdnr);
-       restore_flags(flags);
+       spin_unlock_irqrestore(&brd_lock, flags);
 }
 
 /*****************************************************************************/
@@ -4588,13 +4453,12 @@ static void stl_sc26198setsignals(stlport_t *portp, int dtr, int rts)
        else if (rts > 0)
                iopioron |= IPR_RTS;
 
-       save_flags(flags);
-       cli();
+       spin_lock_irqsave(&brd_lock, flags);
        BRDENABLE(portp->brdnr, portp->pagenr);
        stl_sc26198setreg(portp, IOPIOR,
                ((stl_sc26198getreg(portp, IOPIOR) & ~iopioroff) | iopioron));
        BRDDISABLE(portp->brdnr);
-       restore_flags(flags);
+       spin_unlock_irqrestore(&brd_lock, flags);
 }
 
 /*****************************************************************************/
@@ -4613,12 +4477,11 @@ static int stl_sc26198getsignals(stlport_t *portp)
        printk("stl_sc26198getsignals(portp=%x)\n", (int) portp);
 #endif
 
-       save_flags(flags);
-       cli();
+       spin_lock_irqsave(&brd_lock, flags);
        BRDENABLE(portp->brdnr, portp->pagenr);
        ipr = stl_sc26198getreg(portp, IPR);
        BRDDISABLE(portp->brdnr);
-       restore_flags(flags);
+       spin_unlock_irqrestore(&brd_lock, flags);
 
        sigs = 0;
        sigs |= (ipr & IPR_DCD) ? 0 : TIOCM_CD;
@@ -4626,7 +4489,7 @@ static int stl_sc26198getsignals(stlport_t *portp)
        sigs |= (ipr & IPR_DTR) ? 0: TIOCM_DTR;
        sigs |= (ipr & IPR_RTS) ? 0: TIOCM_RTS;
        sigs |= TIOCM_DSR;
-       return(sigs);
+       return sigs;
 }
 
 /*****************************************************************************/
@@ -4655,13 +4518,12 @@ static void stl_sc26198enablerxtx(stlport_t *portp, int rx, int tx)
        else if (rx > 0)
                ccr |= CR_RXENABLE;
 
-       save_flags(flags);
-       cli();
+       spin_lock_irqsave(&brd_lock, flags);
        BRDENABLE(portp->brdnr, portp->pagenr);
        stl_sc26198setreg(portp, SCCR, ccr);
        BRDDISABLE(portp->brdnr);
        portp->crenable = ccr;
-       restore_flags(flags);
+       spin_unlock_irqrestore(&brd_lock, flags);
 }
 
 /*****************************************************************************/
@@ -4690,15 +4552,14 @@ static void stl_sc26198startrxtx(stlport_t *portp, int rx, int tx)
        else if (rx > 0)
                imr |= IR_RXRDY | IR_RXBREAK | IR_RXWATCHDOG;
 
-       save_flags(flags);
-       cli();
+       spin_lock_irqsave(&brd_lock, flags);
        BRDENABLE(portp->brdnr, portp->pagenr);
        stl_sc26198setreg(portp, IMR, imr);
        BRDDISABLE(portp->brdnr);
        portp->imr = imr;
        if (tx > 0)
                set_bit(ASYI_TXBUSY, &portp->istate);
-       restore_flags(flags);
+       spin_unlock_irqrestore(&brd_lock, flags);
 }
 
 /*****************************************************************************/
@@ -4715,13 +4576,12 @@ static void stl_sc26198disableintrs(stlport_t *portp)
        printk("stl_sc26198disableintrs(portp=%x)\n", (int) portp);
 #endif
 
-       save_flags(flags);
-       cli();
+       spin_lock_irqsave(&brd_lock, flags);
        BRDENABLE(portp->brdnr, portp->pagenr);
        portp->imr = 0;
        stl_sc26198setreg(portp, IMR, 0);
        BRDDISABLE(portp->brdnr);
-       restore_flags(flags);
+       spin_unlock_irqrestore(&brd_lock, flags);
 }
 
 /*****************************************************************************/
@@ -4734,8 +4594,7 @@ static void stl_sc26198sendbreak(stlport_t *portp, int len)
        printk("stl_sc26198sendbreak(portp=%x,len=%d)\n", (int) portp, len);
 #endif
 
-       save_flags(flags);
-       cli();
+       spin_lock_irqsave(&brd_lock, flags);
        BRDENABLE(portp->brdnr, portp->pagenr);
        if (len == 1) {
                stl_sc26198setreg(portp, SCCR, CR_TXSTARTBREAK);
@@ -4744,7 +4603,7 @@ static void stl_sc26198sendbreak(stlport_t *portp, int len)
                stl_sc26198setreg(portp, SCCR, CR_TXSTOPBREAK);
        }
        BRDDISABLE(portp->brdnr);
-       restore_flags(flags);
+       spin_unlock_irqrestore(&brd_lock, flags);
 }
 
 /*****************************************************************************/
@@ -4769,8 +4628,7 @@ static void stl_sc26198flowctrl(stlport_t *portp, int state)
        if (tty == (struct tty_struct *) NULL)
                return;
 
-       save_flags(flags);
-       cli();
+       spin_lock_irqsave(&brd_lock, flags);
        BRDENABLE(portp->brdnr, portp->pagenr);
 
        if (state) {
@@ -4816,7 +4674,7 @@ static void stl_sc26198flowctrl(stlport_t *portp, int state)
        }
 
        BRDDISABLE(portp->brdnr);
-       restore_flags(flags);
+       spin_unlock_irqrestore(&brd_lock, flags);
 }
 
 /*****************************************************************************/
@@ -4841,8 +4699,7 @@ static void stl_sc26198sendflow(stlport_t *portp, int state)
        if (tty == (struct tty_struct *) NULL)
                return;
 
-       save_flags(flags);
-       cli();
+       spin_lock_irqsave(&brd_lock, flags);
        BRDENABLE(portp->brdnr, portp->pagenr);
        if (state) {
                mr0 = stl_sc26198getreg(portp, MR0);
@@ -4862,7 +4719,7 @@ static void stl_sc26198sendflow(stlport_t *portp, int state)
                stl_sc26198setreg(portp, MR0, mr0);
        }
        BRDDISABLE(portp->brdnr);
-       restore_flags(flags);
+       spin_unlock_irqrestore(&brd_lock, flags);
 }
 
 /*****************************************************************************/
@@ -4878,14 +4735,13 @@ static void stl_sc26198flush(stlport_t *portp)
        if (portp == (stlport_t *) NULL)
                return;
 
-       save_flags(flags);
-       cli();
+       spin_lock_irqsave(&brd_lock, flags);
        BRDENABLE(portp->brdnr, portp->pagenr);
        stl_sc26198setreg(portp, SCCR, CR_TXRESET);
        stl_sc26198setreg(portp, SCCR, portp->crenable);
        BRDDISABLE(portp->brdnr);
        portp->tx.tail = portp->tx.head;
-       restore_flags(flags);
+       spin_unlock_irqrestore(&brd_lock, flags);
 }
 
 /*****************************************************************************/
@@ -4908,18 +4764,17 @@ static int stl_sc26198datastate(stlport_t *portp)
 #endif
 
        if (portp == (stlport_t *) NULL)
-               return(0);
+               return 0;
        if (test_bit(ASYI_TXBUSY, &portp->istate))
-               return(1);
+               return 1;
 
-       save_flags(flags);
-       cli();
+       spin_lock_irqsave(&brd_lock, flags);
        BRDENABLE(portp->brdnr, portp->pagenr);
        sr = stl_sc26198getreg(portp, SR);
        BRDDISABLE(portp->brdnr);
-       restore_flags(flags);
+       spin_unlock_irqrestore(&brd_lock, flags);
 
-       return((sr & SR_TXEMPTY) ? 0 : 1);
+       return (sr & SR_TXEMPTY) ? 0 : 1;
 }
 
 /*****************************************************************************/
@@ -4975,6 +4830,8 @@ static void stl_sc26198intr(stlpanel_t *panelp, unsigned int iobase)
        stlport_t       *portp;
        unsigned int    iack;
 
+       spin_lock(&brd_lock);
+
 /* 
  *     Work around bug in sc26198 chip... Cannot have A6 address
  *     line of UART high, else iack will be returned as 0.
@@ -4990,6 +4847,8 @@ static void stl_sc26198intr(stlpanel_t *panelp, unsigned int iobase)
                stl_sc26198txisr(portp);
        else
                stl_sc26198otherisr(portp, iack);
+
+       spin_unlock(&brd_lock);
 }
 
 /*****************************************************************************/
@@ -5082,9 +4941,7 @@ static void stl_sc26198rxisr(stlport_t *portp, unsigned int iack)
        len = inb(ioaddr + XP_DATA) + 1;
 
        if ((iack & IVR_TYPEMASK) == IVR_RXDATA) {
-               if ((tty == (struct tty_struct *) NULL) ||
-                   (tty->flip.char_buf_ptr == (char *) NULL) ||
-                   ((buflen = TTY_FLIPBUF_SIZE - tty->flip.count) == 0)) {
+               if (tty == NULL || (buflen = tty_buffer_request_room(tty, len)) == 0) {
                        len = MIN(len, sizeof(stl_unwanted));
                        outb(GRXFIFO, (ioaddr + XP_ADDR));
                        insb((ioaddr + XP_DATA), &stl_unwanted[0], len);
@@ -5093,12 +4950,10 @@ static void stl_sc26198rxisr(stlport_t *portp, unsigned int iack)
                } else {
                        len = MIN(len, buflen);
                        if (len > 0) {
+                               unsigned char *ptr;
                                outb(GRXFIFO, (ioaddr + XP_ADDR));
-                               insb((ioaddr + XP_DATA), tty->flip.char_buf_ptr, len);
-                               memset(tty->flip.flag_buf_ptr, 0, len);
-                               tty->flip.flag_buf_ptr += len;
-                               tty->flip.char_buf_ptr += len;
-                               tty->flip.count += len;
+                               tty_prepare_flip_string(tty, &ptr, len);
+                               insb((ioaddr + XP_DATA), ptr, len);
                                tty_schedule_flip(tty);
                                portp->stats.rxtotal += len;
                        }
@@ -5166,14 +5021,8 @@ static inline void stl_sc26198rxbadch(stlport_t *portp, unsigned char status, ch
                        status = 0;
                }
 
-               if (tty->flip.char_buf_ptr != (char *) NULL) {
-                       if (tty->flip.count < TTY_FLIPBUF_SIZE) {
-                               *tty->flip.flag_buf_ptr++ = status;
-                               *tty->flip.char_buf_ptr++ = ch;
-                               tty->flip.count++;
-                       }
-                       tty_schedule_flip(tty);
-               }
+               tty_insert_flip_char(tty, ch, status);
+               tty_schedule_flip(tty);
 
                if (status == 0)
                        portp->stats.rxtotal++;