When a break signal is detected, the next character should be ignored.
This was not implemented correctly for the pnx8xxx_uart driver. [From further discussion: Correct, you can look to it as two separate bugs: a) the next character is not ignored while it should; b) the status bits 31-8 are copied to the 'ch' variable while they shouldn't. Both bugs prevent correct break signal handling (and therefore correct behaviour of the magic SysRq key). Bug b didn't cause too much trouble earlier because in most situations the status bits are all zero; for this case they unfortunately aren't. ] Signed-off-by: Mischa Jonker <mischa.jonker@nxp.com> Signed-off-by: Alan Cox <alan@redhat.com> Signed-off-by: Linus Torvalds <torvalds@linux-foundation.org>
This commit is contained in:
parent
7fdd4f76e9
commit
cd1e40f098
@ -187,7 +187,7 @@ static void pnx8xxx_rx_chars(struct pnx8xxx_port *sport)
|
||||
status = FIFO_TO_SM(serial_in(sport, PNX8XXX_FIFO)) |
|
||||
ISTAT_TO_SM(serial_in(sport, PNX8XXX_ISTAT));
|
||||
while (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFIFO)) {
|
||||
ch = serial_in(sport, PNX8XXX_FIFO);
|
||||
ch = serial_in(sport, PNX8XXX_FIFO) & 0xff;
|
||||
|
||||
sport->port.icount.rx++;
|
||||
|
||||
@ -198,9 +198,16 @@ static void pnx8xxx_rx_chars(struct pnx8xxx_port *sport)
|
||||
* out of the main execution path
|
||||
*/
|
||||
if (status & (FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFE |
|
||||
PNX8XXX_UART_FIFO_RXPAR) |
|
||||
PNX8XXX_UART_FIFO_RXPAR |
|
||||
PNX8XXX_UART_FIFO_RXBRK) |
|
||||
ISTAT_TO_SM(PNX8XXX_UART_INT_RXOVRN))) {
|
||||
if (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXPAR))
|
||||
if (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXBRK)) {
|
||||
status &= ~(FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFE) |
|
||||
FIFO_TO_SM(PNX8XXX_UART_FIFO_RXPAR));
|
||||
sport->port.icount.brk++;
|
||||
if (uart_handle_break(&sport->port))
|
||||
goto ignore_char;
|
||||
} else if (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXPAR))
|
||||
sport->port.icount.parity++;
|
||||
else if (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFE))
|
||||
sport->port.icount.frame++;
|
||||
@ -284,14 +291,8 @@ static irqreturn_t pnx8xxx_int(int irq, void *dev_id)
|
||||
/* Get the interrupts */
|
||||
status = serial_in(sport, PNX8XXX_ISTAT) & serial_in(sport, PNX8XXX_IEN);
|
||||
|
||||
/* Break signal received */
|
||||
if (status & PNX8XXX_UART_INT_BREAK) {
|
||||
sport->port.icount.brk++;
|
||||
uart_handle_break(&sport->port);
|
||||
}
|
||||
|
||||
/* Byte received */
|
||||
if (status & PNX8XXX_UART_INT_RX)
|
||||
/* Byte or break signal received */
|
||||
if (status & (PNX8XXX_UART_INT_RX | PNX8XXX_UART_INT_BREAK))
|
||||
pnx8xxx_rx_chars(sport);
|
||||
|
||||
/* TX holding register empty - transmit a byte */
|
||||
|
Loading…
Reference in New Issue
Block a user