From nobody Mon Sep 17 00:00:00 2001 From: HÃ¥vard Skinnemoen Date: Thu Feb 2 15:48:50 2006 +0100 Subject: [PATCH] Add flush_buffer() operation to uart_ops Serial drivers using DMA (like the Atmel USART3 driver) tend to get very confused when the xmit buffer is flushed and nobody told them. They also tend to spew a lot of garbage since the DMA engine keeps running after the buffer is flushed and possibly refilled with unrelated data. This patch adds a new flush_buffer operation to the uart_ops struct, along with a call to it from uart_flush_buffer() right after the xmit buffer has been cleared. The driver can implement this in order to syncronize its internal DMA state with the xmit buffer when the buffer is flushed. --- Documentation/serial/driver | 11 +++++++++++ drivers/serial/serial_core.c | 2 ++ include/linux/serial_core.h | 1 + 3 files changed, 14 insertions(+) Index: linux-2.6.16-avr32/Documentation/serial/driver =================================================================== --- linux-2.6.16-avr32.orig/Documentation/serial/driver 2006-03-20 06:53:29.000000000 +0100 +++ linux-2.6.16-avr32/Documentation/serial/driver 2006-04-03 18:57:11.000000000 +0200 @@ -186,6 +186,17 @@ hardware. Locking: port_sem taken. Interrupts: caller dependent. + flush_buffer(port) + Flush any write buffers, reset any DMA state and stop any + ongoing DMA transfers. + + This will be called whenever the port->info->xmit circular + buffer is cleared. + + Locking: port->lock taken. + Interrupts: locally disabled. + This call must not sleep + set_termios(port,termios,oldtermios) Change the port parameters, including word length, parity, stop bits. Update read_status_mask and ignore_status_mask to indicate Index: linux-2.6.16-avr32/drivers/serial/serial_core.c =================================================================== --- linux-2.6.16-avr32.orig/drivers/serial/serial_core.c 2006-03-20 06:53:29.000000000 +0100 +++ linux-2.6.16-avr32/drivers/serial/serial_core.c 2006-04-03 18:57:11.000000000 +0200 @@ -556,6 +556,8 @@ static void uart_flush_buffer(struct tty spin_lock_irqsave(&port->lock, flags); uart_circ_clear(&state->info->xmit); + if (port->ops->flush_buffer) + port->ops->flush_buffer(port); spin_unlock_irqrestore(&port->lock, flags); tty_wakeup(tty); } Index: linux-2.6.16-avr32/include/linux/serial_core.h =================================================================== --- linux-2.6.16-avr32.orig/include/linux/serial_core.h 2006-03-20 06:53:29.000000000 +0100 +++ linux-2.6.16-avr32/include/linux/serial_core.h 2006-04-03 18:57:11.000000000 +0200 @@ -164,6 +164,7 @@ struct uart_ops { void (*break_ctl)(struct uart_port *, int ctl); int (*startup)(struct uart_port *); void (*shutdown)(struct uart_port *); + void (*flush_buffer)(struct uart_port *); void (*set_termios)(struct uart_port *, struct termios *new, struct termios *old); void (*pm)(struct uart_port *, unsigned int state,