Commit 6bb0e3a59a089e23eecc0af3b6f6012b2a9affba

Authored by Haavard Skinnemoen
Committed by Linus Torvalds
1 parent 15648f154a

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>

Showing 3 changed files with 14 additions and 0 deletions Side-by-side Diff

Documentation/serial/driver
... ... @@ -186,6 +186,17 @@
186 186 Locking: port_sem taken.
187 187 Interrupts: caller dependent.
188 188  
  189 + flush_buffer(port)
  190 + Flush any write buffers, reset any DMA state and stop any
  191 + ongoing DMA transfers.
  192 +
  193 + This will be called whenever the port->info->xmit circular
  194 + buffer is cleared.
  195 +
  196 + Locking: port->lock taken.
  197 + Interrupts: locally disabled.
  198 + This call must not sleep
  199 +
189 200 set_termios(port,termios,oldtermios)
190 201 Change the port parameters, including word length, parity, stop
191 202 bits. Update read_status_mask and ignore_status_mask to indicate
drivers/serial/serial_core.c
... ... @@ -573,6 +573,8 @@
573 573  
574 574 spin_lock_irqsave(&port->lock, flags);
575 575 uart_circ_clear(&state->info->xmit);
  576 + if (port->ops->flush_buffer)
  577 + port->ops->flush_buffer(port);
576 578 spin_unlock_irqrestore(&port->lock, flags);
577 579 tty_wakeup(tty);
578 580 }
include/linux/serial_core.h
... ... @@ -190,6 +190,7 @@
190 190 void (*break_ctl)(struct uart_port *, int ctl);
191 191 int (*startup)(struct uart_port *);
192 192 void (*shutdown)(struct uart_port *);
  193 + void (*flush_buffer)(struct uart_port *);
193 194 void (*set_termios)(struct uart_port *, struct ktermios *new,
194 195 struct ktermios *old);
195 196 void (*set_ldisc)(struct uart_port *);