diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c index b5def356af63b70e3ebc2e23a48da0753e41b47e..3db9d6e19660da4a89042e8a26113de8d9da5bfa 100644 --- a/drivers/tty/serial/8250/8250_core.c +++ b/drivers/tty/serial/8250/8250_core.c @@ -497,6 +497,11 @@ static void univ8250_rsa_support(struct uart_ops *ops) #define univ8250_rsa_support(x) do { } while (0) #endif /* CONFIG_SERIAL_8250_RSA */ +static inline void serial8250_apply_quirks(struct uart_8250_port *up) +{ + up->port.quirks |= skip_txen_test ? UPQ_NO_TXEN_TEST : 0; +} + static void __init serial8250_isa_init_ports(void) { struct uart_8250_port *up; @@ -577,9 +582,7 @@ serial8250_register_ports(struct uart_driver *drv, struct device *dev) up->port.dev = dev; - if (skip_txen_test) - up->port.flags |= UPF_NO_TXEN_TEST; - + serial8250_apply_quirks(up); uart_add_one_port(drv, &up->port); } } @@ -1006,9 +1009,6 @@ int serial8250_register_8250_port(struct uart_8250_port *up) if (up->port.dev) uart->port.dev = up->port.dev; - if (skip_txen_test) - uart->port.flags |= UPF_NO_TXEN_TEST; - if (up->port.flags & UPF_FIXED_TYPE) uart->port.type = up->port.type; @@ -1047,6 +1047,7 @@ int serial8250_register_8250_port(struct uart_8250_port *up) serial8250_isa_config(0, &uart->port, &uart->capabilities); + serial8250_apply_quirks(uart); ret = uart_add_one_port(&serial8250_reg, &uart->port); if (ret == 0) ret = uart->port.line; @@ -1081,11 +1082,10 @@ void serial8250_unregister_port(int line) uart_remove_one_port(&serial8250_reg, &uart->port); if (serial8250_isa_devs) { uart->port.flags &= ~UPF_BOOT_AUTOCONF; - if (skip_txen_test) - uart->port.flags |= UPF_NO_TXEN_TEST; uart->port.type = PORT_UNKNOWN; uart->port.dev = &serial8250_isa_devs->dev; uart->capabilities = 0; + serial8250_apply_quirks(uart); uart_add_one_port(&serial8250_reg, &uart->port); } else { uart->port.dev = NULL; diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c index 553823c12c2fb395e674dc06243db05718791e5e..e82d7d521010b3a4fd5d272e8f5b46da1c983a3b 100644 --- a/drivers/tty/serial/8250/8250_pci.c +++ b/drivers/tty/serial/8250/8250_pci.c @@ -1548,7 +1548,7 @@ static int skip_tx_en_setup(struct serial_private *priv, const struct pciserial_board *board, struct uart_8250_port *port, int idx) { - port->port.flags |= UPF_NO_TXEN_TEST; + port->port.quirks |= UPQ_NO_TXEN_TEST; dev_dbg(&priv->dev->dev, "serial8250: skipping TxEn test for device [%04x:%04x] subsystem [%04x:%04x]\n", priv->dev->vendor, priv->dev->device, diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c index a5fe0e66c60725bf227ea8acf2e93fe2adda5c4c..25aae660cb9e2821664e806399908f388565c82f 100644 --- a/drivers/tty/serial/8250/8250_port.c +++ b/drivers/tty/serial/8250/8250_port.c @@ -2304,7 +2304,7 @@ int serial8250_do_startup(struct uart_port *port) * test if we receive TX irq. This way, we'll never enable * UART_BUG_TXEN. */ - if (up->port.flags & UPF_NO_TXEN_TEST) + if (up->port.quirks & UPQ_NO_TXEN_TEST) goto dont_test_tx_en; /* diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h index 1775500294bb3bab35087cca19def9fc9df2a717..8dc24c855a70b96841e8a646a16ad7c6edeff9e1 100644 --- a/include/linux/serial_core.h +++ b/include/linux/serial_core.h @@ -20,7 +20,7 @@ #ifndef LINUX_SERIAL_CORE_H #define LINUX_SERIAL_CORE_H - +#include #include #include #include @@ -144,7 +144,7 @@ struct uart_port { unsigned char x_char; /* xon/xoff char */ unsigned char regshift; /* reg offset shift */ unsigned char iotype; /* io access style */ - unsigned char unused1; + unsigned char quirks; /* internal quirks */ #define UPIO_PORT (SERIAL_IO_PORT) /* 8b I/O port access */ #define UPIO_HUB6 (SERIAL_IO_HUB6) /* Hub6 ISA card */ @@ -155,6 +155,9 @@ struct uart_port { #define UPIO_MEM32BE (SERIAL_IO_MEM32BE) /* 32b big endian */ #define UPIO_MEM16 (SERIAL_IO_MEM16) /* 16b little endian */ + /* quirks must be updated while holding port mutex */ +#define UPQ_NO_TXEN_TEST BIT(0) + unsigned int read_status_mask; /* driver specific */ unsigned int ignore_status_mask; /* driver specific */ struct uart_state *state; /* pointer to parent state */ @@ -175,7 +178,6 @@ struct uart_port { * [for bit definitions in the UPF_CHANGE_MASK] * * Bits [0..UPF_LAST_USER] are userspace defined/visible/changeable - * except bit 15 (UPF_NO_TXEN_TEST) which is masked off. * The remaining bits are serial-core specific and not modifiable by * userspace. */ @@ -192,7 +194,6 @@ struct uart_port { #define UPF_SPD_SHI ((__force upf_t) ASYNC_SPD_SHI /* 12 */ ) #define UPF_LOW_LATENCY ((__force upf_t) ASYNC_LOW_LATENCY /* 13 */ ) #define UPF_BUGGY_UART ((__force upf_t) ASYNC_BUGGY_UART /* 14 */ ) -#define UPF_NO_TXEN_TEST ((__force upf_t) (1 << 15)) #define UPF_MAGIC_MULTIPLIER ((__force upf_t) ASYNC_MAGIC_MULTIPLIER /* 16 */ ) #define UPF_NO_THRE_TEST ((__force upf_t) (1 << 19))