tty/serial: lay the foundations for the next set of reworks
authorAlan Cox <alan@lxorguk.ukuu.org.uk>
Wed, 30 Apr 2008 07:53:59 +0000 (00:53 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Wed, 30 Apr 2008 15:29:45 +0000 (08:29 -0700)
- Stop drivers calling their own flush method indirectly, it obfuscates code
  and it will change soon anyway

- A few more lock_kernel paths temporarily needed in some driver internal
  waiting code

- Remove private put_char method that does a write call for one char - we
  have that anyway

- Most but not yet all of the termios copy under lock fixing (some has other
  dependencies to follow)

- Note a few locking bugs in drivers found in the process

- Kill remaining [ab]users of TIOCG/SSOFTCAR in the driver, these must go to
  fix the termios locking

Signed-off-by: Alan Cox <alan@redhat.com>
Cc: Jiri Slaby <jirislaby@gmail.com>
Signed-off-by: Andrew Morton <akpm@linux-foundation.org>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
26 files changed:
drivers/char/amiserial.c
drivers/char/cyclades.c
drivers/char/epca.c
drivers/char/esp.c
drivers/char/generic_serial.c
drivers/char/isicom.c
drivers/char/moxa.c
drivers/char/mxser.c
drivers/char/nozomi.c
drivers/char/pcmcia/synclink_cs.c
drivers/char/riscom8.c
drivers/char/rocket.c
drivers/char/serial167.c
drivers/char/specialix.c
drivers/char/stallion.c
drivers/char/synclink.c
drivers/char/synclink_gt.c
drivers/char/synclinkmp.c
drivers/char/tty_io.c
drivers/char/tty_ioctl.c
drivers/isdn/i4l/isdn_tty.c
drivers/serial/68328serial.c
drivers/serial/68360serial.c
drivers/serial/crisv10.c
drivers/serial/mcfserial.c
drivers/serial/netx-serial.c

index 8ab75a43231bb42904b1950fa44ffc1a8832afc2..a5f3956a5971255401d471cf122fe5d2a12b6295 100644 (file)
@@ -1505,8 +1505,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
                rs_wait_until_sent(tty, info->timeout);
        }
        shutdown(info);
-       if (tty->driver->flush_buffer)
-               tty->driver->flush_buffer(tty);
+       rs_flush_buffer(tty);
                
        tty_ldisc_flush(tty);
        tty->closing = 0;
@@ -1539,6 +1538,8 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
                return; /* Just in case.... */
 
        orig_jiffies = jiffies;
+
+       lock_kernel();
        /*
         * Set the check interval to be 1/5 of the estimated time to
         * send a single character, and make it at least 1.  The check
@@ -1579,6 +1580,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
                        break;
        }
        __set_current_state(TASK_RUNNING);
+       unlock_kernel();
 #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
        printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies);
 #endif
index e61939d3331d40af6ea58bf64b804301b799b23b..571e4fab5bfa83ce0f125cff330d2dc6a9d500a6 100644 (file)
@@ -2522,6 +2522,7 @@ static void cy_wait_until_sent(struct tty_struct *tty, int timeout)
                return;         /* Just in case.... */
 
        orig_jiffies = jiffies;
+       lock_kernel();
        /*
         * Set the check interval to be 1/5 of the estimated time to
         * send a single character, and make it at least 1.  The check
@@ -2573,11 +2574,47 @@ static void cy_wait_until_sent(struct tty_struct *tty, int timeout)
        }
        /* Run one more char cycle */
        msleep_interruptible(jiffies_to_msecs(char_time * 5));
+       unlock_kernel();
 #ifdef CY_DEBUG_WAIT_UNTIL_SENT
        printk(KERN_DEBUG "Clean (jiff=%lu)...done\n", jiffies);
 #endif
 }
 
+static void cy_flush_buffer(struct tty_struct *tty)
+{
+       struct cyclades_port *info = tty->driver_data;
+       struct cyclades_card *card;
+       int channel, retval;
+       unsigned long flags;
+
+#ifdef CY_DEBUG_IO
+       printk(KERN_DEBUG "cyc:cy_flush_buffer ttyC%d\n", info->line);
+#endif
+
+       if (serial_paranoia_check(info, tty->name, "cy_flush_buffer"))
+               return;
+
+       card = info->card;
+       channel = info->line - card->first_line;
+
+       spin_lock_irqsave(&card->card_lock, flags);
+       info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
+       spin_unlock_irqrestore(&card->card_lock, flags);
+
+       if (IS_CYC_Z(*card)) {  /* If it is a Z card, flush the on-board
+                                          buffers as well */
+               spin_lock_irqsave(&card->card_lock, flags);
+               retval = cyz_issue_cmd(card, channel, C_CM_FLUSH_TX, 0L);
+               if (retval != 0) {
+                       printk(KERN_ERR "cyc: flush_buffer retval on ttyC%d "
+                               "was %x\n", info->line, retval);
+               }
+               spin_unlock_irqrestore(&card->card_lock, flags);
+       }
+       tty_wakeup(tty);
+}                              /* cy_flush_buffer */
+
+
 /*
  * This routine is called when a particular tty device is closed.
  */
@@ -2689,8 +2726,7 @@ static void cy_close(struct tty_struct *tty, struct file *filp)
 
        spin_unlock_irqrestore(&card->card_lock, flags);
        shutdown(info);
-       if (tty->driver->flush_buffer)
-               tty->driver->flush_buffer(tty);
+       cy_flush_buffer(tty);
        tty_ldisc_flush(tty);
        spin_lock_irqsave(&card->card_lock, flags);
 
@@ -2881,6 +2917,7 @@ static int cy_chars_in_buffer(struct tty_struct *tty)
                int char_count;
                __u32 tx_put, tx_get, tx_bufsize;
 
+               lock_kernel();
                firm_id = card->base_addr + ID_ADDRESS;
                zfw_ctrl = card->base_addr +
                        (readl(&firm_id->zfwctrl_addr) & 0xfffff);
@@ -2898,6 +2935,7 @@ static int cy_chars_in_buffer(struct tty_struct *tty)
                printk(KERN_DEBUG "cyc:cy_chars_in_buffer ttyC%d %d\n",
                        info->line, info->xmit_cnt + char_count);
 #endif
+               unlock_kernel();
                return info->xmit_cnt + char_count;
        }
 #endif                         /* Z_EXT_CHARS_IN_BUFFER */
@@ -4271,40 +4309,6 @@ static void cy_start(struct tty_struct *tty)
        }
 }                              /* cy_start */
 
-static void cy_flush_buffer(struct tty_struct *tty)
-{
-       struct cyclades_port *info = tty->driver_data;
-       struct cyclades_card *card;
-       int channel, retval;
-       unsigned long flags;
-
-#ifdef CY_DEBUG_IO
-       printk(KERN_DEBUG "cyc:cy_flush_buffer ttyC%d\n", info->line);
-#endif
-
-       if (serial_paranoia_check(info, tty->name, "cy_flush_buffer"))
-               return;
-
-       card = info->card;
-       channel = info->line - card->first_line;
-
-       spin_lock_irqsave(&card->card_lock, flags);
-       info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
-       spin_unlock_irqrestore(&card->card_lock, flags);
-
-       if (IS_CYC_Z(*card)) {  /* If it is a Z card, flush the on-board
-                                          buffers as well */
-               spin_lock_irqsave(&card->card_lock, flags);
-               retval = cyz_issue_cmd(card, channel, C_CM_FLUSH_TX, 0L);
-               if (retval != 0) {
-                       printk(KERN_ERR "cyc: flush_buffer retval on ttyC%d "
-                               "was %x\n", info->line, retval);
-               }
-               spin_unlock_irqrestore(&card->card_lock, flags);
-       }
-       tty_wakeup(tty);
-}                              /* cy_flush_buffer */
-
 /*
  * cy_hangup() --- called by tty_hangup() when a hangup is signaled.
  */
index 37d4dca5a5d4d4572685d1a885c13159ab2941e6..39c6a36e395bbee0586822d98f1072047c740e24 100644 (file)
@@ -157,7 +157,6 @@ static void epca_error(int, char *);
 static void pc_close(struct tty_struct *, struct file *);
 static void shutdown(struct channel *);
 static void pc_hangup(struct tty_struct *);
-static void pc_put_char(struct tty_struct *, unsigned char);
 static int pc_write_room(struct tty_struct *);
 static int pc_chars_in_buffer(struct tty_struct *);
 static void pc_flush_buffer(struct tty_struct *);
@@ -459,8 +458,7 @@ static void pc_close(struct tty_struct *tty, struct file *filp)
                        setup_empty_event(tty, ch);
                        tty_wait_until_sent(tty, 3000); /* 30 seconds timeout */
                }
-               if (tty->driver->flush_buffer)
-                       tty->driver->flush_buffer(tty);
+               pc_flush_buffer(tty);
 
                tty_ldisc_flush(tty);
                shutdown(ch);
@@ -532,8 +530,7 @@ static void pc_hangup(struct tty_struct *tty)
        if ((ch = verifyChannel(tty)) != NULL) {
                unsigned long flags;
 
-               if (tty->driver->flush_buffer)
-                       tty->driver->flush_buffer(tty);
+               pc_flush_buffer(tty);
                tty_ldisc_flush(tty);
                shutdown(ch);
 
@@ -645,11 +642,6 @@ static int pc_write(struct tty_struct *tty,
        return amountCopied;
 }
 
-static void pc_put_char(struct tty_struct *tty, unsigned char c)
-{
-       pc_write(tty, &c, 1);
-}
-
 static int pc_write_room(struct tty_struct *tty)
 {
        int remain;
@@ -1035,7 +1027,6 @@ static const struct tty_operations pc_ops = {
        .flush_buffer = pc_flush_buffer,
        .chars_in_buffer = pc_chars_in_buffer,
        .flush_chars = pc_flush_chars,
-       .put_char = pc_put_char,
        .ioctl = pc_ioctl,
        .set_termios = pc_set_termios,
        .stop = pc_stop,
index 662e9cfdcc96154447a10ea5204ed2eba4cffb51..b1f92db31331dc9d53334e664e5ab7afbe515a48 100644 (file)
@@ -1994,8 +1994,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
                rs_wait_until_sent(tty, info->timeout);
        }
        shutdown(info);
-       if (tty->driver->flush_buffer)
-               tty->driver->flush_buffer(tty);
+       rs_flush_buffer(tty);
        tty_ldisc_flush(tty);
        tty->closing = 0;
        info->tty = NULL;
index 7ed7da1d99cf9120f238601e794df7845992ff2a..f6610f28d657c223c730797f53d22357a6ceb984 100644 (file)
@@ -586,8 +586,7 @@ void gs_close(struct tty_struct * tty, struct file * filp)
 
        port->flags &= ~GS_ACTIVE;
 
-       if (tty->driver->flush_buffer)
-               tty->driver->flush_buffer(tty);
+       gs_flush_buffer(tty);
 
        tty_ldisc_flush(tty);
        tty->closing = 0;
index a69e4bb91ad4d35cf887c9a166e5ae33eebe63fb..6812fda20953cc14f4268402aba8030122c35582 100644 (file)
@@ -1012,6 +1012,22 @@ static void isicom_shutdown_port(struct isi_port *port)
        }
 }
 
+static void isicom_flush_buffer(struct tty_struct *tty)
+{
+       struct isi_port *port = tty->driver_data;
+       struct isi_board *card = port->card;
+       unsigned long flags;
+
+       if (isicom_paranoia_check(port, tty->name, "isicom_flush_buffer"))
+               return;
+
+       spin_lock_irqsave(&card->card_lock, flags);
+       port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
+       spin_unlock_irqrestore(&card->card_lock, flags);
+
+       tty_wakeup(tty);
+}
+
 static void isicom_close(struct tty_struct *tty, struct file *filp)
 {
        struct isi_port *port = tty->driver_data;
@@ -1065,8 +1081,7 @@ static void isicom_close(struct tty_struct *tty, struct file *filp)
        isicom_shutdown_port(port);
        spin_unlock_irqrestore(&card->card_lock, flags);
 
-       if (tty->driver->flush_buffer)
-               tty->driver->flush_buffer(tty);
+       isicom_flush_buffer(tty);
        tty_ldisc_flush(tty);
 
        spin_lock_irqsave(&card->card_lock, flags);
@@ -1447,22 +1462,6 @@ static void isicom_hangup(struct tty_struct *tty)
        wake_up_interruptible(&port->open_wait);
 }
 
-/* flush_buffer et all */
-static void isicom_flush_buffer(struct tty_struct *tty)
-{
-       struct isi_port *port = tty->driver_data;
-       struct isi_board *card = port->card;
-       unsigned long flags;
-
-       if (isicom_paranoia_check(port, tty->name, "isicom_flush_buffer"))
-               return;
-
-       spin_lock_irqsave(&card->card_lock, flags);
-       port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
-       spin_unlock_irqrestore(&card->card_lock, flags);
-
-       tty_wakeup(tty);
-}
 
 /*
  * Driver init and deinit functions
index 1ab9517c24c5ff84c5ee4d2960ae319114734ad5..585fac179ec60a0d4099aff04aa7e5e6c714c648 100644 (file)
@@ -1280,6 +1280,7 @@ static int moxa_chars_in_buffer(struct tty_struct *tty)
         */
        if (ch == NULL)
                return 0;
+       lock_kernel();
        chars = MoxaPortTxQueue(ch);
        if (chars) {
                /*
@@ -1289,6 +1290,7 @@ static int moxa_chars_in_buffer(struct tty_struct *tty)
                if (!(ch->statusflags & EMPTYWAIT))
                        moxa_setup_empty_event(tty);
        }
+       unlock_kernel();
        return chars;
 }
 
index 00cf09aa11fc3256d8255c138a70cd4823e44a28..28f63566ab8a2029f417ed5983c30a24781792e6 100644 (file)
@@ -927,6 +927,27 @@ static int mxser_open(struct tty_struct *tty, struct file *filp)
        return 0;
 }
 
+static void mxser_flush_buffer(struct tty_struct *tty)
+{
+       struct mxser_port *info = tty->driver_data;
+       char fcr;
+       unsigned long flags;
+
+
+       spin_lock_irqsave(&info->slock, flags);
+       info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
+
+       fcr = inb(info->ioaddr + UART_FCR);
+       outb((fcr | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT),
+               info->ioaddr + UART_FCR);
+       outb(fcr, info->ioaddr + UART_FCR);
+
+       spin_unlock_irqrestore(&info->slock, flags);
+
+       tty_wakeup(tty);
+}
+
+
 /*
  * This routine is called when the serial port gets closed.  First, we
  * wait for the last remaining data to be sent.  Then, we unlink its
@@ -1013,9 +1034,7 @@ static void mxser_close(struct tty_struct *tty, struct file *filp)
        }
        mxser_shutdown(info);
 
-       if (tty->driver->flush_buffer)
-               tty->driver->flush_buffer(tty);
-
+       mxser_flush_buffer(tty);
        tty_ldisc_flush(tty);
 
        tty->closing = 0;
@@ -1142,26 +1161,6 @@ static int mxser_chars_in_buffer(struct tty_struct *tty)
        return info->xmit_cnt;
 }
 
-static void mxser_flush_buffer(struct tty_struct *tty)
-{
-       struct mxser_port *info = tty->driver_data;
-       char fcr;
-       unsigned long flags;
-
-
-       spin_lock_irqsave(&info->slock, flags);
-       info->xmit_cnt = info->xmit_head = info->xmit_tail = 0;
-
-       fcr = inb(info->ioaddr + UART_FCR);
-       outb((fcr | UART_FCR_CLEAR_RCVR | UART_FCR_CLEAR_XMIT),
-               info->ioaddr + UART_FCR);
-       outb(fcr, info->ioaddr + UART_FCR);
-
-       spin_unlock_irqrestore(&info->slock, flags);
-
-       tty_wakeup(tty);
-}
-
 /*
  * ------------------------------------------------------------
  * friends of mxser_ioctl()
@@ -1992,6 +1991,7 @@ static void mxser_wait_until_sent(struct tty_struct *tty, int timeout)
                timeout, char_time);
        printk("jiff=%lu...", jiffies);
 #endif
+       lock_kernel();
        while (!((lsr = inb(info->ioaddr + UART_LSR)) & UART_LSR_TEMT)) {
 #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
                printk("lsr = %d (jiff=%lu)...", lsr, jiffies);
@@ -2003,6 +2003,7 @@ static void mxser_wait_until_sent(struct tty_struct *tty, int timeout)
                        break;
        }
        set_current_state(TASK_RUNNING);
+       unlock_kernel();
 
 #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
        printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies);
index 6a6843a0a6742ba15b44cbf47fe93856ed71b26f..b55c933d558556dc5cb41d34a39e2bd481d61411 100644 (file)
@@ -1724,6 +1724,8 @@ static int ntty_tiocmget(struct tty_struct *tty, struct file *file)
        const struct ctrl_dl *ctrl_dl = &port->ctrl_dl;
        const struct ctrl_ul *ctrl_ul = &port->ctrl_ul;
 
+       /* Note: these could change under us but it is not clear this
+          matters if so */
        return  (ctrl_ul->RTS ? TIOCM_RTS : 0) |
                (ctrl_ul->DTR ? TIOCM_DTR : 0) |
                (ctrl_dl->DCD ? TIOCM_CAR : 0) |
@@ -1849,16 +1851,6 @@ static void ntty_throttle(struct tty_struct *tty)
        spin_unlock_irqrestore(&dc->spin_mutex, flags);
 }
 
-/* just to discard single character writes */
-static void ntty_put_char(struct tty_struct *tty, unsigned char c)
-{
-       /*
-        * card does not react correct when we write single chars
-        * to the card, so we discard them
-        */
-       DBG2("PUT CHAR Function: %c", c);
-}
-
 /* Returns number of chars in buffer, called by tty layer */
 static s32 ntty_chars_in_buffer(struct tty_struct *tty)
 {
@@ -1892,7 +1884,6 @@ static const struct tty_operations tty_ops = {
        .unthrottle = ntty_unthrottle,
        .throttle = ntty_throttle,
        .chars_in_buffer = ntty_chars_in_buffer,
-       .put_char = ntty_put_char,
        .tiocmget = ntty_tiocmget,
        .tiocmset = ntty_tiocmset,
 };
index 583356426dfb1fb7a8c675bb82a4a0e1d3436ba6..45d8eb5de69f770418e6d1440867a2fde79c4189 100644 (file)
@@ -503,20 +503,9 @@ static void* mgslpc_get_text_ptr(void)
  * The wrappers maintain line discipline references
  * while calling into the line discipline.
  *
- * ldisc_flush_buffer - flush line discipline receive buffers
  * ldisc_receive_buf  - pass receive data to line discipline
  */
 
-static void ldisc_flush_buffer(struct tty_struct *tty)
-{
-       struct tty_ldisc *ld = tty_ldisc_ref(tty);
-       if (ld) {
-               if (ld->flush_buffer)
-                       ld->flush_buffer(tty);
-               tty_ldisc_deref(ld);
-       }
-}
-
 static void ldisc_receive_buf(struct tty_struct *tty,
                              const __u8 *data, char *flags, int count)
 {
@@ -2467,10 +2456,9 @@ static void mgslpc_close(struct tty_struct *tty, struct file * filp)
        if (info->flags & ASYNC_INITIALIZED)
                mgslpc_wait_until_sent(tty, info->timeout);
 
-       if (tty->driver->flush_buffer)
-               tty->driver->flush_buffer(tty);
+       mgslpc_flush_buffer(tty);
 
-       ldisc_flush_buffer(tty);
+       tty_ldisc_flush(tty);
 
        shutdown(info);
 
index b56e0e04cb4a16afbe4144e95f8db2665a3aa59c..a82c2a2d5e6c6922fdd6cfe75ceb0a09d3ef1171 100644 (file)
@@ -1015,6 +1015,24 @@ static int rc_open(struct tty_struct * tty, struct file * filp)
        return 0;
 }
 
+static void rc_flush_buffer(struct tty_struct *tty)
+{
+       struct riscom_port *port = (struct riscom_port *)tty->driver_data;
+       unsigned long flags;
+
+       if (rc_paranoia_check(port, tty->name, "rc_flush_buffer"))
+               return;
+
+       spin_lock_irqsave(&riscom_lock, flags);
+
+       port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
+
+       spin_unlock_irqrestore(&riscom_lock, flags);
+
+       tty_wakeup(tty);
+}
+
+
 static void rc_close(struct tty_struct * tty, struct file * filp)
 {
        struct riscom_port *port = (struct riscom_port *) tty->driver_data;
@@ -1078,8 +1096,7 @@ static void rc_close(struct tty_struct * tty, struct file * filp)
                }
        }
        rc_shutdown_port(bp, port);
-       if (tty->driver->flush_buffer)
-               tty->driver->flush_buffer(tty);
+       rc_flush_buffer(tty);
        tty_ldisc_flush(tty);
 
        tty->closing = 0;
@@ -1213,23 +1230,6 @@ static int rc_chars_in_buffer(struct tty_struct *tty)
        return port->xmit_cnt;
 }
 
-static void rc_flush_buffer(struct tty_struct *tty)
-{
-       struct riscom_port *port = (struct riscom_port *)tty->driver_data;
-       unsigned long flags;
-                               
-       if (rc_paranoia_check(port, tty->name, "rc_flush_buffer"))
-               return;
-
-       spin_lock_irqsave(&riscom_lock, flags);
-
-       port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
-
-       spin_unlock_irqrestore(&riscom_lock, flags);
-       
-       tty_wakeup(tty);
-}
-
 static int rc_tiocmget(struct tty_struct *tty, struct file *file)
 {
        struct riscom_port *port = (struct riscom_port *)tty->driver_data;
index 32fe8dca24b63620596f939aef30039e6cb62fff..00cfb6c7fd4698b019188cfefb46ec457667a0bd 100644 (file)
@@ -1585,6 +1585,7 @@ static void rp_wait_until_sent(struct tty_struct *tty, int timeout)
               jiffies);
        printk(KERN_INFO "cps=%d...\n", info->cps);
 #endif
+       lock_kernel();
        while (1) {
                txcnt = sGetTxCnt(cp);
                if (!txcnt) {
@@ -1612,6 +1613,7 @@ static void rp_wait_until_sent(struct tty_struct *tty, int timeout)
                        break;
        }
        __set_current_state(TASK_RUNNING);
+       unlock_kernel();
 #ifdef ROCKET_DEBUG_WAIT_UNTIL_SENT
        printk(KERN_INFO "txcnt = %d (jiff=%lu)...done\n", txcnt, jiffies);
 #endif
index f62fb9360c3f0a53463ac1e49502b995c7d69733..62d6f2e0fd1881c960fd322ca12f4d75ff1cc22d 100644 (file)
@@ -1674,8 +1674,7 @@ static void cy_close(struct tty_struct *tty, struct file *filp)
        if (info->flags & ASYNC_INITIALIZED)
                tty_wait_until_sent(tty, 3000); /* 30 seconds timeout */
        shutdown(info);
-       if (tty->driver->flush_buffer)
-               tty->driver->flush_buffer(tty);
+       cy_flush_buffer(tty);
        tty_ldisc_flush(tty);
        info->tty = NULL;
        if (info->blocked_open) {
index 9f9a4bdc1b0e36ad948eae65637fb1c881254be4..075ad924dd047dacf0040405bc4164bb83a33624 100644 (file)
@@ -1504,6 +1504,27 @@ static int sx_open(struct tty_struct * tty, struct file * filp)
        return 0;
 }
 
+static void sx_flush_buffer(struct tty_struct *tty)
+{
+       struct specialix_port *port = (struct specialix_port *)tty->driver_data;
+       unsigned long flags;
+       struct specialix_board  * bp;
+
+       func_enter();
+
+       if (sx_paranoia_check(port, tty->name, "sx_flush_buffer")) {
+               func_exit();
+               return;
+       }
+
+       bp = port_Board(port);
+       spin_lock_irqsave(&port->lock, flags);
+       port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
+       spin_unlock_irqrestore(&port->lock, flags);
+       tty_wakeup(tty);
+
+       func_exit();
+}
 
 static void sx_close(struct tty_struct * tty, struct file * filp)
 {
@@ -1597,8 +1618,7 @@ static void sx_close(struct tty_struct * tty, struct file * filp)
        }
 
        sx_shutdown_port(bp, port);
-       if (tty->driver->flush_buffer)
-               tty->driver->flush_buffer(tty);
+       sx_flush_buffer(tty);
        tty_ldisc_flush(tty);
        spin_lock_irqsave(&port->lock, flags);
        tty->closing = 0;
@@ -1770,28 +1790,6 @@ static int sx_chars_in_buffer(struct tty_struct *tty)
 }
 
 
-static void sx_flush_buffer(struct tty_struct *tty)
-{
-       struct specialix_port *port = (struct specialix_port *)tty->driver_data;
-       unsigned long flags;
-       struct specialix_board  * bp;
-
-       func_enter();
-
-       if (sx_paranoia_check(port, tty->name, "sx_flush_buffer")) {
-               func_exit();
-               return;
-       }
-
-       bp = port_Board(port);
-       spin_lock_irqsave(&port->lock, flags);
-       port->xmit_cnt = port->xmit_head = port->xmit_tail = 0;
-       spin_unlock_irqrestore(&port->lock, flags);
-       tty_wakeup(tty);
-
-       func_exit();
-}
-
 
 static int sx_tiocmget(struct tty_struct *tty, struct file *file)
 {
index 983244ab1362ce1252a38c0f40b04df967bb26b7..d17be10c5d2108f436a1479f15eb1f83373d82f4 100644 (file)
@@ -875,6 +875,7 @@ static void stl_waituntilsent(struct tty_struct *tty, int timeout)
                timeout = HZ;
        tend = jiffies + timeout;
 
+       lock_kernel();
        while (stl_datastate(portp)) {
                if (signal_pending(current))
                        break;
@@ -882,6 +883,7 @@ static void stl_waituntilsent(struct tty_struct *tty, int timeout)
                if (time_after_eq(jiffies, tend))
                        break;
        }
+       unlock_kernel();
 }
 
 /*****************************************************************************/
index 1c9c440f59cee4e42dae1ad7a150ae69b20a3263..dbbd998ae103ad032b1718e259a5855a6d9190a9 100644 (file)
@@ -3157,8 +3157,7 @@ static void mgsl_close(struct tty_struct *tty, struct file * filp)
        if (info->flags & ASYNC_INITIALIZED)
                mgsl_wait_until_sent(tty, info->timeout);
 
-       if (tty->driver->flush_buffer)
-               tty->driver->flush_buffer(tty);
+       mgsl_flush_buffer(tty);
 
        tty_ldisc_flush(tty);
                
@@ -3221,7 +3220,8 @@ static void mgsl_wait_until_sent(struct tty_struct *tty, int timeout)
         * interval should also be less than the timeout.
         * Note: use tight timings here to satisfy the NIST-PCTS.
         */ 
-       
+
+       lock_kernel();
        if ( info->params.data_rate ) {
                char_time = info->timeout/(32 * 5);
                if (!char_time)
@@ -3251,6 +3251,7 @@ static void mgsl_wait_until_sent(struct tty_struct *tty, int timeout)
                                break;
                }
        }
+       unlock_kernel();
       
 exit:
        if (debug_level >= DEBUG_LEVEL_INFO)
index 6473ae023466d202b9e557deb50188f5d38b63f2..1a11717b1adc38ff519a7bfcd1ee919082003fe0 100644 (file)
@@ -771,8 +771,7 @@ static void close(struct tty_struct *tty, struct file *filp)
 
        if (info->flags & ASYNC_INITIALIZED)
                wait_until_sent(tty, info->timeout);
-       if (tty->driver->flush_buffer)
-               tty->driver->flush_buffer(tty);
+       flush_buffer(tty);
        tty_ldisc_flush(tty);
 
        shutdown(info);
@@ -967,6 +966,8 @@ static void wait_until_sent(struct tty_struct *tty, int timeout)
         * Note: use tight timings here to satisfy the NIST-PCTS.
         */
 
+       lock_kernel();
+
        if (info->params.data_rate) {
                char_time = info->timeout/(32 * 5);
                if (!char_time)
@@ -984,6 +985,7 @@ static void wait_until_sent(struct tty_struct *tty, int timeout)
                if (timeout && time_after(jiffies, orig_jiffies + timeout))
                        break;
        }
+       unlock_kernel();
 
 exit:
        DBGINFO(("%s wait_until_sent exit\n", info->device_name));
index b716a73a236ffc7cd63031fa9086ed996bce48ee..2f1988c48ee30247396f1dc507bf7bec0fb6f0cb 100644 (file)
@@ -862,8 +862,7 @@ static void close(struct tty_struct *tty, struct file *filp)
        if (info->flags & ASYNC_INITIALIZED)
                wait_until_sent(tty, info->timeout);
 
-       if (tty->driver->flush_buffer)
-               tty->driver->flush_buffer(tty);
+       flush_buffer(tty);
 
        tty_ldisc_flush(tty);
 
@@ -1119,6 +1118,8 @@ static void wait_until_sent(struct tty_struct *tty, int timeout)
        if (sanity_check(info, tty->name, "wait_until_sent"))
                return;
 
+       lock_kernel();
+
        if (!(info->flags & ASYNC_INITIALIZED))
                goto exit;
 
@@ -1161,6 +1162,7 @@ static void wait_until_sent(struct tty_struct *tty, int timeout)
        }
 
 exit:
+       unlock_kernel();
        if (debug_level >= DEBUG_LEVEL_INFO)
                printk("%s(%d):%s wait_until_sent() exit\n",
                         __FILE__,__LINE__, info->device_name );
@@ -1176,6 +1178,7 @@ static int write_room(struct tty_struct *tty)
        if (sanity_check(info, tty->name, "write_room"))
                return 0;
 
+       lock_kernel();
        if (info->params.mode == MGSL_MODE_HDLC) {
                ret = (info->tx_active) ? 0 : HDLC_MAX_FRAME_SIZE;
        } else {
@@ -1183,6 +1186,7 @@ static int write_room(struct tty_struct *tty)
                if (ret < 0)
                        ret = 0;
        }
+       unlock_kernel();
 
        if (debug_level >= DEBUG_LEVEL_INFO)
                printk("%s(%d):%s write_room()=%d\n",
index 35c7d2eb8b28cbd7ac876378cd31a48eab1eb4d3..b1692afd797efd9332fa82cacbff0639339161fb 100644 (file)
@@ -1204,7 +1204,7 @@ EXPORT_SYMBOL_GPL(tty_find_polling_driver);
  *     not in the foreground, send a SIGTTOU.  If the signal is blocked or
  *     ignored, go ahead and perform the operation.  (POSIX 7.2)
  *
- *     Locking: ctrl_lock - FIXME: review this
+ *     Locking: ctrl_lock
  */
 
 int tty_check_change(struct tty_struct *tty)
index d769e43f73fb7c7c9905e0c6f6f5e81e45bcefdc..8c4bf3e48d5b163533360f4cbf442dcd8322d714 100644 (file)
@@ -396,7 +396,7 @@ EXPORT_SYMBOL(tty_termios_hw_change);
 static void change_termios(struct tty_struct *tty, struct ktermios *new_termios)
 {
        int canon_change;
-       struct ktermios old_termios = *tty->termios;
+       struct ktermios old_termios;
        struct tty_ldisc *ld;
        unsigned long flags;
 
@@ -408,7 +408,7 @@ static void change_termios(struct tty_struct *tty, struct ktermios *new_termios)
        /* FIXME: we need to decide on some locking/ordering semantics
           for the set_termios notification eventually */
        mutex_lock(&tty->termios_mutex);
-
+       old_termios = *tty->termios;
        *tty->termios = *new_termios;
        unset_locked_termios(tty->termios, &old_termios, tty->termios_locked);
        canon_change = (old_termios.c_lflag ^ tty->termios->c_lflag) & ICANON;
@@ -480,7 +480,9 @@ static int set_termios(struct tty_struct *tty, void __user *arg, int opt)
        if (retval)
                return retval;
 
+       mutex_lock(&tty->termios_mutex);
        memcpy(&tmp_termios, tty->termios, sizeof(struct ktermios));
+       mutex_unlock(&tty->termios_mutex);
 
        if (opt & TERMIOS_TERMIO) {
                if (user_termio_to_kernel_termios(&tmp_termios,
@@ -666,12 +668,14 @@ static int get_tchars(struct tty_struct *tty, struct tchars __user *tchars)
 {
        struct tchars tmp;
 
+       mutex_lock(&tty->termios_mutex);
        tmp.t_intrc = tty->termios->c_cc[VINTR];
        tmp.t_quitc = tty->termios->c_cc[VQUIT];
        tmp.t_startc = tty->termios->c_cc[VSTART];
        tmp.t_stopc = tty->termios->c_cc[VSTOP];
        tmp.t_eofc = tty->termios->c_cc[VEOF];
        tmp.t_brkc = tty->termios->c_cc[VEOL2]; /* what is brkc anyway? */
+       mutex_unlock(&tty->termios_mutex);
        return copy_to_user(tchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
 }
 
@@ -681,12 +685,14 @@ static int set_tchars(struct tty_struct *tty, struct tchars __user *tchars)
 
        if (copy_from_user(&tmp, tchars, sizeof(tmp)))
                return -EFAULT;
+       mutex_lock(&tty->termios_mutex);
        tty->termios->c_cc[VINTR] = tmp.t_intrc;
        tty->termios->c_cc[VQUIT] = tmp.t_quitc;
        tty->termios->c_cc[VSTART] = tmp.t_startc;
        tty->termios->c_cc[VSTOP] = tmp.t_stopc;
        tty->termios->c_cc[VEOF] = tmp.t_eofc;
        tty->termios->c_cc[VEOL2] = tmp.t_brkc; /* what is brkc anyway? */
+       mutex_unlock(&tty->termios_mutex);
        return 0;
 }
 #endif
@@ -696,6 +702,7 @@ static int get_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars)
 {
        struct ltchars tmp;
 
+       mutex_lock(&tty->termios_mutex);
        tmp.t_suspc = tty->termios->c_cc[VSUSP];
        /* what is dsuspc anyway? */
        tmp.t_dsuspc = tty->termios->c_cc[VSUSP];
@@ -704,6 +711,7 @@ static int get_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars)
        tmp.t_flushc = tty->termios->c_cc[VEOL2];
        tmp.t_werasc = tty->termios->c_cc[VWERASE];
        tmp.t_lnextc = tty->termios->c_cc[VLNEXT];
+       mutex_unlock(&tty->termios_mutex);
        return copy_to_user(ltchars, &tmp, sizeof(tmp)) ? -EFAULT : 0;
 }
 
@@ -714,6 +722,7 @@ static int set_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars)
        if (copy_from_user(&tmp, ltchars, sizeof(tmp)))
                return -EFAULT;
 
+       mutex_lock(&tty->termios_mutex);
        tty->termios->c_cc[VSUSP] = tmp.t_suspc;
        /* what is dsuspc anyway? */
        tty->termios->c_cc[VEOL2] = tmp.t_dsuspc;
@@ -722,6 +731,7 @@ static int set_ltchars(struct tty_struct *tty, struct ltchars __user *ltchars)
        tty->termios->c_cc[VEOL2] = tmp.t_flushc;
        tty->termios->c_cc[VWERASE] = tmp.t_werasc;
        tty->termios->c_cc[VLNEXT] = tmp.t_lnextc;
+       mutex_unlock(&tty->termios_mutex);
        return 0;
 }
 #endif
index a033f53209d525f5615f73961b46b97831bebb71..1a2222cbb80541bc492d78cef045f0844a08fad6 100644 (file)
@@ -1708,9 +1708,7 @@ isdn_tty_close(struct tty_struct *tty, struct file *filp)
        }
        dev->modempoll--;
        isdn_tty_shutdown(info);
-       
-       if (tty->driver->flush_buffer)
-               tty->driver->flush_buffer(tty);
+       isdn_tty_flush_buffer(tty);
        tty_ldisc_flush(tty);
        info->tty = NULL;
        info->ncarrier = 0;
index 2b8a410e09595f87bffd264a44ce0a840cde599d..5ce3e57bff0bbe413c48daa112c45b6e2a721f84 100644 (file)
@@ -1017,18 +1017,6 @@ static int rs_ioctl(struct tty_struct *tty, struct file * file,
                        tty_wait_until_sent(tty, 0);
                        send_break(info, arg ? arg*(100) : 250);
                        return 0;
-               case TIOCGSOFTCAR:
-                       error = put_user(C_CLOCAL(tty) ? 1 : 0,
-                                   (unsigned long *) arg);
-                       if (error)
-                               return error;
-                       return 0;
-               case TIOCSSOFTCAR:
-                       get_user(arg, (unsigned long *) arg);
-                       tty->termios->c_cflag =
-                               ((tty->termios->c_cflag & ~CLOCAL) |
-                                (arg ? CLOCAL : 0));
-                       return 0;
                case TIOCGSERIAL:
                        if (access_ok(VERIFY_WRITE, (void *) arg,
                                                sizeof(struct serial_struct)))
@@ -1061,9 +1049,6 @@ static void rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 {
        struct m68k_serial *info = (struct m68k_serial *)tty->driver_data;
 
-       if (tty->termios->c_cflag == old_termios->c_cflag)
-               return;
-
        change_speed(info);
 
        if ((old_termios->c_cflag & CRTSCTS) &&
@@ -1140,8 +1125,7 @@ static void rs_close(struct tty_struct *tty, struct file * filp)
        uart->ustcnt &= ~(USTCNT_RXEN | USTCNT_RX_INTR_MASK);
 
        shutdown(info);
-       if (tty->driver->flush_buffer)
-               tty->driver->flush_buffer(tty);
+       rs_flush_buffer(tty);
                
        tty_ldisc_flush(tty);
        tty->closing = 0;
index 6f540107d0bb4386aea12193001266914d05a0aa..f4f737bfa0a7241f9e624ab0460cc949f7b182d9 100644 (file)
@@ -1436,18 +1436,6 @@ static int rs_360_ioctl(struct tty_struct *tty, struct file * file,
                                return retval;
                        end_break(info);
                        return 0;
-               case TIOCGSOFTCAR:
-                       /* return put_user(C_CLOCAL(tty) ? 1 : 0, (int *) arg); */
-                       put_user(C_CLOCAL(tty) ? 1 : 0, (int *) arg);
-                       return 0;
-               case TIOCSSOFTCAR:
-                       error = get_user(arg, (unsigned int *) arg); 
-                       if (error)
-                               return error;
-                       tty->termios->c_cflag =
-                               ((tty->termios->c_cflag & ~CLOCAL) |
-                                (arg ? CLOCAL : 0));
-                       return 0;
 #ifdef maybe
                case TIOCSERGETLSR: /* Get line status register */
                        return get_lsr_info(info, (unsigned int *) arg);
@@ -1665,8 +1653,7 @@ static void rs_360_close(struct tty_struct *tty, struct file * filp)
                rs_360_wait_until_sent(tty, info->timeout);
        }
        shutdown(info);
-       if (tty->driver->flush_buffer)
-               tty->driver->flush_buffer(tty);
+       rs_360_flush_buffer(tty);
        tty_ldisc_flush(tty);           
        tty->closing = 0;
        info->event = 0;
@@ -1717,6 +1704,7 @@ static void rs_360_wait_until_sent(struct tty_struct *tty, int timeout)
        printk("jiff=%lu...", jiffies);
 #endif
 
+       lock_kernel();
        /* We go through the loop at least once because we can't tell
         * exactly when the last character exits the shifter.  There can
         * be at least two characters waiting to be sent after the buffers
@@ -1745,6 +1733,7 @@ static void rs_360_wait_until_sent(struct tty_struct *tty, int timeout)
                        bdp--;
        } while (bdp->status & BD_SC_READY);
        current->state = TASK_RUNNING;
+       unlock_kernel();
 #ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
        printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies);
 #endif
index 88e7c1d5b919f455b47658367b9b7d835d849ba9..8b9af73c1d594f2c43f6c7b8de2d9b22df9c9368 100644 (file)
@@ -3581,8 +3581,9 @@ rs_tiocmset(struct tty_struct *tty, struct file *file,
                unsigned int set, unsigned int clear)
 {
        struct e100_serial *info = (struct e100_serial *)tty->driver_data;
+       unsigned long flags;
 
-       lock_kernel();
+       local_irq_save(flags);
 
        if (clear & TIOCM_RTS)
                e100_rts(info, 0);
@@ -3604,7 +3605,7 @@ rs_tiocmset(struct tty_struct *tty, struct file *file,
        if (set & TIOCM_CD)
                e100_cd_out(info, 1);
 
-       unlock_kernel();
+       local_irq_restore(flags);
        return 0;
 }
 
@@ -3613,8 +3614,10 @@ rs_tiocmget(struct tty_struct *tty, struct file *file)
 {
        struct e100_serial *info = (struct e100_serial *)tty->driver_data;
        unsigned int result;
+       unsigned long flags;
+
+       local_irq_save(flags);
 
-       lock_kernel();
        result =
                (!E100_RTS_GET(info) ? TIOCM_RTS : 0)
                | (!E100_DTR_GET(info) ? TIOCM_DTR : 0)
@@ -3623,7 +3626,7 @@ rs_tiocmget(struct tty_struct *tty, struct file *file)
                | (!E100_CD_GET(info) ? TIOCM_CAR : 0)
                | (!E100_CTS_GET(info) ? TIOCM_CTS : 0);
 
-       unlock_kernel();
+       local_irq_restore(flags);
 
 #ifdef SERIAL_DEBUG_IO
        printk(KERN_DEBUG "ser%i: modem state: %i 0x%08X\n",
@@ -3702,10 +3705,6 @@ rs_set_termios(struct tty_struct *tty, struct ktermios *old_termios)
 {
        struct e100_serial *info = (struct e100_serial *)tty->driver_data;
 
-       if (tty->termios->c_cflag == old_termios->c_cflag &&
-           tty->termios->c_iflag == old_termios->c_iflag)
-               return;
-
        change_speed(info);
 
        /* Handle turning off CRTSCTS */
@@ -3808,10 +3807,8 @@ rs_close(struct tty_struct *tty, struct file * filp)
 #endif
 
        shutdown(info);
-       if (tty->driver->flush_buffer)
-               tty->driver->flush_buffer(tty);
-       if (tty->ldisc.flush_buffer)
-               tty->ldisc.flush_buffer(tty);
+       rs_flush_buffer(tty);
+       tty_ldisc_flush_buffer(tty);
        tty->closing = 0;
        info->event = 0;
        info->tty = 0;
@@ -3885,6 +3882,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
         * Check R_DMA_CHx_STATUS bit 0-6=number of available bytes in FIFO
         * R_DMA_CHx_HWSW bit 31-16=nbr of bytes left in DMA buffer (0=64k)
         */
+       lock_kernel();
        orig_jiffies = jiffies;
        while (info->xmit.head != info->xmit.tail || /* More in send queue */
               (*info->ostatusadr & 0x007f) ||  /* more in FIFO */
@@ -3901,6 +3899,7 @@ static void rs_wait_until_sent(struct tty_struct *tty, int timeout)
                        curr_time_usec - info->last_tx_active_usec;
        }
        set_current_state(TASK_RUNNING);
+       unlock_kernel();
 }
 
 /*
index ddd3aa50d4adef5de5e136df8fbd5fa3a8738ad8..aafa1704e1ab034d318807d6dff9530e0cae1459 100644 (file)
@@ -1072,18 +1072,6 @@ static int mcfrs_ioctl(struct tty_struct *tty, struct file * file,
                        tty_wait_until_sent(tty, 0);
                        send_break(info, arg ? arg*(HZ/10) : HZ/4);
                        return 0;
-               case TIOCGSOFTCAR:
-                       error = put_user(C_CLOCAL(tty) ? 1 : 0,
-                                   (unsigned long *) arg);
-                       if (error)
-                               return error;
-                       return 0;
-               case TIOCSSOFTCAR:
-                       get_user(arg, (unsigned long *) arg);
-                       tty->termios->c_cflag =
-                               ((tty->termios->c_cflag & ~CLOCAL) |
-                                (arg ? CLOCAL : 0));
-                       return 0;
                case TIOCGSERIAL:
                        if (access_ok(VERIFY_WRITE, (void *) arg,
                                                sizeof(struct serial_struct)))
@@ -1222,8 +1210,7 @@ static void mcfrs_close(struct tty_struct *tty, struct file * filp)
        } else
 #endif
        shutdown(info);
-       if (tty->driver->flush_buffer)
-               tty->driver->flush_buffer(tty);
+       mcfrs_flush_buffer(tty);
        tty_ldisc_flush(tty);
        
        tty->closing = 0;
@@ -1276,6 +1263,8 @@ mcfrs_wait_until_sent(struct tty_struct *tty, int timeout)
         * Note: we have to use pretty tight timings here to satisfy
         * the NIST-PCTS.
         */
+       lock_kernel();
+
        fifo_time = (MCF5272_FIFO_SIZE * HZ * 10) / info->baud;
        char_time = fifo_time / 5;
        if (char_time == 0)
@@ -1312,6 +1301,7 @@ mcfrs_wait_until_sent(struct tty_struct *tty, int timeout)
                if (timeout && time_after(jiffies, orig_jiffies + timeout))
                        break;
        }
+       unlock_kernel();
 #else
        /*
         * For the other coldfire models, assume all data has been sent
index 3123ffeac8ad682e4ec383cd9d9606bc095270fe..81ac9bb4f39b74a7a9e1b2456ae6484a49a0f560 100644 (file)
@@ -287,6 +287,7 @@ static void netx_set_mctrl(struct uart_port *port, unsigned int mctrl)
 {
        unsigned int val;
 
+       /* FIXME: Locking needed ? */
        if (mctrl & TIOCM_RTS) {
                val = readl(port->membase + UART_RTS_CR);
                writel(val | RTS_CR_RTS, port->membase + UART_RTS_CR);