@@ -147,6 +147,8 @@ struct max3100_port {
struct work_struct console_work;
/* char tx timeout */
int console_tout;
+ /* lock on receiving chars */
+ struct mutex rx_lock;
#endif
};
@@ -192,6 +194,19 @@ static void max3100_calc_parity(struct max3100_port *s, u16 *c)
*c |= max3100_do_parity(s, *c) << 8;
}
+static void max3100_flip(struct max3100_port *s)
+{
+ if (s->port.state->port.tty != NULL) {
+#ifdef CONFIG_SERIAL_MAX3100_CONSOLE
+ mutex_lock(&s->rx_lock);
+#endif
+ tty_flip_buffer_push(s->port.state->port.tty);
+#ifdef CONFIG_SERIAL_MAX3100_CONSOLE
+ mutex_unlock(&s->rx_lock);
+#endif
+ }
+}
+
static void max3100_resume_work(struct work_struct *w)
{
struct max3100_port *s = container_of(w, struct max3100_port,
@@ -242,6 +257,10 @@ static int max3100_handlerx(struct max3100_port *s, u16 rx)
unsigned int ch, flg, status = 0;
int ret = 0, cts;
+#ifdef CONFIG_SERIAL_MAX3100_CONSOLE
+ mutex_lock(&s->rx_lock);
+#endif
+
if (rx & MAX3100_R && s->rx_enabled) {
dev_dbg(&s->spi->dev, "%s\n", __func__);
ch = rx & (s->parity & MAX3100_7BIT ? 0x7f : 0xff);
@@ -274,6 +293,10 @@ static int max3100_handlerx(struct max3100_port *s, u16 rx)
uart_handle_cts_change(&s->port, cts ? TIOCM_CTS : 0);
}
+#ifdef CONFIG_SERIAL_MAX3100_CONSOLE
+ mutex_unlock(&s->rx_lock);
+#endif
+
return ret;
}
@@ -329,8 +352,8 @@ static irqreturn_t max3100_ist(int irq, void *dev_id)
}
}
- if (rxchars > 16 && s->port.state->port.tty != NULL) {
- tty_flip_buffer_push(s->port.state->port.tty);
+ if (rxchars > 16) {
+ max3100_flip(s);
rxchars = 0;
}
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
@@ -341,8 +364,8 @@ static irqreturn_t max3100_ist(int irq, void *dev_id)
(!uart_circ_empty(xmit) &&
!uart_tx_stopped(&s->port))));
- if (rxchars > 0 && s->port.state->port.tty != NULL)
- tty_flip_buffer_push(s->port.state->port.tty);
+ if (rxchars > 0)
+ max3100_flip(s);
return IRQ_HANDLED;
}
@@ -699,6 +722,7 @@ static void max3100_console_work(struct work_struct *w)
console_work);
unsigned long start;
u16 tx, rx;
+ int rxchars = 0;
while (s->console_head != s->console_tail &&
(s->console_flags & MAX3100_SUSPENDING) == 0) {
@@ -710,10 +734,19 @@ static void max3100_console_work(struct work_struct *w)
!time_after(jiffies, start + s->console_tout));
tx = s->console_buf[s->console_tail];
max3100_calc_parity(s, &tx);
- tx |= MAX3100_WD | MAX3100_RTS;
+ tx |= MAX3100_WD | (s->rts ? MAX3100_RTS : 0);
max3100_sr(s, tx, &rx);
+ if (s->port.state->port.tty != NULL) {
+ rxchars += max3100_handlerx(s, rx);
+ if (rxchars > 16) {
+ max3100_flip(s);
+ rxchars = 0;
+ }
+ }
s->console_tail = (s->console_tail + 1) % CONSOLE_BUF_SIZE;
}
+ if (rxchars)
+ max3100_flip(s);
}
static void max3100_console_putchar(struct uart_port *port, int ch)
@@ -809,6 +842,10 @@ static int max3100_console_setup(struct console *co, char *options)
if (parity == 'o')
s->parity |= MAX3100_PARITY_ODD;
s->console_tout = 1 + (20 * HZ) / baud; /* jiffies to send 20 bits */
+ if (flow != 'n')
+ s->rts = 1;
+ else
+ s->rts = 0;
tx |= MAX3100_WC;
max3100_sr(s, tx, &rx);
@@ -912,6 +949,7 @@ static int __devinit max3100_probe(struct spi_device *spi)
i, retval);
#ifdef CONFIG_SERIAL_MAX3100_CONSOLE
+ mutex_init(&max3100s[i]->rx_lock);
if (pdata->console && !max3100_console_registered) {
register_console(&max3100_console);
max3100_console_registered = 1;