diff options
| author | Greg Kroah-Hartman <gregkh@suse.de> | 2010-07-22 16:57:38 -0700 |
|---|---|---|
| committer | Greg Kroah-Hartman <gregkh@suse.de> | 2010-07-22 16:57:38 -0700 |
| commit | 6bbbb136e761db39158852c9b42619c2438e9d45 (patch) | |
| tree | 4b48eba7be3ba0e7ffbddc0fee4988d26623099a /tty/serial-mcf-don-t-take-spinlocks-in-already-protected-functions.patch | |
| parent | 5caca10b163e38f1671c4be83c480581da4d90d6 (diff) | |
| download | patches-6bbbb136e761db39158852c9b42619c2438e9d45.tar.gz | |
lots of patches
Diffstat (limited to 'tty/serial-mcf-don-t-take-spinlocks-in-already-protected-functions.patch')
| -rw-r--r-- | tty/serial-mcf-don-t-take-spinlocks-in-already-protected-functions.patch | 133 |
1 files changed, 133 insertions, 0 deletions
diff --git a/tty/serial-mcf-don-t-take-spinlocks-in-already-protected-functions.patch b/tty/serial-mcf-don-t-take-spinlocks-in-already-protected-functions.patch new file mode 100644 index 00000000000000..4694b7fd29b273 --- /dev/null +++ b/tty/serial-mcf-don-t-take-spinlocks-in-already-protected-functions.patch @@ -0,0 +1,133 @@ +From akpm@linux-foundation.org Thu Jul 22 15:55:47 2010 +Message-Id: <201007202226.o6KMQpNm021530@imap1.linux-foundation.org> +Subject: serial: mcf: don't take spinlocks in already protected functions +To: greg@kroah.com +Cc: linux-serial@vger.kernel.org, akpm@linux-foundation.org, + ygeorgie@gmail.com, alan@lxorguk.ukuu.org.uk, gerg@uclinux.org +From: akpm@linux-foundation.org +Date: Tue, 20 Jul 2010 15:26:50 -0700 + +From: Yury Georgievskiy <ygeorgie@gmail.com> + +Don't take the port spinlock in uart functions where the serial core +already takes care of locking/unlocking them. + +The code would actually lock up on architectures where spinlocks are +implemented. + +Also protect calling mcf_rx_chars/mcf_tx_chars in the interrupt handler by +the port spinlock and use IRQ_RETVAL to return from isr. + +[akpm@linux-foundation.org: make irq-handler return value more explicit] +Signed-off-by: Yury Georgievskiy <ygeorgie@gmail.com> +Cc: Alan Cox <alan@lxorguk.ukuu.org.uk> +Acked-by: Greg Ungerer <gerg@uclinux.org> +Signed-off-by: Andrew Morton <akpm@linux-foundation.org> +Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de> + +--- + drivers/serial/mcf.c | 31 +++++++++++++------------------ + 1 file changed, 13 insertions(+), 18 deletions(-) + +--- a/drivers/serial/mcf.c ++++ b/drivers/serial/mcf.c +@@ -70,16 +70,14 @@ static unsigned int mcf_tx_empty(struct + static unsigned int mcf_get_mctrl(struct uart_port *port) + { + struct mcf_uart *pp = container_of(port, struct mcf_uart, port); +- unsigned long flags; + unsigned int sigs; + +- spin_lock_irqsave(&port->lock, flags); + sigs = (readb(port->membase + MCFUART_UIPR) & MCFUART_UIPR_CTS) ? + 0 : TIOCM_CTS; + sigs |= (pp->sigs & TIOCM_RTS); + sigs |= (mcf_getppdcd(port->line) ? TIOCM_CD : 0); + sigs |= (mcf_getppdtr(port->line) ? TIOCM_DTR : 0); +- spin_unlock_irqrestore(&port->lock, flags); ++ + return sigs; + } + +@@ -88,16 +86,13 @@ static unsigned int mcf_get_mctrl(struct + static void mcf_set_mctrl(struct uart_port *port, unsigned int sigs) + { + struct mcf_uart *pp = container_of(port, struct mcf_uart, port); +- unsigned long flags; + +- spin_lock_irqsave(&port->lock, flags); + pp->sigs = sigs; + mcf_setppdtr(port->line, (sigs & TIOCM_DTR)); + if (sigs & TIOCM_RTS) + writeb(MCFUART_UOP_RTS, port->membase + MCFUART_UOP1); + else + writeb(MCFUART_UOP_RTS, port->membase + MCFUART_UOP0); +- spin_unlock_irqrestore(&port->lock, flags); + } + + /****************************************************************************/ +@@ -105,12 +100,9 @@ static void mcf_set_mctrl(struct uart_po + static void mcf_start_tx(struct uart_port *port) + { + struct mcf_uart *pp = container_of(port, struct mcf_uart, port); +- unsigned long flags; + +- spin_lock_irqsave(&port->lock, flags); + pp->imr |= MCFUART_UIR_TXREADY; + writeb(pp->imr, port->membase + MCFUART_UIMR); +- spin_unlock_irqrestore(&port->lock, flags); + } + + /****************************************************************************/ +@@ -118,12 +110,9 @@ static void mcf_start_tx(struct uart_por + static void mcf_stop_tx(struct uart_port *port) + { + struct mcf_uart *pp = container_of(port, struct mcf_uart, port); +- unsigned long flags; + +- spin_lock_irqsave(&port->lock, flags); + pp->imr &= ~MCFUART_UIR_TXREADY; + writeb(pp->imr, port->membase + MCFUART_UIMR); +- spin_unlock_irqrestore(&port->lock, flags); + } + + /****************************************************************************/ +@@ -131,12 +120,9 @@ static void mcf_stop_tx(struct uart_port + static void mcf_stop_rx(struct uart_port *port) + { + struct mcf_uart *pp = container_of(port, struct mcf_uart, port); +- unsigned long flags; + +- spin_lock_irqsave(&port->lock, flags); + pp->imr &= ~MCFUART_UIR_RXREADY; + writeb(pp->imr, port->membase + MCFUART_UIMR); +- spin_unlock_irqrestore(&port->lock, flags); + } + + /****************************************************************************/ +@@ -366,13 +352,22 @@ static irqreturn_t mcf_interrupt(int irq + struct uart_port *port = data; + struct mcf_uart *pp = container_of(port, struct mcf_uart, port); + unsigned int isr; ++ irqreturn_t ret = IRQ_NONE; + + isr = readb(port->membase + MCFUART_UISR) & pp->imr; +- if (isr & MCFUART_UIR_RXREADY) ++ ++ spin_lock(&port->lock); ++ if (isr & MCFUART_UIR_RXREADY) { + mcf_rx_chars(pp); +- if (isr & MCFUART_UIR_TXREADY) ++ ret = IRQ_HANDLED; ++ } ++ if (isr & MCFUART_UIR_TXREADY) { + mcf_tx_chars(pp); +- return IRQ_HANDLED; ++ ret = IRQ_HANDLED; ++ } ++ spin_unlock(&port->lock); ++ ++ return ret; + } + + /****************************************************************************/ |
