Gitweb:     
http://git.kernel.org/git/?p=linux/kernel/git/torvalds/linux-2.6.git;a=commit;h=f574874bc861414bbae220b1fe623cbdd098243b
Commit:     f574874bc861414bbae220b1fe623cbdd098243b
Parent:     765d94c1b37d08be02eea6abbff70c0fda0ba984
Author:     Jiri Slaby <[EMAIL PROTECTED]>
AuthorDate: Sat Feb 10 01:45:18 2007 -0800
Committer:  Linus Torvalds <[EMAIL PROTECTED]>
CommitDate: Sun Feb 11 10:51:29 2007 -0800

    [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 <[EMAIL PROTECTED]>
    Signed-off-by: Jiri Slaby <[EMAIL PROTECTED]>
    Signed-off-by: Andrew Morton <[EMAIL PROTECTED]>
    Signed-off-by: Linus Torvalds <[EMAIL PROTECTED]>
---
 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 8da8833..ec61cf8 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)
        int cnt = 0;
        int recv_room;
        int max = 256;
-       unsigned long flags;
-
-       spin_lock_irqsave(&port->slock, flags);
 
        recv_room = tty->receive_room;
        if ((recv_room == 0) && (!port->ldisc_stop_rx))
@@ -2159,7 +2156,6 @@ end_intr:
        mxvar_log.rxcnt[port->tty->index] += cnt;
        port->mon_data.rxcnt += cnt;
        port->mon_data.up_rxcnt += cnt;
-       spin_unlock_irqrestore(&port->slock, flags);
 
        tty_flip_buffer_push(tty);
 }
@@ -2167,9 +2163,6 @@ end_intr:
 static void mxser_transmit_chars(struct mxser_port *port)
 {
        int count, cnt;
-       unsigned long flags;
-
-       spin_lock_irqsave(&port->slock, flags);
 
        if (port->x_char) {
                outb(port->x_char, port->ioaddr + UART_TX);
@@ -2178,11 +2171,11 @@ static void mxser_transmit_chars(struct mxser_port 
*port)
                port->mon_data.txcnt++;
                port->mon_data.up_txcnt++;
                port->icount.tx++;
-               goto unlock;
+               return;
        }
 
        if (port->xmit_buf == 0)
-               goto unlock;
+               return;
 
        if ((port->xmit_cnt <= 0) || port->tty->stopped ||
                        (port->tty->hw_stopped &&
@@ -2190,7 +2183,7 @@ static void mxser_transmit_chars(struct mxser_port *port)
                        (!port->board->chip_flag))) {
                port->IER &= ~UART_IER_THRI;
                outb(port->IER, port->ioaddr + UART_IER);
-               goto unlock;
+               return;
        }
 
        cnt = port->xmit_cnt;
@@ -2215,8 +2208,6 @@ static void mxser_transmit_chars(struct mxser_port *port)
                port->IER &= ~UART_IER_THRI;
                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)
                        port = &brd->ports[i];
 
                        int_cnt = 0;
+                       spin_lock(&port->slock);
                        do {
                                iir = inb(port->ioaddr + UART_IIR);
                                if (iir & UART_IIR_NO_INT)
                                        break;
                                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);
                                        outb(0x27, port->ioaddr + UART_FCR);
                                        inb(port->ioaddr + UART_MSR);
@@ -2308,6 +2303,7 @@ static irqreturn_t mxser_interrupt(int irq, void *dev_id)
                                                mxser_transmit_chars(port);
                                }
                        } while (int_cnt++ < MXSER_ISR_PASS_LIMIT);
+                       spin_unlock(&port->slock);
                }
                if (pass_counter++ > MXSER_ISR_PASS_LIMIT)
                        break;  /* Prevent infinite loops */
-
To unsubscribe from this list: send the line "unsubscribe git-commits-head" in
the body of a message to [EMAIL PROTECTED]
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to