|
@@ -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) {
|