2009-06-02 07:12:20

by Mike Frysinger

[permalink] [raw]
Subject: [PATCH 01/11] Blackfin SPORT UART: fix typo in sport_set_termios prototype

Signed-off-by: Mike Frysinger <[email protected]>
Signed-off-by: Bryan Wu <[email protected]>
---
drivers/serial/bfin_sport_uart.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/serial/bfin_sport_uart.c b/drivers/serial/bfin_sport_uart.c
index 529c0ff..fd5cb95 100644
--- a/drivers/serial/bfin_sport_uart.c
+++ b/drivers/serial/bfin_sport_uart.c
@@ -419,7 +419,7 @@ static void sport_shutdown(struct uart_port *port)
}

static void sport_set_termios(struct uart_port *port,
- struct termios *termios, struct termios *old)
+ struct ktermios *termios, struct ktermios *old)
{
pr_debug("%s enter, c_cflag:%08x\n", __func__, termios->c_cflag);
uart_update_timeout(port, CS8 ,port->uartclk);
--
1.6.3.1


2009-06-02 07:12:00

by Mike Frysinger

[permalink] [raw]
Subject: [PATCH 02/11] Blackfin SPORT UART: fix data misses while using transmit frame sync

From: Michael Hennerich <[email protected]>

SPORT transmit frame sync (TFS) isn't used as an electrical signal during
normal SPORT UART emulation. However, it is useful in EIA RS-485
emulation as RS-485 Transceiver Driver Enable DE strobe.

This patch configures:
TFS to be active high in order to drive an DE strobe of
an eventually connected RS-485 Transceiver.

Late frame sync mode (LATFS) gating the entire TX shift cycle.

Signed-off-by: Michael Hennerich <[email protected]>
Signed-off-by: Mike Frysinger <[email protected]>
Signed-off-by: Bryan Wu <[email protected]>
---
drivers/serial/bfin_sport_uart.c | 2 +-
1 files changed, 1 insertions(+), 1 deletions(-)

diff --git a/drivers/serial/bfin_sport_uart.c b/drivers/serial/bfin_sport_uart.c
index fd5cb95..6687ccd 100644
--- a/drivers/serial/bfin_sport_uart.c
+++ b/drivers/serial/bfin_sport_uart.c
@@ -149,7 +149,7 @@ static int sport_uart_setup(struct sport_uart_port *up, int sclk, int baud_rate)
int tclkdiv, tfsdiv, rclkdiv;

/* Set TCR1 and TCR2 */
- SPORT_PUT_TCR1(up, (LTFS | ITFS | TFSR | TLSBIT | ITCLK));
+ SPORT_PUT_TCR1(up, (LATFS | ITFS | TFSR | TLSBIT | ITCLK));
SPORT_PUT_TCR2(up, 10);
pr_debug("%s TCR1:%x, TCR2:%x\n", __func__, SPORT_GET_TCR1(up), SPORT_GET_TCR2(up));

--
1.6.3.1

2009-06-02 07:12:32

by Mike Frysinger

[permalink] [raw]
Subject: [PATCH 03/11] Blackfin SPORT UART: rewrite inline assembly

Hopefuly the new version is easier to read, but in the process it declares
proper clobber lists and better constraints so that GCC can do a better
job at allocating free registers.

Signed-off-by: Mike Frysinger <[email protected]>
Acked-by: Alan Cox <[email protected]>
Signed-off-by: Bryan Wu <[email protected]>
---
drivers/serial/bfin_sport_uart.c | 54 ++++++++++++++++++++-----------------
1 files changed, 29 insertions(+), 25 deletions(-)

diff --git a/drivers/serial/bfin_sport_uart.c b/drivers/serial/bfin_sport_uart.c
index 6687ccd..34b4ae0 100644
--- a/drivers/serial/bfin_sport_uart.c
+++ b/drivers/serial/bfin_sport_uart.c
@@ -101,15 +101,16 @@ static inline void tx_one_byte(struct sport_uart_port *up, unsigned int value)
{
pr_debug("%s value:%x\n", __func__, value);
/* Place a Start and Stop bit */
- __asm__ volatile (
- "R2 = b#01111111100;\n\t"
- "R3 = b#10000000001;\n\t"
- "%0 <<= 2;\n\t"
- "%0 = %0 & R2;\n\t"
- "%0 = %0 | R3;\n\t"
- :"=r"(value)
- :"0"(value)
- :"R2", "R3");
+ __asm__ __volatile__ (
+ "R2 = b#01111111100;"
+ "R3 = b#10000000001;"
+ "%0 <<= 2;"
+ "%0 = %0 & R2;"
+ "%0 = %0 | R3;"
+ : "=d"(value)
+ : "d"(value)
+ : "ASTAT", "R2", "R3"
+ );
pr_debug("%s value:%x\n", __func__, value);

SPORT_PUT_TX(up, value);
@@ -118,27 +119,30 @@ static inline void tx_one_byte(struct sport_uart_port *up, unsigned int value)
static inline unsigned int rx_one_byte(struct sport_uart_port *up)
{
unsigned int value, extract;
+ u32 tmp_mask1, tmp_mask2, tmp_shift, tmp;

value = SPORT_GET_RX32(up);
pr_debug("%s value:%x\n", __func__, value);

/* Extract 8 bits data */
- __asm__ volatile (
- "R5 = 0;\n\t"
- "P0 = 8;\n\t"
- "R1 = 0x1801(Z);\n\t"
- "R3 = 0x0300(Z);\n\t"
- "R4 = 0;\n\t"
- "LSETUP(loop_s, loop_e) LC0 = P0;\nloop_s:\t"
- "R2 = extract(%1, R1.L)(Z);\n\t"
- "R2 <<= R4;\n\t"
- "R5 = R5 | R2;\n\t"
- "R1 = R1 - R3;\nloop_e:\t"
- "R4 += 1;\n\t"
- "%0 = R5;\n\t"
- :"=r"(extract)
- :"r"(value)
- :"P0", "R1", "R2","R3","R4", "R5");
+ __asm__ __volatile__ (
+ "%[extr] = 0;"
+ "%[mask1] = 0x1801(Z);"
+ "%[mask2] = 0x0300(Z);"
+ "%[shift] = 0;"
+ "LSETUP(.Lloop_s, .Lloop_e) LC0 = %[lc];"
+ ".Lloop_s:"
+ "%[tmp] = extract(%[val], %[mask1].L)(Z);"
+ "%[tmp] <<= %[shift];"
+ "%[extr] = %[extr] | %[tmp];"
+ "%[mask1] = %[mask1] - %[mask2];"
+ ".Lloop_e:"
+ "%[shift] += 1;"
+ : [val]"=d"(value), [extr]"=d"(extract), [shift]"=d"(tmp_shift), [tmp]"=d"(tmp),
+ [mask1]"=d"(tmp_mask1), [mask2]"=d"(tmp_mask2)
+ : "d"(value), [lc]"a"(8)
+ : "ASTAT", "LB0", "LC0", "LT0"
+ );

pr_debug(" extract:%x\n", extract);
return extract;
--
1.6.3.1

2009-06-02 07:12:44

by Mike Frysinger

[permalink] [raw]
Subject: [PATCH 04/11] Blackfin SPORT UART: fix overrun errors

From: Cliff Cai <[email protected]>

Push the ty_flip_buffer_push() call from the IRQ handler to a timer so as
to improve performance and decrease likelihood of overruns.

URL: http://blackfin.uclinux.org/gf/tracker/3911
Signed-off-by: Cliff Cai <[email protected]>
Signed-off-by: Bryan Wu <[email protected]>
---
drivers/serial/bfin_sport_uart.c | 31 ++++++++++++++++++++++++-------
1 files changed, 24 insertions(+), 7 deletions(-)

diff --git a/drivers/serial/bfin_sport_uart.c b/drivers/serial/bfin_sport_uart.c
index 34b4ae0..fa80411 100644
--- a/drivers/serial/bfin_sport_uart.c
+++ b/drivers/serial/bfin_sport_uart.c
@@ -88,7 +88,8 @@ unsigned short bfin_uart_pin_req_sport1[] =
struct sport_uart_port {
struct uart_port port;
char *name;
-
+ struct timer_list rx_timer;
+ int once;
int tx_irq;
int rx_irq;
int err_irq;
@@ -116,9 +117,10 @@ static inline void tx_one_byte(struct sport_uart_port *up, unsigned int value)
SPORT_PUT_TX(up, value);
}

-static inline unsigned int rx_one_byte(struct sport_uart_port *up)
+static inline unsigned char rx_one_byte(struct sport_uart_port *up)
{
- unsigned int value, extract;
+ unsigned int value;
+ unsigned char extract;
u32 tmp_mask1, tmp_mask2, tmp_shift, tmp;

value = SPORT_GET_RX32(up);
@@ -175,11 +177,19 @@ static int sport_uart_setup(struct sport_uart_port *up, int sclk, int baud_rate)
return 0;
}

+static void rx_push(unsigned long data)
+{
+ struct sport_uart_port *up = (struct sport_uart_port *)data;
+ struct tty_struct *tty = up->port.info->port.tty;
+ tty_flip_buffer_push(tty);
+ add_timer(&up->rx_timer);
+}
+
static irqreturn_t sport_uart_rx_irq(int irq, void *dev_id)
{
struct sport_uart_port *up = dev_id;
struct tty_struct *tty = up->port.info->port.tty;
- unsigned int ch;
+ unsigned char ch;

do {
ch = rx_one_byte(up);
@@ -190,8 +200,10 @@ static irqreturn_t sport_uart_rx_irq(int irq, void *dev_id)
else
tty_insert_flip_char(tty, ch, TTY_NORMAL);
} while (SPORT_GET_STAT(up) & RXNE);
- tty_flip_buffer_push(tty);
-
+ if (up->once == 0) {
+ add_timer(&up->rx_timer);
+ up->once = 1;
+ }
return IRQ_HANDLED;
}

@@ -257,7 +269,10 @@ static int sport_startup(struct uart_port *port)
printk(KERN_ERR "Unable to request interrupt %s\n", buffer);
goto fail2;
}
-
+ init_timer(&up->rx_timer);
+ up->rx_timer.data = (unsigned long)up;
+ up->rx_timer.expires = jiffies + 5;
+ up->rx_timer.function = (void *)rx_push;
if (port->line) {
if (peripheral_request_list(bfin_uart_pin_req_sport1, DRV_NAME))
goto fail3;
@@ -384,6 +399,8 @@ static void sport_stop_rx(struct uart_port *port)
{
struct sport_uart_port *up = (struct sport_uart_port *)port;

+ del_timer(&up->rx_timer);
+ up->once = 0;
pr_debug("%s enter\n", __func__);
/* Disable sport to stop rx */
SPORT_PUT_RCR1(up, (SPORT_GET_RCR1(up) & ~RSPEN));
--
1.6.3.1

2009-06-02 07:12:56

by Mike Frysinger

[permalink] [raw]
Subject: [PATCH 05/11] Blackfin Serial Driver: fix error while transferring large files

From: Sonic Zhang <[email protected]>

Ignore receiving data if new position is in the same line of current
buffer tail and is small. This should decrease overruns.

Signed-off-by: Sonic Zhang <[email protected]>
Signed-off-by: Mike Frysinger <[email protected]>
Signed-off-by: Bryan Wu <[email protected]>
---
drivers/serial/bfin_5xx.c | 31 +++++++++++++++++++++++++++++--
1 files changed, 29 insertions(+), 2 deletions(-)

diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c
index d86123e..65a4c07 100644
--- a/drivers/serial/bfin_5xx.c
+++ b/drivers/serial/bfin_5xx.c
@@ -477,6 +477,15 @@ void bfin_serial_rx_dma_timeout(struct bfin_serial_port *uart)

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

+ /* 2D DMA RX buffer ring is used. Because curr_y_count and
+ * curr_x_count can't be read as an atomic operation,
+ * curr_y_count should be read before curr_x_count. When
+ * curr_x_count is read, curr_y_count may already indicate
+ * next buffer line. But, the position calculated here is
+ * still indicate the old line. The wrong position data may
+ * be smaller than current buffer tail, which cause garbages
+ * are received if it is not prohibit.
+ */
uart->rx_dma_nrows = get_dma_curr_ycount(uart->rx_dma_channel);
x_pos = get_dma_curr_xcount(uart->rx_dma_channel);
uart->rx_dma_nrows = DMA_RX_YCOUNT - uart->rx_dma_nrows;
@@ -487,7 +496,11 @@ void bfin_serial_rx_dma_timeout(struct bfin_serial_port *uart)
x_pos = 0;

pos = uart->rx_dma_nrows * DMA_RX_XCOUNT + x_pos;
- if (pos != uart->rx_dma_buf.tail) {
+ /* Ignore receiving data if new position is in the same line of
+ * current buffer tail and small.
+ */
+ if (pos > uart->rx_dma_buf.tail ||
+ uart->rx_dma_nrows < (uart->rx_dma_buf.tail/DMA_RX_XCOUNT)) {
uart->rx_dma_buf.head = pos;
bfin_serial_dma_rx_chars(uart);
uart->rx_dma_buf.tail = uart->rx_dma_buf.head;
@@ -532,11 +545,25 @@ static irqreturn_t bfin_serial_dma_rx_int(int irq, void *dev_id)
{
struct bfin_serial_port *uart = dev_id;
unsigned short irqstat;
+ int pos;

spin_lock(&uart->port.lock);
irqstat = get_dma_curr_irqstat(uart->rx_dma_channel);
clear_dma_irqstat(uart->rx_dma_channel);
- bfin_serial_dma_rx_chars(uart);
+
+ uart->rx_dma_nrows = get_dma_curr_ycount(uart->rx_dma_channel);
+ uart->rx_dma_nrows = DMA_RX_YCOUNT - uart->rx_dma_nrows;
+ if (uart->rx_dma_nrows == DMA_RX_YCOUNT)
+ uart->rx_dma_nrows = 0;
+
+ pos = uart->rx_dma_nrows * DMA_RX_XCOUNT;
+ if (pos > uart->rx_dma_buf.tail ||
+ uart->rx_dma_nrows < (uart->rx_dma_buf.tail/DMA_RX_XCOUNT)) {
+ uart->rx_dma_buf.head = pos;
+ bfin_serial_dma_rx_chars(uart);
+ uart->rx_dma_buf.tail = uart->rx_dma_buf.head;
+ }
+
spin_unlock(&uart->port.lock);

return IRQ_HANDLED;
--
1.6.3.1

2009-06-02 07:13:16

by Mike Frysinger

[permalink] [raw]
Subject: [PATCH 06/11] Blackfin Serial Driver: fix baudrate for early_printk

From: Robin Getz <[email protected]>

Since we already setup the early console UART in
arch/blackfin/kernel/early_printk.c, and common functions which are
enabled from the .setup will override the proper settings later, don't
fill in these structures. Otherwise we get mangled baudrate settings when
using early_printk.

Signed-off-by: Robin Getz <[email protected]>
Signed-off-by: Mike Frysinger <[email protected]>
Signed-off-by: Bryan Wu <[email protected]>
---
drivers/serial/bfin_5xx.c | 7 ++++++-
1 files changed, 6 insertions(+), 1 deletions(-)

diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c
index 65a4c07..dfae22d 100644
--- a/drivers/serial/bfin_5xx.c
+++ b/drivers/serial/bfin_5xx.c
@@ -1272,12 +1272,17 @@ static __init void early_serial_write(struct console *con, const char *s,
}
}

+/*
+ * This should have a .setup or .early_setup in it, but then things get called
+ * without the command line options, and the baud rate gets messed up - so
+ * don't let the common infrastructure play with things. (see calls to setup
+ * & earlysetup in ./kernel/printk.c:register_console()
+ */
static struct __initdata console bfin_early_serial_console = {
.name = "early_BFuart",
.write = early_serial_write,
.device = uart_console_device,
.flags = CON_PRINTBUFFER,
- .setup = bfin_serial_console_setup,
.index = -1,
.data = &bfin_serial_reg,
};
--
1.6.3.1

2009-06-02 07:13:29

by Mike Frysinger

[permalink] [raw]
Subject: [PATCH 07/11] Blackfin Serial Driver: fix missing new lines when under load

From: Graf Yang <[email protected]>

Add a SSYNC() into bfin_serial_dma_tx_chars() to ensure DMA registers are
written with new data otherwise we might miss a byte or two when the
system is under load. PIO mode is OK though.

Signed-off-by: Graf Yang <[email protected]>
Signed-off-by: Mike Frysinger <[email protected]>
Signed-off-by: Bryan Wu <[email protected]>
---
drivers/serial/bfin_5xx.c | 1 +
1 files changed, 1 insertions(+), 0 deletions(-)

diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c
index dfae22d..676efda 100644
--- a/drivers/serial/bfin_5xx.c
+++ b/drivers/serial/bfin_5xx.c
@@ -415,6 +415,7 @@ static void bfin_serial_dma_tx_chars(struct bfin_serial_port *uart)
set_dma_start_addr(uart->tx_dma_channel, (unsigned long)(xmit->buf+xmit->tail));
set_dma_x_count(uart->tx_dma_channel, uart->tx_count);
set_dma_x_modify(uart->tx_dma_channel, 1);
+ SSYNC();
enable_dma(uart->tx_dma_channel);

UART_SET_IER(uart, ETBEI);
--
1.6.3.1

2009-06-02 07:13:40

by Mike Frysinger

[permalink] [raw]
Subject: [PATCH 08/11] Blackfin Serial Driver: handle irregular DMA register status in auto start mode

From: Sonic Zhang <[email protected]>

This bug is caused by irregular behavior of DMA register CURR_X_COUNT
and CURR_Y_COUNT when an auto restart uart rx DMA run to last byte in
DMA buffer, trigger the interrupt and stay at this possiton. The status
of current x and y is 0:7 instead of 512:8 or 0:8. The driver doesn't
take care of this case when calculating the position.

URL: http://blackfin.uclinux.org/gf/tracker/5063
Signed-off-by: Sonic Zhang <[email protected]>
Signed-off-by: Mike Frysinger <[email protected]>
Reported-by: Tomasz Motylewski <[email protected]>
---
drivers/serial/bfin_5xx.c | 7 ++++---
1 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c
index 676efda..854e96d 100644
--- a/drivers/serial/bfin_5xx.c
+++ b/drivers/serial/bfin_5xx.c
@@ -490,7 +490,7 @@ void bfin_serial_rx_dma_timeout(struct bfin_serial_port *uart)
uart->rx_dma_nrows = get_dma_curr_ycount(uart->rx_dma_channel);
x_pos = get_dma_curr_xcount(uart->rx_dma_channel);
uart->rx_dma_nrows = DMA_RX_YCOUNT - uart->rx_dma_nrows;
- if (uart->rx_dma_nrows == DMA_RX_YCOUNT)
+ if (uart->rx_dma_nrows == DMA_RX_YCOUNT || x_pos == 0)
uart->rx_dma_nrows = 0;
x_pos = DMA_RX_XCOUNT - x_pos;
if (x_pos == DMA_RX_XCOUNT)
@@ -546,15 +546,16 @@ static irqreturn_t bfin_serial_dma_rx_int(int irq, void *dev_id)
{
struct bfin_serial_port *uart = dev_id;
unsigned short irqstat;
- int pos;
+ int x_pos, pos;

spin_lock(&uart->port.lock);
irqstat = get_dma_curr_irqstat(uart->rx_dma_channel);
clear_dma_irqstat(uart->rx_dma_channel);

uart->rx_dma_nrows = get_dma_curr_ycount(uart->rx_dma_channel);
+ x_pos = get_dma_curr_xcount(uart->rx_dma_channel);
uart->rx_dma_nrows = DMA_RX_YCOUNT - uart->rx_dma_nrows;
- if (uart->rx_dma_nrows == DMA_RX_YCOUNT)
+ if (uart->rx_dma_nrows == DMA_RX_YCOUNT || x_pos == 0)
uart->rx_dma_nrows = 0;

pos = uart->rx_dma_nrows * DMA_RX_XCOUNT;
--
1.6.3.1

2009-06-02 07:13:52

by Mike Frysinger

[permalink] [raw]
Subject: [PATCH 09/11] Blackfin Serial Driver: annotate anomalies 05000215 and 05000099

From: Sonic Zhang <[email protected]>

Add some comments for how these anomalies are addressed:

05000215 - UART TX Interrupt Masked Erroneously
We always clear ETBEI within last UART TX interrupt to end
a string. It is always set when starting a new tx transfer.

05000099 - UART Line Status Register (UART_LSR) Bits Are Not Updated at
the Same Time
This anomaly affects driver only in POLL code where multi bits of
UART_LSR are checked. It doesn't affect current bfin_5xx.c driver.

Signed-off-by: Sonic Zhang <[email protected]>
Signed-off-by: Mike Frysinger <[email protected]>
---
drivers/serial/bfin_5xx.c | 14 ++++++++++++++
1 files changed, 14 insertions(+), 0 deletions(-)

diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c
index 854e96d..ab583ef 100644
--- a/drivers/serial/bfin_5xx.c
+++ b/drivers/serial/bfin_5xx.c
@@ -330,6 +330,11 @@ static void bfin_serial_tx_chars(struct bfin_serial_port *uart)
/* Clear TFI bit */
UART_PUT_LSR(uart, TFI);
#endif
+ /* Anomaly notes:
+ * 05000215 - we always clear ETBEI within last UART TX
+ * interrupt to end a string. It is always set
+ * when start a new tx.
+ */
UART_CLEAR_IER(uart, ETBEI);
return;
}
@@ -528,6 +533,11 @@ static irqreturn_t bfin_serial_dma_tx_int(int irq, void *dev_id)
if (!(get_dma_curr_irqstat(uart->tx_dma_channel)&DMA_RUN)) {
disable_dma(uart->tx_dma_channel);
clear_dma_irqstat(uart->tx_dma_channel);
+ /* Anomaly notes:
+ * 05000215 - we always clear ETBEI within last UART TX
+ * interrupt to end a string. It is always set
+ * when start a new tx.
+ */
UART_CLEAR_IER(uart, ETBEI);
xmit->tail = (xmit->tail + uart->tx_count) & (UART_XMIT_SIZE - 1);
uart->port.icount.tx += uart->tx_count;
@@ -969,6 +979,10 @@ static void bfin_serial_reset_irda(struct uart_port *port)
}

#ifdef CONFIG_CONSOLE_POLL
+/* Anomaly notes:
+ * 05000099 - Because we only use THRE in poll_put and DR in poll_get,
+ * losing other bits of UART_LSR is not a problem here.
+ */
static void bfin_serial_poll_put_char(struct uart_port *port, unsigned char chr)
{
struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
--
1.6.3.1

2009-06-02 07:14:06

by Mike Frysinger

[permalink] [raw]
Subject: [PATCH 10/11] Blackfin Serial Driver: handle anomaly 05000231

From: Sonic Zhang <[email protected]>

05000231 - UART STB Bit Incorrectly Affects Receiver Setting
For processors affected by this, we cannot safely allow CSTOPB to be set
as the UART will then be unable to properly clock in bytes.

Signed-off-by: Sonic Zhang <[email protected]>
Signed-off-by: Mike Frysinger <[email protected]>
---
drivers/serial/bfin_5xx.c | 12 ++++++++++--
1 files changed, 10 insertions(+), 2 deletions(-)

diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c
index ab583ef..64603f5 100644
--- a/drivers/serial/bfin_5xx.c
+++ b/drivers/serial/bfin_5xx.c
@@ -828,8 +828,16 @@ bfin_serial_set_termios(struct uart_port *port, struct ktermios *termios,
__func__);
}

- if (termios->c_cflag & CSTOPB)
- lcr |= STB;
+ /* Anomaly notes:
+ * 05000231 - STOP bit is always set to 1 whatever the user is set.
+ */
+ if (termios->c_cflag & CSTOPB) {
+ if (ANOMALY_05000231)
+ printk(KERN_WARNING "STOP bits other than 1 is not "
+ "supported in case of anomaly 05000231.\n");
+ else
+ lcr |= STB;
+ }
if (termios->c_cflag & PARENB)
lcr |= PEN;
if (!(termios->c_cflag & PARODD))
--
1.6.3.1

2009-06-02 07:14:24

by Mike Frysinger

[permalink] [raw]
Subject: [PATCH 11/11] Blackfin Serial Driver: disable dma rx interrupt only rather than all irqs

From: Sonic Zhang <[email protected]>

The UART RX handling code isn't exactly speeding, so don't go disabling
all interrupts when processing the buffer. Just disable the relevant DMA
interrupt. This greatly improves latency of the system when utilizing the
UART.

Signed-off-by: Sonic Zhang <[email protected]>
Signed-off-by: Mike Frysinger <[email protected]>
---
drivers/serial/bfin_5xx.c | 7 ++++---
1 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/serial/bfin_5xx.c b/drivers/serial/bfin_5xx.c
index 64603f5..e2f6b1b 100644
--- a/drivers/serial/bfin_5xx.c
+++ b/drivers/serial/bfin_5xx.c
@@ -479,9 +479,9 @@ static void bfin_serial_dma_rx_chars(struct bfin_serial_port *uart)
void bfin_serial_rx_dma_timeout(struct bfin_serial_port *uart)
{
int x_pos, pos;
- unsigned long flags;

- spin_lock_irqsave(&uart->port.lock, flags);
+ dma_disable_irq(uart->rx_dma_channel);
+ spin_lock_bh(&uart->port.lock);

/* 2D DMA RX buffer ring is used. Because curr_y_count and
* curr_x_count can't be read as an atomic operation,
@@ -512,7 +512,8 @@ void bfin_serial_rx_dma_timeout(struct bfin_serial_port *uart)
uart->rx_dma_buf.tail = uart->rx_dma_buf.head;
}

- spin_unlock_irqrestore(&uart->port.lock, flags);
+ spin_unlock_bh(&uart->port.lock);
+ dma_enable_irq(uart->rx_dma_channel);

mod_timer(&(uart->rx_dma_timer), jiffies + DMA_RX_FLUSH_JIFFIES);
}
--
1.6.3.1

2009-06-02 09:05:27

by Alan

[permalink] [raw]
Subject: Re: [PATCH 04/11] Blackfin SPORT UART: fix overrun errors

On Tue, 2 Jun 2009 03:11:33 -0400
Mike Frysinger <[email protected]> wrote:

> From: Cliff Cai <[email protected]>
>
> Push the ty_flip_buffer_push() call from the IRQ handler to a timer so as
> to improve performance and decrease likelihood of overruns.

This should have no effect on a modern kernel. There is 64K of queueing
between you and the ldisc nowdays. Furthermore unless you set
tty->low_latency the kernel already basically does this aggregation for
you as the buffer push queues stuff for the ldisc to wake up and process.

2009-06-03 08:04:25

by Mike Frysinger

[permalink] [raw]
Subject: Re: [PATCH 04/11] Blackfin SPORT UART: fix overrun errors

On Tue, Jun 2, 2009 at 05:00, Alan Cox wrote:
> On Tue,  2 Jun 2009 03:11:33 -0400 Mike Frysinger wrote:
>> From: Cliff Cai <[email protected]>
>>
>> Push the ty_flip_buffer_push() call from the IRQ handler to a timer so as
>> to improve performance and decrease likelihood of overruns.
>
> This should have no effect on a modern kernel.

well, we wouldnt be making changes if we werent seeing data overruns today

> There is 64K of queueing between you and the ldisc nowdays.

i dont think that really matters ... we do too much work in the
interrupt and so we miss new data

> Furthermore unless you set tty->low_latency the kernel already basically
> does this aggregation for you as the buffer push queues stuff for the ldisc
> to wake up and process.

i guess we could try setting the low_latency bool instead and see if
that fixes things
-mike

2009-06-03 08:46:19

by Cai, Cliff

[permalink] [raw]
Subject: RE: [PATCH 04/11] Blackfin SPORT UART: fix overrun errors



>-----Original Message-----
>From: Mike Frysinger [mailto:[email protected]]
>Sent: Wednesday, June 03, 2009 4:04 PM
>To: Alan Cox
>Cc: Mike Frysinger; [email protected];
>[email protected];
>[email protected]; Cai, Cliff; Bryan Wu
>Subject: Re: [PATCH 04/11] Blackfin SPORT UART: fix overrun errors
>
>On Tue, Jun 2, 2009 at 05:00, Alan Cox wrote:
>> On Tue, ?2 Jun 2009 03:11:33 -0400 Mike Frysinger wrote:
>>> From: Cliff Cai <[email protected]>
>>>
>>> Push the ty_flip_buffer_push() call from the IRQ handler to a timer
>>> so as to improve performance and decrease likelihood of overruns.
>>
>> This should have no effect on a modern kernel.
>
>well, we wouldnt be making changes if we werent seeing data
>overruns today
>
>> There is 64K of queueing between you and the ldisc nowdays.
>
>i dont think that really matters ... we do too much work in
>the interrupt and so we miss new data
>
>> Furthermore unless you set tty->low_latency the kernel already
>> basically does this aggregation for you as the buffer push queues
>> stuff for the ldisc to wake up and process.
>
>i guess we could try setting the low_latency bool instead and
>see if that fixes things -mike
>

The overrrun problem doesn't exist even without my patch now,so I will drop it.

Thanks

Cliff

2009-06-03 08:56:11

by Alan

[permalink] [raw]
Subject: Re: [PATCH 04/11] Blackfin SPORT UART: fix overrun errors

> > This should have no effect on a modern kernel.
>
> well, we wouldnt be making changes if we werent seeing data overruns today

If it has an effect then something else is going on.
>
> > There is 64K of queueing between you and the ldisc nowdays.
>
> i dont think that really matters ... we do too much work in the
> interrupt and so we miss new data

Which the other patches addressed so my guess is the real fixes were the
other changes.

Alan

2009-06-03 09:47:43

by Mike Frysinger

[permalink] [raw]
Subject: Re: [PATCH 04/11] Blackfin SPORT UART: fix overrun errors

On Wed, Jun 3, 2009 at 04:53, Alan Cox wrote:
>> > This should have no effect on a modern kernel.
>>
>> well, we wouldnt be making changes if we werent seeing data overruns today
>
> If it has an effect then something else is going on.
>>
>> > There is 64K of queueing between you and the ldisc nowdays.
>>
>> i dont think that really matters ... we do too much work in the
>> interrupt and so we miss new data
>
> Which the other patches addressed so my guess is the real fixes were the
> other changes.

pfft, always got to make us do real work :)

since the serial stuff is in a bit of orphaned state (going by
MAINTAINERS), should i merge the other changes through the Blackfin
tree ?
-mike

2009-06-03 09:58:56

by Alan

[permalink] [raw]
Subject: Re: [PATCH 04/11] Blackfin SPORT UART: fix overrun errors

> since the serial stuff is in a bit of orphaned state (going by
> MAINTAINERS), should i merge the other changes through the Blackfin
> tree ?

The other bits are all merged into the ttydev tree

Alan

2009-06-03 10:15:26

by Mike Frysinger

[permalink] [raw]
Subject: Re: [PATCH 04/11] Blackfin SPORT UART: fix overrun errors

On Wed, Jun 3, 2009 at 05:57, Alan Cox wrote:
>> since the serial stuff is in a bit of orphaned state (going by
>> MAINTAINERS), should i merge the other changes through the Blackfin
>> tree ?
>
> The other bits are all merged into the ttydev tree

ah, ok. i'm guessing that is this:
http://www.linux.org.uk/~alan/ttydev/

useful to add to MAINTAINERS ?
-mike