diff -Naur old/uart.c new/uart.c --- old/uart.c Mon Sep 15 11:52:02 2003 +++ new/uart.c Mon Sep 15 11:51:32 2003 @@ -44,6 +44,7 @@ #include #include #include +#include #include #include #include @@ -253,6 +254,11 @@ cbd_t *rx_cur; cbd_t *tx_bd_base; cbd_t *tx_cur; + + /* for output synchronization + */ + spinlock_t output_lock; + } ser_info_t; static void change_speed(ser_info_t *info); @@ -1010,6 +1016,7 @@ { ser_info_t *info = (ser_info_t *)tty->driver_data; volatile cbd_t *bdp; + unsigned long flags; if (serial_paranoia_check(info, tty->device, "rs_put_char")) return; @@ -1017,6 +1024,8 @@ if (!tty) return; + spin_lock_irqsave(&(info->output_lock), flags); + bdp = info->tx_cur; while (bdp->cbd_sc & BD_SC_READY); @@ -1033,6 +1042,8 @@ info->tx_cur = (cbd_t *)bdp; + spin_unlock_irqrestore(&(info->output_lock), flags); + } static int rs_8xx_write(struct tty_struct * tty, int from_user, @@ -1041,6 +1052,7 @@ int c, ret = 0; ser_info_t *info = (ser_info_t *)tty->driver_data; volatile cbd_t *bdp; + unsigned long flags; if (serial_paranoia_check(info, tty->device, "rs_write")) return 0; @@ -1048,6 +1060,8 @@ if (!tty) return 0; + spin_lock_irqsave(&(info->output_lock), flags); + bdp = info->tx_cur; while (1) { @@ -1086,6 +1100,9 @@ bdp++; info->tx_cur = (cbd_t *)bdp; } + + spin_unlock_irqrestore(&(info->output_lock), flags); + return ret; } @@ -1143,12 +1160,15 @@ static void rs_8xx_send_xchar(struct tty_struct *tty, char ch) { volatile cbd_t *bdp; + unsigned long flags; ser_info_t *info = (ser_info_t *)tty->driver_data; if (serial_paranoia_check(info, tty->device, "rs_send_char")) return; + spin_lock_irqsave(&(info->output_lock), flags); + bdp = info->tx_cur; while (bdp->cbd_sc & BD_SC_READY); @@ -1164,6 +1184,8 @@ bdp++; info->tx_cur = (cbd_t *)bdp; + + spin_unlock_irqrestore(&(info->output_lock), flags); } /* @@ -2227,9 +2249,11 @@ volatile cbd_t *bdp, *bdbase; volatile smc_uart_t *up; volatile u_char *cp; + unsigned long flags; ser = rs_table + idx; + /* If the port has been initialized for general use, we have * to use the buffer descriptors allocated there. Otherwise, * we simply use the single buffer allocated. @@ -2237,6 +2261,7 @@ if ((info = (ser_info_t *)ser->info) != NULL) { bdp = info->tx_cur; bdbase = info->tx_bd_base; + spin_lock_irqsave(&(info->output_lock), flags); } else { /* Pointer to UART in parameter ram. @@ -2309,6 +2334,9 @@ if (info) info->tx_cur = (cbd_t *)bdp; + + if (info) + spin_unlock_irqrestore(&(info->output_lock), flags); } static void serial_console_write(struct console *c, const char *s, @@ -2764,6 +2792,7 @@ info->tqueue_hangup.data = info; info->line = i; info->state = state; + spin_lock_init(&(info->output_lock)); state->info = (struct async_struct *)info; /* We need to allocate a transmit and receive buffer