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 /drivers/serial | |
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>
Diffstat (limited to 'drivers/serial')
-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); |