aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMichael Trimarchi <trimarchimichael@yahoo.it>2008-04-02 16:04:41 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2008-04-02 18:28:19 -0400
commitba0657ff0527bab83387e19eb98b423fcc290674 (patch)
treee7644086f7425033950980bdae8a457ab151503a
parentdd135ebbd2a6b5e07dadb66c4dd033bb69531051 (diff)
atmel_serial: avoid stopping pdc during transmission
I found a problem related to losing data during pdc transmission in atmel_serial: connect ttyS1 with ttyS2 using a loopback cable, send 30 byte of packet from one to the other and waiting for 30 byte. On the other side just read and echo the data received. We always call atmel_tx_dma() from the tasklet regardless of what interrupt triggered it. Signed-off-by: michael <trimarchi@gandalf.sssup.it> Acked-by: Haavard Skinnemoen <hskinnemoen@atmel.com> Signed-off-by: Andrew Morton <akpm@linux-foundation.org> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
-rw-r--r--drivers/serial/atmel_serial.c19
1 files changed, 10 insertions, 9 deletions
diff --git a/drivers/serial/atmel_serial.c b/drivers/serial/atmel_serial.c
index d57bf3e708d8..e99a28387505 100644
--- a/drivers/serial/atmel_serial.c
+++ b/drivers/serial/atmel_serial.c
@@ -96,6 +96,7 @@
96 96
97 /* PDC registers */ 97 /* PDC registers */
98#define UART_PUT_PTCR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_PTCR) 98#define UART_PUT_PTCR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_PTCR)
99#define UART_GET_TCR(port) __raw_readl((port)->membase + ATMEL_PDC_TCR)
99#define UART_GET_PTSR(port) __raw_readl((port)->membase + ATMEL_PDC_PTSR) 100#define UART_GET_PTSR(port) __raw_readl((port)->membase + ATMEL_PDC_PTSR)
100 101
101#define UART_PUT_RPR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_RPR) 102#define UART_PUT_RPR(port,v) __raw_writel(v, (port)->membase + ATMEL_PDC_RPR)
@@ -562,17 +563,22 @@ static void atmel_tx_dma(struct uart_port *port)
562 struct atmel_dma_buffer *pdc = &atmel_port->pdc_tx; 563 struct atmel_dma_buffer *pdc = &atmel_port->pdc_tx;
563 int count; 564 int count;
564 565
566 /* nothing left to transmit? */
567 if (UART_GET_TCR(port))
568 return;
569
565 xmit->tail += pdc->ofs; 570 xmit->tail += pdc->ofs;
566 xmit->tail &= UART_XMIT_SIZE - 1; 571 xmit->tail &= UART_XMIT_SIZE - 1;
567 572
568 port->icount.tx += pdc->ofs; 573 port->icount.tx += pdc->ofs;
569 pdc->ofs = 0; 574 pdc->ofs = 0;
570 575
571 if (!uart_circ_empty(xmit)) { 576 /* more to transmit - setup next transfer */
572 /* more to transmit - setup next transfer */
573 577
574 /* disable PDC transmit */ 578 /* disable PDC transmit */
575 UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS); 579 UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS);
580
581 if (!uart_circ_empty(xmit)) {
576 dma_sync_single_for_device(port->dev, 582 dma_sync_single_for_device(port->dev,
577 pdc->dma_addr, 583 pdc->dma_addr,
578 pdc->dma_size, 584 pdc->dma_size,
@@ -586,11 +592,6 @@ static void atmel_tx_dma(struct uart_port *port)
586 /* re-enable PDC transmit and interrupts */ 592 /* re-enable PDC transmit and interrupts */
587 UART_PUT_PTCR(port, ATMEL_PDC_TXTEN); 593 UART_PUT_PTCR(port, ATMEL_PDC_TXTEN);
588 UART_PUT_IER(port, ATMEL_US_ENDTX | ATMEL_US_TXBUFE); 594 UART_PUT_IER(port, ATMEL_US_ENDTX | ATMEL_US_TXBUFE);
589 } else {
590 /* nothing left to transmit - disable the transmitter */
591
592 /* disable PDC transmit */
593 UART_PUT_PTCR(port, ATMEL_PDC_TXTDIS);
594 } 595 }
595 596
596 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) 597 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)