diff options
author | Sonic Zhang <sonic.zhang@analog.com> | 2007-11-21 04:00:32 -0500 |
---|---|---|
committer | Bryan Wu <cooloney@kernel.org> | 2007-11-21 04:00:32 -0500 |
commit | 759eb040901af60d8a1a2b59b93805521b156cbb (patch) | |
tree | 91a18e28643ff6112a7a4f7ee4468487c6b664a7 | |
parent | c051489df8b027238ff22d64d4e01ede3ad77dd5 (diff) |
Blackfin Serial driver: Fix bug - serial driver in PIO mode cant handle 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>
-rw-r--r-- | drivers/serial/bfin_5xx.c | 62 |
1 files changed, 14 insertions, 48 deletions
diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c index ac2a3ef28d55..e059475c91ae 100644 --- a/drivers/serial/bfin_5xx.c +++ b/drivers/serial/bfin_5xx.c | |||
@@ -74,7 +74,6 @@ static void bfin_serial_dma_tx_chars(struct bfin_serial_port *uart); | |||
74 | #else | 74 | #else |
75 | static void bfin_serial_do_work(struct work_struct *work); | 75 | static void bfin_serial_do_work(struct work_struct *work); |
76 | static void bfin_serial_tx_chars(struct bfin_serial_port *uart); | 76 | static void bfin_serial_tx_chars(struct bfin_serial_port *uart); |
77 | static void local_put_char(struct bfin_serial_port *uart, char ch); | ||
78 | #endif | 77 | #endif |
79 | 78 | ||
80 | static void bfin_serial_mctrl_check(struct bfin_serial_port *uart); | 79 | static void bfin_serial_mctrl_check(struct bfin_serial_port *uart); |
@@ -85,6 +84,9 @@ static void bfin_serial_mctrl_check(struct bfin_serial_port *uart); | |||
85 | static void bfin_serial_stop_tx(struct uart_port *port) | 84 | static void bfin_serial_stop_tx(struct uart_port *port) |
86 | { | 85 | { |
87 | struct bfin_serial_port *uart = (struct bfin_serial_port *)port; | 86 | struct bfin_serial_port *uart = (struct bfin_serial_port *)port; |
87 | #ifndef CONFIG_BF54x | ||
88 | unsigned short ier; | ||
89 | #endif | ||
88 | 90 | ||
89 | while (!(UART_GET_LSR(uart) & TEMT)) | 91 | while (!(UART_GET_LSR(uart) & TEMT)) |
90 | continue; | 92 | continue; |
@@ -100,8 +102,6 @@ static void bfin_serial_stop_tx(struct uart_port *port) | |||
100 | UART_PUT_LSR(uart, TFI); | 102 | UART_PUT_LSR(uart, TFI); |
101 | UART_CLEAR_IER(uart, ETBEI); | 103 | UART_CLEAR_IER(uart, ETBEI); |
102 | #else | 104 | #else |
103 | unsigned short ier; | ||
104 | |||
105 | ier = UART_GET_IER(uart); | 105 | ier = UART_GET_IER(uart); |
106 | ier &= ~ETBEI; | 106 | ier &= ~ETBEI; |
107 | UART_PUT_IER(uart, ier); | 107 | UART_PUT_IER(uart, ier); |
@@ -210,23 +210,6 @@ int kgdb_get_debug_char(void) | |||
210 | #endif | 210 | #endif |
211 | 211 | ||
212 | #ifdef CONFIG_SERIAL_BFIN_PIO | 212 | #ifdef CONFIG_SERIAL_BFIN_PIO |
213 | static void local_put_char(struct bfin_serial_port *uart, char ch) | ||
214 | { | ||
215 | unsigned short status; | ||
216 | int flags = 0; | ||
217 | |||
218 | spin_lock_irqsave(&uart->port.lock, flags); | ||
219 | |||
220 | do { | ||
221 | status = UART_GET_LSR(uart); | ||
222 | } while (!(status & THRE)); | ||
223 | |||
224 | UART_PUT_CHAR(uart, ch); | ||
225 | SSYNC(); | ||
226 | |||
227 | spin_unlock_irqrestore(&uart->port.lock, flags); | ||
228 | } | ||
229 | |||
230 | static void bfin_serial_rx_chars(struct bfin_serial_port *uart) | 213 | static void bfin_serial_rx_chars(struct bfin_serial_port *uart) |
231 | { | 214 | { |
232 | struct tty_struct *tty = uart->port.info->tty; | 215 | struct tty_struct *tty = uart->port.info->tty; |
@@ -236,8 +219,8 @@ static void bfin_serial_rx_chars(struct bfin_serial_port *uart) | |||
236 | struct pt_regs *regs = get_irq_regs(); | 219 | struct pt_regs *regs = get_irq_regs(); |
237 | #endif | 220 | #endif |
238 | 221 | ||
239 | status = UART_GET_LSR(uart); | ||
240 | ch = UART_GET_CHAR(uart); | 222 | ch = UART_GET_CHAR(uart); |
223 | status = UART_GET_LSR(uart); | ||
241 | uart->port.icount.rx++; | 224 | uart->port.icount.rx++; |
242 | 225 | ||
243 | #ifdef CONFIG_KGDB_UART | 226 | #ifdef CONFIG_KGDB_UART |
@@ -337,9 +320,12 @@ static void bfin_serial_tx_chars(struct bfin_serial_port *uart) | |||
337 | return; | 320 | return; |
338 | } | 321 | } |
339 | 322 | ||
340 | local_put_char(uart, xmit->buf[xmit->tail]); | 323 | while ((UART_GET_LSR(uart) & THRE) && xmit->tail != xmit->head) { |
341 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); | 324 | UART_PUT_CHAR(uart, xmit->buf[xmit->tail]); |
342 | uart->port.icount.tx++; | 325 | xmit->tail = (xmit->tail + 1) & (UART_XMIT_SIZE - 1); |
326 | uart->port.icount.tx++; | ||
327 | SSYNC(); | ||
328 | } | ||
343 | 329 | ||
344 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) | 330 | if (uart_circ_chars_pending(xmit) < WAKEUP_CHARS) |
345 | uart_write_wakeup(&uart->port); | 331 | uart_write_wakeup(&uart->port); |
@@ -352,21 +338,11 @@ static irqreturn_t bfin_serial_rx_int(int irq, void *dev_id) | |||
352 | { | 338 | { |
353 | struct bfin_serial_port *uart = dev_id; | 339 | struct bfin_serial_port *uart = dev_id; |
354 | 340 | ||
355 | #ifdef CONFIG_BF54x | ||
356 | unsigned short status; | ||
357 | spin_lock(&uart->port.lock); | 341 | spin_lock(&uart->port.lock); |
358 | status = UART_GET_LSR(uart); | 342 | while ((UART_GET_IER(uart) & ERBFI) && (UART_GET_LSR(uart) & DR)) |
359 | while ((UART_GET_IER(uart) & ERBFI) && (status & DR)) { | ||
360 | bfin_serial_rx_chars(uart); | 343 | bfin_serial_rx_chars(uart); |
361 | status = UART_GET_LSR(uart); | ||
362 | } | ||
363 | spin_unlock(&uart->port.lock); | 344 | spin_unlock(&uart->port.lock); |
364 | #else | 345 | |
365 | spin_lock(&uart->port.lock); | ||
366 | while ((UART_GET_IIR(uart) & IIR_STATUS) == IIR_RX_READY) | ||
367 | bfin_serial_rx_chars(uart); | ||
368 | spin_unlock(&uart->port.lock); | ||
369 | #endif | ||
370 | return IRQ_HANDLED; | 346 | return IRQ_HANDLED; |
371 | } | 347 | } |
372 | 348 | ||
@@ -374,21 +350,11 @@ static irqreturn_t bfin_serial_tx_int(int irq, void *dev_id) | |||
374 | { | 350 | { |
375 | struct bfin_serial_port *uart = dev_id; | 351 | struct bfin_serial_port *uart = dev_id; |
376 | 352 | ||
377 | #ifdef CONFIG_BF54x | ||
378 | unsigned short status; | ||
379 | spin_lock(&uart->port.lock); | 353 | spin_lock(&uart->port.lock); |
380 | status = UART_GET_LSR(uart); | 354 | if ((UART_GET_IER(uart) & ETBEI) && (UART_GET_LSR(uart) & THRE)) |
381 | while ((UART_GET_IER(uart) & ETBEI) && (status & THRE)) { | ||
382 | bfin_serial_tx_chars(uart); | 355 | bfin_serial_tx_chars(uart); |
383 | status = UART_GET_LSR(uart); | ||
384 | } | ||
385 | spin_unlock(&uart->port.lock); | 356 | spin_unlock(&uart->port.lock); |
386 | #else | 357 | |
387 | spin_lock(&uart->port.lock); | ||
388 | while ((UART_GET_IIR(uart) & IIR_STATUS) == IIR_TX_READY) | ||
389 | bfin_serial_tx_chars(uart); | ||
390 | spin_unlock(&uart->port.lock); | ||
391 | #endif | ||
392 | return IRQ_HANDLED; | 358 | return IRQ_HANDLED; |
393 | } | 359 | } |
394 | 360 | ||