aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/char
diff options
context:
space:
mode:
authorJiri Slaby <jirislaby@gmail.com>2007-02-10 04:45:18 -0500
committerLinus Torvalds <torvalds@woody.linux-foundation.org>2007-02-11 13:51:29 -0500
commitf574874bc861414bbae220b1fe623cbdd098243b (patch)
treef905e9170338a295e897013c9ab01ca189f08dbe /drivers/char
parent765d94c1b37d08be02eea6abbff70c0fda0ba984 (diff)
[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: Jiri Slaby <jirislaby@gmail.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
Diffstat (limited to 'drivers/char')
-rw-r--r--drivers/char/mxser_new.c22
1 files changed, 9 insertions, 13 deletions
diff --git a/drivers/char/mxser_new.c b/drivers/char/mxser_new.c
index 8da883340dd6..ec61cf81b7e6 100644
--- a/drivers/char/mxser_new.c
+++ b/drivers/char/mxser_new.c
@@ -2073,9 +2073,6 @@ static void mxser_receive_chars(struct mxser_port *port, int *status)
2073 int cnt = 0; 2073 int cnt = 0;
2074 int recv_room; 2074 int recv_room;
2075 int max = 256; 2075 int max = 256;
2076 unsigned long flags;
2077
2078 spin_lock_irqsave(&port->slock, flags);
2079 2076
2080 recv_room = tty->receive_room; 2077 recv_room = tty->receive_room;
2081 if ((recv_room == 0) && (!port->ldisc_stop_rx)) 2078 if ((recv_room == 0) && (!port->ldisc_stop_rx))
@@ -2159,7 +2156,6 @@ end_intr:
2159 mxvar_log.rxcnt[port->tty->index] += cnt; 2156 mxvar_log.rxcnt[port->tty->index] += cnt;
2160 port->mon_data.rxcnt += cnt; 2157 port->mon_data.rxcnt += cnt;
2161 port->mon_data.up_rxcnt += cnt; 2158 port->mon_data.up_rxcnt += cnt;
2162 spin_unlock_irqrestore(&port->slock, flags);
2163 2159
2164 tty_flip_buffer_push(tty); 2160 tty_flip_buffer_push(tty);
2165} 2161}
@@ -2167,9 +2163,6 @@ end_intr:
2167static void mxser_transmit_chars(struct mxser_port *port) 2163static void mxser_transmit_chars(struct mxser_port *port)
2168{ 2164{
2169 int count, cnt; 2165 int count, cnt;
2170 unsigned long flags;
2171
2172 spin_lock_irqsave(&port->slock, flags);
2173 2166
2174 if (port->x_char) { 2167 if (port->x_char) {
2175 outb(port->x_char, port->ioaddr + UART_TX); 2168 outb(port->x_char, port->ioaddr + UART_TX);
@@ -2178,11 +2171,11 @@ static void mxser_transmit_chars(struct mxser_port *port)
2178 port->mon_data.txcnt++; 2171 port->mon_data.txcnt++;
2179 port->mon_data.up_txcnt++; 2172 port->mon_data.up_txcnt++;
2180 port->icount.tx++; 2173 port->icount.tx++;
2181 goto unlock; 2174 return;
2182 } 2175 }
2183 2176
2184 if (port->xmit_buf == 0) 2177 if (port->xmit_buf == 0)
2185 goto unlock; 2178 return;
2186 2179
2187 if ((port->xmit_cnt <= 0) || port->tty->stopped || 2180 if ((port->xmit_cnt <= 0) || port->tty->stopped ||
2188 (port->tty->hw_stopped && 2181 (port->tty->hw_stopped &&
@@ -2190,7 +2183,7 @@ static void mxser_transmit_chars(struct mxser_port *port)
2190 (!port->board->chip_flag))) { 2183 (!port->board->chip_flag))) {
2191 port->IER &= ~UART_IER_THRI; 2184 port->IER &= ~UART_IER_THRI;
2192 outb(port->IER, port->ioaddr + UART_IER); 2185 outb(port->IER, port->ioaddr + UART_IER);
2193 goto unlock; 2186 return;
2194 } 2187 }
2195 2188
2196 cnt = port->xmit_cnt; 2189 cnt = port->xmit_cnt;
@@ -2215,8 +2208,6 @@ static void mxser_transmit_chars(struct mxser_port *port)
2215 port->IER &= ~UART_IER_THRI; 2208 port->IER &= ~UART_IER_THRI;
2216 outb(port->IER, port->ioaddr + UART_IER); 2209 outb(port->IER, port->ioaddr + UART_IER);
2217 } 2210 }
2218unlock:
2219 spin_unlock_irqrestore(&port->slock, flags);
2220} 2211}
2221 2212
2222/* 2213/*
@@ -2257,12 +2248,16 @@ static irqreturn_t mxser_interrupt(int irq, void *dev_id)
2257 port = &brd->ports[i]; 2248 port = &brd->ports[i];
2258 2249
2259 int_cnt = 0; 2250 int_cnt = 0;
2251 spin_lock(&port->slock);
2260 do { 2252 do {
2261 iir = inb(port->ioaddr + UART_IIR); 2253 iir = inb(port->ioaddr + UART_IIR);
2262 if (iir & UART_IIR_NO_INT) 2254 if (iir & UART_IIR_NO_INT)
2263 break; 2255 break;
2264 iir &= MOXA_MUST_IIR_MASK; 2256 iir &= MOXA_MUST_IIR_MASK;
2265 if (!port->tty) { 2257 if (!port->tty ||
2258 (port->flags & ASYNC_CLOSING) ||
2259 !(port->flags &
2260 ASYNC_INITIALIZED)) {
2266 status = inb(port->ioaddr + UART_LSR); 2261 status = inb(port->ioaddr + UART_LSR);
2267 outb(0x27, port->ioaddr + UART_FCR); 2262 outb(0x27, port->ioaddr + UART_FCR);
2268 inb(port->ioaddr + UART_MSR); 2263 inb(port->ioaddr + UART_MSR);
@@ -2308,6 +2303,7 @@ static irqreturn_t mxser_interrupt(int irq, void *dev_id)
2308 mxser_transmit_chars(port); 2303 mxser_transmit_chars(port);
2309 } 2304 }
2310 } while (int_cnt++ < MXSER_ISR_PASS_LIMIT); 2305 } while (int_cnt++ < MXSER_ISR_PASS_LIMIT);
2306 spin_unlock(&port->slock);
2311 } 2307 }
2312 if (pass_counter++ > MXSER_ISR_PASS_LIMIT) 2308 if (pass_counter++ > MXSER_ISR_PASS_LIMIT)
2313 break; /* Prevent infinite loops */ 2309 break; /* Prevent infinite loops */