diff options
| author | Sonic Zhang <sonic.zhang@analog.com> | 2008-02-25 02:19:09 -0500 |
|---|---|---|
| committer | Bryan Wu <cooloney@kernel.org> | 2008-02-25 02:19:09 -0500 |
| commit | 56f5de8fe7c127f6fb94b7a061d53090fd4a1c49 (patch) | |
| tree | 1c3a737c980f9c11b038cd6d72664c857fc941bb | |
| parent | 0711d857605ba598cd6d4254462d1419b233321b (diff) | |
Blackfin Serial Driver: Fix bug - update tx dma buffer tail before wake up processes.
Also make rx dma buffer work as a loop.
Signed-off-by: Sonic Zhang <sonic.zhang@analog.com>
Signed-off-by: Bryan Wu <cooloney@kernel.org>
| -rw-r--r-- | drivers/serial/bfin_5xx.c | 51 |
1 files changed, 29 insertions, 22 deletions
diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c index 2fb3081c5022..2a4117485799 100644 --- a/drivers/serial/bfin_5xx.c +++ b/drivers/serial/bfin_5xx.c | |||
| @@ -415,7 +415,6 @@ static void bfin_serial_dma_tx_chars(struct bfin_serial_port *uart) | |||
| 415 | */ | 415 | */ |
| 416 | bfin_serial_mctrl_check(uart); | 416 | bfin_serial_mctrl_check(uart); |
| 417 | 417 | ||
| 418 | spin_lock_irqsave(&uart->port.lock, flags); | ||
| 419 | uart->tx_count = CIRC_CNT(xmit->head, xmit->tail, UART_XMIT_SIZE); | 418 | uart->tx_count = CIRC_CNT(xmit->head, xmit->tail, UART_XMIT_SIZE); |
| 420 | if (uart->tx_count > (UART_XMIT_SIZE - xmit->tail)) | 419 | if (uart->tx_count > (UART_XMIT_SIZE - xmit->tail)) |
| 421 | uart->tx_count = UART_XMIT_SIZE - xmit->tail; | 420 | uart->tx_count = UART_XMIT_SIZE - xmit->tail; |
| @@ -439,7 +438,6 @@ static void bfin_serial_dma_tx_chars(struct bfin_serial_port *uart) | |||
| 439 | ier |= ETBEI; | 438 | ier |= ETBEI; |
| 440 | UART_PUT_IER(uart, ier); | 439 | UART_PUT_IER(uart, ier); |
| 441 | #endif | 440 | #endif |
| 442 | spin_unlock_irqrestore(&uart->port.lock, flags); | ||
| 443 | } | 441 | } |
| 444 | 442 | ||
| 445 | static void bfin_serial_dma_rx_chars(struct bfin_serial_port *uart) | 443 | static void bfin_serial_dma_rx_chars(struct bfin_serial_port *uart) |
| @@ -450,7 +448,9 @@ static void bfin_serial_dma_rx_chars(struct bfin_serial_port *uart) | |||
| 450 | status = UART_GET_LSR(uart); | 448 | status = UART_GET_LSR(uart); |
| 451 | UART_CLEAR_LSR(uart); | 449 | UART_CLEAR_LSR(uart); |
| 452 | 450 | ||
| 453 | uart->port.icount.rx += CIRC_CNT(uart->rx_dma_buf.head, uart->rx_dma_buf.tail, UART_XMIT_SIZE);; | 451 | uart->port.icount.rx += |
| 452 | CIRC_CNT(uart->rx_dma_buf.head, uart->rx_dma_buf.tail, | ||
| 453 | UART_XMIT_SIZE); | ||
| 454 | 454 | ||
| 455 | if (status & BI) { | 455 | if (status & BI) { |
| 456 | uart->port.icount.brk++; | 456 | uart->port.icount.brk++; |
| @@ -476,10 +476,12 @@ static void bfin_serial_dma_rx_chars(struct bfin_serial_port *uart) | |||
| 476 | else | 476 | else |
| 477 | flg = TTY_NORMAL; | 477 | flg = TTY_NORMAL; |
| 478 | 478 | ||
| 479 | for (i = uart->rx_dma_buf.head; i < uart->rx_dma_buf.tail; i++) { | 479 | for (i = uart->rx_dma_buf.tail; i != uart->rx_dma_buf.head; i++) { |
| 480 | if (uart_handle_sysrq_char(&uart->port, uart->rx_dma_buf.buf[i])) | 480 | if (i >= UART_XMIT_SIZE) |
| 481 | goto dma_ignore_char; | 481 | i = 0; |
| 482 | uart_insert_char(&uart->port, status, OE, uart->rx_dma_buf.buf[i], flg); | 482 | if (!uart_handle_sysrq_char(&uart->port, uart->rx_dma_buf.buf[i])) |
| 483 | uart_insert_char(&uart->port, status, OE, | ||
| 484 | uart->rx_dma_buf.buf[i], flg); | ||
| 483 | } | 485 | } |
| 484 | 486 | ||
| 485 | dma_ignore_char: | 487 | dma_ignore_char: |
| @@ -492,16 +494,20 @@ void bfin_serial_rx_dma_timeout(struct bfin_serial_port *uart) | |||
| 492 | int flags = 0; | 494 | int flags = 0; |
| 493 | 495 | ||
| 494 | spin_lock_irqsave(&uart->port.lock, flags); | 496 | spin_lock_irqsave(&uart->port.lock, flags); |
| 495 | x_pos = DMA_RX_XCOUNT - get_dma_curr_xcount(uart->rx_dma_channel); | 497 | uart->rx_dma_nrows = get_dma_curr_ycount(uart->rx_dma_channel); |
| 498 | x_pos = get_dma_curr_xcount(uart->rx_dma_channel); | ||
| 499 | uart->rx_dma_nrows = DMA_RX_YCOUNT - uart->rx_dma_nrows; | ||
| 500 | if (uart->rx_dma_nrows == DMA_RX_YCOUNT) | ||
| 501 | uart->rx_dma_nrows = 0; | ||
| 502 | x_pos = DMA_RX_XCOUNT - x_pos; | ||
| 496 | if (x_pos == DMA_RX_XCOUNT) | 503 | if (x_pos == DMA_RX_XCOUNT) |
| 497 | x_pos = 0; | 504 | x_pos = 0; |
| 498 | 505 | ||
| 499 | pos = uart->rx_dma_nrows * DMA_RX_XCOUNT + x_pos; | 506 | pos = uart->rx_dma_nrows * DMA_RX_XCOUNT + x_pos; |
| 500 | 507 | if (pos != uart->rx_dma_buf.tail) { | |
| 501 | if (pos>uart->rx_dma_buf.tail) { | 508 | uart->rx_dma_buf.head = pos; |
| 502 | uart->rx_dma_buf.tail = pos; | ||
| 503 | bfin_serial_dma_rx_chars(uart); | 509 | bfin_serial_dma_rx_chars(uart); |
| 504 | uart->rx_dma_buf.head = uart->rx_dma_buf.tail; | 510 | uart->rx_dma_buf.tail = uart->rx_dma_buf.head; |
| 505 | } | 511 | } |
| 506 | spin_unlock_irqrestore(&uart->port.lock, flags); | 512 | spin_unlock_irqrestore(&uart->port.lock, flags); |
| 507 | uart->rx_dma_timer.expires = jiffies + DMA_RX_FLUSH_JIFFIES; | 513 | uart->rx_dma_timer.expires = jiffies + DMA_RX_FLUSH_JIFFIES; |
| @@ -525,12 +531,12 @@ static irqreturn_t bfin_serial_dma_tx_int(int irq, void *dev_id) | |||
| 525 | ier &= ~ETBEI; | 531 | ier &= ~ETBEI; |
| 526 | UART_PUT_IER(uart, ier); | 532 | UART_PUT_IER(uart, ier); |
| 527 | #endif | 533 | #endif |
| 528 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | ||
| 529 | uart_write_wakeup(&uart->port); | ||
| 530 | |||
| 531 | xmit->tail = (xmit->tail + uart->tx_count) & (UART_XMIT_SIZE - 1); | 534 | xmit->tail = (xmit->tail + uart->tx_count) & (UART_XMIT_SIZE - 1); |
| 532 | uart->port.icount.tx += uart->tx_count; | 535 | uart->port.icount.tx += uart->tx_count; |
| 533 | 536 | ||
| 537 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | ||
| 538 | uart_write_wakeup(&uart->port); | ||
| 539 | |||
| 534 | bfin_serial_dma_tx_chars(uart); | 540 | bfin_serial_dma_tx_chars(uart); |
| 535 | } | 541 | } |
| 536 | 542 | ||
| @@ -542,15 +548,16 @@ static irqreturn_t bfin_serial_dma_rx_int(int irq, void *dev_id) | |||
| 542 | { | 548 | { |
| 543 | struct bfin_serial_port *uart = dev_id; | 549 | struct bfin_serial_port *uart = dev_id; |
| 544 | unsigned short irqstat; | 550 | unsigned short irqstat; |
| 551 | int pos; | ||
| 545 | 552 | ||
| 546 | uart->rx_dma_nrows++; | 553 | uart->rx_dma_nrows = DMA_RX_YCOUNT - |
| 547 | uart->rx_dma_buf.tail = DMA_RX_XCOUNT * uart->rx_dma_nrows; | 554 | get_dma_curr_ycount(uart->rx_dma_channel); |
| 548 | bfin_serial_dma_rx_chars(uart); | 555 | pos = DMA_RX_XCOUNT * uart->rx_dma_nrows; |
| 549 | if (uart->rx_dma_nrows >= DMA_RX_YCOUNT) { | 556 | if (pos != uart->rx_dma_buf.tail) { |
| 550 | uart->rx_dma_nrows = 0; | 557 | uart->rx_dma_buf.head = pos; |
| 551 | uart->rx_dma_buf.tail = 0; | 558 | bfin_serial_dma_rx_chars(uart); |
| 559 | uart->rx_dma_buf.tail = uart->rx_dma_buf.head; | ||
| 552 | } | 560 | } |
| 553 | uart->rx_dma_buf.head = uart->rx_dma_buf.tail; | ||
| 554 | 561 | ||
| 555 | spin_lock(&uart->port.lock); | 562 | spin_lock(&uart->port.lock); |
| 556 | irqstat = get_dma_curr_irqstat(uart->rx_dma_channel); | 563 | irqstat = get_dma_curr_irqstat(uart->rx_dma_channel); |
