summaryrefslogtreecommitdiff
path: root/drivers/tty/serial
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/tty/serial')
-rw-r--r--drivers/tty/serial/samsung.c36
1 files changed, 21 insertions, 15 deletions
diff --git a/drivers/tty/serial/samsung.c b/drivers/tty/serial/samsung.c
index faee021c27b0..856686d6dcdb 100644
--- a/drivers/tty/serial/samsung.c
+++ b/drivers/tty/serial/samsung.c
@@ -294,15 +294,6 @@ static int s3c24xx_serial_start_tx_dma(struct s3c24xx_uart_port *ourport,
if (ourport->tx_mode != S3C24XX_TX_DMA)
enable_tx_dma(ourport);
- while (xmit->tail & (dma_get_cache_alignment() - 1)) {
- if (rd_regl(port, S3C2410_UFSTAT) & ourport->info->tx_fifofull)
- return 0;
- wr_regb(port, S3C2410_UTXH, xmit->buf[xmit->tail]);
- xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
- port->icount.tx++;
- count--;
- }
-
dma->tx_size = count & ~(dma_get_cache_alignment() - 1);
dma->tx_transfer_addr = dma->tx_addr + xmit->tail;
@@ -342,7 +333,8 @@ static void s3c24xx_serial_start_next_tx(struct s3c24xx_uart_port *ourport)
}
if (!ourport->dma || !ourport->dma->tx_chan ||
- count < ourport->min_dma_size)
+ count < ourport->min_dma_size ||
+ xmit->tail & (dma_get_cache_alignment() - 1))
s3c24xx_serial_start_tx_pio(ourport);
else
s3c24xx_serial_start_tx_dma(ourport, count);
@@ -736,7 +728,7 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)
struct uart_port *port = &ourport->port;
struct circ_buf *xmit = &port->state->xmit;
unsigned long flags;
- int count;
+ int count, dma_count = 0;
spin_lock_irqsave(&port->lock, flags);
@@ -744,8 +736,12 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)
if (ourport->dma && ourport->dma->tx_chan &&
count >= ourport->min_dma_size) {
- s3c24xx_serial_start_tx_dma(ourport, count);
- goto out;
+ int align = dma_get_cache_alignment() -
+ (xmit->tail & (dma_get_cache_alignment() - 1));
+ if (count-align >= ourport->min_dma_size) {
+ dma_count = count-align;
+ count = align;
+ }
}
if (port->x_char) {
@@ -766,14 +762,24 @@ static irqreturn_t s3c24xx_serial_tx_chars(int irq, void *id)
/* try and drain the buffer... */
- count = port->fifosize;
- while (!uart_circ_empty(xmit) && count-- > 0) {
+ if (count > port->fifosize) {
+ count = port->fifosize;
+ dma_count = 0;
+ }
+
+ while (!uart_circ_empty(xmit) && count > 0) {
if (rd_regl(port, S3C2410_UFSTAT) & ourport->info->tx_fifofull)
break;
wr_regb(port, S3C2410_UTXH, xmit->buf[xmit->tail]);
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
port->icount.tx++;
+ count--;
+ }
+
+ if (!count && dma_count) {
+ s3c24xx_serial_start_tx_dma(ourport, dma_count);
+ goto out;
}
if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) {