[PATCH] tty/serial: Lay the foundations for the next set of reworks

From: Alan Cox
Date: Tue Apr 08 2008 - 12:03:44 EST


- 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 dependancies 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@xxxxxxxxxx>

diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.25-rc8-mm1/drivers/char/amiserial.c linux-2.6.25-rc8-mm1/drivers/char/amiserial.c
--- linux.vanilla-2.6.25-rc8-mm1/drivers/char/amiserial.c 2008-04-08 11:34:51.000000000 +0100
+++ linux-2.6.25-rc8-mm1/drivers/char/amiserial.c 2008-04-08 11:42:51.000000000 +0100
@@ -1505,8 +1506,7 @@
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 +1539,8 @@
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 +1581,7 @@
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
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.25-rc8-mm1/drivers/char/cyclades.c linux-2.6.25-rc8-mm1/drivers/char/cyclades.c
--- linux.vanilla-2.6.25-rc8-mm1/drivers/char/cyclades.c 2008-04-08 11:34:51.000000000 +0100
+++ linux-2.6.25-rc8-mm1/drivers/char/cyclades.c 2008-04-08 11:43:19.000000000 +0100
@@ -2522,6 +2522,7 @@
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 @@
}
/* 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 @@

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);

@@ -2882,6 +2919,7 @@
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);
@@ -2899,6 +2937,7 @@
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 */
@@ -4281,40 +4320,6 @@
}
} /* 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.
*/
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.25-rc8-mm1/drivers/char/epca.c linux-2.6.25-rc8-mm1/drivers/char/epca.c
--- linux.vanilla-2.6.25-rc8-mm1/drivers/char/epca.c 2008-04-08 11:34:51.000000000 +0100
+++ linux-2.6.25-rc8-mm1/drivers/char/epca.c 2008-04-08 11:43:26.000000000 +0100
@@ -157,7 +157,6 @@
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 @@
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 @@
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 @@
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 @@
.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,
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.25-rc8-mm1/drivers/char/esp.c linux-2.6.25-rc8-mm1/drivers/char/esp.c
--- linux.vanilla-2.6.25-rc8-mm1/drivers/char/esp.c 2008-04-08 11:34:51.000000000 +0100
+++ linux-2.6.25-rc8-mm1/drivers/char/esp.c 2008-04-08 11:43:34.000000000 +0100
@@ -1994,8 +1997,7 @@
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;
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.25-rc8-mm1/drivers/char/generic_serial.c linux-2.6.25-rc8-mm1/drivers/char/generic_serial.c
--- linux.vanilla-2.6.25-rc8-mm1/drivers/char/generic_serial.c 2008-04-08 11:34:51.000000000 +0100
+++ linux-2.6.25-rc8-mm1/drivers/char/generic_serial.c 2008-04-08 11:43:42.000000000 +0100
@@ -587,8 +588,7 @@

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;
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.25-rc8-mm1/drivers/char/isicom.c linux-2.6.25-rc8-mm1/drivers/char/isicom.c
--- linux.vanilla-2.6.25-rc8-mm1/drivers/char/isicom.c 2008-04-08 11:34:51.000000000 +0100
+++ linux-2.6.25-rc8-mm1/drivers/char/isicom.c 2008-04-08 11:43:50.000000000 +0100
@@ -1012,6 +1012,22 @@
}
}

+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 @@
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 +1463,6 @@
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
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.25-rc8-mm1/drivers/char/moxa.c linux-2.6.25-rc8-mm1/drivers/char/moxa.c
--- linux.vanilla-2.6.25-rc8-mm1/drivers/char/moxa.c 2008-04-08 11:34:51.000000000 +0100
+++ linux-2.6.25-rc8-mm1/drivers/char/moxa.c 2008-04-08 11:44:00.000000000 +0100
@@ -1280,6 +1280,7 @@
*/
if (ch == NULL)
return 0;
+ lock_kernel();
chars = MoxaPortTxQueue(ch);
if (chars) {
/*
@@ -1289,6 +1290,7 @@
if (!(ch->statusflags & EMPTYWAIT))
moxa_setup_empty_event(tty);
}
+ unlock_kernel();
return chars;
}

diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.25-rc8-mm1/drivers/char/mxser.c linux-2.6.25-rc8-mm1/drivers/char/mxser.c
--- linux.vanilla-2.6.25-rc8-mm1/drivers/char/mxser.c 2008-04-08 11:34:51.000000000 +0100
+++ linux-2.6.25-rc8-mm1/drivers/char/mxser.c 2008-04-08 11:44:00.000000000 +0100
@@ -1125,6 +1125,27 @@
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
@@ -1211,9 +1232,7 @@
}
mxser_shutdown(info);

- if (tty->driver->flush_buffer)
- tty->driver->flush_buffer(tty);
-
+ mxser_flush_buffer(tty);
tty_ldisc_flush(tty);

tty->closing = 0;
@@ -1340,26 +1360,6 @@
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()
@@ -2191,6 +2191,7 @@
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);
@@ -2202,6 +2203,7 @@
break;
}
set_current_state(TASK_RUNNING);
+ unlock_kernel();

#ifdef SERIAL_DEBUG_RS_WAIT_UNTIL_SENT
printk("lsr = %d (jiff=%lu)...done\n", lsr, jiffies);
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.25-rc8-mm1/drivers/char/nozomi.c linux-2.6.25-rc8-mm1/drivers/char/nozomi.c
--- linux.vanilla-2.6.25-rc8-mm1/drivers/char/nozomi.c 2008-04-08 11:34:51.000000000 +0100
+++ linux-2.6.25-rc8-mm1/drivers/char/nozomi.c 2008-04-08 11:44:09.000000000 +0100
@@ -1724,6 +1724,8 @@
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 @@
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 @@
.unthrottle = ntty_unthrottle,
.throttle = ntty_throttle,
.chars_in_buffer = ntty_chars_in_buffer,
- .put_char = ntty_put_char,
.tiocmget = ntty_tiocmget,
.tiocmset = ntty_tiocmset,
};
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.25-rc8-mm1/drivers/char/pcmcia/synclink_cs.c linux-2.6.25-rc8-mm1/drivers/char/pcmcia/synclink_cs.c
--- linux.vanilla-2.6.25-rc8-mm1/drivers/char/pcmcia/synclink_cs.c 2008-04-08 11:34:51.000000000 +0100
+++ linux-2.6.25-rc8-mm1/drivers/char/pcmcia/synclink_cs.c 2008-04-08 11:44:22.000000000 +0100
@@ -503,20 +503,9 @@
* 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)
{
@@ -2469,10 +2459,9 @@
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);

diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.25-rc8-mm1/drivers/char/riscom8.c linux-2.6.25-rc8-mm1/drivers/char/riscom8.c
--- linux.vanilla-2.6.25-rc8-mm1/drivers/char/riscom8.c 2008-04-08 11:34:51.000000000 +0100
+++ linux-2.6.25-rc8-mm1/drivers/char/riscom8.c 2008-04-08 11:44:38.000000000 +0100
@@ -1015,6 +1015,24 @@
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 @@
}
}
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 +1233,6 @@
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;
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.25-rc8-mm1/drivers/char/rocket.c linux-2.6.25-rc8-mm1/drivers/char/rocket.c
--- linux.vanilla-2.6.25-rc8-mm1/drivers/char/rocket.c 2008-04-08 11:34:51.000000000 +0100
+++ linux-2.6.25-rc8-mm1/drivers/char/rocket.c 2008-04-08 11:44:38.000000000 +0100
@@ -1585,6 +1585,7 @@
jiffies);
printk(KERN_INFO "cps=%d...\n", info->cps);
#endif
+ lock_kernel();
while (1) {
txcnt = sGetTxCnt(cp);
if (!txcnt) {
@@ -1612,6 +1613,7 @@
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
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.25-rc8-mm1/drivers/char/serial167.c linux-2.6.25-rc8-mm1/drivers/char/serial167.c
--- linux.vanilla-2.6.25-rc8-mm1/drivers/char/serial167.c 2008-04-08 11:34:51.000000000 +0100
+++ linux-2.6.25-rc8-mm1/drivers/char/serial167.c 2008-04-08 11:44:38.000000000 +0100
@@ -1674,8 +1675,7 @@
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) {
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.25-rc8-mm1/drivers/char/specialix.c linux-2.6.25-rc8-mm1/drivers/char/specialix.c
--- linux.vanilla-2.6.25-rc8-mm1/drivers/char/specialix.c 2008-04-08 11:34:51.000000000 +0100
+++ linux-2.6.25-rc8-mm1/drivers/char/specialix.c 2008-04-08 11:44:46.000000000 +0100
@@ -1506,6 +1506,27 @@
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)
{
@@ -1599,8 +1620,7 @@
}

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;
@@ -1772,28 +1793,6 @@
}


-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)
{
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.25-rc8-mm1/drivers/char/stallion.c linux-2.6.25-rc8-mm1/drivers/char/stallion.c
--- linux.vanilla-2.6.25-rc8-mm1/drivers/char/stallion.c 2008-04-08 11:34:51.000000000 +0100
+++ linux-2.6.25-rc8-mm1/drivers/char/stallion.c 2008-04-08 11:44:46.000000000 +0100
@@ -875,6 +875,7 @@
timeout = HZ;
tend = jiffies + timeout;

+ lock_kernel();
while (stl_datastate(portp)) {
if (signal_pending(current))
break;
@@ -882,6 +883,7 @@
if (time_after_eq(jiffies, tend))
break;
}
+ unlock_kernel();
}

/*****************************************************************************/
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.25-rc8-mm1/drivers/char/synclink.c linux-2.6.25-rc8-mm1/drivers/char/synclink.c
--- linux.vanilla-2.6.25-rc8-mm1/drivers/char/synclink.c 2008-04-08 11:34:51.000000000 +0100
+++ linux-2.6.25-rc8-mm1/drivers/char/synclink.c 2008-04-08 11:45:10.000000000 +0100
@@ -3160,8 +3161,7 @@
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);

@@ -3224,7 +3224,8 @@
* 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)
@@ -3254,6 +3255,7 @@
break;
}
}
+ unlock_kernel();

exit:
if (debug_level >= DEBUG_LEVEL_INFO)
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.25-rc8-mm1/drivers/char/synclink_gt.c linux-2.6.25-rc8-mm1/drivers/char/synclink_gt.c
--- linux.vanilla-2.6.25-rc8-mm1/drivers/char/synclink_gt.c 2008-04-08 11:34:51.000000000 +0100
+++ linux-2.6.25-rc8-mm1/drivers/char/synclink_gt.c 2008-04-08 11:45:10.000000000 +0100
@@ -772,8 +772,7 @@

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);
@@ -968,6 +971,8 @@
* 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)
@@ -985,6 +990,7 @@
if (timeout && time_after(jiffies, orig_jiffies + timeout))
break;
}
+ unlock_kernel();

exit:
DBGINFO(("%s wait_until_sent exit\n", info->device_name));
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.25-rc8-mm1/drivers/char/synclinkmp.c linux-2.6.25-rc8-mm1/drivers/char/synclinkmp.c
--- linux.vanilla-2.6.25-rc8-mm1/drivers/char/synclinkmp.c 2008-04-08 11:34:51.000000000 +0100
+++ linux-2.6.25-rc8-mm1/drivers/char/synclinkmp.c 2008-04-08 11:45:10.000000000 +0100
@@ -862,8 +862,7 @@
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 +1121,8 @@
if (sanity_check(info, tty->name, "wait_until_sent"))
return;

+ lock_kernel();
+
if (!(info->flags & ASYNC_INITIALIZED))
goto exit;

@@ -1161,6 +1165,7 @@
}

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 +1181,7 @@
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 +1189,7 @@
if (ret < 0)
ret = 0;
}
+ unlock_kernel();

if (debug_level >= DEBUG_LEVEL_INFO)
printk("%s(%d):%s write_room()=%d\n",
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.25-rc8-mm1/drivers/char/tty_io.c linux-2.6.25-rc8-mm1/drivers/char/tty_io.c
--- linux.vanilla-2.6.25-rc8-mm1/drivers/char/tty_io.c 2008-04-08 11:34:51.000000000 +0100
+++ linux-2.6.25-rc8-mm1/drivers/char/tty_io.c 2008-04-08 11:49:52.000000000 +0100
@@ -1204,7 +1204,7 @@
* 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)
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.25-rc8-mm1/drivers/char/tty_ioctl.c linux-2.6.25-rc8-mm1/drivers/char/tty_ioctl.c
--- linux.vanilla-2.6.25-rc8-mm1/drivers/char/tty_ioctl.c 2008-04-08 11:34:51.000000000 +0100
+++ linux-2.6.25-rc8-mm1/drivers/char/tty_ioctl.c 2008-04-08 11:50:56.000000000 +0100
@@ -396,7 +420,7 @@
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 +432,7 @@
/* 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 +504,9 @@
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 +692,14 @@
{
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 +709,14 @@

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 +726,7 @@
{
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 +735,7 @@
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 +746,7 @@
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 +755,7 @@
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
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.25-rc8-mm1/drivers/isdn/i4l/isdn_tty.c linux-2.6.25-rc8-mm1/drivers/isdn/i4l/isdn_tty.c
--- linux.vanilla-2.6.25-rc8-mm1/drivers/isdn/i4l/isdn_tty.c 2008-04-08 11:34:51.000000000 +0100
+++ linux-2.6.25-rc8-mm1/drivers/isdn/i4l/isdn_tty.c 2008-04-08 11:53:15.000000000 +0100
@@ -1708,9 +1708,7 @@
}
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;
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.25-rc8-mm1/drivers/serial/68328serial.c linux-2.6.25-rc8-mm1/drivers/serial/68328serial.c
--- linux.vanilla-2.6.25-rc8-mm1/drivers/serial/68328serial.c 2008-04-08 11:34:40.000000000 +0100
+++ linux-2.6.25-rc8-mm1/drivers/serial/68328serial.c 2008-04-08 11:56:00.000000000 +0100
@@ -1017,18 +1018,6 @@
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 +1050,6 @@
{
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 +1126,7 @@
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;
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.25-rc8-mm1/drivers/serial/68360serial.c linux-2.6.25-rc8-mm1/drivers/serial/68360serial.c
--- linux.vanilla-2.6.25-rc8-mm1/drivers/serial/68360serial.c 2008-04-08 11:34:52.000000000 +0100
+++ linux-2.6.25-rc8-mm1/drivers/serial/68360serial.c 2008-04-08 11:56:00.000000000 +0100
@@ -1435,18 +1436,6 @@
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);
@@ -1664,8 +1653,7 @@
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;
@@ -1716,6 +1704,7 @@
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
@@ -1744,6 +1733,7 @@
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
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.25-rc8-mm1/drivers/serial/crisv10.c linux-2.6.25-rc8-mm1/drivers/serial/crisv10.c
--- linux.vanilla-2.6.25-rc8-mm1/drivers/serial/crisv10.c 2008-04-08 11:34:52.000000000 +0100
+++ linux-2.6.25-rc8-mm1/drivers/serial/crisv10.c 2008-04-08 11:56:13.000000000 +0100
@@ -3581,9 +3581,10 @@
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);
if (clear & TIOCM_DTR)
@@ -3604,7 +3605,7 @@
if (set & TIOCM_CD)
e100_cd_out(info, 1);

- unlock_kernel();
+ local_irq_restore(flags);
return 0;
}

@@ -3613,8 +3614,10 @@
{
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 @@
| (!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 @@
{
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 @@
#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 @@
* 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 @@
curr_time_usec - info->last_tx_active_usec;
}
set_current_state(TASK_RUNNING);
+ unlock_kernel();
}

/*
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.25-rc8-mm1/drivers/serial/mcfserial.c linux-2.6.25-rc8-mm1/drivers/serial/mcfserial.c
--- linux.vanilla-2.6.25-rc8-mm1/drivers/serial/mcfserial.c 2008-04-08 11:33:59.000000000 +0100
+++ linux-2.6.25-rc8-mm1/drivers/serial/mcfserial.c 2008-04-08 11:56:13.000000000 +0100
@@ -1073,18 +1073,6 @@
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)))
@@ -1223,8 +1211,7 @@
} 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;
@@ -1277,6 +1264,8 @@
* 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)
@@ -1313,6 +1302,7 @@
if (timeout && time_after(jiffies, orig_jiffies + timeout))
break;
}
+ unlock_kernel();
#else
/*
* For the other coldfire models, assume all data has been sent
diff -u --new-file --recursive --exclude-from /usr/src/exclude linux.vanilla-2.6.25-rc8-mm1/drivers/serial/netx-serial.c linux-2.6.25-rc8-mm1/drivers/serial/netx-serial.c
--- linux.vanilla-2.6.25-rc8-mm1/drivers/serial/netx-serial.c 2008-04-08 11:33:30.000000000 +0100
+++ linux-2.6.25-rc8-mm1/drivers/serial/netx-serial.c 2008-04-08 11:56:13.000000000 +0100
@@ -287,6 +287,7 @@
{
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);
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at http://vger.kernel.org/majordomo-info.html
Please read the FAQ at http://www.tux.org/lkml/