aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
authorSonic Zhang <sonic.zhang@analog.com>2007-11-21 04:00:32 -0500
committerBryan Wu <cooloney@kernel.org>2007-11-21 04:00:32 -0500
commit759eb040901af60d8a1a2b59b93805521b156cbb (patch)
tree91a18e28643ff6112a7a4f7ee4468487c6b664a7 /drivers
parentc051489df8b027238ff22d64d4e01ede3ad77dd5 (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>
Diffstat (limited to 'drivers')
-rw-r--r--drivers/serial/bfin_5xx.c62
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
75static void bfin_serial_do_work(struct work_struct *work); 75static void bfin_serial_do_work(struct work_struct *work);
76static void bfin_serial_tx_chars(struct bfin_serial_port *uart); 76static void bfin_serial_tx_chars(struct bfin_serial_port *uart);
77static void local_put_char(struct bfin_serial_port *uart, char ch);
78#endif 77#endif
79 78
80static void bfin_serial_mctrl_check(struct bfin_serial_port *uart); 79static 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);
85static void bfin_serial_stop_tx(struct uart_port *port) 84static 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
213static 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
230static void bfin_serial_rx_chars(struct bfin_serial_port *uart) 213static 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