aboutsummaryrefslogtreecommitdiffstats
path: root/tty/serial-mcf-don-t-take-spinlocks-in-already-protected-functions.patch
diff options
authorGreg Kroah-Hartman <gregkh@suse.de>2010-07-22 16:57:38 -0700
committerGreg Kroah-Hartman <gregkh@suse.de>2010-07-22 16:57:38 -0700
commit6bbbb136e761db39158852c9b42619c2438e9d45 (patch)
tree4b48eba7be3ba0e7ffbddc0fee4988d26623099a /tty/serial-mcf-don-t-take-spinlocks-in-already-protected-functions.patch
parent5caca10b163e38f1671c4be83c480581da4d90d6 (diff)
downloadpatches-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.patch133
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;
+ }
+
+ /****************************************************************************/