Skip to content

Commit

Permalink
Blackfin Serial Driver: fix bug - SIR driver stop receiving randomly
Browse files Browse the repository at this point in the history
Bug description:
The IRDA receiver may can't receiving any more after processed some signals.

To duplicate this issue is put three IRDA devices together, one blackfin,
two none blackfin, they will detect each other. Let one none blackfin devices
irdaping the blackfin devices, when it stopped print out ping information,
it is the time that blackfin stoped receiving, the time is random.

The related register bit is OK, the other devices is sending data continuously.
But no interrupt come.

Fixing:
I tried Michael's suggestion that request the UARTx error interrupt, and reset
the IRDA when found FE error. This method helps much, but it can't completely
avoid stop.

Reset the IRDA before every time sending the data is more safe.

Signed-off-by: Graf Yang <graf.yang@analog.com>
Signed-off-by: Bryan Wu <cooloney@kernel.org>
Signed-off-by: Alan Cox <alan@redhat.com>
Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
  • Loading branch information
Graf Yang authored and Linus Torvalds committed Jan 2, 2009
1 parent 52e15f0 commit 80d5c47
Showing 1 changed file with 24 additions and 0 deletions.
24 changes: 24 additions & 0 deletions drivers/serial/bfin_5xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -73,6 +73,8 @@ static void bfin_serial_tx_chars(struct bfin_serial_port *uart);

static void bfin_serial_mctrl_check(struct bfin_serial_port *uart);

static void bfin_serial_reset_irda(struct uart_port *port);

/*
* interrupts are disabled on entry
*/
Expand Down Expand Up @@ -105,6 +107,14 @@ static void bfin_serial_stop_tx(struct uart_port *port)
static void bfin_serial_start_tx(struct uart_port *port)
{
struct bfin_serial_port *uart = (struct bfin_serial_port *)port;
struct tty_struct *tty = uart->port.info->port.tty;

/*
* To avoid losting RX interrupt, we reset IR function
* before sending data.
*/
if (tty->termios->c_line == N_IRDA)
bfin_serial_reset_irda(port);

#ifdef CONFIG_SERIAL_BFIN_DMA
if (uart->tx_done)
Expand Down Expand Up @@ -890,6 +900,20 @@ static int bfin_kgdboc_port_startup(struct uart_port *port)
}
#endif

static void bfin_serial_reset_irda(struct uart_port *port)
{
int line = port->line;
unsigned short val;

val = UART_GET_GCTL(&bfin_serial_ports[line]);
val &= ~(IREN | RPOLC);
UART_PUT_GCTL(&bfin_serial_ports[line], val);
SSYNC();
val |= (IREN | RPOLC);
UART_PUT_GCTL(&bfin_serial_ports[line], val);
SSYNC();
}

static struct uart_ops bfin_serial_pops = {
.tx_empty = bfin_serial_tx_empty,
.set_mctrl = bfin_serial_set_mctrl,
Expand Down

0 comments on commit 80d5c47

Please sign in to comment.