Skip to content

Commit

Permalink
Blackfin Serial driver: Fix bug - serial driver in PIO mode cant hand…
Browse files Browse the repository at this point in the history
…le input very quickly

Output as many bytes as possible in PIO tx handler.
This reduce the number of tx interrupts and shorten the delay to handle
rx interrupt. So, rx overrun disappears.

Signed-off-by: Sonic Zhang <sonic.zhang@analog.com>
Signed-off-by: Bryan Wu <bryan.wu@analog.com>
  • Loading branch information
Sonic Zhang authored and Bryan Wu committed Nov 21, 2007
1 parent c051489 commit 759eb04
Showing 1 changed file with 14 additions and 48 deletions.
62 changes: 14 additions & 48 deletions drivers/serial/bfin_5xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -74,7 +74,6 @@ static void bfin_serial_dma_tx_chars(struct bfin_serial_port *uart);
#else
static void bfin_serial_do_work(struct work_struct *work);
static void bfin_serial_tx_chars(struct bfin_serial_port *uart);
static void local_put_char(struct bfin_serial_port *uart, char ch);
#endif

static void bfin_serial_mctrl_check(struct bfin_serial_port *uart);
Expand All @@ -85,6 +84,9 @@ static void bfin_serial_mctrl_check(struct bfin_serial_port *uart);
static void bfin_serial_stop_tx(struct uart_port *port)
{
struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
#ifndef CONFIG_BF54x
unsigned short ier;
#endif

while (!(UART_GET_LSR(uart) & TEMT))
continue;
Expand All @@ -100,8 +102,6 @@ static void bfin_serial_stop_tx(struct uart_port *port)
UART_PUT_LSR(uart, TFI);
UART_CLEAR_IER(uart, ETBEI);
#else
unsigned short ier;

ier = UART_GET_IER(uart);
ier &= ~ETBEI;
UART_PUT_IER(uart, ier);
Expand Down Expand Up @@ -210,23 +210,6 @@ int kgdb_get_debug_char(void)
#endif

#ifdef CONFIG_SERIAL_BFIN_PIO
static void local_put_char(struct bfin_serial_port *uart, char ch)
{
unsigned short status;
int flags = 0;

spin_lock_irqsave(&uart->port.lock, flags);

do {
status = UART_GET_LSR(uart);
} while (!(status & THRE));

UART_PUT_CHAR(uart, ch);
SSYNC();

spin_unlock_irqrestore(&uart->port.lock, flags);
}

static void bfin_serial_rx_chars(struct bfin_serial_port *uart)
{
struct tty_struct *tty = uart->port.info->tty;
Expand All @@ -236,8 +219,8 @@ static void bfin_serial_rx_chars(struct bfin_serial_port *uart)
struct pt_regs *regs = get_irq_regs();
#endif

status = UART_GET_LSR(uart);
ch = UART_GET_CHAR(uart);
status = UART_GET_LSR(uart);
uart->port.icount.rx++;

#ifdef CONFIG_KGDB_UART
Expand Down Expand Up @@ -337,9 +320,12 @@ static void bfin_serial_tx_chars(struct bfin_serial_port *uart)
return;
}

local_put_char(uart, xmit->buf[xmit->tail]);
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
uart->port.icount.tx++;
while ((UART_GET_LSR(uart) & THRE) && xmit->tail != xmit->head) {
UART_PUT_CHAR(uart, xmit->buf[xmit->tail]);
xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1);
uart->port.icount.tx++;
SSYNC();
}

if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS)
uart_write_wakeup(&uart->port);
Expand All @@ -352,43 +338,23 @@ static irqreturn_t bfin_serial_rx_int(int irq, void *dev_id)
{
struct bfin_serial_port *uart = dev_id;

#ifdef CONFIG_BF54x
unsigned short status;
spin_lock(&uart->port.lock);
status = UART_GET_LSR(uart);
while ((UART_GET_IER(uart) & ERBFI) && (status & DR)) {
while ((UART_GET_IER(uart) & ERBFI) && (UART_GET_LSR(uart) & DR))
bfin_serial_rx_chars(uart);
status = UART_GET_LSR(uart);
}
spin_unlock(&uart->port.lock);
#else
spin_lock(&uart->port.lock);
while ((UART_GET_IIR(uart) & IIR_STATUS) == IIR_RX_READY)
bfin_serial_rx_chars(uart);
spin_unlock(&uart->port.lock);
#endif

return IRQ_HANDLED;
}

static irqreturn_t bfin_serial_tx_int(int irq, void *dev_id)
{
struct bfin_serial_port *uart = dev_id;

#ifdef CONFIG_BF54x
unsigned short status;
spin_lock(&uart->port.lock);
status = UART_GET_LSR(uart);
while ((UART_GET_IER(uart) & ETBEI) && (status & THRE)) {
if ((UART_GET_IER(uart) & ETBEI) && (UART_GET_LSR(uart) & THRE))
bfin_serial_tx_chars(uart);
status = UART_GET_LSR(uart);
}
spin_unlock(&uart->port.lock);
#else
spin_lock(&uart->port.lock);
while ((UART_GET_IIR(uart) & IIR_STATUS) == IIR_TX_READY)
bfin_serial_tx_chars(uart);
spin_unlock(&uart->port.lock);
#endif

return IRQ_HANDLED;
}

Expand Down

0 comments on commit 759eb04

Please sign in to comment.