summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorHaavard Skinnemoen <haavard.skinnemoen@atmel.com>2008-07-16 21:52:36 +0100
committerLinus Torvalds <torvalds@linux-foundation.org>2008-07-20 17:12:34 -0700
commit6bb0e3a59a089e23eecc0af3b6f6012b2a9affba (patch)
tree06790c1e5a3505b9d790506710d59d88c780f819
parent15648f154a8faea97cbe931e189cf0a57fd066f4 (diff)
Subject: [PATCH 1/2] serial: Add flush_buffer() operation to uart_ops
Serial drivers using DMA (like the atmel_serial 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. Signed-off-by: Haavard Skinnemoen <haavard.skinnemoen@atmel.com> Acked-by: Alan Cox <alan@redhat.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--Documentation/serial/driver11
-rw-r--r--drivers/serial/serial_core.c2
-rw-r--r--include/linux/serial_core.h1
3 files changed, 14 insertions, 0 deletions
diff --git a/Documentation/serial/driver b/Documentation/serial/driver
index 88ad615dd338..77ba0afbe4db 100644
--- a/Documentation/serial/driver
+++ b/Documentation/serial/driver
@@ -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
diff --git a/drivers/serial/serial_core.c b/drivers/serial/serial_core.c
index 42d2e108b679..9884bc9eecb1 100644
--- a/drivers/serial/serial_core.c
+++ b/drivers/serial/serial_core.c
@@ -573,6 +573,8 @@ static void uart_flush_buffer(struct tty_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);
}
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index d8f31de632c5..1d2faa6592ae 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -190,6 +190,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 ktermios *new,
struct ktermios *old);
void (*set_ldisc)(struct uart_port *);