Commit f574874b authored by Jiri Slaby's avatar Jiri Slaby Committed by Linus Torvalds

[PATCH] Char: mxser_new, alter locking in isr

Avoid oopsing when stress-testing open/close -- port->tty is NULL sometimes,
but is expected to be non-NULL, since dereferencing.  Receive/transmit chars
iff ASYNC_CLOSING is not set and ASYNC_INITIALIZED is set.  Thanks Sergei for
pointing this out and testing.

Cc: Sergei Organov <osv@javad.com>
Signed-off-by: default avatarJiri Slaby <jirislaby@gmail.com>
Signed-off-by: default avatarAndrew Morton <akpm@linux-foundation.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@linux-foundation.org>
parent 765d94c1
...@@ -2073,9 +2073,6 @@ static void mxser_receive_chars(struct mxser_port *port, int *status) ...@@ -2073,9 +2073,6 @@ static void mxser_receive_chars(struct mxser_port *port, int *status)
int cnt = 0; int cnt = 0;
int recv_room; int recv_room;
int max = 256; int max = 256;
unsigned long flags;
spin_lock_irqsave(&port->slock, flags);
recv_room = tty->receive_room; recv_room = tty->receive_room;
if ((recv_room == 0) && (!port->ldisc_stop_rx)) if ((recv_room == 0) && (!port->ldisc_stop_rx))
...@@ -2159,7 +2156,6 @@ static void mxser_receive_chars(struct mxser_port *port, int *status) ...@@ -2159,7 +2156,6 @@ static void mxser_receive_chars(struct mxser_port *port, int *status)
mxvar_log.rxcnt[port->tty->index] += cnt; mxvar_log.rxcnt[port->tty->index] += cnt;
port->mon_data.rxcnt += cnt; port->mon_data.rxcnt += cnt;
port->mon_data.up_rxcnt += cnt; port->mon_data.up_rxcnt += cnt;
spin_unlock_irqrestore(&port->slock, flags);
tty_flip_buffer_push(tty); tty_flip_buffer_push(tty);
} }
...@@ -2167,9 +2163,6 @@ static void mxser_receive_chars(struct mxser_port *port, int *status) ...@@ -2167,9 +2163,6 @@ static void mxser_receive_chars(struct mxser_port *port, int *status)
static void mxser_transmit_chars(struct mxser_port *port) static void mxser_transmit_chars(struct mxser_port *port)
{ {
int count, cnt; int count, cnt;
unsigned long flags;
spin_lock_irqsave(&port->slock, flags);
if (port->x_char) { if (port->x_char) {
outb(port->x_char, port->ioaddr + UART_TX); outb(port->x_char, port->ioaddr + UART_TX);
...@@ -2178,11 +2171,11 @@ static void mxser_transmit_chars(struct mxser_port *port) ...@@ -2178,11 +2171,11 @@ static void mxser_transmit_chars(struct mxser_port *port)
port->mon_data.txcnt++; port->mon_data.txcnt++;
port->mon_data.up_txcnt++; port->mon_data.up_txcnt++;
port->icount.tx++; port->icount.tx++;
goto unlock; return;
} }
if (port->xmit_buf == 0) if (port->xmit_buf == 0)
goto unlock; return;
if ((port->xmit_cnt <= 0) || port->tty->stopped || if ((port->xmit_cnt <= 0) || port->tty->stopped ||
(port->tty->hw_stopped && (port->tty->hw_stopped &&
...@@ -2190,7 +2183,7 @@ static void mxser_transmit_chars(struct mxser_port *port) ...@@ -2190,7 +2183,7 @@ static void mxser_transmit_chars(struct mxser_port *port)
(!port->board->chip_flag))) { (!port->board->chip_flag))) {
port->IER &= ~UART_IER_THRI; port->IER &= ~UART_IER_THRI;
outb(port->IER, port->ioaddr + UART_IER); outb(port->IER, port->ioaddr + UART_IER);
goto unlock; return;
} }
cnt = port->xmit_cnt; cnt = port->xmit_cnt;
...@@ -2215,8 +2208,6 @@ static void mxser_transmit_chars(struct mxser_port *port) ...@@ -2215,8 +2208,6 @@ static void mxser_transmit_chars(struct mxser_port *port)
port->IER &= ~UART_IER_THRI; port->IER &= ~UART_IER_THRI;
outb(port->IER, port->ioaddr + UART_IER); outb(port->IER, port->ioaddr + UART_IER);
} }
unlock:
spin_unlock_irqrestore(&port->slock, flags);
} }
/* /*
...@@ -2257,12 +2248,16 @@ static irqreturn_t mxser_interrupt(int irq, void *dev_id) ...@@ -2257,12 +2248,16 @@ static irqreturn_t mxser_interrupt(int irq, void *dev_id)
port = &brd->ports[i]; port = &brd->ports[i];
int_cnt = 0; int_cnt = 0;
spin_lock(&port->slock);
do { do {
iir = inb(port->ioaddr + UART_IIR); iir = inb(port->ioaddr + UART_IIR);
if (iir & UART_IIR_NO_INT) if (iir & UART_IIR_NO_INT)
break; break;
iir &= MOXA_MUST_IIR_MASK; iir &= MOXA_MUST_IIR_MASK;
if (!port->tty) { if (!port->tty ||
(port->flags & ASYNC_CLOSING) ||
!(port->flags &
ASYNC_INITIALIZED)) {
status = inb(port->ioaddr + UART_LSR); status = inb(port->ioaddr + UART_LSR);
outb(0x27, port->ioaddr + UART_FCR); outb(0x27, port->ioaddr + UART_FCR);
inb(port->ioaddr + UART_MSR); inb(port->ioaddr + UART_MSR);
...@@ -2308,6 +2303,7 @@ static irqreturn_t mxser_interrupt(int irq, void *dev_id) ...@@ -2308,6 +2303,7 @@ static irqreturn_t mxser_interrupt(int irq, void *dev_id)
mxser_transmit_chars(port); mxser_transmit_chars(port);
} }
} while (int_cnt++ < MXSER_ISR_PASS_LIMIT); } while (int_cnt++ < MXSER_ISR_PASS_LIMIT);
spin_unlock(&port->slock);
} }
if (pass_counter++ > MXSER_ISR_PASS_LIMIT) if (pass_counter++ > MXSER_ISR_PASS_LIMIT)
break; /* Prevent infinite loops */ break; /* Prevent infinite loops */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment