diff options
author | Maciej W. Rozycki <macro@linux-mips.org> | 2008-02-07 03:15:11 -0500 |
---|---|---|
committer | Linus Torvalds <torvalds@woody.linux-foundation.org> | 2008-02-07 11:42:24 -0500 |
commit | 43d46ab1cdeb12b8d072cfdf84956073a1fa8866 (patch) | |
tree | 00e55a9babe058feef7065621f12c63dd493ff07 /drivers/serial/dz.c | |
parent | 6d83c067ebd11d375b34c53192c10826947e8568 (diff) |
dz: fix locking issues
The ->start_tx(), ->stop_tx() and ->stop_rx() backends are called with the
port's lock already taken. Remove locking from within them and wrap around
calls as necessary.
Signed-off-by: Maciej W. Rozycki <macro@linux-mips.org>
Cc: 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/serial/dz.c')
-rw-r--r-- | drivers/serial/dz.c | 23 |
1 files changed, 12 insertions, 11 deletions
diff --git a/drivers/serial/dz.c b/drivers/serial/dz.c index c2f867777145..656c342a80f8 100644 --- a/drivers/serial/dz.c +++ b/drivers/serial/dz.c | |||
@@ -108,37 +108,28 @@ static void dz_stop_tx(struct uart_port *uport) | |||
108 | { | 108 | { |
109 | struct dz_port *dport = (struct dz_port *)uport; | 109 | struct dz_port *dport = (struct dz_port *)uport; |
110 | unsigned short tmp, mask = 1 << dport->port.line; | 110 | unsigned short tmp, mask = 1 << dport->port.line; |
111 | unsigned long flags; | ||
112 | 111 | ||
113 | spin_lock_irqsave(&dport->port.lock, flags); | ||
114 | tmp = dz_in(dport, DZ_TCR); /* read the TX flag */ | 112 | tmp = dz_in(dport, DZ_TCR); /* read the TX flag */ |
115 | tmp &= ~mask; /* clear the TX flag */ | 113 | tmp &= ~mask; /* clear the TX flag */ |
116 | dz_out(dport, DZ_TCR, tmp); | 114 | dz_out(dport, DZ_TCR, tmp); |
117 | spin_unlock_irqrestore(&dport->port.lock, flags); | ||
118 | } | 115 | } |
119 | 116 | ||
120 | static void dz_start_tx(struct uart_port *uport) | 117 | static void dz_start_tx(struct uart_port *uport) |
121 | { | 118 | { |
122 | struct dz_port *dport = (struct dz_port *)uport; | 119 | struct dz_port *dport = (struct dz_port *)uport; |
123 | unsigned short tmp, mask = 1 << dport->port.line; | 120 | unsigned short tmp, mask = 1 << dport->port.line; |
124 | unsigned long flags; | ||
125 | 121 | ||
126 | spin_lock_irqsave(&dport->port.lock, flags); | ||
127 | tmp = dz_in(dport, DZ_TCR); /* read the TX flag */ | 122 | tmp = dz_in(dport, DZ_TCR); /* read the TX flag */ |
128 | tmp |= mask; /* set the TX flag */ | 123 | tmp |= mask; /* set the TX flag */ |
129 | dz_out(dport, DZ_TCR, tmp); | 124 | dz_out(dport, DZ_TCR, tmp); |
130 | spin_unlock_irqrestore(&dport->port.lock, flags); | ||
131 | } | 125 | } |
132 | 126 | ||
133 | static void dz_stop_rx(struct uart_port *uport) | 127 | static void dz_stop_rx(struct uart_port *uport) |
134 | { | 128 | { |
135 | struct dz_port *dport = (struct dz_port *)uport; | 129 | struct dz_port *dport = (struct dz_port *)uport; |
136 | unsigned long flags; | ||
137 | 130 | ||
138 | spin_lock_irqsave(&dport->port.lock, flags); | ||
139 | dport->cflag &= ~DZ_CREAD; | 131 | dport->cflag &= ~DZ_CREAD; |
140 | dz_out(dport, DZ_LPR, dport->cflag | dport->port.line); | 132 | dz_out(dport, DZ_LPR, dport->cflag | dport->port.line); |
141 | spin_unlock_irqrestore(&dport->port.lock, flags); | ||
142 | } | 133 | } |
143 | 134 | ||
144 | static void dz_enable_ms(struct uart_port *port) | 135 | static void dz_enable_ms(struct uart_port *port) |
@@ -268,7 +259,9 @@ static inline void dz_transmit_chars(struct dz_port *dport_in) | |||
268 | } | 259 | } |
269 | /* If nothing to do or stopped or hardware stopped. */ | 260 | /* If nothing to do or stopped or hardware stopped. */ |
270 | if (uart_circ_empty(xmit) || uart_tx_stopped(&dport->port)) { | 261 | if (uart_circ_empty(xmit) || uart_tx_stopped(&dport->port)) { |
262 | spin_lock(&dport->port.lock); | ||
271 | dz_stop_tx(&dport->port); | 263 | dz_stop_tx(&dport->port); |
264 | spin_unlock(&dport->port.lock); | ||
272 | return; | 265 | return; |
273 | } | 266 | } |
274 | 267 | ||
@@ -285,8 +278,11 @@ static inline void dz_transmit_chars(struct dz_port *dport_in) | |||
285 | uart_write_wakeup(&dport->port); | 278 | uart_write_wakeup(&dport->port); |
286 | 279 | ||
287 | /* Are we are done. */ | 280 | /* Are we are done. */ |
288 | if (uart_circ_empty(xmit)) | 281 | if (uart_circ_empty(xmit)) { |
282 | spin_lock(&dport->port.lock); | ||
289 | dz_stop_tx(&dport->port); | 283 | dz_stop_tx(&dport->port); |
284 | spin_unlock(&dport->port.lock); | ||
285 | } | ||
290 | } | 286 | } |
291 | 287 | ||
292 | /* | 288 | /* |
@@ -417,7 +413,12 @@ static int dz_startup(struct uart_port *uport) | |||
417 | */ | 413 | */ |
418 | static void dz_shutdown(struct uart_port *uport) | 414 | static void dz_shutdown(struct uart_port *uport) |
419 | { | 415 | { |
420 | dz_stop_tx(uport); | 416 | struct dz_port *dport = (struct dz_port *)uport; |
417 | unsigned long flags; | ||
418 | |||
419 | spin_lock_irqsave(&dport->port.lock, flags); | ||
420 | dz_stop_tx(&dport->port); | ||
421 | spin_unlock_irqrestore(&dport->port.lock, flags); | ||
421 | } | 422 | } |
422 | 423 | ||
423 | /* | 424 | /* |