Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

Mischa Jonker and committed by
Linus Torvalds
cd1e40f0 7fdd4f76

+12 -11
+12 -11
drivers/serial/pnx8xxx_uart.c
··· 187 187 status = FIFO_TO_SM(serial_in(sport, PNX8XXX_FIFO)) | 188 188 ISTAT_TO_SM(serial_in(sport, PNX8XXX_ISTAT)); 189 189 while (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFIFO)) { 190 - ch = serial_in(sport, PNX8XXX_FIFO); 190 + ch = serial_in(sport, PNX8XXX_FIFO) & 0xff; 191 191 192 192 sport->port.icount.rx++; 193 193 ··· 198 198 * out of the main execution path 199 199 */ 200 200 if (status & (FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFE | 201 - PNX8XXX_UART_FIFO_RXPAR) | 201 + PNX8XXX_UART_FIFO_RXPAR | 202 + PNX8XXX_UART_FIFO_RXBRK) | 202 203 ISTAT_TO_SM(PNX8XXX_UART_INT_RXOVRN))) { 203 - if (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXPAR)) 204 + if (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXBRK)) { 205 + status &= ~(FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFE) | 206 + FIFO_TO_SM(PNX8XXX_UART_FIFO_RXPAR)); 207 + sport->port.icount.brk++; 208 + if (uart_handle_break(&sport->port)) 209 + goto ignore_char; 210 + } else if (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXPAR)) 204 211 sport->port.icount.parity++; 205 212 else if (status & FIFO_TO_SM(PNX8XXX_UART_FIFO_RXFE)) 206 213 sport->port.icount.frame++; ··· 291 284 /* Get the interrupts */ 292 285 status = serial_in(sport, PNX8XXX_ISTAT) & serial_in(sport, PNX8XXX_IEN); 293 286 294 - /* Break signal received */ 295 - if (status & PNX8XXX_UART_INT_BREAK) { 296 - sport->port.icount.brk++; 297 - uart_handle_break(&sport->port); 298 - } 299 - 300 - /* Byte received */ 301 - if (status & PNX8XXX_UART_INT_RX) 287 + /* Byte or break signal received */ 288 + if (status & (PNX8XXX_UART_INT_RX | PNX8XXX_UART_INT_BREAK)) 302 289 pnx8xxx_rx_chars(sport); 303 290 304 291 /* TX holding register empty - transmit a byte */