Commit 05a90fce authored by Tom Rini's avatar Tom Rini Committed by Linus Torvalds

[PATCH] ppc32: remove cli()/sti() in arch/ppc/4xx_io/serial_sicc.c

Replace save_flags()/restore_flags() with
spin_lock_irqsave()/spin_unlock_irqrestore() and document reasons for using
spinlocks.
Signed-off-by: default avatarJames Nelson <james4765@gmail.com>
Signed-off-by: default avatarTom Rini <trini@kernel.crashing.org>
Signed-off-by: default avatarAndrew Morton <akpm@osdl.org>
Signed-off-by: default avatarLinus Torvalds <torvalds@osdl.org>
parent 00a284c3
...@@ -264,6 +264,7 @@ struct SICC_state { ...@@ -264,6 +264,7 @@ struct SICC_state {
unsigned int flags; unsigned int flags;
int count; int count;
struct SICC_info *info; struct SICC_info *info;
spinlock_t sicc_lock;
}; };
#define SICC_XMIT_SIZE 1024 #define SICC_XMIT_SIZE 1024
...@@ -385,9 +386,10 @@ static void siccuart_stop(struct tty_struct *tty) ...@@ -385,9 +386,10 @@ static void siccuart_stop(struct tty_struct *tty)
struct SICC_info *info = tty->driver_data; struct SICC_info *info = tty->driver_data;
unsigned long flags; unsigned long flags;
save_flags(flags); cli(); /* disable interrupts while stopping serial port interrupts */
spin_lock_irqsave(&info->state->sicc_lock,flags);
siccuart_disable_tx_interrupt(info); siccuart_disable_tx_interrupt(info);
restore_flags(flags); spin_unlock_irqrestore(&info->state->sicc_lock,flags);
} }
static void siccuart_start(struct tty_struct *tty) static void siccuart_start(struct tty_struct *tty)
...@@ -395,11 +397,12 @@ static void siccuart_start(struct tty_struct *tty) ...@@ -395,11 +397,12 @@ static void siccuart_start(struct tty_struct *tty)
struct SICC_info *info = tty->driver_data; struct SICC_info *info = tty->driver_data;
unsigned long flags; unsigned long flags;
save_flags(flags); cli(); /* disable interrupts while starting serial port interrupts */
spin_lock_irqsave(&info->state->sicc_lock,flags);
if (info->xmit.head != info->xmit.tail if (info->xmit.head != info->xmit.tail
&& info->xmit.buf) && info->xmit.buf)
siccuart_enable_tx_interrupt(info); siccuart_enable_tx_interrupt(info);
restore_flags(flags); spin_unlock_irqrestore(&info->state->sicc_lock,flags);
} }
...@@ -604,7 +607,8 @@ static int siccuart_startup(struct SICC_info *info) ...@@ -604,7 +607,8 @@ static int siccuart_startup(struct SICC_info *info)
return -ENOMEM; return -ENOMEM;
} }
save_flags(flags); cli(); /* lock access to info while doing setup */
spin_lock_irqsave(&info->state->sicc_lock,flags);
if (info->xmit.buf) if (info->xmit.buf)
free_page(page); free_page(page);
...@@ -688,12 +692,12 @@ static int siccuart_startup(struct SICC_info *info) ...@@ -688,12 +692,12 @@ static int siccuart_startup(struct SICC_info *info)
siccuart_enable_rx_interrupt(info); siccuart_enable_rx_interrupt(info);
info->flags |= ASYNC_INITIALIZED; info->flags |= ASYNC_INITIALIZED;
restore_flags(flags); spin_unlock_irqrestore(&info->state->sicc_lock,flags);
return 0; return 0;
errout: errout:
restore_flags(flags); spin_unlock_irqrestore(&info->state->sicc_lock,flags);
return retval; return retval;
} }
...@@ -708,7 +712,8 @@ static void siccuart_shutdown(struct SICC_info *info) ...@@ -708,7 +712,8 @@ static void siccuart_shutdown(struct SICC_info *info)
if (!(info->flags & ASYNC_INITIALIZED)) if (!(info->flags & ASYNC_INITIALIZED))
return; return;
save_flags(flags); cli(); /* Disable interrupts */ /* lock while shutting down port */
spin_lock_irqsave(&info->state->sicc_lock,flags); /* Disable interrupts */
/* /*
* clear delta_msr_wait queue to avoid mem leaks: we may free the irq * clear delta_msr_wait queue to avoid mem leaks: we may free the irq
...@@ -746,7 +751,7 @@ static void siccuart_shutdown(struct SICC_info *info) ...@@ -746,7 +751,7 @@ static void siccuart_shutdown(struct SICC_info *info)
info->flags &= ~ASYNC_INITIALIZED; info->flags &= ~ASYNC_INITIALIZED;
restore_flags(flags); spin_unlock_irqrestore(&info->state->sicc_lock,flags);
} }
...@@ -868,8 +873,8 @@ static void siccuart_change_speed(struct SICC_info *info, struct termios *old_te ...@@ -868,8 +873,8 @@ static void siccuart_change_speed(struct SICC_info *info, struct termios *old_te
info->ignore_status_mask |= _LSR_OE_MASK; info->ignore_status_mask |= _LSR_OE_MASK;
} }
/* first, disable everything */ /* disable interrupts while reading and clearing registers */
save_flags(flags); cli(); spin_lock_irqsave(&info->state->sicc_lock,flags);
old_rcr = readb(info->port->uart_base + BL_SICC_RCR); old_rcr = readb(info->port->uart_base + BL_SICC_RCR);
old_tcr = readb(info->port->uart_base + BL_SICC_TxCR); old_tcr = readb(info->port->uart_base + BL_SICC_TxCR);
...@@ -881,7 +886,7 @@ static void siccuart_change_speed(struct SICC_info *info, struct termios *old_te ...@@ -881,7 +886,7 @@ static void siccuart_change_speed(struct SICC_info *info, struct termios *old_te
/*RLBtrace (&ppc403Chan0, 0x2000000c, 0, 0);*/ /*RLBtrace (&ppc403Chan0, 0x2000000c, 0, 0);*/
restore_flags(flags); spin_unlock_irqrestore(&info->state->sicc_lock,flags);
/* Set baud rate */ /* Set baud rate */
...@@ -909,12 +914,13 @@ static void siccuart_put_char(struct tty_struct *tty, u_char ch) ...@@ -909,12 +914,13 @@ static void siccuart_put_char(struct tty_struct *tty, u_char ch)
if (!tty || !info->xmit.buf) if (!tty || !info->xmit.buf)
return; return;
save_flags(flags); cli(); /* lock info->xmit while adding character to tx buffer */
spin_lock_irqsave(&info->state->sicc_lock,flags);
if (CIRC_SPACE(info->xmit.head, info->xmit.tail, SICC_XMIT_SIZE) != 0) { if (CIRC_SPACE(info->xmit.head, info->xmit.tail, SICC_XMIT_SIZE) != 0) {
info->xmit.buf[info->xmit.head] = ch; info->xmit.buf[info->xmit.head] = ch;
info->xmit.head = (info->xmit.head + 1) & (SICC_XMIT_SIZE - 1); info->xmit.head = (info->xmit.head + 1) & (SICC_XMIT_SIZE - 1);
} }
restore_flags(flags); spin_unlock_irqrestore(&info->state->sicc_lock,flags);
} }
static void siccuart_flush_chars(struct tty_struct *tty) static void siccuart_flush_chars(struct tty_struct *tty)
...@@ -928,9 +934,10 @@ static void siccuart_flush_chars(struct tty_struct *tty) ...@@ -928,9 +934,10 @@ static void siccuart_flush_chars(struct tty_struct *tty)
|| !info->xmit.buf) || !info->xmit.buf)
return; return;
save_flags(flags); cli(); /* disable interrupts while transmitting characters */
spin_lock_irqsave(&info->state->sicc_lock,flags);
siccuart_enable_tx_interrupt(info); siccuart_enable_tx_interrupt(info);
restore_flags(flags); spin_unlock_irqrestore(&info->state->sicc_lock,flags);
} }
static int siccuart_write(struct tty_struct *tty, static int siccuart_write(struct tty_struct *tty,
...@@ -943,8 +950,8 @@ static int siccuart_write(struct tty_struct *tty, ...@@ -943,8 +950,8 @@ static int siccuart_write(struct tty_struct *tty,
if (!tty || !info->xmit.buf || !tmp_buf) if (!tty || !info->xmit.buf || !tmp_buf)
return 0; return 0;
save_flags(flags); /* lock info->xmit while removing characters from buffer */
cli(); spin_lock_irqsave(&info->state->sicc_lock,flags);
while (1) { while (1) {
c = CIRC_SPACE_TO_END(info->xmit.head, c = CIRC_SPACE_TO_END(info->xmit.head,
info->xmit.tail, info->xmit.tail,
...@@ -960,11 +967,11 @@ static int siccuart_write(struct tty_struct *tty, ...@@ -960,11 +967,11 @@ static int siccuart_write(struct tty_struct *tty,
count -= c; count -= c;
ret += c; ret += c;
} }
restore_flags(flags);
if (info->xmit.head != info->xmit.tail if (info->xmit.head != info->xmit.tail
&& !tty->stopped && !tty->stopped
&& !tty->hw_stopped) && !tty->hw_stopped)
siccuart_enable_tx_interrupt(info); siccuart_enable_tx_interrupt(info);
spin_unlock_irqrestore(&info->state->sicc_lock,flags);
return ret; return ret;
} }
...@@ -988,9 +995,10 @@ static void siccuart_flush_buffer(struct tty_struct *tty) ...@@ -988,9 +995,10 @@ static void siccuart_flush_buffer(struct tty_struct *tty)
unsigned long flags; unsigned long flags;
pr_debug("siccuart_flush_buffer(%d) called\n", tty->index); pr_debug("siccuart_flush_buffer(%d) called\n", tty->index);
save_flags(flags); cli(); /* lock info->xmit while zeroing buffer counts */
spin_lock_irqsave(&info->state->sicc_lock,flags);
info->xmit.head = info->xmit.tail = 0; info->xmit.head = info->xmit.tail = 0;
restore_flags(flags); spin_unlock_irqrestore(&info->state->sicc_lock,flags);
wake_up_interruptible(&tty->write_wait); wake_up_interruptible(&tty->write_wait);
if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) && if ((tty->flags & (1 << TTY_DO_WRITE_WAKEUP)) &&
tty->ldisc.write_wakeup) tty->ldisc.write_wakeup)
...@@ -1019,10 +1027,11 @@ static void siccuart_throttle(struct tty_struct *tty) ...@@ -1019,10 +1027,11 @@ static void siccuart_throttle(struct tty_struct *tty)
siccuart_send_xchar(tty, STOP_CHAR(tty)); siccuart_send_xchar(tty, STOP_CHAR(tty));
if (tty->termios->c_cflag & CRTSCTS) { if (tty->termios->c_cflag & CRTSCTS) {
save_flags(flags); cli(); /* disable interrupts while setting modem control lines */
spin_lock_irqsave(&info->state->sicc_lock,flags);
info->mctrl &= ~TIOCM_RTS; info->mctrl &= ~TIOCM_RTS;
info->port->set_mctrl(info->port, info->mctrl); info->port->set_mctrl(info->port, info->mctrl);
restore_flags(flags); spin_unlock_irqrestore(&info->state->sicc_lock,flags);
} }
} }
...@@ -1039,10 +1048,11 @@ static void siccuart_unthrottle(struct tty_struct *tty) ...@@ -1039,10 +1048,11 @@ static void siccuart_unthrottle(struct tty_struct *tty)
} }
if (tty->termios->c_cflag & CRTSCTS) { if (tty->termios->c_cflag & CRTSCTS) {
save_flags(flags); cli(); /* disable interrupts while setting modem control lines */
spin_lock_irqsave(&info->state->sicc_lock,flags);
info->mctrl |= TIOCM_RTS; info->mctrl |= TIOCM_RTS;
info->port->set_mctrl(info->port, info->mctrl); info->port->set_mctrl(info->port, info->mctrl);
restore_flags(flags); spin_unlock_irqrestore(&info->state->sicc_lock,flags);
} }
} }
...@@ -1181,9 +1191,10 @@ static int get_lsr_info(struct SICC_info *info, unsigned int *value) ...@@ -1181,9 +1191,10 @@ static int get_lsr_info(struct SICC_info *info, unsigned int *value)
unsigned int result, status; unsigned int result, status;
unsigned long flags; unsigned long flags;
save_flags(flags); cli(); /* disable interrupts while reading status from port */
spin_lock_irqsave(&info->state->sicc_lock,flags);
status = readb(info->port->uart_base + BL_SICC_LSR); status = readb(info->port->uart_base + BL_SICC_LSR);
restore_flags(flags); spin_unlock_irqrestore(&info->state->sicc_lock,flags);
result = status & _LSR_TSR_EMPTY ? TIOCSER_TEMT : 0; result = status & _LSR_TSR_EMPTY ? TIOCSER_TEMT : 0;
/* /*
...@@ -1234,10 +1245,11 @@ static int set_modem_info(struct SICC_info *info, unsigned int cmd, ...@@ -1234,10 +1245,11 @@ static int set_modem_info(struct SICC_info *info, unsigned int cmd,
default: default:
return -EINVAL; return -EINVAL;
} }
save_flags(flags); cli(); /* disable interrupts while setting modem control lines */
spin_lock_irqsave(&info->state->sicc_lock,flags);
if (old != info->mctrl) if (old != info->mctrl)
info->port->set_mctrl(info->port, info->mctrl); info->port->set_mctrl(info->port, info->mctrl);
restore_flags(flags); spin_unlock_irqrestore(&info->state->sicc_lock,flags);
return 0; return 0;
} }
...@@ -1248,14 +1260,15 @@ static void siccuart_break_ctl(struct tty_struct *tty, int break_state) ...@@ -1248,14 +1260,15 @@ static void siccuart_break_ctl(struct tty_struct *tty, int break_state)
unsigned int lcr_h; unsigned int lcr_h;
save_flags(flags); cli(); /* disable interrupts while setting break state */
spin_lock_irqsave(&info->state->sicc_lock,flags);
lcr_h = readb(info->port + BL_SICC_LSR); lcr_h = readb(info->port + BL_SICC_LSR);
if (break_state == -1) if (break_state == -1)
lcr_h |= _LSR_LB_MASK; lcr_h |= _LSR_LB_MASK;
else else
lcr_h &= ~_LSR_LB_MASK; lcr_h &= ~_LSR_LB_MASK;
writeb(lcr_h, info->port + BL_SICC_LSRS); writeb(lcr_h, info->port + BL_SICC_LSRS);
restore_flags(flags); spin_unlock_irqrestore(&info->state->sicc_lock,flags);
} }
static int siccuart_ioctl(struct tty_struct *tty, struct file *file, static int siccuart_ioctl(struct tty_struct *tty, struct file *file,
...@@ -1303,9 +1316,10 @@ static int siccuart_ioctl(struct tty_struct *tty, struct file *file, ...@@ -1303,9 +1316,10 @@ static int siccuart_ioctl(struct tty_struct *tty, struct file *file,
* RI where only 0->1 is counted. * RI where only 0->1 is counted.
*/ */
case TIOCGICOUNT: case TIOCGICOUNT:
save_flags(flags); cli(); /* disable interrupts while getting interrupt count */
spin_lock_irqsave(&info->state->sicc_lock,flags);
cnow = info->state->icount; cnow = info->state->icount;
restore_flags(flags); spin_unlock_irqrestore(&info->state->sicc_lock,flags);
icount.cts = cnow.cts; icount.cts = cnow.cts;
icount.dsr = cnow.dsr; icount.dsr = cnow.dsr;
icount.rng = cnow.rng; icount.rng = cnow.rng;
...@@ -1342,22 +1356,24 @@ static void siccuart_set_termios(struct tty_struct *tty, struct termios *old_ter ...@@ -1342,22 +1356,24 @@ static void siccuart_set_termios(struct tty_struct *tty, struct termios *old_ter
/* Handle transition to B0 status */ /* Handle transition to B0 status */
if ((old_termios->c_cflag & CBAUD) && if ((old_termios->c_cflag & CBAUD) &&
!(cflag & CBAUD)) { !(cflag & CBAUD)) {
save_flags(flags); cli(); /* disable interrupts while setting break state */
spin_lock_irqsave(&info->state->sicc_lock,flags);
info->mctrl &= ~(TIOCM_RTS | TIOCM_DTR); info->mctrl &= ~(TIOCM_RTS | TIOCM_DTR);
info->port->set_mctrl(info->port, info->mctrl); info->port->set_mctrl(info->port, info->mctrl);
restore_flags(flags); spin_unlock_irqrestore(&info->state->sicc_lock,flags);
} }
/* Handle transition away from B0 status */ /* Handle transition away from B0 status */
if (!(old_termios->c_cflag & CBAUD) && if (!(old_termios->c_cflag & CBAUD) &&
(cflag & CBAUD)) { (cflag & CBAUD)) {
save_flags(flags); cli(); /* disable interrupts while setting break state */
spin_lock_irqsave(&info->state->sicc_lock,flags);
info->mctrl |= TIOCM_DTR; info->mctrl |= TIOCM_DTR;
if (!(cflag & CRTSCTS) || if (!(cflag & CRTSCTS) ||
!test_bit(TTY_THROTTLED, &tty->flags)) !test_bit(TTY_THROTTLED, &tty->flags))
info->mctrl |= TIOCM_RTS; info->mctrl |= TIOCM_RTS;
info->port->set_mctrl(info->port, info->mctrl); info->port->set_mctrl(info->port, info->mctrl);
restore_flags(flags); spin_unlock_irqrestore(&info->state->sicc_lock,flags);
} }
/* Handle turning off CRTSCTS */ /* Handle turning off CRTSCTS */
...@@ -1393,11 +1409,11 @@ static void siccuart_close(struct tty_struct *tty, struct file *filp) ...@@ -1393,11 +1409,11 @@ static void siccuart_close(struct tty_struct *tty, struct file *filp)
//pr_debug("siccuart_close() called\n"); //pr_debug("siccuart_close() called\n");
save_flags(flags); cli(); /* lock tty->driver_data while closing port */
spin_lock_irqsave(&info->state->sicc_lock,flags);
if (tty_hung_up_p(filp)) { if (tty_hung_up_p(filp)) {
restore_flags(flags); goto quick_close;
return;
} }
if ((tty->count == 1) && (state->count != 1)) { if ((tty->count == 1) && (state->count != 1)) {
...@@ -1416,11 +1432,10 @@ static void siccuart_close(struct tty_struct *tty, struct file *filp) ...@@ -1416,11 +1432,10 @@ static void siccuart_close(struct tty_struct *tty, struct file *filp)
state->count = 0; state->count = 0;
} }
if (state->count) { if (state->count) {
restore_flags(flags); goto quick_close;
return;
} }
info->flags |= ASYNC_CLOSING; info->flags |= ASYNC_CLOSING;
restore_flags(flags); spin_unlock_irqrestore(&info->state->sicc_lock,flags);
/* /*
* Now we wait for the transmit buffer to clear; and we notify * Now we wait for the transmit buffer to clear; and we notify
* the line discipline to only process XON/XOFF characters. * the line discipline to only process XON/XOFF characters.
...@@ -1458,6 +1473,11 @@ static void siccuart_close(struct tty_struct *tty, struct file *filp) ...@@ -1458,6 +1473,11 @@ static void siccuart_close(struct tty_struct *tty, struct file *filp)
} }
info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING); info->flags &= ~(ASYNC_NORMAL_ACTIVE|ASYNC_CLOSING);
wake_up_interruptible(&info->close_wait); wake_up_interruptible(&info->close_wait);
return;
quick_close:
spin_unlock_irqrestore(&info->state->sicc_lock,flags);
return;
} }
static void siccuart_wait_until_sent(struct tty_struct *tty, int timeout) static void siccuart_wait_until_sent(struct tty_struct *tty, int timeout)
...@@ -1569,20 +1589,22 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp, ...@@ -1569,20 +1589,22 @@ static int block_til_ready(struct tty_struct *tty, struct file *filp,
*/ */
retval = 0; retval = 0;
add_wait_queue(&info->open_wait, &wait); add_wait_queue(&info->open_wait, &wait);
save_flags(flags); cli(); /* lock while decrementing state->count */
spin_lock_irqsave(&info->state->sicc_lock,flags);
if (!tty_hung_up_p(filp)) { if (!tty_hung_up_p(filp)) {
extra_count = 1; extra_count = 1;
state->count--; state->count--;
} }
restore_flags(flags); spin_unlock_irqrestore(&info->state->sicc_lock,flags);
info->blocked_open++; info->blocked_open++;
while (1) { while (1) {
save_flags(flags); cli(); /* disable interrupts while setting modem control lines */
spin_lock_irqsave(&info->state->sicc_lock,flags);
if (tty->termios->c_cflag & CBAUD) { if (tty->termios->c_cflag & CBAUD) {
info->mctrl = TIOCM_DTR | TIOCM_RTS; info->mctrl = TIOCM_DTR | TIOCM_RTS;
info->port->set_mctrl(info->port, info->mctrl); info->port->set_mctrl(info->port, info->mctrl);
} }
restore_flags(flags); spin_unlock_irqrestore(&info->state->sicc_lock,flags);
set_current_state(TASK_INTERRUPTIBLE); set_current_state(TASK_INTERRUPTIBLE);
if (tty_hung_up_p(filp) || if (tty_hung_up_p(filp) ||
!(info->flags & ASYNC_INITIALIZED)) { !(info->flags & ASYNC_INITIALIZED)) {
...@@ -1753,6 +1775,7 @@ int __init siccuart_init(void) ...@@ -1753,6 +1775,7 @@ int __init siccuart_init(void)
state->line = i; state->line = i;
state->close_delay = 5 * HZ / 10; state->close_delay = 5 * HZ / 10;
state->closing_wait = 30 * HZ; state->closing_wait = 30 * HZ;
spin_lock_init(&state->sicc_lock);
} }
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment