diff options
author | Jiri Slaby <jirislaby@gmail.com> | 2007-02-10 04:45:18 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2007-02-11 13:51:29 -0500 |
commit | f574874bc861414bbae220b1fe623cbdd098243b (patch) | |
tree | f905e9170338a295e897013c9ab01ca189f08dbe /drivers/char/mxser_new.c | |
parent | 765d94c1b37d08be02eea6abbff70c0fda0ba984 (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/mxser_new.c')
-rw-r--r-- | drivers/char/mxser_new.c | 22 |
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: | |||
2167 | static void mxser_transmit_chars(struct mxser_port *port) | 2163 | static 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 | } |
2218 | unlock: | ||
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 */ |