aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/serial/bfin_5xx.c
diff options
context:
space:
mode:
authorSonic Zhang <sonic.zhang@analog.com>2008-02-25 02:16:50 -0500
committerBryan Wu <cooloney@kernel.org>2008-02-25 02:16:50 -0500
commit0711d857605ba598cd6d4254462d1419b233321b (patch)
treecb8793180ab496b299eaab0c21fc29fb6f3e763b /drivers/serial/bfin_5xx.c
parentdb288381e26e592b11572ce8199bedeadf0c0830 (diff)
Blackfin Serial Driver: Fix bug - Increase buffer tail immediately before starting tx dma.
http://blackfin.uclinux.org/gf/project/uclinux-dist/tracker/?action=TrackerItemEdit&tracker_item_id=2920 Signed-off-by: Sonic Zhang <sonic.zhang@analog.com> Signed-off-by: Bryan Wu <cooloney@kernel.org>
Diffstat (limited to 'drivers/serial/bfin_5xx.c')
-rw-r--r--drivers/serial/bfin_5xx.c32
1 files changed, 18 insertions, 14 deletions
diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c
index 69ac7007682e..2fb3081c5022 100644
--- a/drivers/serial/bfin_5xx.c
+++ b/drivers/serial/bfin_5xx.c
@@ -64,15 +64,20 @@ static void bfin_serial_mctrl_check(struct bfin_serial_port *uart);
64static void bfin_serial_stop_tx(struct uart_port *port) 64static void bfin_serial_stop_tx(struct uart_port *port)
65{ 65{
66 struct bfin_serial_port *uart = (struct bfin_serial_port *)port; 66 struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
67 struct circ_buf *xmit = &uart->port.info->xmit;
67#if !defined(CONFIG_BF54x) && !defined(CONFIG_SERIAL_BFIN_DMA) 68#if !defined(CONFIG_BF54x) && !defined(CONFIG_SERIAL_BFIN_DMA)
68 unsigned short ier; 69 unsigned short ier;
69#endif 70#endif
70 71
71 while (!(UART_GET_LSR(uart) & TEMT)) 72 while (!(UART_GET_LSR(uart) & TEMT))
72 continue; 73 cpu_relax();
73 74
74#ifdef CONFIG_SERIAL_BFIN_DMA 75#ifdef CONFIG_SERIAL_BFIN_DMA
75 disable_dma(uart->tx_dma_channel); 76 disable_dma(uart->tx_dma_channel);
77 xmit->tail = (xmit->tail + uart->tx_count) & (UART_XMIT_SIZE - 1);
78 uart->port.icount.tx += uart->tx_count;
79 uart->tx_count = 0;
80 uart->tx_done = 1;
76#else 81#else
77#ifdef CONFIG_BF54x 82#ifdef CONFIG_BF54x
78 /* Clear TFI bit */ 83 /* Clear TFI bit */
@@ -94,7 +99,8 @@ static void bfin_serial_start_tx(struct uart_port *port)
94 struct bfin_serial_port *uart = (struct bfin_serial_port *)port; 99 struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
95 100
96#ifdef CONFIG_SERIAL_BFIN_DMA 101#ifdef CONFIG_SERIAL_BFIN_DMA
97 bfin_serial_dma_tx_chars(uart); 102 if (uart->tx_done)
103 bfin_serial_dma_tx_chars(uart);
98#else 104#else
99#ifdef CONFIG_BF54x 105#ifdef CONFIG_BF54x
100 UART_SET_IER(uart, ETBEI); 106 UART_SET_IER(uart, ETBEI);
@@ -389,12 +395,10 @@ static void bfin_serial_dma_tx_chars(struct bfin_serial_port *uart)
389 unsigned short ier; 395 unsigned short ier;
390 int flags = 0; 396 int flags = 0;
391 397
392 if (!uart->tx_done)
393 return;
394 uart->tx_done = 0; 398 uart->tx_done = 0;
395 399
396 if (uart_circ_empty(xmit) || uart_tx_stopped(&uart->port)) { 400 if (uart_circ_empty(xmit) || uart_tx_stopped(&uart->port)) {
397 bfin_serial_stop_tx(&uart->port); 401 uart->tx_count = 0;
398 uart->tx_done = 1; 402 uart->tx_done = 1;
399 return; 403 return;
400 } 404 }
@@ -428,9 +432,6 @@ static void bfin_serial_dma_tx_chars(struct bfin_serial_port *uart)
428 set_dma_x_modify(uart->tx_dma_channel, 1); 432 set_dma_x_modify(uart->tx_dma_channel, 1);
429 enable_dma(uart->tx_dma_channel); 433 enable_dma(uart->tx_dma_channel);
430 434
431 xmit->tail = (xmit->tail + uart->tx_count) & (UART_XMIT_SIZE - 1);
432 uart->port.icount.tx += uart->tx_count;
433
434#ifdef CONFIG_BF54x 435#ifdef CONFIG_BF54x
435 UART_SET_IER(uart, ETBEI); 436 UART_SET_IER(uart, ETBEI);
436#else 437#else
@@ -515,8 +516,8 @@ static irqreturn_t bfin_serial_dma_tx_int(int irq, void *dev_id)
515 516
516 spin_lock(&uart->port.lock); 517 spin_lock(&uart->port.lock);
517 if (!(get_dma_curr_irqstat(uart->tx_dma_channel)&DMA_RUN)) { 518 if (!(get_dma_curr_irqstat(uart->tx_dma_channel)&DMA_RUN)) {
518 clear_dma_irqstat(uart->tx_dma_channel);
519 disable_dma(uart->tx_dma_channel); 519 disable_dma(uart->tx_dma_channel);
520 clear_dma_irqstat(uart->tx_dma_channel);
520#ifdef CONFIG_BF54x 521#ifdef CONFIG_BF54x
521 UART_CLEAR_IER(uart, ETBEI); 522 UART_CLEAR_IER(uart, ETBEI);
522#else 523#else
@@ -527,7 +528,8 @@ static irqreturn_t bfin_serial_dma_tx_int(int irq, void *dev_id)
527 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) 528 if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
528 uart_write_wakeup(&uart->port); 529 uart_write_wakeup(&uart->port);
529 530
530 uart->tx_done = 1; 531 xmit->tail = (xmit->tail + uart->tx_count) & (UART_XMIT_SIZE - 1);
532 uart->port.icount.tx += uart->tx_count;
531 533
532 bfin_serial_dma_tx_chars(uart); 534 bfin_serial_dma_tx_chars(uart);
533 } 535 }
@@ -542,12 +544,14 @@ static irqreturn_t bfin_serial_dma_rx_int(int irq, void *dev_id)
542 unsigned short irqstat; 544 unsigned short irqstat;
543 545
544 uart->rx_dma_nrows++; 546 uart->rx_dma_nrows++;
545 if (uart->rx_dma_nrows == DMA_RX_YCOUNT) { 547 uart->rx_dma_buf.tail = DMA_RX_XCOUNT * uart->rx_dma_nrows;
548 bfin_serial_dma_rx_chars(uart);
549 if (uart->rx_dma_nrows >= DMA_RX_YCOUNT) {
546 uart->rx_dma_nrows = 0; 550 uart->rx_dma_nrows = 0;
547 uart->rx_dma_buf.tail = DMA_RX_XCOUNT*DMA_RX_YCOUNT; 551 uart->rx_dma_buf.tail = 0;
548 bfin_serial_dma_rx_chars(uart);
549 uart->rx_dma_buf.head = uart->rx_dma_buf.tail = 0;
550 } 552 }
553 uart->rx_dma_buf.head = uart->rx_dma_buf.tail;
554
551 spin_lock(&uart->port.lock); 555 spin_lock(&uart->port.lock);
552 irqstat = get_dma_curr_irqstat(uart->rx_dma_channel); 556 irqstat = get_dma_curr_irqstat(uart->rx_dma_channel);
553 clear_dma_irqstat(uart->rx_dma_channel); 557 clear_dma_irqstat(uart->rx_dma_channel);