]> pilppa.org Git - linux-2.6-omap-h63xx.git/blobdiff - drivers/char/stallion.c
Merge branch 'core-fixes-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[linux-2.6-omap-h63xx.git] / drivers / char / stallion.c
index 19db1eb87c26fa22eb9e4f17d8b6ec384e6c021b..e1e0dd89ac9aa309e2f92c9183618948b09b6900 100644 (file)
@@ -130,6 +130,8 @@ static char         stl_unwanted[SC26198_RXFIFOSIZE];
 static DEFINE_MUTEX(stl_brdslock);
 static struct stlbrd           *stl_brds[STL_MAXBRDS];
 
+static const struct tty_port_operations stl_port_ops;
+
 /*
  *     Per board state flags. Used with the state field of the board struct.
  *     Not really much here!
@@ -405,9 +407,8 @@ static unsigned int stl_baudrates[] = {
 
 static int     stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg);
 static int     stl_brdinit(struct stlbrd *brdp);
-static int     stl_getportstats(struct stlport *portp, comstats_t __user *cp);
+static int     stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp);
 static int     stl_clrportstats(struct stlport *portp, comstats_t __user *cp);
-static int     stl_waitcarrier(struct stlport *portp, struct file *filp);
 
 /*
  *     CD1400 uart specific handling functions.
@@ -612,8 +613,9 @@ static struct class *stallion_class;
 static void stl_cd_change(struct stlport *portp)
 {
        unsigned int oldsigs = portp->sigs;
+       struct tty_struct *tty = tty_port_tty_get(&portp->port);
 
-       if (!portp->port.tty)
+       if (!tty)
                return;
 
        portp->sigs = stl_getsignals(portp);
@@ -623,7 +625,8 @@ static void stl_cd_change(struct stlport *portp)
 
        if ((oldsigs & TIOCM_CD) && ((portp->sigs & TIOCM_CD) == 0))
                if (portp->port.flags & ASYNC_CHECK_CD)
-                       tty_hangup(portp->port.tty);
+                       tty_hangup(tty);
+       tty_kref_put(tty);
 }
 
 /*
@@ -701,8 +704,9 @@ static int stl_open(struct tty_struct *tty, struct file *filp)
 {
        struct stlport  *portp;
        struct stlbrd   *brdp;
+       struct tty_port *port;
        unsigned int    minordev, brdnr, panelnr;
-       int             portnr, rc;
+       int             portnr;
 
        pr_debug("stl_open(tty=%p,filp=%p): device=%s\n", tty, filp, tty->name);
 
@@ -713,6 +717,7 @@ static int stl_open(struct tty_struct *tty, struct file *filp)
        brdp = stl_brds[brdnr];
        if (brdp == NULL)
                return -ENODEV;
+
        minordev = MINOR2PORT(minordev);
        for (portnr = -1, panelnr = 0; panelnr < STL_MAXPANELS; panelnr++) {
                if (brdp->panels[panelnr] == NULL)
@@ -729,16 +734,17 @@ static int stl_open(struct tty_struct *tty, struct file *filp)
        portp = brdp->panels[panelnr]->ports[portnr];
        if (portp == NULL)
                return -ENODEV;
+       port = &portp->port;
 
 /*
  *     On the first open of the device setup the port hardware, and
  *     initialize the per port data structure.
  */
-       portp->port.tty = tty;
+       tty_port_tty_set(port, tty);
        tty->driver_data = portp;
-       portp->port.count++;
+       port->count++;
 
-       if ((portp->port.flags & ASYNC_INITIALIZED) == 0) {
+       if ((port->flags & ASYNC_INITIALIZED) == 0) {
                if (!portp->tx.buf) {
                        portp->tx.buf = kmalloc(STL_TXBUFSIZE, GFP_KERNEL);
                        if (!portp->tx.buf)
@@ -752,90 +758,24 @@ static int stl_open(struct tty_struct *tty, struct file *filp)
                stl_enablerxtx(portp, 1, 1);
                stl_startrxtx(portp, 1, 0);
                clear_bit(TTY_IO_ERROR, &tty->flags);
-               portp->port.flags |= ASYNC_INITIALIZED;
+               port->flags |= ASYNC_INITIALIZED;
        }
-
-/*
- *     Check if this port is in the middle of closing. If so then wait
- *     until it is closed then return error status, based on flag settings.
- *     The sleep here does not need interrupt protection since the wakeup
- *     for it is done with the same context.
- */
-       if (portp->port.flags & ASYNC_CLOSING) {
-               interruptible_sleep_on(&portp->port.close_wait);
-               if (portp->port.flags & ASYNC_HUP_NOTIFY)
-                       return -EAGAIN;
-               return -ERESTARTSYS;
-       }
-
-/*
- *     Based on type of open being done check if it can overlap with any
- *     previous opens still in effect. If we are a normal serial device
- *     then also we might have to wait for carrier.
- */
-       if (!(filp->f_flags & O_NONBLOCK))
-               if ((rc = stl_waitcarrier(portp, filp)) != 0)
-                       return rc;
-
-       portp->port.flags |= ASYNC_NORMAL_ACTIVE;
-
-       return 0;
+       return tty_port_block_til_ready(port, tty, filp);
 }
 
 /*****************************************************************************/
 
-/*
- *     Possibly need to wait for carrier (DCD signal) to come high. Say
- *     maybe because if we are clocal then we don't need to wait...
- */
-
-static int stl_waitcarrier(struct stlport *portp, struct file *filp)
+static int stl_carrier_raised(struct tty_port *port)
 {
-       unsigned long   flags;
-       int             rc, doclocal;
-
-       pr_debug("stl_waitcarrier(portp=%p,filp=%p)\n", portp, filp);
-
-       rc = 0;
-       doclocal = 0;
-
-       spin_lock_irqsave(&stallion_lock, flags);
-
-       if (portp->port.tty->termios->c_cflag & CLOCAL)
-               doclocal++;
-
-       portp->openwaitcnt++;
-       if (! tty_hung_up_p(filp))
-               portp->port.count--;
-
-       for (;;) {
-               /* Takes brd_lock internally */
-               stl_setsignals(portp, 1, 1);
-               if (tty_hung_up_p(filp) ||
-                   ((portp->port.flags & ASYNC_INITIALIZED) == 0)) {
-                       if (portp->port.flags & ASYNC_HUP_NOTIFY)
-                               rc = -EBUSY;
-                       else
-                               rc = -ERESTARTSYS;
-                       break;
-               }
-               if (((portp->port.flags & ASYNC_CLOSING) == 0) &&
-                   (doclocal || (portp->sigs & TIOCM_CD)))
-                       break;
-               if (signal_pending(current)) {
-                       rc = -ERESTARTSYS;
-                       break;
-               }
-               /* FIXME */
-               interruptible_sleep_on(&portp->port.open_wait);
-       }
-
-       if (! tty_hung_up_p(filp))
-               portp->port.count++;
-       portp->openwaitcnt--;
-       spin_unlock_irqrestore(&stallion_lock, flags);
+       struct stlport *portp = container_of(port, struct stlport, port);
+       return (portp->sigs & TIOCM_CD) ? 1 : 0;
+}
 
-       return rc;
+static void stl_raise_dtr_rts(struct tty_port *port)
+{
+       struct stlport *portp = container_of(port, struct stlport, port);
+       /* Takes brd_lock internally */
+       stl_setsignals(portp, 1, 1);
 }
 
 /*****************************************************************************/
@@ -846,8 +786,6 @@ static void stl_flushbuffer(struct tty_struct *tty)
 
        pr_debug("stl_flushbuffer(tty=%p)\n", tty);
 
-       if (tty == NULL)
-               return;
        portp = tty->driver_data;
        if (portp == NULL)
                return;
@@ -865,8 +803,6 @@ static void stl_waituntilsent(struct tty_struct *tty, int timeout)
 
        pr_debug("stl_waituntilsent(tty=%p,timeout=%d)\n", tty, timeout);
 
-       if (tty == NULL)
-               return;
        portp = tty->driver_data;
        if (portp == NULL)
                return;
@@ -891,47 +827,29 @@ static void stl_waituntilsent(struct tty_struct *tty, int timeout)
 static void stl_close(struct tty_struct *tty, struct file *filp)
 {
        struct stlport  *portp;
+       struct tty_port *port;
        unsigned long   flags;
 
        pr_debug("stl_close(tty=%p,filp=%p)\n", tty, filp);
 
        portp = tty->driver_data;
-       if (portp == NULL)
-               return;
-
-       spin_lock_irqsave(&stallion_lock, flags);
-       if (tty_hung_up_p(filp)) {
-               spin_unlock_irqrestore(&stallion_lock, flags);
-               return;
-       }
-       if ((tty->count == 1) && (portp->port.count != 1))
-               portp->port.count = 1;
-       if (portp->port.count-- > 1) {
-               spin_unlock_irqrestore(&stallion_lock, flags);
-               return;
-       }
+       BUG_ON(portp == NULL);
 
-       portp->port.count = 0;
-       portp->port.flags |= ASYNC_CLOSING;
+       port = &portp->port;
 
+       if (tty_port_close_start(port, tty, filp) == 0)
+               return;
 /*
  *     May want to wait for any data to drain before closing. The BUSY
  *     flag keeps track of whether we are still sending or not - it is
  *     very accurate for the cd1400, not quite so for the sc26198.
  *     (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);
+       spin_lock_irqsave(&port->lock, flags);
        portp->port.flags &= ~ASYNC_INITIALIZED;
-       spin_unlock_irqrestore(&stallion_lock, flags);
+       spin_unlock_irqrestore(&port->lock, flags);
 
        stl_disableintrs(portp);
        if (tty->termios->c_cflag & HUPCL)
@@ -945,20 +863,9 @@ static void stl_close(struct tty_struct *tty, struct file *filp)
                portp->tx.head = NULL;
                portp->tx.tail = NULL;
        }
-       set_bit(TTY_IO_ERROR, &tty->flags);
-       tty_ldisc_flush(tty);
-
-       tty->closing = 0;
-       portp->port.tty = NULL;
 
-       if (portp->openwaitcnt) {
-               if (portp->close_delay)
-                       msleep_interruptible(jiffies_to_msecs(portp->close_delay));
-               wake_up_interruptible(&portp->port.open_wait);
-       }
-
-       portp->port.flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
-       wake_up_interruptible(&portp->port.close_wait);
+       tty_port_close_end(port, tty);
+       tty_port_tty_set(port, NULL);
 }
 
 /*****************************************************************************/
@@ -1033,8 +940,6 @@ static int stl_putchar(struct tty_struct *tty, unsigned char ch)
 
        pr_debug("stl_putchar(tty=%p,ch=%x)\n", tty, ch);
 
-       if (tty == NULL)
-               return -EINVAL;
        portp = tty->driver_data;
        if (portp == NULL)
                return -EINVAL;
@@ -1070,8 +975,6 @@ static void stl_flushchars(struct tty_struct *tty)
 
        pr_debug("stl_flushchars(tty=%p)\n", tty);
 
-       if (tty == NULL)
-               return;
        portp = tty->driver_data;
        if (portp == NULL)
                return;
@@ -1090,8 +993,6 @@ static int stl_writeroom(struct tty_struct *tty)
 
        pr_debug("stl_writeroom(tty=%p)\n", tty);
 
-       if (tty == NULL)
-               return 0;
        portp = tty->driver_data;
        if (portp == NULL)
                return 0;
@@ -1122,8 +1023,6 @@ static int stl_charsinbuffer(struct tty_struct *tty)
 
        pr_debug("stl_charsinbuffer(tty=%p)\n", tty);
 
-       if (tty == NULL)
-               return 0;
        portp = tty->driver_data;
        if (portp == NULL)
                return 0;
@@ -1183,8 +1082,9 @@ static int stl_getserial(struct stlport *portp, struct serial_struct __user *sp)
  *     just quietly ignore any requests to change irq, etc.
  */
 
-static int stl_setserial(struct stlport *portp, struct serial_struct __user *sp)
+static int stl_setserial(struct tty_struct *tty, struct serial_struct __user *sp)
 {
+       struct stlport *        portp = tty->driver_data;
        struct serial_struct    sio;
 
        pr_debug("stl_setserial(portp=%p,sp=%p)\n", portp, sp);
@@ -1205,7 +1105,7 @@ static int stl_setserial(struct stlport *portp, struct serial_struct __user *sp)
        portp->close_delay = sio.close_delay;
        portp->closing_wait = sio.closing_wait;
        portp->custom_divisor = sio.custom_divisor;
-       stl_setport(portp, portp->port.tty->termios);
+       stl_setport(portp, tty->termios);
        return 0;
 }
 
@@ -1215,8 +1115,6 @@ static int stl_tiocmget(struct tty_struct *tty, struct file *file)
 {
        struct stlport  *portp;
 
-       if (tty == NULL)
-               return -ENODEV;
        portp = tty->driver_data;
        if (portp == NULL)
                return -ENODEV;
@@ -1232,8 +1130,6 @@ static int stl_tiocmset(struct tty_struct *tty, struct file *file,
        struct stlport  *portp;
        int rts = -1, dtr = -1;
 
-       if (tty == NULL)
-               return -ENODEV;
        portp = tty->driver_data;
        if (portp == NULL)
                return -ENODEV;
@@ -1262,8 +1158,6 @@ static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd
        pr_debug("stl_ioctl(tty=%p,file=%p,cmd=%x,arg=%lx)\n", tty, file, cmd,
                        arg);
 
-       if (tty == NULL)
-               return -ENODEV;
        portp = tty->driver_data;
        if (portp == NULL)
                return -ENODEV;
@@ -1282,10 +1176,10 @@ static int stl_ioctl(struct tty_struct *tty, struct file *file, unsigned int cmd
                rc = stl_getserial(portp, argp);
                break;
        case TIOCSSERIAL:
-               rc = stl_setserial(portp, argp);
+               rc = stl_setserial(tty, argp);
                break;
        case COM_GETPORTSTATS:
-               rc = stl_getportstats(portp, argp);
+               rc = stl_getportstats(tty, portp, argp);
                break;
        case COM_CLRPORTSTATS:
                rc = stl_clrportstats(portp, argp);
@@ -1317,8 +1211,6 @@ static void stl_start(struct tty_struct *tty)
 
        pr_debug("stl_start(tty=%p)\n", tty);
 
-       if (tty == NULL)
-               return;
        portp = tty->driver_data;
        if (portp == NULL)
                return;
@@ -1334,8 +1226,6 @@ static void stl_settermios(struct tty_struct *tty, struct ktermios *old)
 
        pr_debug("stl_settermios(tty=%p,old=%p)\n", tty, old);
 
-       if (tty == NULL)
-               return;
        portp = tty->driver_data;
        if (portp == NULL)
                return;
@@ -1369,8 +1259,6 @@ static void stl_throttle(struct tty_struct *tty)
 
        pr_debug("stl_throttle(tty=%p)\n", tty);
 
-       if (tty == NULL)
-               return;
        portp = tty->driver_data;
        if (portp == NULL)
                return;
@@ -1389,8 +1277,6 @@ static void stl_unthrottle(struct tty_struct *tty)
 
        pr_debug("stl_unthrottle(tty=%p)\n", tty);
 
-       if (tty == NULL)
-               return;
        portp = tty->driver_data;
        if (portp == NULL)
                return;
@@ -1410,8 +1296,6 @@ static void stl_stop(struct tty_struct *tty)
 
        pr_debug("stl_stop(tty=%p)\n", tty);
 
-       if (tty == NULL)
-               return;
        portp = tty->driver_data;
        if (portp == NULL)
                return;
@@ -1429,16 +1313,20 @@ static void stl_stop(struct tty_struct *tty)
 static void stl_hangup(struct tty_struct *tty)
 {
        struct stlport  *portp;
+       struct tty_port *port;
+       unsigned long flags;
 
        pr_debug("stl_hangup(tty=%p)\n", tty);
 
-       if (tty == NULL)
-               return;
        portp = tty->driver_data;
        if (portp == NULL)
                return;
+       port = &portp->port;
+
+       spin_lock_irqsave(&port->lock, flags);
+       port->flags &= ~ASYNC_INITIALIZED;
+       spin_unlock_irqrestore(&port->lock, flags);
 
-       portp->port.flags &= ~ASYNC_INITIALIZED;
        stl_disableintrs(portp);
        if (tty->termios->c_cflag & HUPCL)
                stl_setsignals(portp, 0, 0);
@@ -1452,10 +1340,7 @@ static void stl_hangup(struct tty_struct *tty)
                portp->tx.head = NULL;
                portp->tx.tail = NULL;
        }
-       portp->port.tty = NULL;
-       portp->port.flags &= ~ASYNC_NORMAL_ACTIVE;
-       portp->port.count = 0;
-       wake_up_interruptible(&portp->port.open_wait);
+       tty_port_hangup(port);
 }
 
 /*****************************************************************************/
@@ -1466,8 +1351,6 @@ static int stl_breakctl(struct tty_struct *tty, int state)
 
        pr_debug("stl_breakctl(tty=%p,state=%d)\n", tty, state);
 
-       if (tty == NULL)
-               return -EINVAL;
        portp = tty->driver_data;
        if (portp == NULL)
                return -EINVAL;
@@ -1484,8 +1367,6 @@ static void stl_sendxchar(struct tty_struct *tty, char ch)
 
        pr_debug("stl_sendxchar(tty=%p,ch=%x)\n", tty, ch);
 
-       if (tty == NULL)
-               return;
        portp = tty->driver_data;
        if (portp == NULL)
                return;
@@ -1805,7 +1686,8 @@ static int __devinit stl_initports(struct stlbrd *brdp, struct stlpanel *panelp)
                                "(size=%Zd)\n", sizeof(struct stlport));
                        break;
                }
-
+               tty_port_init(&portp->port);
+               portp->port.ops = &stl_port_ops;
                portp->magic = STL_PORTMAGIC;
                portp->portnr = i;
                portp->brdnr = panelp->brdnr;
@@ -1832,6 +1714,7 @@ static void stl_cleanup_panels(struct stlbrd *brdp)
        struct stlpanel *panelp;
        struct stlport *portp;
        unsigned int j, k;
+       struct tty_struct *tty;
 
        for (j = 0; j < STL_MAXPANELS; j++) {
                panelp = brdp->panels[j];
@@ -1841,8 +1724,11 @@ static void stl_cleanup_panels(struct stlbrd *brdp)
                        portp = panelp->ports[k];
                        if (portp == NULL)
                                continue;
-                       if (portp->port.tty != NULL)
-                               stl_hangup(portp->port.tty);
+                       tty = tty_port_tty_get(&portp->port);
+                       if (tty != NULL) {
+                               stl_hangup(tty);
+                               tty_kref_put(tty);
+                       }
                        kfree(portp->tx.buf);
                        kfree(portp);
                }
@@ -2498,7 +2384,7 @@ static struct stlport *stl_getport(int brdnr, int panelnr, int portnr)
  *     what port to get stats for (used through board control device).
  */
 
-static int stl_getportstats(struct stlport *portp, comstats_t __user *cp)
+static int stl_getportstats(struct tty_struct *tty, struct stlport *portp, comstats_t __user *cp)
 {
        comstats_t      stl_comstats;
        unsigned char   *head, *tail;
@@ -2525,18 +2411,17 @@ static int stl_getportstats(struct stlport *portp, comstats_t __user *cp)
        portp->stats.rxbuffered = 0;
 
        spin_lock_irqsave(&stallion_lock, flags);
-       if (portp->port.tty != NULL)
-               if (portp->port.tty->driver_data == portp) {
-                       portp->stats.ttystate = portp->port.tty->flags;
-                       /* No longer available as a statistic */
-                       portp->stats.rxbuffered = 1; /*portp->port.tty->flip.count; */
-                       if (portp->port.tty->termios != NULL) {
-                               portp->stats.cflags = portp->port.tty->termios->c_cflag;
-                               portp->stats.iflags = portp->port.tty->termios->c_iflag;
-                               portp->stats.oflags = portp->port.tty->termios->c_oflag;
-                               portp->stats.lflags = portp->port.tty->termios->c_lflag;
-                       }
+       if (tty != NULL && portp->port.tty == tty) {
+               portp->stats.ttystate = tty->flags;
+               /* No longer available as a statistic */
+               portp->stats.rxbuffered = 1; /*tty->flip.count; */
+               if (tty->termios != NULL) {
+                       portp->stats.cflags = tty->termios->c_cflag;
+                       portp->stats.iflags = tty->termios->c_iflag;
+                       portp->stats.oflags = tty->termios->c_oflag;
+                       portp->stats.lflags = tty->termios->c_lflag;
                }
+       }
        spin_unlock_irqrestore(&stallion_lock, flags);
 
        head = portp->tx.head;
@@ -2640,7 +2525,7 @@ static int stl_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, uns
 
        switch (cmd) {
        case COM_GETPORTSTATS:
-               rc = stl_getportstats(NULL, argp);
+               rc = stl_getportstats(NULL, NULL, argp);
                break;
        case COM_CLRPORTSTATS:
                rc = stl_clrportstats(NULL, argp);
@@ -2686,6 +2571,11 @@ static const struct tty_operations stl_ops = {
        .tiocmset = stl_tiocmset,
 };
 
+static const struct tty_port_operations stl_port_ops = {
+       .carrier_raised = stl_carrier_raised,
+       .raise_dtr_rts = stl_raise_dtr_rts,
+};
+
 /*****************************************************************************/
 /*                       CD1400 HARDWARE FUNCTIONS                           */
 /*****************************************************************************/
@@ -3243,7 +3133,7 @@ static void stl_cd1400flowctrl(struct stlport *portp, int state)
 
        if (portp == NULL)
                return;
-       tty = portp->port.tty;
+       tty = tty_port_tty_get(&portp->port);
        if (tty == NULL)
                return;
 
@@ -3288,6 +3178,7 @@ static void stl_cd1400flowctrl(struct stlport *portp, int state)
 
        BRDDISABLE(portp->brdnr);
        spin_unlock_irqrestore(&brd_lock, flags);
+       tty_kref_put(tty);
 }
 
 /*****************************************************************************/
@@ -3305,7 +3196,7 @@ static void stl_cd1400sendflow(struct stlport *portp, int state)
 
        if (portp == NULL)
                return;
-       tty = portp->port.tty;
+       tty = tty_port_tty_get(&portp->port);
        if (tty == NULL)
                return;
 
@@ -3325,6 +3216,7 @@ static void stl_cd1400sendflow(struct stlport *portp, int state)
        }
        BRDDISABLE(portp->brdnr);
        spin_unlock_irqrestore(&brd_lock, flags);
+       tty_kref_put(tty);
 }
 
 /*****************************************************************************/
@@ -3478,6 +3370,7 @@ static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr)
        int             len, stlen;
        char            *head, *tail;
        unsigned char   ioack, srer;
+       struct tty_struct *tty;
 
        pr_debug("stl_cd1400txisr(panelp=%p,ioaddr=%x)\n", panelp, ioaddr);
 
@@ -3504,8 +3397,11 @@ static void stl_cd1400txisr(struct stlpanel *panelp, int ioaddr)
        if ((len == 0) || ((len < STL_TXBUFLOW) &&
            (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
                set_bit(ASYI_TXLOW, &portp->istate);
-               if (portp->port.tty)
-                       tty_wakeup(portp->port.tty);
+               tty = tty_port_tty_get(&portp->port);
+               if (tty) {
+                       tty_wakeup(tty);
+                       tty_kref_put(tty);
+               }
        }
 
        if (len == 0) {
@@ -3569,7 +3465,7 @@ static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr)
                return;
        }
        portp = panelp->ports[(ioack >> 3)];
-       tty = portp->port.tty;
+       tty = tty_port_tty_get(&portp->port);
 
        if ((ioack & ACK_TYPMASK) == ACK_TYPRXGOOD) {
                outb((RDCR + portp->uartaddr), ioaddr);
@@ -3633,10 +3529,12 @@ static void stl_cd1400rxisr(struct stlpanel *panelp, int ioaddr)
                }
        } else {
                printk("STALLION: bad RX interrupt ack value=%x\n", ioack);
+               tty_kref_put(tty);
                return;
        }
 
 stl_rxalldone:
+       tty_kref_put(tty);
        outb((EOSRR + portp->uartaddr), ioaddr);
        outb(0, (ioaddr + EREG_DATA));
 }
@@ -4175,7 +4073,7 @@ static void stl_sc26198flowctrl(struct stlport *portp, int state)
 
        if (portp == NULL)
                return;
-       tty = portp->port.tty;
+       tty = tty_port_tty_get(&portp->port);
        if (tty == NULL)
                return;
 
@@ -4226,6 +4124,7 @@ static void stl_sc26198flowctrl(struct stlport *portp, int state)
 
        BRDDISABLE(portp->brdnr);
        spin_unlock_irqrestore(&brd_lock, flags);
+       tty_kref_put(tty);
 }
 
 /*****************************************************************************/
@@ -4244,7 +4143,7 @@ static void stl_sc26198sendflow(struct stlport *portp, int state)
 
        if (portp == NULL)
                return;
-       tty = portp->port.tty;
+       tty = tty_port_tty_get(&portp->port);
        if (tty == NULL)
                return;
 
@@ -4269,6 +4168,7 @@ static void stl_sc26198sendflow(struct stlport *portp, int state)
        }
        BRDDISABLE(portp->brdnr);
        spin_unlock_irqrestore(&brd_lock, flags);
+       tty_kref_put(tty);
 }
 
 /*****************************************************************************/
@@ -4408,6 +4308,7 @@ static void stl_sc26198intr(struct stlpanel *panelp, unsigned int iobase)
 
 static void stl_sc26198txisr(struct stlport *portp)
 {
+       struct tty_struct *tty;
        unsigned int    ioaddr;
        unsigned char   mr0;
        int             len, stlen;
@@ -4422,8 +4323,11 @@ static void stl_sc26198txisr(struct stlport *portp)
        if ((len == 0) || ((len < STL_TXBUFLOW) &&
            (test_bit(ASYI_TXLOW, &portp->istate) == 0))) {
                set_bit(ASYI_TXLOW, &portp->istate);
-               if (portp->port.tty)
-                       tty_wakeup(portp->port.tty);
+               tty = tty_port_tty_get(&portp->port);
+               if (tty) {
+                       tty_wakeup(tty);
+                       tty_kref_put(tty);
+               }
        }
 
        if (len == 0) {
@@ -4476,7 +4380,7 @@ static void stl_sc26198rxisr(struct stlport *portp, unsigned int iack)
 
        pr_debug("stl_sc26198rxisr(portp=%p,iack=%x)\n", portp, iack);
 
-       tty = portp->port.tty;
+       tty = tty_port_tty_get(&portp->port);
        ioaddr = portp->ioaddr;
        outb(GIBCR, (ioaddr + XP_ADDR));
        len = inb(ioaddr + XP_DATA) + 1;
@@ -4515,6 +4419,7 @@ static void stl_sc26198rxisr(struct stlport *portp, unsigned int iack)
                        stl_sc26198txunflow(portp, tty);
                }
        }
+       tty_kref_put(tty);
 }
 
 /*****************************************************************************/
@@ -4528,7 +4433,7 @@ static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char
        struct tty_struct       *tty;
        unsigned int            ioaddr;
 
-       tty = portp->port.tty;
+       tty = tty_port_tty_get(&portp->port);
        ioaddr = portp->ioaddr;
 
        if (status & SR_RXPARITY)
@@ -4566,6 +4471,7 @@ static void stl_sc26198rxbadch(struct stlport *portp, unsigned char status, char
                if (status == 0)
                        portp->stats.rxtotal++;
        }
+       tty_kref_put(tty);
 }
 
 /*****************************************************************************/
@@ -4754,8 +4660,8 @@ static int __init stallion_module_init(void)
        if (IS_ERR(stallion_class))
                printk("STALLION: failed to create class\n");
        for (i = 0; i < 4; i++)
-               device_create_drvdata(stallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i),
-                                     NULL, "staliomem%d", i);
+               device_create(stallion_class, NULL, MKDEV(STL_SIOMEMMAJOR, i),
+                             NULL, "staliomem%d", i);
 
        return 0;
 err_unrtty: