Commit 978e595f authored by Alan Cox's avatar Alan Cox Committed by Linus Torvalds

tty/serial: lay the foundations for the next set of reworks

- 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: 's avatarAlan Cox <alan@redhat.com>
Cc: Jiri Slaby <jirislaby@gmail.com>
Signed-off-by: 's avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: 's avatarLinus Torvalds <torvalds@linux-foundation.org>
parent ac0e4b7d
......@@ -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
......
......@@ -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.
*/
......
......@@ -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,
......
......@@ -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;
......
......@@ -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;
......
......@@ -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
......
......@@ -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;
}
......
......@@ -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);
......
......@@ -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,
};
......
......@@ -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);
......
......@@ -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;
......
......@@ -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
......
......@@ -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) {
......
......@@ -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)
{
......
......@@ -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();
}
/*****************************************************************************/
......
......@@ -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)
......
......@@ -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));
......
......@@ -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",
......
......@@ -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)
......
......@@ -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);