| From 82776f6c75a90e1d2103e689b84a689de8f1aa02 Mon Sep 17 00:00:00 2001 |
| From: Russell King <rmk+kernel@armlinux.org.uk> |
| Date: Sun, 18 Oct 2020 09:42:04 +0100 |
| Subject: tty: serial: 21285: fix lockup on open |
| |
| From: Russell King <rmk+kernel@armlinux.org.uk> |
| |
| commit 82776f6c75a90e1d2103e689b84a689de8f1aa02 upstream. |
| |
| Commit 293f89959483 ("tty: serial: 21285: stop using the unused[] |
| variable from struct uart_port") introduced a bug which stops the |
| transmit interrupt being disabled when there are no characters to |
| transmit - disabling the transmit interrupt at the interrupt controller |
| is the only way to stop an interrupt storm. If this interrupt is not |
| disabled when there are no transmit characters, we end up with an |
| interrupt storm which prevents the machine making forward progress. |
| |
| Fixes: 293f89959483 ("tty: serial: 21285: stop using the unused[] variable from struct uart_port") |
| Signed-off-by: Russell King <rmk+kernel@armlinux.org.uk> |
| Cc: stable <stable@vger.kernel.org> |
| Link: https://lore.kernel.org/r/E1kU4GS-0006lE-OO@rmk-PC.armlinux.org.uk |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| |
| --- |
| drivers/tty/serial/21285.c | 12 ++++++------ |
| 1 file changed, 6 insertions(+), 6 deletions(-) |
| |
| --- a/drivers/tty/serial/21285.c |
| +++ b/drivers/tty/serial/21285.c |
| @@ -50,25 +50,25 @@ static const char serial21285_name[] = " |
| |
| static bool is_enabled(struct uart_port *port, int bit) |
| { |
| - unsigned long private_data = (unsigned long)port->private_data; |
| + unsigned long *private_data = (unsigned long *)&port->private_data; |
| |
| - if (test_bit(bit, &private_data)) |
| + if (test_bit(bit, private_data)) |
| return true; |
| return false; |
| } |
| |
| static void enable(struct uart_port *port, int bit) |
| { |
| - unsigned long private_data = (unsigned long)port->private_data; |
| + unsigned long *private_data = (unsigned long *)&port->private_data; |
| |
| - set_bit(bit, &private_data); |
| + set_bit(bit, private_data); |
| } |
| |
| static void disable(struct uart_port *port, int bit) |
| { |
| - unsigned long private_data = (unsigned long)port->private_data; |
| + unsigned long *private_data = (unsigned long *)&port->private_data; |
| |
| - clear_bit(bit, &private_data); |
| + clear_bit(bit, private_data); |
| } |
| |
| #define is_tx_enabled(port) is_enabled(port, tx_enabled_bit) |