Merge branch 'urgent' of git://git.kernel.org/pub/scm/linux/kernel/git/brodo/pcmcia-2.6
[safe/jmp/linux-2.6] / drivers / char / istallion.c
index fff19f7..4cd6c52 100644 (file)
@@ -19,7 +19,9 @@
 /*****************************************************************************/
 
 #include <linux/module.h>
+#include <linux/sched.h>
 #include <linux/slab.h>
+#include <linux/smp_lock.h>
 #include <linux/interrupt.h>
 #include <linux/tty.h>
 #include <linux/tty_flip.h>
@@ -211,7 +213,6 @@ static int          stli_shared;
  *     with the slave. Most of them need to be updated atomically, so always
  *     use the bit setting operations (unless protected by cli/sti).
  */
-#define        ST_INITIALIZING 1
 #define        ST_OPENING      2
 #define        ST_CLOSING      3
 #define        ST_CMDING       4
@@ -619,7 +620,7 @@ static int  stli_brdinit(struct stlibrd *brdp);
 static int     stli_startbrd(struct stlibrd *brdp);
 static ssize_t stli_memread(struct file *fp, char __user *buf, size_t count, loff_t *offp);
 static ssize_t stli_memwrite(struct file *fp, const char __user *buf, size_t count, loff_t *offp);
-static int     stli_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg);
+static long    stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg);
 static void    stli_brdpoll(struct stlibrd *brdp, cdkhdr_t __iomem *hdrp);
 static void    stli_poll(unsigned long arg);
 static int     stli_hostcmd(struct stlibrd *brdp, struct stliport *portp);
@@ -702,7 +703,7 @@ static const struct file_operations stli_fsiomem = {
        .owner          = THIS_MODULE,
        .read           = stli_memread,
        .write          = stli_memwrite,
-       .ioctl          = stli_memioctl,
+       .unlocked_ioctl = stli_memioctl,
 };
 
 /*****************************************************************************/
@@ -781,13 +782,32 @@ static int stli_parsebrd(struct stlconf *confp, char **argp)
 
 /*****************************************************************************/
 
+/*
+ *     On the first open of the device setup the port hardware, and
+ *     initialize the per port data structure. Since initializing the port
+ *     requires several commands to the board we will need to wait for any
+ *     other open that is already initializing the port.
+ *
+ *     Locking: protected by the port mutex.
+ */
+
+static int stli_activate(struct tty_port *port, struct tty_struct *tty)
+{
+       struct stliport *portp = container_of(port, struct stliport, port);
+       struct stlibrd *brdp = stli_brds[portp->brdnr];
+       int rc;
+
+       if ((rc = stli_initopen(tty, brdp, portp)) >= 0)
+               clear_bit(TTY_IO_ERROR, &tty->flags);
+       wake_up_interruptible(&portp->raw_wait);
+       return rc;
+}
+
 static int stli_open(struct tty_struct *tty, struct file *filp)
 {
        struct stlibrd *brdp;
        struct stliport *portp;
-       struct tty_port *port;
        unsigned int minordev, brdnr, portnr;
-       int rc;
 
        minordev = tty->index;
        brdnr = MINOR2BRD(minordev);
@@ -807,95 +827,56 @@ static int stli_open(struct tty_struct *tty, struct file *filp)
                return -ENODEV;
        if (portp->devnr < 1)
                return -ENODEV;
-       port = &portp->port;
-
-/*
- *     On the first open of the device setup the port hardware, and
- *     initialize the per port data structure. Since initializing the port
- *     requires several commands to the board we will need to wait for any
- *     other open that is already initializing the port.
- *
- *     Review - locking
- */
-       tty_port_tty_set(port, tty);
-       tty->driver_data = portp;
-       port->count++;
-
-       wait_event_interruptible(portp->raw_wait,
-                       !test_bit(ST_INITIALIZING, &portp->state));
-       if (signal_pending(current))
-               return -ERESTARTSYS;
-
-       if ((portp->port.flags & ASYNC_INITIALIZED) == 0) {
-               set_bit(ST_INITIALIZING, &portp->state);
-               if ((rc = stli_initopen(tty, brdp, portp)) >= 0) {
-                       /* Locking */
-                       port->flags |= ASYNC_INITIALIZED;
-                       clear_bit(TTY_IO_ERROR, &tty->flags);
-               }
-               clear_bit(ST_INITIALIZING, &portp->state);
-               wake_up_interruptible(&portp->raw_wait);
-               if (rc < 0)
-                       return rc;
-       }
-       return tty_port_block_til_ready(&portp->port, tty, filp);
+       return tty_port_open(&portp->port, tty, filp);
 }
 
+
 /*****************************************************************************/
 
-static void stli_close(struct tty_struct *tty, struct file *filp)
+static void stli_shutdown(struct tty_port *port)
 {
        struct stlibrd *brdp;
-       struct stliport *portp;
-       struct tty_port *port;
+       unsigned long ftype;
        unsigned long flags;
+       struct stliport *portp = container_of(port, struct stliport, port);
 
-       portp = tty->driver_data;
-       if (portp == NULL)
+       if (portp->brdnr >= stli_nrbrds)
                return;
-       port = &portp->port;
-
-       if (tty_port_close_start(port, tty, filp) == 0)
+       brdp = stli_brds[portp->brdnr];
+       if (brdp == NULL)
                return;
 
-/*
- *     May want to wait for data to drain before closing. The BUSY flag
- *     keeps track of whether we are still transmitting or not. It is
- *     updated by messages from the slave - indicating when all chars
- *     really have drained.
- */
-       spin_lock_irqsave(&stli_lock, flags);
-       if (tty == stli_txcooktty)
-               stli_flushchars(tty);
-       spin_unlock_irqrestore(&stli_lock, flags);
-
-       /* We end up doing this twice for the moment. This needs looking at
-          eventually. Note we still use portp->closing_wait as a result */
-       if (portp->closing_wait != ASYNC_CLOSING_WAIT_NONE)
-               tty_wait_until_sent(tty, portp->closing_wait);
+       /*
+        *      May want to wait for data to drain before closing. The BUSY
+        *      flag keeps track of whether we are still transmitting or not.
+        *      It is updated by messages from the slave - indicating when all
+        *      chars really have drained.
+        */
 
-       /* FIXME: port locking here needs attending to */
-       port->flags &= ~ASYNC_INITIALIZED;
+       if (!test_bit(ST_CLOSING, &portp->state))
+               stli_rawclose(brdp, portp, 0, 0);
 
-       brdp = stli_brds[portp->brdnr];
-       stli_rawclose(brdp, portp, 0, 0);
-       if (tty->termios->c_cflag & HUPCL) {
-               stli_mkasysigs(&portp->asig, 0, 0);
-               if (test_bit(ST_CMDING, &portp->state))
-                       set_bit(ST_DOSIGS, &portp->state);
-               else
-                       stli_sendcmd(brdp, portp, A_SETSIGNALS, &portp->asig,
-                               sizeof(asysigs_t), 0);
-       }
+       spin_lock_irqsave(&stli_lock, flags);
        clear_bit(ST_TXBUSY, &portp->state);
        clear_bit(ST_RXSTOP, &portp->state);
-       set_bit(TTY_IO_ERROR, &tty->flags);
-       tty_ldisc_flush(tty);
-       set_bit(ST_DOFLUSHRX, &portp->state);
-       stli_flushbuffer(tty);
+       spin_unlock_irqrestore(&stli_lock, flags);
 
-       tty_port_close_end(port, tty);
-       tty_port_tty_set(port, NULL);
+       ftype = FLUSHTX | FLUSHRX;
+       stli_cmdwait(brdp, portp, A_FLUSH, &ftype, sizeof(u32), 0);
+}
+
+static void stli_close(struct tty_struct *tty, struct file *filp)
+{
+       struct stliport *portp = tty->driver_data;
+       unsigned long flags;
+       if (portp == NULL)
+               return;
+       spin_lock_irqsave(&stli_lock, flags);
+       /*      Flush any internal buffering out first */
+       if (tty == stli_txcooktty)
+               stli_flushchars(tty);
+       spin_unlock_irqrestore(&stli_lock, flags);
+       tty_port_close(&portp->port, tty, filp);
 }
 
 /*****************************************************************************/
@@ -1140,14 +1121,14 @@ static int stli_carrier_raised(struct tty_port *port)
        return (portp->sigs & TIOCM_CD) ? 1 : 0;
 }
 
-static void stli_raise_dtr_rts(struct tty_port *port)
+static void stli_dtr_rts(struct tty_port *port, int on)
 {
        struct stliport *portp = container_of(port, struct stliport, port);
        struct stlibrd *brdp = stli_brds[portp->brdnr];
-       stli_mkasysigs(&portp->asig, 1, 1);
+       stli_mkasysigs(&portp->asig, on, on);
        if (stli_cmdwait(brdp, portp, A_SETSIGNALS, &portp->asig,
                sizeof(asysigs_t), 0) < 0)
-                       printk(KERN_WARNING "istallion: dtr raise failed.\n");
+                       printk(KERN_WARNING "istallion: dtr set failed.\n");
 }
 
 
@@ -1722,6 +1703,7 @@ static void stli_start(struct tty_struct *tty)
 
 /*****************************************************************************/
 
+
 /*
  *     Hangup this port. This is pretty much like closing the port, only
  *     a little more brutal. No waiting for data to drain. Shutdown the
@@ -1731,47 +1713,8 @@ static void stli_start(struct tty_struct *tty)
 
 static void stli_hangup(struct tty_struct *tty)
 {
-       struct stliport *portp;
-       struct stlibrd *brdp;
-       struct tty_port *port;
-       unsigned long flags;
-
-       portp = tty->driver_data;
-       if (portp == NULL)
-               return;
-       if (portp->brdnr >= stli_nrbrds)
-               return;
-       brdp = stli_brds[portp->brdnr];
-       if (brdp == NULL)
-               return;
-       port = &portp->port;
-
-       spin_lock_irqsave(&port->lock, flags);
-       port->flags &= ~ASYNC_INITIALIZED;
-       spin_unlock_irqrestore(&port->lock, flags);
-
-       if (!test_bit(ST_CLOSING, &portp->state))
-               stli_rawclose(brdp, portp, 0, 0);
-
-       spin_lock_irqsave(&stli_lock, flags);
-       if (tty->termios->c_cflag & HUPCL) {
-               stli_mkasysigs(&portp->asig, 0, 0);
-               if (test_bit(ST_CMDING, &portp->state)) {
-                       set_bit(ST_DOSIGS, &portp->state);
-                       set_bit(ST_DOFLUSHTX, &portp->state);
-                       set_bit(ST_DOFLUSHRX, &portp->state);
-               } else {
-                       stli_sendcmd(brdp, portp, A_SETSIGNALSF,
-                               &portp->asig, sizeof(asysigs_t), 0);
-               }
-       }
-
-       clear_bit(ST_TXBUSY, &portp->state);
-       clear_bit(ST_RXSTOP, &portp->state);
-       set_bit(TTY_IO_ERROR, &tty->flags);
-       spin_unlock_irqrestore(&stli_lock, flags);
-
-       tty_port_hangup(port);
+       struct stliport *portp = tty->driver_data;
+       tty_port_hangup(&portp->port);
 }
 
 /*****************************************************************************/
@@ -3785,7 +3728,7 @@ err:
        return retval;
 }
 
-static void stli_pciremove(struct pci_dev *pdev)
+static void __devexit stli_pciremove(struct pci_dev *pdev)
 {
        struct stlibrd *brdp = pci_get_drvdata(pdev);
 
@@ -4309,7 +4252,7 @@ static int stli_getbrdstruct(struct stlibrd __user *arg)
  *     reset it, and start/stop it.
  */
 
-static int stli_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, unsigned long arg)
+static long stli_memioctl(struct file *fp, unsigned int cmd, unsigned long arg)
 {
        struct stlibrd *brdp;
        int brdnr, rc, done;
@@ -4354,7 +4297,7 @@ static int stli_memioctl(struct inode *ip, struct file *fp, unsigned int cmd, un
  *     Now handle the board specific ioctls. These all depend on the
  *     minor number of the device they were called from.
  */
-       brdnr = iminor(ip);
+       brdnr = iminor(fp->f_dentry->d_inode);
        if (brdnr >= STL_MAXBRDS)
                return -ENODEV;
        brdp = stli_brds[brdnr];
@@ -4417,7 +4360,9 @@ static const struct tty_operations stli_ops = {
 
 static const struct tty_port_operations stli_port_ops = {
        .carrier_raised = stli_carrier_raised,
-       .raise_dtr_rts = stli_raise_dtr_rts,
+       .dtr_rts = stli_dtr_rts,
+       .activate = stli_activate,
+       .shutdown = stli_shutdown,
 };
 
 /*****************************************************************************/