* [PATCH 1/2] tty: serial: remove hub6 multiport support
@ 2026-10-16 12:59 Arnd Bergmann
2026-10-16 12:59 ` [PATCH 2/2] [v2] serial: 8250: remove obsolete and broken PORT_RSA support Arnd Bergmann
` (6 more replies)
0 siblings, 7 replies; 14+ messages in thread
From: Arnd Bergmann @ 2026-10-16 12:59 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby, Andy Shevchenko,
Uwe Kleine-König (The Capable Hub), Hugo Villeneuve
Cc: Arnd Bergmann, linux-kernel, linux-serial, linux-arm-kernel, imx
From: Arnd Bergmann <arnd@arndb.de>
hub6 support was added in linux-0.99 and the hardware was already old at
the time, being discontinued in 1990. The code for it has always been a
mess since it adds another dimension to the I/O addressing in the driver
that has leaked into many individual files.
Hugo and Uwe have attempted several times this year alone to isolate
the hub6 handling into the 8250_hub6.c file, but I feel that none of
this has been a real improvement over the original standalone loadable
module support.
Any machine that would have used this ISA card in practice is likely
30 to 40 years old, and with i486 support now removed, it is clearly
safe to just kill this all off. The only bit that has to remain
is the ioctl interface, to ensure the serial_struct field is always
zero.
Link: https://mirrors.nycbug.org/pub/The_Unix_Archive/Unix_Usenet/comp.unix.sysv386/1990-December/007174.html
Fixes: a300273c458c ("serial: 8250: hub6: Add cleanup code")
Fixes: c526404a4a92 ("serial: 8250: Fix corner case for port matching")
Fixes: 7ab80d1e7243 ("serial: 8250: fix compile error with hub6_match_port() when compiled as a module")
Fixes: da7b5fd4e17f ("serial: 8250_hub6: add missing include for hub6_match_port()")
Fixes: 3d406299d882 ("serial: 8250_hub6: add hub6_match_port()")
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
drivers/tty/serial/8250/8250.h | 15 -------
drivers/tty/serial/8250/8250_core.c | 2 -
drivers/tty/serial/8250/8250_hub6.c | 60 -------------------------
drivers/tty/serial/8250/8250_platform.c | 11 +----
drivers/tty/serial/8250/8250_port.c | 23 ----------
drivers/tty/serial/8250/Kconfig | 15 ++-----
drivers/tty/serial/8250/Makefile | 1 -
drivers/tty/serial/atmel_serial.c | 2 -
drivers/tty/serial/fsl_lpuart.c | 2 -
drivers/tty/serial/imx.c | 2 -
drivers/tty/serial/mpc52xx_uart.c | 3 +-
drivers/tty/serial/sa1100.c | 2 -
drivers/tty/serial/serial_core.c | 18 +++-----
drivers/tty/serial/sunsu.c | 9 ----
drivers/tty/serial/xilinx_uartps.c | 2 -
include/linux/serial_8250.h | 2 -
include/linux/serial_core.h | 2 -
17 files changed, 12 insertions(+), 159 deletions(-)
delete mode 100644 drivers/tty/serial/8250/8250_hub6.c
diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h
index 21ed9c41b751..75afeb8c0cef 100644
--- a/drivers/tty/serial/8250/8250.h
+++ b/drivers/tty/serial/8250/8250.h
@@ -323,14 +323,6 @@ static inline int serial8250_pnp_init(void) { return 0; }
static inline void serial8250_pnp_exit(void) { }
#endif
-#ifdef CONFIG_SERIAL_8250_HUB6
-int serial8250_hub6_init(void);
-void serial8250_hub6_exit(void);
-#else
-static inline int serial8250_hub6_init(void) { return 0; }
-static inline void serial8250_hub6_exit(void) { }
-#endif
-
#ifdef CONFIG_SERIAL_8250_RSA
void univ8250_rsa_support(struct uart_ops *ops, const struct uart_ops *core_ops);
void rsa_enable(struct uart_8250_port *up);
@@ -351,13 +343,6 @@ int fintek_8250_probe(struct uart_8250_port *uart);
static inline int fintek_8250_probe(struct uart_8250_port *uart) { return 0; }
#endif
-#if IS_ENABLED(CONFIG_SERIAL_8250_HUB6)
-bool hub6_match_port(const struct uart_port *port1, const struct uart_port *port2);
-#else
-static inline bool hub6_match_port(const struct uart_port *port1, const struct uart_port *port2)
-{ return false; }
-#endif
-
#ifdef CONFIG_ARCH_OMAP1
#include <linux/soc/ti/omap1-soc.h>
static inline int is_omap1_8250(struct uart_8250_port *pt)
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index 42319843cb5b..96c99f0ae683 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -686,8 +686,6 @@ static bool serial8250_match_port(const struct uart_port *port1,
return false;
else if (port1->iotype == UPIO_PORT)
return port1->iobase == port2->iobase;
- else if (port1->iotype == UPIO_HUB6)
- return hub6_match_port(port1, port2);
else if (uart_iotype_mmio(port1->iotype))
return port1->mapbase == port2->mapbase;
else
diff --git a/drivers/tty/serial/8250/8250_hub6.c b/drivers/tty/serial/8250/8250_hub6.c
deleted file mode 100644
index 848d9723ac56..000000000000
--- a/drivers/tty/serial/8250/8250_hub6.c
+++ /dev/null
@@ -1,60 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/*
- * Copyright (C) 2005 Russell King.
- * Data taken from include/asm-i386/serial.h
- */
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/serial_8250.h>
-
-#include "8250.h"
-
-#define HUB6(card, port) \
- { \
- .iobase = 0x302, \
- .irq = 3, \
- .uartclk = 1843200, \
- .iotype = UPIO_HUB6, \
- .flags = UPF_BOOT_AUTOCONF, \
- .hub6 = (card) << 6 | (port) << 3 | 1, \
- }
-
-static struct plat_serial8250_port hub6_data[] = {
- HUB6(0, 0),
- HUB6(0, 1),
- HUB6(0, 2),
- HUB6(0, 3),
- HUB6(0, 4),
- HUB6(0, 5),
- HUB6(1, 0),
- HUB6(1, 1),
- HUB6(1, 2),
- HUB6(1, 3),
- HUB6(1, 4),
- HUB6(1, 5),
- { },
-};
-
-static struct platform_device hub6_device = {
- .name = "serial8250",
- .id = PLAT8250_DEV_HUB6,
- .dev = {
- .platform_data = hub6_data,
- },
-};
-
-bool hub6_match_port(const struct uart_port *port1, const struct uart_port *port2)
-{
- return port1->iobase == port2->iobase && port1->hub6 == port2->hub6;
-}
-EXPORT_SYMBOL_GPL(hub6_match_port);
-
-int __init serial8250_hub6_init(void)
-{
- return platform_device_register(&hub6_device);
-}
-
-void serial8250_hub6_exit(void)
-{
- platform_device_unregister(&hub6_device);
-}
diff --git a/drivers/tty/serial/8250/8250_platform.c b/drivers/tty/serial/8250/8250_platform.c
index 7ce7ad295fae..8aa769085bfa 100644
--- a/drivers/tty/serial/8250/8250_platform.c
+++ b/drivers/tty/serial/8250/8250_platform.c
@@ -86,7 +86,6 @@ static void __init __serial8250_isa_init_ports(void)
port->irqflags = 0;
port->uartclk = old_serial_port[i].baud_base * 16;
port->flags = old_serial_port[i].flags;
- port->hub6 = 0;
port->membase = old_serial_port[i].iomem_base;
port->iotype = old_serial_port[i].io_type;
port->regshift = old_serial_port[i].iomem_reg_shift;
@@ -169,7 +168,6 @@ static int serial8250_probe_platform(struct platform_device *dev, struct plat_se
uart->port.flags = p->flags;
uart->port.mapbase = p->mapbase;
uart->port.mapsize = p->mapsize;
- uart->port.hub6 = p->hub6;
uart->port.has_sysrq = p->has_sysrq;
uart->port.private_data = p->private_data;
uart->port.type = p->type;
@@ -317,14 +315,10 @@ static int __init serial8250_init(void)
if (ret)
goto unreg_uart_drv;
- ret = serial8250_hub6_init();
- if (ret)
- goto unreg_pnp;
-
serial8250_isa_devs = platform_device_alloc("serial8250", PLAT8250_DEV_LEGACY);
if (!serial8250_isa_devs) {
ret = -ENOMEM;
- goto unreg_hub6;
+ goto unreg_pnp;
}
ret = platform_device_add(serial8250_isa_devs);
@@ -340,8 +334,6 @@ static int __init serial8250_init(void)
platform_device_del(serial8250_isa_devs);
put_dev:
platform_device_put(serial8250_isa_devs);
-unreg_hub6:
- serial8250_hub6_exit();
unreg_pnp:
serial8250_pnp_exit();
unreg_uart_drv:
@@ -369,7 +361,6 @@ static void __exit serial8250_exit(void)
platform_driver_unregister(&serial8250_isa_driver);
platform_device_unregister(isa_dev);
- serial8250_hub6_exit();
serial8250_pnp_exit();
#ifdef CONFIG_SPARC
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
index 36b2b0a2c05c..3593e7209879 100644
--- a/drivers/tty/serial/8250/8250_port.c
+++ b/drivers/tty/serial/8250/8250_port.c
@@ -354,22 +354,6 @@ static void default_serial_dl_write(struct uart_8250_port *up, u32 value)
serial_out(up, UART_DLM, value >> 8 & 0xff);
}
-#ifdef CONFIG_HAS_IOPORT
-static u32 hub6_serial_in(struct uart_port *p, unsigned int offset)
-{
- offset = offset << p->regshift;
- outb(p->hub6 - 1 + offset, p->iobase);
- return inb(p->iobase + 1);
-}
-
-static void hub6_serial_out(struct uart_port *p, unsigned int offset, u32 value)
-{
- offset = offset << p->regshift;
- outb(p->hub6 - 1 + offset, p->iobase);
- outb(value, p->iobase + 1);
-}
-#endif /* CONFIG_HAS_IOPORT */
-
static u32 mem_serial_in(struct uart_port *p, unsigned int offset)
{
offset = offset << p->regshift;
@@ -450,13 +434,6 @@ static void set_io_from_upio(struct uart_port *p)
up->dl_write = default_serial_dl_write;
switch (p->iotype) {
-#ifdef CONFIG_HAS_IOPORT
- case UPIO_HUB6:
- p->serial_in = hub6_serial_in;
- p->serial_out = hub6_serial_out;
- break;
-#endif
-
case UPIO_MEM:
p->serial_in = mem_serial_in;
p->serial_out = mem_serial_out;
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 82e761b8298a..9917b7e1bb26 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -208,9 +208,9 @@ config SERIAL_8250_EXTENDED
depends on SERIAL_8250
help
If you wish to use any non-standard features of the standard "dumb"
- driver, say Y here. This includes HUB6 support, shared serial
- interrupts, special multiport support, support for more than the
- four COM 1/2/3/4 boards, etc.
+ driver, say Y here. This includes shared serial interrupts, special
+ multiport support, support for more than the four COM 1/2/3/4 boards,
+ etc.
Note that the answer to this question won't directly affect the
kernel: saying N will just cause the configurator to skip all
@@ -303,15 +303,6 @@ config SERIAL_8250_EXAR_ST16C554
To compile this driver as a module, choose M here: the module
will be called 8250_exar_st16c554.
-config SERIAL_8250_HUB6
- bool "Support Hub6 cards"
- depends on SERIAL_8250_MANY_PORTS && ISA
- help
- Say Y here if you have a HUB6 serial board.
-
- To compile this driver as a module, choose M here: the module
- will be called 8250_hub6.
-
config SERIAL_8250_PCI1XXXX
tristate "Microchip 8250 based serial port"
depends on SERIAL_8250 && PCI
diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
index 5ff2ba414e13..d241ce486953 100644
--- a/drivers/tty/serial/8250/Makefile
+++ b/drivers/tty/serial/8250/Makefile
@@ -7,7 +7,6 @@ obj-$(CONFIG_SERIAL_8250) += 8250.o
8250-y := 8250_core.o
8250-y += 8250_platform.o
8250-$(CONFIG_SERIAL_8250_PNP) += 8250_pnp.o
-8250-$(CONFIG_SERIAL_8250_HUB6) += 8250_hub6.o
obj-$(CONFIG_SERIAL_8250) += 8250_base.o
8250_base-y := 8250_port.o
diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
index c3880259e3bc..9c40ccee0c82 100644
--- a/drivers/tty/serial/atmel_serial.c
+++ b/drivers/tty/serial/atmel_serial.c
@@ -2448,8 +2448,6 @@ static int atmel_verify_port(struct uart_port *port, struct serial_struct *ser)
ret = -EINVAL;
if (port->iobase != ser->port)
ret = -EINVAL;
- if (ser->hub6 != 0)
- ret = -EINVAL;
return ret;
}
diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
index c8575c965203..6e1248840022 100644
--- a/drivers/tty/serial/fsl_lpuart.c
+++ b/drivers/tty/serial/fsl_lpuart.c
@@ -2432,8 +2432,6 @@ static int lpuart_verify_port(struct uart_port *port, struct serial_struct *ser)
ret = -EINVAL;
if (port->iobase != ser->port)
ret = -EINVAL;
- if (ser->hub6 != 0)
- ret = -EINVAL;
return ret;
}
diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
index 986fefb45c63..d89be62e3852 100644
--- a/drivers/tty/serial/imx.c
+++ b/drivers/tty/serial/imx.c
@@ -1936,8 +1936,6 @@ imx_uart_verify_port(struct uart_port *port, struct serial_struct *ser)
ret = -EINVAL;
if (port->iobase != ser->port)
ret = -EINVAL;
- if (ser->hub6 != 0)
- ret = -EINVAL;
return ret;
}
diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
index 472ec39caf27..240009333fb5 100644
--- a/drivers/tty/serial/mpc52xx_uart.c
+++ b/drivers/tty/serial/mpc52xx_uart.c
@@ -1339,8 +1339,7 @@ mpc52xx_uart_verify_port(struct uart_port *port, struct serial_struct *ser)
if ((ser->irq != port->irq) ||
(ser->io_type != UPIO_MEM) ||
(ser->baud_base != port->uartclk) ||
- (ser->iomem_base != (void *)port->mapbase) ||
- (ser->hub6 != 0))
+ (ser->iomem_base != (void *)port->mapbase))
return -EINVAL;
return 0;
diff --git a/drivers/tty/serial/sa1100.c b/drivers/tty/serial/sa1100.c
index 72b1bb76415c..ee5f3960d1e4 100644
--- a/drivers/tty/serial/sa1100.c
+++ b/drivers/tty/serial/sa1100.c
@@ -556,8 +556,6 @@ sa1100_verify_port(struct uart_port *port, struct serial_struct *ser)
ret = -EINVAL;
if (sport->port.iobase != ser->port)
ret = -EINVAL;
- if (ser->hub6 != 0)
- ret = -EINVAL;
return ret;
}
diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
index 9eea8d1a0e8a..15d8c3ed6edc 100644
--- a/drivers/tty/serial/serial_core.c
+++ b/drivers/tty/serial/serial_core.c
@@ -812,7 +812,7 @@ static int uart_get_info(struct tty_port *port, struct serial_struct *retinfo)
ASYNC_CLOSING_WAIT_NONE :
jiffies_to_msecs(port->closing_wait) / 10;
retinfo->custom_divisor = uport->custom_divisor;
- retinfo->hub6 = uport->hub6;
+ retinfo->hub6 = 0;
retinfo->io_type = uport->iotype;
retinfo->iomem_reg_shift = uport->regshift;
retinfo->iomem_base = (void *)(unsigned long)uport->mapbase;
@@ -834,13 +834,12 @@ static int uart_change_port(struct uart_port *uport,
unsigned long new_port)
{
unsigned long old_iobase, old_mapbase;
- unsigned int old_type, old_iotype, old_hub6, old_shift;
+ unsigned int old_type, old_iotype, old_shift;
int retval;
old_iobase = uport->iobase;
old_mapbase = uport->mapbase;
old_type = uport->type;
- old_hub6 = uport->hub6;
old_iotype = uport->iotype;
old_shift = uport->regshift;
@@ -849,7 +848,6 @@ static int uart_change_port(struct uart_port *uport,
uport->iobase = new_port;
uport->type = new_info->type;
- uport->hub6 = new_info->hub6;
uport->iotype = new_info->io_type;
uport->regshift = new_info->iomem_reg_shift;
uport->mapbase = (unsigned long)new_info->iomem_base;
@@ -867,7 +865,6 @@ static int uart_change_port(struct uart_port *uport,
*/
uport->iobase = old_iobase;
uport->type = old_type;
- uport->hub6 = old_hub6;
uport->iotype = old_iotype;
uport->regshift = old_shift;
uport->mapbase = old_mapbase;
@@ -924,7 +921,6 @@ static int uart_set_info(struct tty_struct *tty, struct tty_port *port,
change_port = !(uport->flags & UPF_FIXED_PORT)
&& (new_port != uport->iobase ||
(unsigned long)new_info->iomem_base != uport->mapbase ||
- new_info->hub6 != uport->hub6 ||
new_info->io_type != uport->iotype ||
new_info->iomem_reg_shift != uport->regshift ||
new_info->type != uport->type);
@@ -954,6 +950,10 @@ static int uart_set_info(struct tty_struct *tty, struct tty_port *port,
goto check_and_exit;
}
+ /* hub6 is no longer support */
+ if (new_info->hub6 != 0)
+ return -EINVAL;
+
if (change_irq || change_port) {
retval = security_locked_down(LOCKDOWN_TIOCSSERIAL);
if (retval)
@@ -2010,7 +2010,6 @@ bool uart_iotype_io(enum uart_iotype iotype)
{
switch (iotype) {
case UPIO_PORT:
- case UPIO_HUB6:
return true;
default:
return false;
@@ -2538,10 +2537,7 @@ void uart_get_ioinfos(struct uart_port *port, char *buf, size_t size)
if (uart_iotype_mmio(port->iotype)) {
scnprintf(buf, size, " MMIO%s:%pa", uart_get_mmio_width(port), &port->mapbase);
} else if (uart_iotype_io(port->iotype)) {
- if (port->iotype == UPIO_PORT)
- scnprintf(buf, size, " I/O:0x%lx", port->iobase);
- else if (port->iotype == UPIO_HUB6)
- scnprintf(buf, size, " I/O:0x%lx, offset 0x%x", port->iobase, port->hub6);
+ scnprintf(buf, size, " I/O:0x%lx", port->iobase);
}
}
EXPORT_SYMBOL(uart_get_ioinfos);
diff --git a/drivers/tty/serial/sunsu.c b/drivers/tty/serial/sunsu.c
index 4ff3e5c41dab..f43b802add12 100644
--- a/drivers/tty/serial/sunsu.c
+++ b/drivers/tty/serial/sunsu.c
@@ -106,10 +106,6 @@ static unsigned int serial_in(struct uart_sunsu_port *up, int offset)
offset <<= up->port.regshift;
switch (up->port.iotype) {
- case UPIO_HUB6:
- outb(up->port.hub6 - 1 + offset, up->port.iobase);
- return inb(up->port.iobase + 1);
-
case UPIO_MEM:
return readb(up->port.membase + offset);
@@ -136,11 +132,6 @@ static void serial_out(struct uart_sunsu_port *up, int offset, int value)
offset <<= up->port.regshift;
switch (up->port.iotype) {
- case UPIO_HUB6:
- outb(up->port.hub6 - 1 + offset, up->port.iobase);
- outb(value, up->port.iobase + 1);
- break;
-
case UPIO_MEM:
writeb(value, up->port.membase + offset);
break;
diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c
index a072b75dbaf2..4066cc99fe1a 100644
--- a/drivers/tty/serial/xilinx_uartps.c
+++ b/drivers/tty/serial/xilinx_uartps.c
@@ -1079,8 +1079,6 @@ static int cdns_uart_verify_port(struct uart_port *port,
return -EINVAL;
if (port->iobase != ser->port)
return -EINVAL;
- if (ser->hub6 != 0)
- return -EINVAL;
return 0;
}
diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
index d91c0477be9d..d55bce4d4709 100644
--- a/include/linux/serial_8250.h
+++ b/include/linux/serial_8250.h
@@ -41,7 +41,6 @@ struct plat_serial8250_port {
void *private_data;
unsigned char regshift; /* register shift */
unsigned char iotype; /* UPIO_* */
- unsigned char hub6;
unsigned char has_sysrq; /* supports magic SysRq */
unsigned int type; /* If UPF_FIXED_TYPE */
upf_t flags; /* UPF_* flags */
@@ -75,7 +74,6 @@ enum {
PLAT8250_DEV_ACCENT,
PLAT8250_DEV_BOCA,
PLAT8250_DEV_EXAR_ST16C554,
- PLAT8250_DEV_HUB6,
PLAT8250_DEV_AU1X00,
PLAT8250_DEV_SM501,
};
diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
index 4eeb8253752a..ca8d009e5c36 100644
--- a/include/linux/serial_core.h
+++ b/include/linux/serial_core.h
@@ -430,7 +430,6 @@ typedef unsigned int __bitwise upstat_t;
enum uart_iotype {
UPIO_UNKNOWN = -1,
UPIO_PORT = SERIAL_IO_PORT, /* 8b I/O port access */
- UPIO_HUB6 = SERIAL_IO_HUB6, /* Hub6 ISA card */
UPIO_MEM = SERIAL_IO_MEM, /* driver-specific */
UPIO_MEM32 = SERIAL_IO_MEM32, /* 32b little endian */
UPIO_AU = SERIAL_IO_AU, /* Au1x00 and RT288x type IO */
@@ -590,7 +589,6 @@ struct uart_port {
unsigned char has_sysrq;
unsigned char sysrq_seq; /* index in sysrq_toggle_seq */
- unsigned char hub6; /* this should be in the 8250 driver */
unsigned char suspended;
unsigned char console_reinit;
const char *name; /* port name */
--
2.53.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* [PATCH 2/2] [v2] serial: 8250: remove obsolete and broken PORT_RSA support
2026-10-16 12:59 [PATCH 1/2] tty: serial: remove hub6 multiport support Arnd Bergmann
@ 2026-10-16 12:59 ` Arnd Bergmann
2026-10-16 13:14 ` Arnd Bergmann
2026-10-16 13:28 ` [PATCH 1/2] tty: serial: remove hub6 multiport support Andy Shevchenko
` (5 subsequent siblings)
6 siblings, 1 reply; 14+ messages in thread
From: Arnd Bergmann @ 2026-10-16 12:59 UTC (permalink / raw)
To: Greg Kroah-Hartman, Jiri Slaby
Cc: Arnd Bergmann, linux-kernel, linux-serial, linux-arm-kernel, imx,
Andy Shevchenko, Hugo Villeneuve,
Uwe Kleine-König (The Capable Hub)
From: Arnd Bergmann <arnd@arndb.de>
For all I can tell, the RSA support in the 8250 driver is not functional
and has not been for a long time.
The RSA-DV II/S ISA card[1] was sold by IODATA in the 1990s as a faster
alternative to regular ISA serial ports, and it was discontinued in
2002. Linux support was added by Kiyokazu SUTO in 2000.
The driver defines an I/O port base address of -8 (negative eight),
which should always get refused by request_region on all architectures
for being outside of the valid resource range.
Further, it seems that a patch to setserial would be required in order
to set PORT_RSA when not using autoconfiguration.
This patch removes all code related to the RSA support, with the exception
of the user-visible PORT_RSA definition.
Link: http://translate.google.com/translate?hl=en&sl=ja&u=http://www.iodata.jp/products/network/rsadv2s.htm
Link: https://lore.kernel.org/all/1309211120-2803-6-git-send-email-arnd@arndb.de/
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
---
v2: rebased my own patch after 15 years
---
drivers/tty/serial/8250/8250.h | 17 --
drivers/tty/serial/8250/8250_core.c | 6 -
drivers/tty/serial/8250/8250_platform.c | 4 -
drivers/tty/serial/8250/8250_port.c | 8 -
drivers/tty/serial/8250/8250_rsa.c | 209 ------------------------
drivers/tty/serial/8250/Kconfig | 11 --
include/uapi/linux/serial_reg.h | 51 ------
7 files changed, 306 deletions(-)
delete mode 100644 drivers/tty/serial/8250/8250_rsa.c
diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h
index 75afeb8c0cef..6225027ed7b4 100644
--- a/drivers/tty/serial/8250/8250.h
+++ b/drivers/tty/serial/8250/8250.h
@@ -126,9 +126,6 @@ void serial8250_isa_init_ports(void);
extern struct platform_device *serial8250_isa_devs;
-extern const struct uart_ops *univ8250_port_base_ops;
-extern struct uart_ops univ8250_port_ops;
-
static inline int serial_in(struct uart_8250_port *up, int offset)
{
return up->port.serial_in(&up->port, offset);
@@ -323,20 +320,6 @@ static inline int serial8250_pnp_init(void) { return 0; }
static inline void serial8250_pnp_exit(void) { }
#endif
-#ifdef CONFIG_SERIAL_8250_RSA
-void univ8250_rsa_support(struct uart_ops *ops, const struct uart_ops *core_ops);
-void rsa_enable(struct uart_8250_port *up);
-void rsa_disable(struct uart_8250_port *up);
-void rsa_autoconfig(struct uart_8250_port *up);
-void rsa_reset(struct uart_8250_port *up);
-#else
-static inline void univ8250_rsa_support(struct uart_ops *ops, const struct uart_ops *core_ops) { }
-static inline void rsa_enable(struct uart_8250_port *up) {}
-static inline void rsa_disable(struct uart_8250_port *up) {}
-static inline void rsa_autoconfig(struct uart_8250_port *up) {}
-static inline void rsa_reset(struct uart_8250_port *up) {}
-#endif
-
#ifdef CONFIG_SERIAL_8250_FINTEK
int fintek_8250_probe(struct uart_8250_port *uart);
#else
diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
index 96c99f0ae683..b9ce22948389 100644
--- a/drivers/tty/serial/8250/8250_core.c
+++ b/drivers/tty/serial/8250/8250_core.c
@@ -307,9 +307,6 @@ static void univ8250_release_irq(struct uart_8250_port *up)
serial_unlink_irq_chain(up);
}
-const struct uart_ops *univ8250_port_base_ops;
-struct uart_ops univ8250_port_ops;
-
static const struct uart_8250_ops univ8250_driver_ops = {
.setup_irq = univ8250_setup_irq,
.release_irq = univ8250_release_irq,
@@ -352,9 +349,6 @@ struct uart_8250_port *serial8250_setup_port(int index)
up->port.port_id = index;
serial8250_init_port(up);
- if (!univ8250_port_base_ops)
- univ8250_port_base_ops = up->port.ops;
- up->port.ops = &univ8250_port_ops;
timer_setup(&up->timer, serial8250_timeout, 0);
diff --git a/drivers/tty/serial/8250/8250_platform.c b/drivers/tty/serial/8250/8250_platform.c
index 8aa769085bfa..1a41a4ac25f8 100644
--- a/drivers/tty/serial/8250/8250_platform.c
+++ b/drivers/tty/serial/8250/8250_platform.c
@@ -73,10 +73,6 @@ static void __init __serial8250_isa_init_ports(void)
for (i = 0; i < nr_uarts; i++)
serial8250_setup_port(i);
- /* chain base port ops to support Remote Supervisor Adapter */
- univ8250_port_ops = *univ8250_port_base_ops;
- univ8250_rsa_support(&univ8250_port_ops, univ8250_port_base_ops);
-
for (i = 0; i < ARRAY_SIZE(old_serial_port) && i < nr_uarts; i++) {
struct uart_8250_port *up = serial8250_get_port(i);
struct uart_port *port = &up->port;
diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
index 3593e7209879..462441237a90 100644
--- a/drivers/tty/serial/8250/8250_port.c
+++ b/drivers/tty/serial/8250/8250_port.c
@@ -1186,8 +1186,6 @@ static void autoconfig(struct uart_8250_port *up)
break;
}
- rsa_autoconfig(up);
-
serial_out(up, UART_LCR, save_lcr);
port->fifosize = uart_config[up->port.type].fifo_size;
@@ -1199,7 +1197,6 @@ static void autoconfig(struct uart_8250_port *up)
/*
* Reset the UART.
*/
- rsa_reset(up);
serial8250_out_MCR(up, save_mcr);
serial8250_clear_fifos(up);
serial_in(up, UART_RX);
@@ -2156,9 +2153,6 @@ static void serial8250_startup_special(struct uart_port *port)
UART_DA830_PWREMU_MGMT_URRST |
UART_DA830_PWREMU_MGMT_FREE);
break;
- case PORT_RSA:
- rsa_enable(up);
- break;
}
}
@@ -2450,8 +2444,6 @@ void serial8250_do_shutdown(struct uart_port *port)
serial8250_clear_fifos(up);
- rsa_disable(up);
-
/*
* Read data port to reset things, and then unlink from
* the IRQ chain.
diff --git a/drivers/tty/serial/8250/8250_rsa.c b/drivers/tty/serial/8250/8250_rsa.c
deleted file mode 100644
index da971437e89c..000000000000
--- a/drivers/tty/serial/8250/8250_rsa.c
+++ /dev/null
@@ -1,209 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0+
-
-#include <linux/errno.h>
-#include <linux/ioport.h>
-#include <linux/module.h>
-#include <linux/moduleparam.h>
-
-#include <linux/serial.h>
-#include <linux/serial_8250.h>
-
-#include "8250.h"
-
-#define PORT_RSA_MAX 4
-static unsigned long probe_rsa[PORT_RSA_MAX];
-static unsigned int probe_rsa_count;
-
-static const struct uart_ops *core_port_base_ops;
-
-static int rsa8250_request_resource(struct uart_8250_port *up)
-{
- struct uart_port *port = &up->port;
- unsigned long start;
- unsigned int size;
-
- if (!uart_iotype_io(port->iotype))
- return -EINVAL;
-
- start = UART_RSA_BASE << port->regshift;
- start += port->iobase;
- size = 8 << port->regshift;
-
- if (!request_region(start, size, "serial-rsa"))
- return -EBUSY;
- return 0;
-}
-
-static void rsa8250_release_resource(struct uart_8250_port *up)
-{
- struct uart_port *port = &up->port;
- unsigned long offset;
- unsigned int size;
-
- if (!uart_iotype_io(port->iotype))
- return;
-
- offset = UART_RSA_BASE << port->regshift;
- size = 8 << port->regshift;
- release_region(port->iobase + offset, size);
-}
-
-static void univ8250_config_port(struct uart_port *port, int flags)
-{
- struct uart_8250_port *up = up_to_u8250p(port);
- unsigned int i;
-
- up->probe &= ~UART_PROBE_RSA;
- if (port->type == PORT_RSA) {
- if (rsa8250_request_resource(up) == 0)
- up->probe |= UART_PROBE_RSA;
- } else if (flags & UART_CONFIG_TYPE) {
- for (i = 0; i < probe_rsa_count; i++) {
- if (probe_rsa[i] == up->port.iobase) {
- if (rsa8250_request_resource(up) == 0)
- up->probe |= UART_PROBE_RSA;
- break;
- }
- }
- }
-
- core_port_base_ops->config_port(port, flags);
-
- if (port->type != PORT_RSA && up->probe & UART_PROBE_RSA)
- rsa8250_release_resource(up);
-}
-
-static int univ8250_request_port(struct uart_port *port)
-{
- struct uart_8250_port *up = up_to_u8250p(port);
- int ret;
-
- ret = core_port_base_ops->request_port(port);
- if (ret == 0 && port->type == PORT_RSA) {
- ret = rsa8250_request_resource(up);
- if (ret < 0)
- core_port_base_ops->release_port(port);
- }
-
- return ret;
-}
-
-static void univ8250_release_port(struct uart_port *port)
-{
- struct uart_8250_port *up = up_to_u8250p(port);
-
- if (port->type == PORT_RSA)
- rsa8250_release_resource(up);
- core_port_base_ops->release_port(port);
-}
-
-/*
- * It is not allowed to directly reference any symbols from 8250.ko here as
- * that would result in a dependency loop between the 8250.ko and
- * 8250_base.ko modules. This function is called from 8250.ko and is used to
- * break the symbolic dependency cycle. Anything that is needed from 8250.ko
- * has to be passed as pointers to this function which then can adjust those
- * variables on 8250.ko side or store them locally as needed.
- */
-void univ8250_rsa_support(struct uart_ops *ops, const struct uart_ops *core_ops)
-{
- core_port_base_ops = core_ops;
- ops->config_port = univ8250_config_port;
- ops->request_port = univ8250_request_port;
- ops->release_port = univ8250_release_port;
-}
-EXPORT_SYMBOL_FOR_MODULES(univ8250_rsa_support, "8250");
-
-module_param_hw_array(probe_rsa, ulong, ioport, &probe_rsa_count, 0444);
-MODULE_PARM_DESC(probe_rsa, "Probe I/O ports for RSA");
-
-/*
- * Attempts to turn on the RSA FIFO. Returns zero on failure.
- * We set the port uart clock rate if we succeed.
- */
-static int __rsa_enable(struct uart_8250_port *up)
-{
- unsigned char mode;
- int result;
-
- mode = serial_in(up, UART_RSA_MSR);
- result = mode & UART_RSA_MSR_FIFO;
-
- if (!result) {
- serial_out(up, UART_RSA_MSR, mode | UART_RSA_MSR_FIFO);
- mode = serial_in(up, UART_RSA_MSR);
- result = mode & UART_RSA_MSR_FIFO;
- }
-
- if (result)
- up->port.uartclk = SERIAL_RSA_BAUD_BASE * 16;
-
- return result;
-}
-
-/*
- * If this is an RSA port, see if we can kick it up to the higher speed clock.
- */
-void rsa_enable(struct uart_8250_port *up)
-{
- if (up->port.type != PORT_RSA)
- return;
-
- if (up->port.uartclk != SERIAL_RSA_BAUD_BASE * 16) {
- guard(uart_port_lock_irq)(&up->port);
- __rsa_enable(up);
- }
- if (up->port.uartclk == SERIAL_RSA_BAUD_BASE * 16)
- serial_out(up, UART_RSA_FRR, 0);
-}
-
-/*
- * Attempts to turn off the RSA FIFO and resets the RSA board back to 115kbps compat mode. It is
- * unknown why interrupts were disabled in here. However, the caller is expected to preserve this
- * behaviour by grabbing the spinlock before calling this function.
- */
-void rsa_disable(struct uart_8250_port *up)
-{
- unsigned char mode;
- int result;
-
- if (up->port.type != PORT_RSA)
- return;
-
- if (up->port.uartclk != SERIAL_RSA_BAUD_BASE * 16)
- return;
-
- guard(uart_port_lock_irq)(&up->port);
-
- mode = serial_in(up, UART_RSA_MSR);
- result = !(mode & UART_RSA_MSR_FIFO);
-
- if (!result) {
- serial_out(up, UART_RSA_MSR, mode & ~UART_RSA_MSR_FIFO);
- mode = serial_in(up, UART_RSA_MSR);
- result = !(mode & UART_RSA_MSR_FIFO);
- }
-
- if (result)
- up->port.uartclk = SERIAL_RSA_BAUD_BASE_LO * 16;
-}
-
-void rsa_autoconfig(struct uart_8250_port *up)
-{
- /* Only probe for RSA ports if we got the region. */
- if (up->port.type != PORT_16550A)
- return;
- if (!(up->probe & UART_PROBE_RSA))
- return;
-
- if (__rsa_enable(up))
- up->port.type = PORT_RSA;
-}
-
-void rsa_reset(struct uart_8250_port *up)
-{
- if (up->port.type != PORT_RSA)
- return;
-
- serial_out(up, UART_RSA_FRR, 0);
-}
diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
index 9917b7e1bb26..908fc86852b6 100644
--- a/drivers/tty/serial/8250/Kconfig
+++ b/drivers/tty/serial/8250/Kconfig
@@ -236,17 +236,6 @@ config SERIAL_8250_DETECT_IRQ
If unsure, say N.
-config SERIAL_8250_RSA
- bool "Support RSA serial ports"
- depends on SERIAL_8250_EXTENDED
- help
- Say Y here if you have a IODATA RSA-DV II/S ISA card and
- would like to use its >115kbps speeds.
- You will need to provide module parameter "probe_rsa", or boot-time
- parameter 8250.probe_rsa with I/O addresses of this card then.
-
- If you don't have such card, or if unsure, say N.
-
config SERIAL_8250_MANY_PORTS
bool "Support more than 4 legacy serial ports"
depends on SERIAL_8250_EXTENDED
diff --git a/include/uapi/linux/serial_reg.h b/include/uapi/linux/serial_reg.h
index 9c987b04e2d0..e4f288b557ca 100644
--- a/include/uapi/linux/serial_reg.h
+++ b/include/uapi/linux/serial_reg.h
@@ -285,57 +285,6 @@
#define UART_ACR_ICRRD 0x40 /* ICR Read enable */
#define UART_ACR_ASREN 0x80 /* Additional status enable */
-
-
-/*
- * These definitions are for the RSA-DV II/S card, from
- *
- * Kiyokazu SUTO <suto@ks-and-ks.ne.jp>
- */
-
-#define UART_RSA_BASE (-8)
-
-#define UART_RSA_MSR ((UART_RSA_BASE) + 0) /* I/O: Mode Select Register */
-
-#define UART_RSA_MSR_SWAP (1 << 0) /* Swap low/high 8 bytes in I/O port addr */
-#define UART_RSA_MSR_FIFO (1 << 2) /* Enable the external FIFO */
-#define UART_RSA_MSR_FLOW (1 << 3) /* Enable the auto RTS/CTS flow control */
-#define UART_RSA_MSR_ITYP (1 << 4) /* Level (1) / Edge triger (0) */
-
-#define UART_RSA_IER ((UART_RSA_BASE) + 1) /* I/O: Interrupt Enable Register */
-
-#define UART_RSA_IER_Rx_FIFO_H (1 << 0) /* Enable Rx FIFO half full int. */
-#define UART_RSA_IER_Tx_FIFO_H (1 << 1) /* Enable Tx FIFO half full int. */
-#define UART_RSA_IER_Tx_FIFO_E (1 << 2) /* Enable Tx FIFO empty int. */
-#define UART_RSA_IER_Rx_TOUT (1 << 3) /* Enable char receive timeout int */
-#define UART_RSA_IER_TIMER (1 << 4) /* Enable timer interrupt */
-
-#define UART_RSA_SRR ((UART_RSA_BASE) + 2) /* IN: Status Read Register */
-
-#define UART_RSA_SRR_Tx_FIFO_NEMP (1 << 0) /* Tx FIFO is not empty (1) */
-#define UART_RSA_SRR_Tx_FIFO_NHFL (1 << 1) /* Tx FIFO is not half full (1) */
-#define UART_RSA_SRR_Tx_FIFO_NFUL (1 << 2) /* Tx FIFO is not full (1) */
-#define UART_RSA_SRR_Rx_FIFO_NEMP (1 << 3) /* Rx FIFO is not empty (1) */
-#define UART_RSA_SRR_Rx_FIFO_NHFL (1 << 4) /* Rx FIFO is not half full (1) */
-#define UART_RSA_SRR_Rx_FIFO_NFUL (1 << 5) /* Rx FIFO is not full (1) */
-#define UART_RSA_SRR_Rx_TOUT (1 << 6) /* Character reception timeout occurred (1) */
-#define UART_RSA_SRR_TIMER (1 << 7) /* Timer interrupt occurred */
-
-#define UART_RSA_FRR ((UART_RSA_BASE) + 2) /* OUT: FIFO Reset Register */
-
-#define UART_RSA_TIVSR ((UART_RSA_BASE) + 3) /* I/O: Timer Interval Value Set Register */
-
-#define UART_RSA_TCR ((UART_RSA_BASE) + 4) /* OUT: Timer Control Register */
-
-#define UART_RSA_TCR_SWITCH (1 << 0) /* Timer on */
-
-/*
- * The RSA DSV/II board has two fixed clock frequencies. One is the
- * standard rate, and the other is 8 times faster.
- */
-#define SERIAL_RSA_BAUD_BASE (921600)
-#define SERIAL_RSA_BAUD_BASE_LO (SERIAL_RSA_BAUD_BASE / 8)
-
/* Extra registers for TI DA8xx/66AK2x */
#define UART_DA830_PWREMU_MGMT 12
--
2.53.0
^ permalink raw reply related [flat|nested] 14+ messages in thread
* Re: [PATCH 2/2] [v2] serial: 8250: remove obsolete and broken PORT_RSA support
2026-10-16 12:59 ` [PATCH 2/2] [v2] serial: 8250: remove obsolete and broken PORT_RSA support Arnd Bergmann
@ 2026-10-16 13:14 ` Arnd Bergmann
0 siblings, 0 replies; 14+ messages in thread
From: Arnd Bergmann @ 2026-10-16 13:14 UTC (permalink / raw)
To: Arnd Bergmann, Greg Kroah-Hartman, Jiri Slaby
Cc: linux-kernel, linux-serial, linux-arm-kernel, imx,
Andy Shevchenko, Hugo Villeneuve, Uwe Kleine-König
On Fri, Oct 16, 2026, at 14:59, Arnd Bergmann wrote:
> Link:
> http://translate.google.com/translate?hl=en&sl=ja&u=http://www.iodata.jp/products/network/rsadv2s.htm
> Link:
> https://lore.kernel.org/all/1309211120-2803-6-git-send-email-arnd@arndb.de/
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> ---
> v2: rebased my own patch after 15 years
> ---
> drivers/tty/serial/8250/8250.h | 17 --
> drivers/tty/serial/8250/8250_core.c | 6 -
> drivers/tty/serial/8250/8250_platform.c | 4 -
> drivers/tty/serial/8250/8250_port.c | 8 -
> drivers/tty/serial/8250/8250_rsa.c | 209 ------------------------
> drivers/tty/serial/8250/Kconfig | 11 --
> include/uapi/linux/serial_reg.h | 51 ------
I had this one in my testing tree for several years but it
looks like I lost the necessary Makefile change, and
the corresponding change to drivers/tty/serial/sunsu.c.
Arnd
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 1/2] tty: serial: remove hub6 multiport support
2026-10-16 12:59 [PATCH 1/2] tty: serial: remove hub6 multiport support Arnd Bergmann
2026-10-16 12:59 ` [PATCH 2/2] [v2] serial: 8250: remove obsolete and broken PORT_RSA support Arnd Bergmann
@ 2026-10-16 13:28 ` Andy Shevchenko
2026-10-16 14:41 ` Arnd Bergmann
2026-10-16 13:32 ` Andy Shevchenko
` (4 subsequent siblings)
6 siblings, 1 reply; 14+ messages in thread
From: Andy Shevchenko @ 2026-10-16 13:28 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Greg Kroah-Hartman, Jiri Slaby,
Uwe Kleine-König (The Capable Hub), Hugo Villeneuve,
Arnd Bergmann, linux-kernel, linux-serial, linux-arm-kernel, imx
On Fri, Oct 16, 2026 at 02:59:47PM +0200, Arnd Bergmann wrote:
>
> hub6 support was added in linux-0.99 and the hardware was already old at
> the time, being discontinued in 1990. The code for it has always been a
> mess since it adds another dimension to the I/O addressing in the driver
> that has leaked into many individual files.
>
> Hugo and Uwe have attempted several times this year alone to isolate
> the hub6 handling into the 8250_hub6.c file, but I feel that none of
> this has been a real improvement over the original standalone loadable
> module support.
>
> Any machine that would have used this ISA card in practice is likely
> 30 to 40 years old, and with i486 support now removed, it is clearly
> safe to just kill this all off.
Please!
> The only bit that has to remain
> is the ioctl interface, to ensure the serial_struct field is always
> zero.
Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
But there are some minor issues to fix, see below.
...
> {
> unsigned long old_iobase, old_mapbase;
> - unsigned int old_type, old_iotype, old_hub6, old_shift;
> + unsigned int old_type, old_iotype, old_shift;
Move it line up, so we will have reversed xmas tree order.
> int retval;
...
> + /* hub6 is no longer support */
> + if (new_info->hub6 != 0)
> + return -EINVAL;
Please, fix the indentation, should use tabs.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 1/2] tty: serial: remove hub6 multiport support
2026-10-16 12:59 [PATCH 1/2] tty: serial: remove hub6 multiport support Arnd Bergmann
2026-10-16 12:59 ` [PATCH 2/2] [v2] serial: 8250: remove obsolete and broken PORT_RSA support Arnd Bergmann
2026-10-16 13:28 ` [PATCH 1/2] tty: serial: remove hub6 multiport support Andy Shevchenko
@ 2026-10-16 13:32 ` Andy Shevchenko
2026-10-16 14:10 ` Hugo Villeneuve
` (3 subsequent siblings)
6 siblings, 0 replies; 14+ messages in thread
From: Andy Shevchenko @ 2026-10-16 13:32 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Greg Kroah-Hartman, Jiri Slaby,
Uwe Kleine-König (The Capable Hub), Hugo Villeneuve,
Arnd Bergmann, linux-kernel, linux-serial, linux-arm-kernel, imx
On Fri, Oct 16, 2026 at 02:59:47PM +0200, Arnd Bergmann wrote:
> hub6 support was added in linux-0.99 and the hardware was already old at
> the time, being discontinued in 1990. The code for it has always been a
> mess since it adds another dimension to the I/O addressing in the driver
> that has leaked into many individual files.
>
> Hugo and Uwe have attempted several times this year alone to isolate
> the hub6 handling into the 8250_hub6.c file, but I feel that none of
> this has been a real improvement over the original standalone loadable
> module support.
>
> Any machine that would have used this ISA card in practice is likely
> 30 to 40 years old, and with i486 support now removed, it is clearly
> safe to just kill this all off. The only bit that has to remain
> is the ioctl interface, to ensure the serial_struct field is always
> zero.
After reading patch 2/2 I noticed also a SERIAL_IO_HUB6 leftover. Most likely
it should stay as is until the user space gets rid of the use.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 1/2] tty: serial: remove hub6 multiport support
2026-10-16 12:59 [PATCH 1/2] tty: serial: remove hub6 multiport support Arnd Bergmann
` (2 preceding siblings ...)
2026-10-16 13:32 ` Andy Shevchenko
@ 2026-10-16 14:10 ` Hugo Villeneuve
2026-10-16 15:56 ` Hugo Villeneuve
` (2 subsequent siblings)
6 siblings, 0 replies; 14+ messages in thread
From: Hugo Villeneuve @ 2026-10-16 14:10 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Greg Kroah-Hartman, Jiri Slaby, Andy Shevchenko,
Uwe Kleine-König, Hugo Villeneuve, Arnd Bergmann,
linux-kernel, linux-serial, linux-arm-kernel, imx
Hi Arnd,
On Fri, 16 Oct 2026 14:59:47 +0200
Arnd Bergmann <arnd@kernel.org> wrote:
> From: Arnd Bergmann <arnd@arndb.de>
>
> hub6 support was added in linux-0.99 and the hardware was already old at
> the time, being discontinued in 1990. The code for it has always been a
> mess since it adds another dimension to the I/O addressing in the driver
> that has leaked into many individual files.
>
> Hugo and Uwe have attempted several times this year alone to isolate
> the hub6 handling into the 8250_hub6.c file, but I feel that none of
> this has been a real improvement over the original standalone loadable
> module support.
>
> Any machine that would have used this ISA card in practice is likely
> 30 to 40 years old, and with i486 support now removed, it is clearly
> safe to just kill this all off. The only bit that has to remain
> is the ioctl interface, to ensure the serial_struct field is always
> zero.
>
> Link: https://mirrors.nycbug.org/pub/The_Unix_Archive/Unix_Usenet/comp.unix.sysv386/1990-December/007174.html
> Fixes: a300273c458c ("serial: 8250: hub6: Add cleanup code")
> Fixes: c526404a4a92 ("serial: 8250: Fix corner case for port matching")
> Fixes: 7ab80d1e7243 ("serial: 8250: fix compile error with hub6_match_port() when compiled as a module")
> Fixes: da7b5fd4e17f ("serial: 8250_hub6: add missing include for hub6_match_port()")
> Fixes: 3d406299d882 ("serial: 8250_hub6: add hub6_match_port()")
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> ---
> drivers/tty/serial/8250/8250.h | 15 -------
> drivers/tty/serial/8250/8250_core.c | 2 -
> drivers/tty/serial/8250/8250_hub6.c | 60 -------------------------
> drivers/tty/serial/8250/8250_platform.c | 11 +----
> drivers/tty/serial/8250/8250_port.c | 23 ----------
> drivers/tty/serial/8250/Kconfig | 15 ++-----
> drivers/tty/serial/8250/Makefile | 1 -
> drivers/tty/serial/atmel_serial.c | 2 -
> drivers/tty/serial/fsl_lpuart.c | 2 -
> drivers/tty/serial/imx.c | 2 -
> drivers/tty/serial/mpc52xx_uart.c | 3 +-
> drivers/tty/serial/sa1100.c | 2 -
> drivers/tty/serial/serial_core.c | 18 +++-----
> drivers/tty/serial/sunsu.c | 9 ----
> drivers/tty/serial/xilinx_uartps.c | 2 -
> include/linux/serial_8250.h | 2 -
> include/linux/serial_core.h | 2 -
> 17 files changed, 12 insertions(+), 159 deletions(-)
> delete mode 100644 drivers/tty/serial/8250/8250_hub6.c
>
> diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h
> index 21ed9c41b751..75afeb8c0cef 100644
> --- a/drivers/tty/serial/8250/8250.h
> +++ b/drivers/tty/serial/8250/8250.h
> @@ -323,14 +323,6 @@ static inline int serial8250_pnp_init(void) { return 0; }
> static inline void serial8250_pnp_exit(void) { }
> #endif
>
> -#ifdef CONFIG_SERIAL_8250_HUB6
> -int serial8250_hub6_init(void);
> -void serial8250_hub6_exit(void);
> -#else
> -static inline int serial8250_hub6_init(void) { return 0; }
> -static inline void serial8250_hub6_exit(void) { }
> -#endif
> -
> #ifdef CONFIG_SERIAL_8250_RSA
> void univ8250_rsa_support(struct uart_ops *ops, const struct uart_ops *core_ops);
> void rsa_enable(struct uart_8250_port *up);
> @@ -351,13 +343,6 @@ int fintek_8250_probe(struct uart_8250_port *uart);
> static inline int fintek_8250_probe(struct uart_8250_port *uart) { return 0; }
> #endif
>
> -#if IS_ENABLED(CONFIG_SERIAL_8250_HUB6)
> -bool hub6_match_port(const struct uart_port *port1, const struct uart_port *port2);
> -#else
> -static inline bool hub6_match_port(const struct uart_port *port1, const struct uart_port *port2)
> -{ return false; }
> -#endif
> -
> #ifdef CONFIG_ARCH_OMAP1
> #include <linux/soc/ti/omap1-soc.h>
> static inline int is_omap1_8250(struct uart_8250_port *pt)
> diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
> index 42319843cb5b..96c99f0ae683 100644
> --- a/drivers/tty/serial/8250/8250_core.c
> +++ b/drivers/tty/serial/8250/8250_core.c
> @@ -686,8 +686,6 @@ static bool serial8250_match_port(const struct uart_port *port1,
> return false;
> else if (port1->iotype == UPIO_PORT)
> return port1->iobase == port2->iobase;
> - else if (port1->iotype == UPIO_HUB6)
> - return hub6_match_port(port1, port2);
> else if (uart_iotype_mmio(port1->iotype))
> return port1->mapbase == port2->mapbase;
> else
> diff --git a/drivers/tty/serial/8250/8250_hub6.c b/drivers/tty/serial/8250/8250_hub6.c
> deleted file mode 100644
> index 848d9723ac56..000000000000
> --- a/drivers/tty/serial/8250/8250_hub6.c
> +++ /dev/null
> @@ -1,60 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0
> -/*
> - * Copyright (C) 2005 Russell King.
> - * Data taken from include/asm-i386/serial.h
> - */
> -#include <linux/module.h>
> -#include <linux/init.h>
> -#include <linux/serial_8250.h>
> -
> -#include "8250.h"
> -
> -#define HUB6(card, port) \
> - { \
> - .iobase = 0x302, \
> - .irq = 3, \
> - .uartclk = 1843200, \
> - .iotype = UPIO_HUB6, \
> - .flags = UPF_BOOT_AUTOCONF, \
> - .hub6 = (card) << 6 | (port) << 3 | 1, \
> - }
> -
> -static struct plat_serial8250_port hub6_data[] = {
> - HUB6(0, 0),
> - HUB6(0, 1),
> - HUB6(0, 2),
> - HUB6(0, 3),
> - HUB6(0, 4),
> - HUB6(0, 5),
> - HUB6(1, 0),
> - HUB6(1, 1),
> - HUB6(1, 2),
> - HUB6(1, 3),
> - HUB6(1, 4),
> - HUB6(1, 5),
> - { },
> -};
> -
> -static struct platform_device hub6_device = {
> - .name = "serial8250",
> - .id = PLAT8250_DEV_HUB6,
> - .dev = {
> - .platform_data = hub6_data,
> - },
> -};
> -
> -bool hub6_match_port(const struct uart_port *port1, const struct uart_port *port2)
> -{
> - return port1->iobase == port2->iobase && port1->hub6 == port2->hub6;
> -}
> -EXPORT_SYMBOL_GPL(hub6_match_port);
> -
> -int __init serial8250_hub6_init(void)
> -{
> - return platform_device_register(&hub6_device);
> -}
> -
> -void serial8250_hub6_exit(void)
> -{
> - platform_device_unregister(&hub6_device);
> -}
> diff --git a/drivers/tty/serial/8250/8250_platform.c b/drivers/tty/serial/8250/8250_platform.c
> index 7ce7ad295fae..8aa769085bfa 100644
> --- a/drivers/tty/serial/8250/8250_platform.c
> +++ b/drivers/tty/serial/8250/8250_platform.c
> @@ -86,7 +86,6 @@ static void __init __serial8250_isa_init_ports(void)
> port->irqflags = 0;
> port->uartclk = old_serial_port[i].baud_base * 16;
> port->flags = old_serial_port[i].flags;
> - port->hub6 = 0;
> port->membase = old_serial_port[i].iomem_base;
> port->iotype = old_serial_port[i].io_type;
> port->regshift = old_serial_port[i].iomem_reg_shift;
> @@ -169,7 +168,6 @@ static int serial8250_probe_platform(struct platform_device *dev, struct plat_se
> uart->port.flags = p->flags;
> uart->port.mapbase = p->mapbase;
> uart->port.mapsize = p->mapsize;
> - uart->port.hub6 = p->hub6;
> uart->port.has_sysrq = p->has_sysrq;
> uart->port.private_data = p->private_data;
> uart->port.type = p->type;
> @@ -317,14 +315,10 @@ static int __init serial8250_init(void)
> if (ret)
> goto unreg_uart_drv;
>
> - ret = serial8250_hub6_init();
> - if (ret)
> - goto unreg_pnp;
> -
> serial8250_isa_devs = platform_device_alloc("serial8250", PLAT8250_DEV_LEGACY);
> if (!serial8250_isa_devs) {
> ret = -ENOMEM;
> - goto unreg_hub6;
> + goto unreg_pnp;
> }
>
> ret = platform_device_add(serial8250_isa_devs);
> @@ -340,8 +334,6 @@ static int __init serial8250_init(void)
> platform_device_del(serial8250_isa_devs);
> put_dev:
> platform_device_put(serial8250_isa_devs);
> -unreg_hub6:
> - serial8250_hub6_exit();
> unreg_pnp:
> serial8250_pnp_exit();
> unreg_uart_drv:
> @@ -369,7 +361,6 @@ static void __exit serial8250_exit(void)
> platform_driver_unregister(&serial8250_isa_driver);
> platform_device_unregister(isa_dev);
>
> - serial8250_hub6_exit();
> serial8250_pnp_exit();
>
> #ifdef CONFIG_SPARC
> diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
> index 36b2b0a2c05c..3593e7209879 100644
> --- a/drivers/tty/serial/8250/8250_port.c
> +++ b/drivers/tty/serial/8250/8250_port.c
> @@ -354,22 +354,6 @@ static void default_serial_dl_write(struct uart_8250_port *up, u32 value)
> serial_out(up, UART_DLM, value >> 8 & 0xff);
> }
>
> -#ifdef CONFIG_HAS_IOPORT
> -static u32 hub6_serial_in(struct uart_port *p, unsigned int offset)
> -{
> - offset = offset << p->regshift;
> - outb(p->hub6 - 1 + offset, p->iobase);
> - return inb(p->iobase + 1);
> -}
> -
> -static void hub6_serial_out(struct uart_port *p, unsigned int offset, u32 value)
> -{
> - offset = offset << p->regshift;
> - outb(p->hub6 - 1 + offset, p->iobase);
> - outb(value, p->iobase + 1);
> -}
> -#endif /* CONFIG_HAS_IOPORT */
> -
> static u32 mem_serial_in(struct uart_port *p, unsigned int offset)
> {
> offset = offset << p->regshift;
> @@ -450,13 +434,6 @@ static void set_io_from_upio(struct uart_port *p)
> up->dl_write = default_serial_dl_write;
>
> switch (p->iotype) {
> -#ifdef CONFIG_HAS_IOPORT
> - case UPIO_HUB6:
> - p->serial_in = hub6_serial_in;
> - p->serial_out = hub6_serial_out;
> - break;
> -#endif
> -
> case UPIO_MEM:
> p->serial_in = mem_serial_in;
> p->serial_out = mem_serial_out;
> diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
> index 82e761b8298a..9917b7e1bb26 100644
> --- a/drivers/tty/serial/8250/Kconfig
> +++ b/drivers/tty/serial/8250/Kconfig
> @@ -208,9 +208,9 @@ config SERIAL_8250_EXTENDED
> depends on SERIAL_8250
> help
> If you wish to use any non-standard features of the standard "dumb"
> - driver, say Y here. This includes HUB6 support, shared serial
> - interrupts, special multiport support, support for more than the
> - four COM 1/2/3/4 boards, etc.
> + driver, say Y here. This includes shared serial interrupts, special
> + multiport support, support for more than the four COM 1/2/3/4 boards,
> + etc.
>
> Note that the answer to this question won't directly affect the
> kernel: saying N will just cause the configurator to skip all
> @@ -303,15 +303,6 @@ config SERIAL_8250_EXAR_ST16C554
> To compile this driver as a module, choose M here: the module
> will be called 8250_exar_st16c554.
>
> -config SERIAL_8250_HUB6
> - bool "Support Hub6 cards"
> - depends on SERIAL_8250_MANY_PORTS && ISA
> - help
> - Say Y here if you have a HUB6 serial board.
> -
> - To compile this driver as a module, choose M here: the module
> - will be called 8250_hub6.
> -
> config SERIAL_8250_PCI1XXXX
> tristate "Microchip 8250 based serial port"
> depends on SERIAL_8250 && PCI
> diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
> index 5ff2ba414e13..d241ce486953 100644
> --- a/drivers/tty/serial/8250/Makefile
> +++ b/drivers/tty/serial/8250/Makefile
> @@ -7,7 +7,6 @@ obj-$(CONFIG_SERIAL_8250) += 8250.o
> 8250-y := 8250_core.o
> 8250-y += 8250_platform.o
> 8250-$(CONFIG_SERIAL_8250_PNP) += 8250_pnp.o
> -8250-$(CONFIG_SERIAL_8250_HUB6) += 8250_hub6.o
>
> obj-$(CONFIG_SERIAL_8250) += 8250_base.o
> 8250_base-y := 8250_port.o
> diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
> index c3880259e3bc..9c40ccee0c82 100644
> --- a/drivers/tty/serial/atmel_serial.c
> +++ b/drivers/tty/serial/atmel_serial.c
> @@ -2448,8 +2448,6 @@ static int atmel_verify_port(struct uart_port *port, struct serial_struct *ser)
> ret = -EINVAL;
> if (port->iobase != ser->port)
> ret = -EINVAL;
> - if (ser->hub6 != 0)
> - ret = -EINVAL;
> return ret;
> }
>
> diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
> index c8575c965203..6e1248840022 100644
> --- a/drivers/tty/serial/fsl_lpuart.c
> +++ b/drivers/tty/serial/fsl_lpuart.c
> @@ -2432,8 +2432,6 @@ static int lpuart_verify_port(struct uart_port *port, struct serial_struct *ser)
> ret = -EINVAL;
> if (port->iobase != ser->port)
> ret = -EINVAL;
> - if (ser->hub6 != 0)
> - ret = -EINVAL;
> return ret;
> }
>
> diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
> index 986fefb45c63..d89be62e3852 100644
> --- a/drivers/tty/serial/imx.c
> +++ b/drivers/tty/serial/imx.c
> @@ -1936,8 +1936,6 @@ imx_uart_verify_port(struct uart_port *port, struct serial_struct *ser)
> ret = -EINVAL;
> if (port->iobase != ser->port)
> ret = -EINVAL;
> - if (ser->hub6 != 0)
> - ret = -EINVAL;
> return ret;
> }
>
> diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
> index 472ec39caf27..240009333fb5 100644
> --- a/drivers/tty/serial/mpc52xx_uart.c
> +++ b/drivers/tty/serial/mpc52xx_uart.c
> @@ -1339,8 +1339,7 @@ mpc52xx_uart_verify_port(struct uart_port *port, struct serial_struct *ser)
> if ((ser->irq != port->irq) ||
> (ser->io_type != UPIO_MEM) ||
> (ser->baud_base != port->uartclk) ||
> - (ser->iomem_base != (void *)port->mapbase) ||
> - (ser->hub6 != 0))
> + (ser->iomem_base != (void *)port->mapbase))
> return -EINVAL;
>
> return 0;
> diff --git a/drivers/tty/serial/sa1100.c b/drivers/tty/serial/sa1100.c
> index 72b1bb76415c..ee5f3960d1e4 100644
> --- a/drivers/tty/serial/sa1100.c
> +++ b/drivers/tty/serial/sa1100.c
> @@ -556,8 +556,6 @@ sa1100_verify_port(struct uart_port *port, struct serial_struct *ser)
> ret = -EINVAL;
> if (sport->port.iobase != ser->port)
> ret = -EINVAL;
> - if (ser->hub6 != 0)
> - ret = -EINVAL;
> return ret;
> }
>
> diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
> index 9eea8d1a0e8a..15d8c3ed6edc 100644
> --- a/drivers/tty/serial/serial_core.c
> +++ b/drivers/tty/serial/serial_core.c
> @@ -812,7 +812,7 @@ static int uart_get_info(struct tty_port *port, struct serial_struct *retinfo)
> ASYNC_CLOSING_WAIT_NONE :
> jiffies_to_msecs(port->closing_wait) / 10;
> retinfo->custom_divisor = uport->custom_divisor;
> - retinfo->hub6 = uport->hub6;
> + retinfo->hub6 = 0;
> retinfo->io_type = uport->iotype;
> retinfo->iomem_reg_shift = uport->regshift;
> retinfo->iomem_base = (void *)(unsigned long)uport->mapbase;
> @@ -834,13 +834,12 @@ static int uart_change_port(struct uart_port *uport,
> unsigned long new_port)
> {
> unsigned long old_iobase, old_mapbase;
> - unsigned int old_type, old_iotype, old_hub6, old_shift;
> + unsigned int old_type, old_iotype, old_shift;
> int retval;
>
> old_iobase = uport->iobase;
> old_mapbase = uport->mapbase;
> old_type = uport->type;
> - old_hub6 = uport->hub6;
> old_iotype = uport->iotype;
> old_shift = uport->regshift;
>
> @@ -849,7 +848,6 @@ static int uart_change_port(struct uart_port *uport,
>
> uport->iobase = new_port;
> uport->type = new_info->type;
> - uport->hub6 = new_info->hub6;
> uport->iotype = new_info->io_type;
> uport->regshift = new_info->iomem_reg_shift;
> uport->mapbase = (unsigned long)new_info->iomem_base;
> @@ -867,7 +865,6 @@ static int uart_change_port(struct uart_port *uport,
> */
> uport->iobase = old_iobase;
> uport->type = old_type;
> - uport->hub6 = old_hub6;
> uport->iotype = old_iotype;
> uport->regshift = old_shift;
> uport->mapbase = old_mapbase;
> @@ -924,7 +921,6 @@ static int uart_set_info(struct tty_struct *tty, struct tty_port *port,
> change_port = !(uport->flags & UPF_FIXED_PORT)
> && (new_port != uport->iobase ||
> (unsigned long)new_info->iomem_base != uport->mapbase ||
> - new_info->hub6 != uport->hub6 ||
> new_info->io_type != uport->iotype ||
> new_info->iomem_reg_shift != uport->regshift ||
> new_info->type != uport->type);
> @@ -954,6 +950,10 @@ static int uart_set_info(struct tty_struct *tty, struct tty_port *port,
> goto check_and_exit;
> }
>
> + /* hub6 is no longer support */
s/support/supported
> + if (new_info->hub6 != 0)
> + return -EINVAL;
> +
> if (change_irq || change_port) {
> retval = security_locked_down(LOCKDOWN_TIOCSSERIAL);
> if (retval)
> @@ -2010,7 +2010,6 @@ bool uart_iotype_io(enum uart_iotype iotype)
> {
> switch (iotype) {
> case UPIO_PORT:
> - case UPIO_HUB6:
> return true;
> default:
> return false;
> @@ -2538,10 +2537,7 @@ void uart_get_ioinfos(struct uart_port *port, char *buf, size_t size)
> if (uart_iotype_mmio(port->iotype)) {
> scnprintf(buf, size, " MMIO%s:%pa", uart_get_mmio_width(port), &port->mapbase);
> } else if (uart_iotype_io(port->iotype)) {
> - if (port->iotype == UPIO_PORT)
> - scnprintf(buf, size, " I/O:0x%lx", port->iobase);
> - else if (port->iotype == UPIO_HUB6)
> - scnprintf(buf, size, " I/O:0x%lx, offset 0x%x", port->iobase, port->hub6);
> + scnprintf(buf, size, " I/O:0x%lx", port->iobase);
> }
> }
> EXPORT_SYMBOL(uart_get_ioinfos);
> diff --git a/drivers/tty/serial/sunsu.c b/drivers/tty/serial/sunsu.c
> index 4ff3e5c41dab..f43b802add12 100644
> --- a/drivers/tty/serial/sunsu.c
> +++ b/drivers/tty/serial/sunsu.c
> @@ -106,10 +106,6 @@ static unsigned int serial_in(struct uart_sunsu_port *up, int offset)
> offset <<= up->port.regshift;
>
> switch (up->port.iotype) {
> - case UPIO_HUB6:
> - outb(up->port.hub6 - 1 + offset, up->port.iobase);
> - return inb(up->port.iobase + 1);
> -
> case UPIO_MEM:
> return readb(up->port.membase + offset);
>
> @@ -136,11 +132,6 @@ static void serial_out(struct uart_sunsu_port *up, int offset, int value)
> offset <<= up->port.regshift;
>
> switch (up->port.iotype) {
> - case UPIO_HUB6:
> - outb(up->port.hub6 - 1 + offset, up->port.iobase);
> - outb(value, up->port.iobase + 1);
> - break;
> -
> case UPIO_MEM:
> writeb(value, up->port.membase + offset);
> break;
> diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c
> index a072b75dbaf2..4066cc99fe1a 100644
> --- a/drivers/tty/serial/xilinx_uartps.c
> +++ b/drivers/tty/serial/xilinx_uartps.c
> @@ -1079,8 +1079,6 @@ static int cdns_uart_verify_port(struct uart_port *port,
> return -EINVAL;
> if (port->iobase != ser->port)
> return -EINVAL;
> - if (ser->hub6 != 0)
> - return -EINVAL;
> return 0;
> }
>
> diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
> index d91c0477be9d..d55bce4d4709 100644
> --- a/include/linux/serial_8250.h
> +++ b/include/linux/serial_8250.h
> @@ -41,7 +41,6 @@ struct plat_serial8250_port {
> void *private_data;
> unsigned char regshift; /* register shift */
> unsigned char iotype; /* UPIO_* */
> - unsigned char hub6;
> unsigned char has_sysrq; /* supports magic SysRq */
> unsigned int type; /* If UPF_FIXED_TYPE */
> upf_t flags; /* UPF_* flags */
> @@ -75,7 +74,6 @@ enum {
> PLAT8250_DEV_ACCENT,
> PLAT8250_DEV_BOCA,
> PLAT8250_DEV_EXAR_ST16C554,
> - PLAT8250_DEV_HUB6,
> PLAT8250_DEV_AU1X00,
> PLAT8250_DEV_SM501,
> };
> diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
> index 4eeb8253752a..ca8d009e5c36 100644
> --- a/include/linux/serial_core.h
> +++ b/include/linux/serial_core.h
> @@ -430,7 +430,6 @@ typedef unsigned int __bitwise upstat_t;
> enum uart_iotype {
> UPIO_UNKNOWN = -1,
> UPIO_PORT = SERIAL_IO_PORT, /* 8b I/O port access */
> - UPIO_HUB6 = SERIAL_IO_HUB6, /* Hub6 ISA card */
> UPIO_MEM = SERIAL_IO_MEM, /* driver-specific */
> UPIO_MEM32 = SERIAL_IO_MEM32, /* 32b little endian */
> UPIO_AU = SERIAL_IO_AU, /* Au1x00 and RT288x type IO */
> @@ -590,7 +589,6 @@ struct uart_port {
> unsigned char has_sysrq;
> unsigned char sysrq_seq; /* index in sysrq_toggle_seq */
>
> - unsigned char hub6; /* this should be in the 8250 driver */
> unsigned char suspended;
> unsigned char console_reinit;
> const char *name; /* port name */
> --
> 2.53.0
>
>
>
--
Hugo Villeneuve
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 1/2] tty: serial: remove hub6 multiport support
2026-10-16 13:28 ` [PATCH 1/2] tty: serial: remove hub6 multiport support Andy Shevchenko
@ 2026-10-16 14:41 ` Arnd Bergmann
0 siblings, 0 replies; 14+ messages in thread
From: Arnd Bergmann @ 2026-10-16 14:41 UTC (permalink / raw)
To: Andy Shevchenko, Arnd Bergmann
Cc: Greg Kroah-Hartman, Jiri Slaby, Uwe Kleine-König,
Hugo Villeneuve, linux-kernel, linux-serial, linux-arm-kernel,
imx
On Fri, Oct 16, 2026, at 15:28, Andy Shevchenko wrote:
> On Fri, Oct 16, 2026 at 02:59:47PM +0200, Arnd Bergmann wrote:
>
> Reviewed-by: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
> But there are some minor issues to fix, see below.
>
> ...
>
>> {
>> unsigned long old_iobase, old_mapbase;
>> - unsigned int old_type, old_iotype, old_hub6, old_shift;
>> + unsigned int old_type, old_iotype, old_shift;
>
> Move it line up, so we will have reversed xmas tree order.
>
> ...
>
>> + /* hub6 is no longer support */
>> + if (new_info->hub6 != 0)
>> + return -EINVAL;
>
> Please, fix the indentation, should use tabs.
Fixed both, and the typo in the comment here, thanks
for the review!
Arnd
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 1/2] tty: serial: remove hub6 multiport support
2026-10-16 12:59 [PATCH 1/2] tty: serial: remove hub6 multiport support Arnd Bergmann
` (3 preceding siblings ...)
2026-10-16 14:10 ` Hugo Villeneuve
@ 2026-10-16 15:56 ` Hugo Villeneuve
2026-10-16 16:16 ` Arnd Bergmann
2026-10-16 16:48 ` Hugo Villeneuve
2026-10-16 18:28 ` Frank Li
6 siblings, 1 reply; 14+ messages in thread
From: Hugo Villeneuve @ 2026-10-16 15:56 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Greg Kroah-Hartman, Jiri Slaby, Andy Shevchenko,
Uwe Kleine-König, Hugo Villeneuve, Arnd Bergmann,
linux-kernel, linux-serial, linux-arm-kernel, imx
Hi Arnd,
On Fri, 16 Oct 2026 14:59:47 +0200
Arnd Bergmann <arnd@kernel.org> wrote:
> From: Arnd Bergmann <arnd@arndb.de>
>
> hub6 support was added in linux-0.99 and the hardware was already old at
> the time, being discontinued in 1990. The code for it has always been a
> mess since it adds another dimension to the I/O addressing in the driver
> that has leaked into many individual files.
>
> Hugo and Uwe have attempted several times this year alone to isolate
> the hub6 handling into the 8250_hub6.c file, but I feel that none of
> this has been a real improvement over the original standalone loadable
> module support.
>
> Any machine that would have used this ISA card in practice is likely
> 30 to 40 years old, and with i486 support now removed, it is clearly
> safe to just kill this all off. The only bit that has to remain
> is the ioctl interface, to ensure the serial_struct field is always
> zero.
>
> Link: https://mirrors.nycbug.org/pub/The_Unix_Archive/Unix_Usenet/comp.unix.sysv386/1990-December/007174.html
> Fixes: a300273c458c ("serial: 8250: hub6: Add cleanup code")
> Fixes: c526404a4a92 ("serial: 8250: Fix corner case for port matching")
> Fixes: 7ab80d1e7243 ("serial: 8250: fix compile error with hub6_match_port() when compiled as a module")
> Fixes: da7b5fd4e17f ("serial: 8250_hub6: add missing include for hub6_match_port()")
> Fixes: 3d406299d882 ("serial: 8250_hub6: add hub6_match_port()")
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> ---
> drivers/tty/serial/8250/8250.h | 15 -------
> drivers/tty/serial/8250/8250_core.c | 2 -
> drivers/tty/serial/8250/8250_hub6.c | 60 -------------------------
> drivers/tty/serial/8250/8250_platform.c | 11 +----
> drivers/tty/serial/8250/8250_port.c | 23 ----------
> drivers/tty/serial/8250/Kconfig | 15 ++-----
> drivers/tty/serial/8250/Makefile | 1 -
> drivers/tty/serial/atmel_serial.c | 2 -
> drivers/tty/serial/fsl_lpuart.c | 2 -
> drivers/tty/serial/imx.c | 2 -
> drivers/tty/serial/mpc52xx_uart.c | 3 +-
> drivers/tty/serial/sa1100.c | 2 -
> drivers/tty/serial/serial_core.c | 18 +++-----
> drivers/tty/serial/sunsu.c | 9 ----
> drivers/tty/serial/xilinx_uartps.c | 2 -
> include/linux/serial_8250.h | 2 -
> include/linux/serial_core.h | 2 -
> 17 files changed, 12 insertions(+), 159 deletions(-)
> delete mode 100644 drivers/tty/serial/8250/8250_hub6.c
>
> diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h
> index 21ed9c41b751..75afeb8c0cef 100644
> --- a/drivers/tty/serial/8250/8250.h
> +++ b/drivers/tty/serial/8250/8250.h
> @@ -323,14 +323,6 @@ static inline int serial8250_pnp_init(void) { return 0; }
> static inline void serial8250_pnp_exit(void) { }
> #endif
>
> -#ifdef CONFIG_SERIAL_8250_HUB6
> -int serial8250_hub6_init(void);
> -void serial8250_hub6_exit(void);
> -#else
> -static inline int serial8250_hub6_init(void) { return 0; }
> -static inline void serial8250_hub6_exit(void) { }
> -#endif
> -
> #ifdef CONFIG_SERIAL_8250_RSA
> void univ8250_rsa_support(struct uart_ops *ops, const struct uart_ops *core_ops);
> void rsa_enable(struct uart_8250_port *up);
> @@ -351,13 +343,6 @@ int fintek_8250_probe(struct uart_8250_port *uart);
> static inline int fintek_8250_probe(struct uart_8250_port *uart) { return 0; }
> #endif
>
> -#if IS_ENABLED(CONFIG_SERIAL_8250_HUB6)
> -bool hub6_match_port(const struct uart_port *port1, const struct uart_port *port2);
> -#else
> -static inline bool hub6_match_port(const struct uart_port *port1, const struct uart_port *port2)
> -{ return false; }
> -#endif
> -
> #ifdef CONFIG_ARCH_OMAP1
> #include <linux/soc/ti/omap1-soc.h>
> static inline int is_omap1_8250(struct uart_8250_port *pt)
> diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
> index 42319843cb5b..96c99f0ae683 100644
> --- a/drivers/tty/serial/8250/8250_core.c
> +++ b/drivers/tty/serial/8250/8250_core.c
> @@ -686,8 +686,6 @@ static bool serial8250_match_port(const struct uart_port *port1,
> return false;
> else if (port1->iotype == UPIO_PORT)
> return port1->iobase == port2->iobase;
> - else if (port1->iotype == UPIO_HUB6)
> - return hub6_match_port(port1, port2);
> else if (uart_iotype_mmio(port1->iotype))
> return port1->mapbase == port2->mapbase;
> else
> diff --git a/drivers/tty/serial/8250/8250_hub6.c b/drivers/tty/serial/8250/8250_hub6.c
> deleted file mode 100644
> index 848d9723ac56..000000000000
> --- a/drivers/tty/serial/8250/8250_hub6.c
> +++ /dev/null
> @@ -1,60 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0
> -/*
> - * Copyright (C) 2005 Russell King.
> - * Data taken from include/asm-i386/serial.h
> - */
> -#include <linux/module.h>
> -#include <linux/init.h>
> -#include <linux/serial_8250.h>
> -
> -#include "8250.h"
> -
> -#define HUB6(card, port) \
> - { \
> - .iobase = 0x302, \
> - .irq = 3, \
> - .uartclk = 1843200, \
> - .iotype = UPIO_HUB6, \
> - .flags = UPF_BOOT_AUTOCONF, \
> - .hub6 = (card) << 6 | (port) << 3 | 1, \
> - }
> -
> -static struct plat_serial8250_port hub6_data[] = {
> - HUB6(0, 0),
> - HUB6(0, 1),
> - HUB6(0, 2),
> - HUB6(0, 3),
> - HUB6(0, 4),
> - HUB6(0, 5),
> - HUB6(1, 0),
> - HUB6(1, 1),
> - HUB6(1, 2),
> - HUB6(1, 3),
> - HUB6(1, 4),
> - HUB6(1, 5),
> - { },
> -};
> -
> -static struct platform_device hub6_device = {
> - .name = "serial8250",
> - .id = PLAT8250_DEV_HUB6,
> - .dev = {
> - .platform_data = hub6_data,
> - },
> -};
> -
> -bool hub6_match_port(const struct uart_port *port1, const struct uart_port *port2)
> -{
> - return port1->iobase == port2->iobase && port1->hub6 == port2->hub6;
> -}
> -EXPORT_SYMBOL_GPL(hub6_match_port);
> -
> -int __init serial8250_hub6_init(void)
> -{
> - return platform_device_register(&hub6_device);
> -}
> -
> -void serial8250_hub6_exit(void)
> -{
> - platform_device_unregister(&hub6_device);
> -}
> diff --git a/drivers/tty/serial/8250/8250_platform.c b/drivers/tty/serial/8250/8250_platform.c
> index 7ce7ad295fae..8aa769085bfa 100644
> --- a/drivers/tty/serial/8250/8250_platform.c
> +++ b/drivers/tty/serial/8250/8250_platform.c
> @@ -86,7 +86,6 @@ static void __init __serial8250_isa_init_ports(void)
> port->irqflags = 0;
> port->uartclk = old_serial_port[i].baud_base * 16;
> port->flags = old_serial_port[i].flags;
> - port->hub6 = 0;
> port->membase = old_serial_port[i].iomem_base;
> port->iotype = old_serial_port[i].io_type;
> port->regshift = old_serial_port[i].iomem_reg_shift;
> @@ -169,7 +168,6 @@ static int serial8250_probe_platform(struct platform_device *dev, struct plat_se
> uart->port.flags = p->flags;
> uart->port.mapbase = p->mapbase;
> uart->port.mapsize = p->mapsize;
> - uart->port.hub6 = p->hub6;
> uart->port.has_sysrq = p->has_sysrq;
> uart->port.private_data = p->private_data;
> uart->port.type = p->type;
> @@ -317,14 +315,10 @@ static int __init serial8250_init(void)
> if (ret)
> goto unreg_uart_drv;
>
> - ret = serial8250_hub6_init();
> - if (ret)
> - goto unreg_pnp;
> -
> serial8250_isa_devs = platform_device_alloc("serial8250", PLAT8250_DEV_LEGACY);
> if (!serial8250_isa_devs) {
> ret = -ENOMEM;
> - goto unreg_hub6;
> + goto unreg_pnp;
> }
>
> ret = platform_device_add(serial8250_isa_devs);
> @@ -340,8 +334,6 @@ static int __init serial8250_init(void)
> platform_device_del(serial8250_isa_devs);
> put_dev:
> platform_device_put(serial8250_isa_devs);
> -unreg_hub6:
> - serial8250_hub6_exit();
> unreg_pnp:
> serial8250_pnp_exit();
> unreg_uart_drv:
> @@ -369,7 +361,6 @@ static void __exit serial8250_exit(void)
> platform_driver_unregister(&serial8250_isa_driver);
> platform_device_unregister(isa_dev);
>
> - serial8250_hub6_exit();
> serial8250_pnp_exit();
>
> #ifdef CONFIG_SPARC
> diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
> index 36b2b0a2c05c..3593e7209879 100644
> --- a/drivers/tty/serial/8250/8250_port.c
> +++ b/drivers/tty/serial/8250/8250_port.c
> @@ -354,22 +354,6 @@ static void default_serial_dl_write(struct uart_8250_port *up, u32 value)
> serial_out(up, UART_DLM, value >> 8 & 0xff);
> }
>
> -#ifdef CONFIG_HAS_IOPORT
> -static u32 hub6_serial_in(struct uart_port *p, unsigned int offset)
> -{
> - offset = offset << p->regshift;
> - outb(p->hub6 - 1 + offset, p->iobase);
> - return inb(p->iobase + 1);
> -}
> -
> -static void hub6_serial_out(struct uart_port *p, unsigned int offset, u32 value)
> -{
> - offset = offset << p->regshift;
> - outb(p->hub6 - 1 + offset, p->iobase);
> - outb(value, p->iobase + 1);
> -}
> -#endif /* CONFIG_HAS_IOPORT */
> -
> static u32 mem_serial_in(struct uart_port *p, unsigned int offset)
> {
> offset = offset << p->regshift;
> @@ -450,13 +434,6 @@ static void set_io_from_upio(struct uart_port *p)
> up->dl_write = default_serial_dl_write;
>
> switch (p->iotype) {
> -#ifdef CONFIG_HAS_IOPORT
> - case UPIO_HUB6:
> - p->serial_in = hub6_serial_in;
> - p->serial_out = hub6_serial_out;
> - break;
> -#endif
> -
> case UPIO_MEM:
> p->serial_in = mem_serial_in;
> p->serial_out = mem_serial_out;
> diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
> index 82e761b8298a..9917b7e1bb26 100644
> --- a/drivers/tty/serial/8250/Kconfig
> +++ b/drivers/tty/serial/8250/Kconfig
> @@ -208,9 +208,9 @@ config SERIAL_8250_EXTENDED
> depends on SERIAL_8250
> help
> If you wish to use any non-standard features of the standard "dumb"
> - driver, say Y here. This includes HUB6 support, shared serial
> - interrupts, special multiport support, support for more than the
> - four COM 1/2/3/4 boards, etc.
> + driver, say Y here. This includes shared serial interrupts, special
> + multiport support, support for more than the four COM 1/2/3/4 boards,
> + etc.
>
> Note that the answer to this question won't directly affect the
> kernel: saying N will just cause the configurator to skip all
> @@ -303,15 +303,6 @@ config SERIAL_8250_EXAR_ST16C554
> To compile this driver as a module, choose M here: the module
> will be called 8250_exar_st16c554.
>
> -config SERIAL_8250_HUB6
> - bool "Support Hub6 cards"
> - depends on SERIAL_8250_MANY_PORTS && ISA
> - help
> - Say Y here if you have a HUB6 serial board.
> -
> - To compile this driver as a module, choose M here: the module
> - will be called 8250_hub6.
> -
> config SERIAL_8250_PCI1XXXX
> tristate "Microchip 8250 based serial port"
> depends on SERIAL_8250 && PCI
> diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
> index 5ff2ba414e13..d241ce486953 100644
> --- a/drivers/tty/serial/8250/Makefile
> +++ b/drivers/tty/serial/8250/Makefile
> @@ -7,7 +7,6 @@ obj-$(CONFIG_SERIAL_8250) += 8250.o
> 8250-y := 8250_core.o
> 8250-y += 8250_platform.o
> 8250-$(CONFIG_SERIAL_8250_PNP) += 8250_pnp.o
> -8250-$(CONFIG_SERIAL_8250_HUB6) += 8250_hub6.o
>
> obj-$(CONFIG_SERIAL_8250) += 8250_base.o
> 8250_base-y := 8250_port.o
> diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
> index c3880259e3bc..9c40ccee0c82 100644
> --- a/drivers/tty/serial/atmel_serial.c
> +++ b/drivers/tty/serial/atmel_serial.c
> @@ -2448,8 +2448,6 @@ static int atmel_verify_port(struct uart_port *port, struct serial_struct *ser)
> ret = -EINVAL;
> if (port->iobase != ser->port)
> ret = -EINVAL;
> - if (ser->hub6 != 0)
> - ret = -EINVAL;
> return ret;
> }
>
> diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
> index c8575c965203..6e1248840022 100644
> --- a/drivers/tty/serial/fsl_lpuart.c
> +++ b/drivers/tty/serial/fsl_lpuart.c
> @@ -2432,8 +2432,6 @@ static int lpuart_verify_port(struct uart_port *port, struct serial_struct *ser)
> ret = -EINVAL;
> if (port->iobase != ser->port)
> ret = -EINVAL;
> - if (ser->hub6 != 0)
> - ret = -EINVAL;
> return ret;
> }
>
> diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
> index 986fefb45c63..d89be62e3852 100644
> --- a/drivers/tty/serial/imx.c
> +++ b/drivers/tty/serial/imx.c
> @@ -1936,8 +1936,6 @@ imx_uart_verify_port(struct uart_port *port, struct serial_struct *ser)
> ret = -EINVAL;
> if (port->iobase != ser->port)
> ret = -EINVAL;
> - if (ser->hub6 != 0)
> - ret = -EINVAL;
> return ret;
> }
>
> diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
> index 472ec39caf27..240009333fb5 100644
> --- a/drivers/tty/serial/mpc52xx_uart.c
> +++ b/drivers/tty/serial/mpc52xx_uart.c
> @@ -1339,8 +1339,7 @@ mpc52xx_uart_verify_port(struct uart_port *port, struct serial_struct *ser)
> if ((ser->irq != port->irq) ||
> (ser->io_type != UPIO_MEM) ||
> (ser->baud_base != port->uartclk) ||
> - (ser->iomem_base != (void *)port->mapbase) ||
> - (ser->hub6 != 0))
> + (ser->iomem_base != (void *)port->mapbase))
> return -EINVAL;
>
> return 0;
> diff --git a/drivers/tty/serial/sa1100.c b/drivers/tty/serial/sa1100.c
> index 72b1bb76415c..ee5f3960d1e4 100644
> --- a/drivers/tty/serial/sa1100.c
> +++ b/drivers/tty/serial/sa1100.c
> @@ -556,8 +556,6 @@ sa1100_verify_port(struct uart_port *port, struct serial_struct *ser)
> ret = -EINVAL;
> if (sport->port.iobase != ser->port)
> ret = -EINVAL;
> - if (ser->hub6 != 0)
> - ret = -EINVAL;
> return ret;
> }
>
> diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
> index 9eea8d1a0e8a..15d8c3ed6edc 100644
> --- a/drivers/tty/serial/serial_core.c
> +++ b/drivers/tty/serial/serial_core.c
> @@ -812,7 +812,7 @@ static int uart_get_info(struct tty_port *port, struct serial_struct *retinfo)
> ASYNC_CLOSING_WAIT_NONE :
> jiffies_to_msecs(port->closing_wait) / 10;
> retinfo->custom_divisor = uport->custom_divisor;
> - retinfo->hub6 = uport->hub6;
> + retinfo->hub6 = 0;
Would a comment here help?
retinfo->hub6 = 0; /* No longer supported */
> retinfo->io_type = uport->iotype;
> retinfo->iomem_reg_shift = uport->regshift;
> retinfo->iomem_base = (void *)(unsigned long)uport->mapbase;
> @@ -834,13 +834,12 @@ static int uart_change_port(struct uart_port *uport,
> unsigned long new_port)
> {
> unsigned long old_iobase, old_mapbase;
> - unsigned int old_type, old_iotype, old_hub6, old_shift;
> + unsigned int old_type, old_iotype, old_shift;
> int retval;
>
> old_iobase = uport->iobase;
> old_mapbase = uport->mapbase;
> old_type = uport->type;
> - old_hub6 = uport->hub6;
> old_iotype = uport->iotype;
> old_shift = uport->regshift;
>
> @@ -849,7 +848,6 @@ static int uart_change_port(struct uart_port *uport,
>
> uport->iobase = new_port;
> uport->type = new_info->type;
> - uport->hub6 = new_info->hub6;
> uport->iotype = new_info->io_type;
> uport->regshift = new_info->iomem_reg_shift;
> uport->mapbase = (unsigned long)new_info->iomem_base;
> @@ -867,7 +865,6 @@ static int uart_change_port(struct uart_port *uport,
> */
> uport->iobase = old_iobase;
> uport->type = old_type;
> - uport->hub6 = old_hub6;
> uport->iotype = old_iotype;
> uport->regshift = old_shift;
> uport->mapbase = old_mapbase;
> @@ -924,7 +921,6 @@ static int uart_set_info(struct tty_struct *tty, struct tty_port *port,
> change_port = !(uport->flags & UPF_FIXED_PORT)
> && (new_port != uport->iobase ||
> (unsigned long)new_info->iomem_base != uport->mapbase ||
> - new_info->hub6 != uport->hub6 ||
Maybe keep this so that change_port is true if someone sets hub6 to a
value other than zero (see below)?
> new_info->io_type != uport->iotype ||
> new_info->iomem_reg_shift != uport->regshift ||
> new_info->type != uport->type);
> @@ -954,6 +950,10 @@ static int uart_set_info(struct tty_struct *tty, struct tty_port *port,
> goto check_and_exit;
> }
>
> + /* hub6 is no longer support */
> + if (new_info->hub6 != 0)
> + return -EINVAL;
> +
I ran sashiko locally (I did not see any sashiko review for your
patches on LKML) and here is an interesting one:
[Severity: Medium]
Before this patch, a non-root caller of TIOCSSERIAL with hub6 set to a
nonzero value would make change_port evaluate true, which later causes
the !capable(CAP_SYS_ADMIN) block to return -EPERM.
With the hub6 term removed from change_port, that path for unprivileged
callers no longer exists.
> @@ -955,6 +951,10 @@ static int uart_set_info(struct tty_struct *tty, struct tty_port *port,
> goto check_and_exit;
> }
>
> + /* hub6 is no longer support */
> + if (new_info->hub6 != 0)
> + return -EINVAL;
> +
> if (change_irq || change_port) {
> retval = security_locked_down(LOCKDOWN_TIOCSSERIAL);
> if (retval)
[Severity: Medium]
The new hub6 rejection check sits after the
"if (!capable(CAP_SYS_ADMIN)) { ... goto check_and_exit; }" block, so it
never runs for non-root callers that reach check_and_exit.
Combined with the change above, can an unprivileged caller now issue
TIOCSSERIAL with hub6 set to a nonzero value (leaving irq, port,
baud_base, and flags unchanged) and get a silent success, while the
same request from a CAP_SYS_ADMIN caller hits this check and gets
-EINVAL?
> if (change_irq || change_port) {
> retval = security_locked_down(LOCKDOWN_TIOCSSERIAL);
> if (retval)
> @@ -2010,7 +2010,6 @@ bool uart_iotype_io(enum uart_iotype iotype)
> {
> switch (iotype) {
> case UPIO_PORT:
> - case UPIO_HUB6:
> return true;
> default:
> return false;
> @@ -2538,10 +2537,7 @@ void uart_get_ioinfos(struct uart_port *port, char *buf, size_t size)
> if (uart_iotype_mmio(port->iotype)) {
> scnprintf(buf, size, " MMIO%s:%pa", uart_get_mmio_width(port), &port->mapbase);
> } else if (uart_iotype_io(port->iotype)) {
> - if (port->iotype == UPIO_PORT)
> - scnprintf(buf, size, " I/O:0x%lx", port->iobase);
> - else if (port->iotype == UPIO_HUB6)
> - scnprintf(buf, size, " I/O:0x%lx, offset 0x%x", port->iobase, port->hub6);
> + scnprintf(buf, size, " I/O:0x%lx", port->iobase);
> }
> }
> EXPORT_SYMBOL(uart_get_ioinfos);
> diff --git a/drivers/tty/serial/sunsu.c b/drivers/tty/serial/sunsu.c
> index 4ff3e5c41dab..f43b802add12 100644
> --- a/drivers/tty/serial/sunsu.c
> +++ b/drivers/tty/serial/sunsu.c
> @@ -106,10 +106,6 @@ static unsigned int serial_in(struct uart_sunsu_port *up, int offset)
> offset <<= up->port.regshift;
>
> switch (up->port.iotype) {
> - case UPIO_HUB6:
> - outb(up->port.hub6 - 1 + offset, up->port.iobase);
> - return inb(up->port.iobase + 1);
> -
> case UPIO_MEM:
> return readb(up->port.membase + offset);
>
> @@ -136,11 +132,6 @@ static void serial_out(struct uart_sunsu_port *up, int offset, int value)
> offset <<= up->port.regshift;
>
> switch (up->port.iotype) {
> - case UPIO_HUB6:
> - outb(up->port.hub6 - 1 + offset, up->port.iobase);
> - outb(value, up->port.iobase + 1);
> - break;
> -
> case UPIO_MEM:
> writeb(value, up->port.membase + offset);
> break;
> diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c
> index a072b75dbaf2..4066cc99fe1a 100644
> --- a/drivers/tty/serial/xilinx_uartps.c
> +++ b/drivers/tty/serial/xilinx_uartps.c
> @@ -1079,8 +1079,6 @@ static int cdns_uart_verify_port(struct uart_port *port,
> return -EINVAL;
> if (port->iobase != ser->port)
> return -EINVAL;
> - if (ser->hub6 != 0)
> - return -EINVAL;
> return 0;
> }
>
> diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
> index d91c0477be9d..d55bce4d4709 100644
> --- a/include/linux/serial_8250.h
> +++ b/include/linux/serial_8250.h
> @@ -41,7 +41,6 @@ struct plat_serial8250_port {
> void *private_data;
> unsigned char regshift; /* register shift */
> unsigned char iotype; /* UPIO_* */
> - unsigned char hub6;
> unsigned char has_sysrq; /* supports magic SysRq */
> unsigned int type; /* If UPF_FIXED_TYPE */
> upf_t flags; /* UPF_* flags */
> @@ -75,7 +74,6 @@ enum {
> PLAT8250_DEV_ACCENT,
> PLAT8250_DEV_BOCA,
> PLAT8250_DEV_EXAR_ST16C554,
> - PLAT8250_DEV_HUB6,
> PLAT8250_DEV_AU1X00,
> PLAT8250_DEV_SM501,
> };
> diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
> index 4eeb8253752a..ca8d009e5c36 100644
> --- a/include/linux/serial_core.h
> +++ b/include/linux/serial_core.h
> @@ -430,7 +430,6 @@ typedef unsigned int __bitwise upstat_t;
> enum uart_iotype {
> UPIO_UNKNOWN = -1,
> UPIO_PORT = SERIAL_IO_PORT, /* 8b I/O port access */
> - UPIO_HUB6 = SERIAL_IO_HUB6, /* Hub6 ISA card */
> UPIO_MEM = SERIAL_IO_MEM, /* driver-specific */
> UPIO_MEM32 = SERIAL_IO_MEM32, /* 32b little endian */
> UPIO_AU = SERIAL_IO_AU, /* Au1x00 and RT288x type IO */
> @@ -590,7 +589,6 @@ struct uart_port {
> unsigned char has_sysrq;
> unsigned char sysrq_seq; /* index in sysrq_toggle_seq */
>
> - unsigned char hub6; /* this should be in the 8250 driver */
> unsigned char suspended;
> unsigned char console_reinit;
> const char *name; /* port name */
> --
> 2.53.0
>
>
>
--
Hugo Villeneuve
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 1/2] tty: serial: remove hub6 multiport support
2026-10-16 15:56 ` Hugo Villeneuve
@ 2026-10-16 16:16 ` Arnd Bergmann
2026-10-16 17:17 ` Hugo Villeneuve
0 siblings, 1 reply; 14+ messages in thread
From: Arnd Bergmann @ 2026-10-16 16:16 UTC (permalink / raw)
To: Hugo Villeneuve, Arnd Bergmann
Cc: Greg Kroah-Hartman, Jiri Slaby, Andy Shevchenko,
Uwe Kleine-König, Hugo Villeneuve, linux-kernel,
linux-serial, linux-arm-kernel, imx
On Fri, Oct 16, 2026, at 17:56, Hugo Villeneuve wrote:
> On Fri, 16 Oct 2026 14:59:47 +0200
>> retinfo->custom_divisor = uport->custom_divisor;
>> - retinfo->hub6 = uport->hub6;
>> + retinfo->hub6 = 0;
>
> Would a comment here help?
>
> retinfo->hub6 = 0; /* No longer supported */
Good idea, added.
>> @@ -924,7 +921,6 @@ static int uart_set_info(struct tty_struct *tty, struct tty_port *port,
>> change_port = !(uport->flags & UPF_FIXED_PORT)
>> && (new_port != uport->iobase ||
>> (unsigned long)new_info->iomem_base != uport->mapbase ||
>> - new_info->hub6 != uport->hub6 ||
>
> Maybe keep this so that change_port is true if someone sets hub6 to a
> value other than zero (see below)?
Right, this would be fairly harmless as nothing looks at the field
afterwards but it makes sense for consistency.
I've moved the hub6 check up before change_port now to behave the
same way for regular users and root:
@@ -935,6 +935,11 @@ static int uart_set_info(struct tty_struct *tty, struct tty_port *port,
if (uartclk == 0)
return -EINVAL;
}
+
+ /* hub6 is no longer supported */
+ if (new_info->hub6 != 0)
+ return -EINVAL;
+
if (!capable(CAP_SYS_ADMIN)) {
if (change_irq || change_port ||
(new_info->baud_base != uport->uartclk / 16) ||
@@ -950,10 +955,6 @@ static int uart_set_info(struct tty_struct *tty, struct tty_port *port,
goto check_and_exit;
}
- /* hub6 is no longer supported */
- if (new_info->hub6 != 0)
- return -EINVAL;
-
if (change_irq || change_port) {
retval = security_locked_down(LOCKDOWN_TIOCSSERIAL);
if (retval)
Thanks for taking a look!
Arnd
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 1/2] tty: serial: remove hub6 multiport support
2026-10-16 12:59 [PATCH 1/2] tty: serial: remove hub6 multiport support Arnd Bergmann
` (4 preceding siblings ...)
2026-10-16 15:56 ` Hugo Villeneuve
@ 2026-10-16 16:48 ` Hugo Villeneuve
2026-10-16 17:12 ` Arnd Bergmann
2026-10-16 18:28 ` Frank Li
6 siblings, 1 reply; 14+ messages in thread
From: Hugo Villeneuve @ 2026-10-16 16:48 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Greg Kroah-Hartman, Jiri Slaby, Andy Shevchenko,
Uwe Kleine-König, Hugo Villeneuve, Arnd Bergmann,
linux-kernel, linux-serial, linux-arm-kernel, imx
Hi Arnd,
On Fri, 16 Oct 2026 14:59:47 +0200
Arnd Bergmann <arnd@kernel.org> wrote:
> From: Arnd Bergmann <arnd@arndb.de>
>
> hub6 support was added in linux-0.99 and the hardware was already old at
> the time, being discontinued in 1990. The code for it has always been a
> mess since it adds another dimension to the I/O addressing in the driver
> that has leaked into many individual files.
>
> Hugo and Uwe have attempted several times this year alone to isolate
> the hub6 handling into the 8250_hub6.c file, but I feel that none of
> this has been a real improvement over the original standalone loadable
> module support.
>
> Any machine that would have used this ISA card in practice is likely
> 30 to 40 years old, and with i486 support now removed, it is clearly
> safe to just kill this all off. The only bit that has to remain
> is the ioctl interface, to ensure the serial_struct field is always
> zero.
>
> Link: https://mirrors.nycbug.org/pub/The_Unix_Archive/Unix_Usenet/comp.unix.sysv386/1990-December/007174.html
> Fixes: a300273c458c ("serial: 8250: hub6: Add cleanup code")
> Fixes: c526404a4a92 ("serial: 8250: Fix corner case for port matching")
> Fixes: 7ab80d1e7243 ("serial: 8250: fix compile error with hub6_match_port() when compiled as a module")
> Fixes: da7b5fd4e17f ("serial: 8250_hub6: add missing include for hub6_match_port()")
> Fixes: 3d406299d882 ("serial: 8250_hub6: add hub6_match_port()")
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> ---
> drivers/tty/serial/8250/8250.h | 15 -------
> drivers/tty/serial/8250/8250_core.c | 2 -
> drivers/tty/serial/8250/8250_hub6.c | 60 -------------------------
> drivers/tty/serial/8250/8250_platform.c | 11 +----
> drivers/tty/serial/8250/8250_port.c | 23 ----------
> drivers/tty/serial/8250/Kconfig | 15 ++-----
> drivers/tty/serial/8250/Makefile | 1 -
> drivers/tty/serial/atmel_serial.c | 2 -
> drivers/tty/serial/fsl_lpuart.c | 2 -
> drivers/tty/serial/imx.c | 2 -
> drivers/tty/serial/mpc52xx_uart.c | 3 +-
> drivers/tty/serial/sa1100.c | 2 -
> drivers/tty/serial/serial_core.c | 18 +++-----
> drivers/tty/serial/sunsu.c | 9 ----
> drivers/tty/serial/xilinx_uartps.c | 2 -
> include/linux/serial_8250.h | 2 -
> include/linux/serial_core.h | 2 -
> 17 files changed, 12 insertions(+), 159 deletions(-)
> delete mode 100644 drivers/tty/serial/8250/8250_hub6.c
>
> diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h
> index 21ed9c41b751..75afeb8c0cef 100644
> --- a/drivers/tty/serial/8250/8250.h
> +++ b/drivers/tty/serial/8250/8250.h
> @@ -323,14 +323,6 @@ static inline int serial8250_pnp_init(void) { return 0; }
> static inline void serial8250_pnp_exit(void) { }
> #endif
>
> -#ifdef CONFIG_SERIAL_8250_HUB6
> -int serial8250_hub6_init(void);
> -void serial8250_hub6_exit(void);
> -#else
> -static inline int serial8250_hub6_init(void) { return 0; }
> -static inline void serial8250_hub6_exit(void) { }
> -#endif
> -
> #ifdef CONFIG_SERIAL_8250_RSA
> void univ8250_rsa_support(struct uart_ops *ops, const struct uart_ops *core_ops);
> void rsa_enable(struct uart_8250_port *up);
> @@ -351,13 +343,6 @@ int fintek_8250_probe(struct uart_8250_port *uart);
> static inline int fintek_8250_probe(struct uart_8250_port *uart) { return 0; }
> #endif
>
> -#if IS_ENABLED(CONFIG_SERIAL_8250_HUB6)
> -bool hub6_match_port(const struct uart_port *port1, const struct uart_port *port2);
> -#else
> -static inline bool hub6_match_port(const struct uart_port *port1, const struct uart_port *port2)
> -{ return false; }
> -#endif
> -
> #ifdef CONFIG_ARCH_OMAP1
> #include <linux/soc/ti/omap1-soc.h>
> static inline int is_omap1_8250(struct uart_8250_port *pt)
> diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
> index 42319843cb5b..96c99f0ae683 100644
> --- a/drivers/tty/serial/8250/8250_core.c
> +++ b/drivers/tty/serial/8250/8250_core.c
> @@ -686,8 +686,6 @@ static bool serial8250_match_port(const struct uart_port *port1,
> return false;
> else if (port1->iotype == UPIO_PORT)
> return port1->iobase == port2->iobase;
> - else if (port1->iotype == UPIO_HUB6)
> - return hub6_match_port(port1, port2);
> else if (uart_iotype_mmio(port1->iotype))
> return port1->mapbase == port2->mapbase;
> else
> diff --git a/drivers/tty/serial/8250/8250_hub6.c b/drivers/tty/serial/8250/8250_hub6.c
> deleted file mode 100644
> index 848d9723ac56..000000000000
> --- a/drivers/tty/serial/8250/8250_hub6.c
> +++ /dev/null
> @@ -1,60 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0
> -/*
> - * Copyright (C) 2005 Russell King.
> - * Data taken from include/asm-i386/serial.h
> - */
> -#include <linux/module.h>
> -#include <linux/init.h>
> -#include <linux/serial_8250.h>
> -
> -#include "8250.h"
> -
> -#define HUB6(card, port) \
> - { \
> - .iobase = 0x302, \
> - .irq = 3, \
> - .uartclk = 1843200, \
> - .iotype = UPIO_HUB6, \
> - .flags = UPF_BOOT_AUTOCONF, \
> - .hub6 = (card) << 6 | (port) << 3 | 1, \
> - }
> -
> -static struct plat_serial8250_port hub6_data[] = {
> - HUB6(0, 0),
> - HUB6(0, 1),
> - HUB6(0, 2),
> - HUB6(0, 3),
> - HUB6(0, 4),
> - HUB6(0, 5),
> - HUB6(1, 0),
> - HUB6(1, 1),
> - HUB6(1, 2),
> - HUB6(1, 3),
> - HUB6(1, 4),
> - HUB6(1, 5),
> - { },
> -};
> -
> -static struct platform_device hub6_device = {
> - .name = "serial8250",
> - .id = PLAT8250_DEV_HUB6,
> - .dev = {
> - .platform_data = hub6_data,
> - },
> -};
> -
> -bool hub6_match_port(const struct uart_port *port1, const struct uart_port *port2)
> -{
> - return port1->iobase == port2->iobase && port1->hub6 == port2->hub6;
> -}
> -EXPORT_SYMBOL_GPL(hub6_match_port);
> -
> -int __init serial8250_hub6_init(void)
> -{
> - return platform_device_register(&hub6_device);
> -}
> -
> -void serial8250_hub6_exit(void)
> -{
> - platform_device_unregister(&hub6_device);
> -}
> diff --git a/drivers/tty/serial/8250/8250_platform.c b/drivers/tty/serial/8250/8250_platform.c
> index 7ce7ad295fae..8aa769085bfa 100644
> --- a/drivers/tty/serial/8250/8250_platform.c
> +++ b/drivers/tty/serial/8250/8250_platform.c
> @@ -86,7 +86,6 @@ static void __init __serial8250_isa_init_ports(void)
> port->irqflags = 0;
> port->uartclk = old_serial_port[i].baud_base * 16;
> port->flags = old_serial_port[i].flags;
> - port->hub6 = 0;
> port->membase = old_serial_port[i].iomem_base;
> port->iotype = old_serial_port[i].io_type;
> port->regshift = old_serial_port[i].iomem_reg_shift;
> @@ -169,7 +168,6 @@ static int serial8250_probe_platform(struct platform_device *dev, struct plat_se
> uart->port.flags = p->flags;
> uart->port.mapbase = p->mapbase;
> uart->port.mapsize = p->mapsize;
> - uart->port.hub6 = p->hub6;
> uart->port.has_sysrq = p->has_sysrq;
> uart->port.private_data = p->private_data;
> uart->port.type = p->type;
> @@ -317,14 +315,10 @@ static int __init serial8250_init(void)
> if (ret)
> goto unreg_uart_drv;
>
> - ret = serial8250_hub6_init();
> - if (ret)
> - goto unreg_pnp;
> -
> serial8250_isa_devs = platform_device_alloc("serial8250", PLAT8250_DEV_LEGACY);
> if (!serial8250_isa_devs) {
> ret = -ENOMEM;
> - goto unreg_hub6;
> + goto unreg_pnp;
> }
>
> ret = platform_device_add(serial8250_isa_devs);
> @@ -340,8 +334,6 @@ static int __init serial8250_init(void)
> platform_device_del(serial8250_isa_devs);
> put_dev:
> platform_device_put(serial8250_isa_devs);
> -unreg_hub6:
> - serial8250_hub6_exit();
> unreg_pnp:
> serial8250_pnp_exit();
> unreg_uart_drv:
> @@ -369,7 +361,6 @@ static void __exit serial8250_exit(void)
> platform_driver_unregister(&serial8250_isa_driver);
> platform_device_unregister(isa_dev);
>
> - serial8250_hub6_exit();
> serial8250_pnp_exit();
>
> #ifdef CONFIG_SPARC
> diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
> index 36b2b0a2c05c..3593e7209879 100644
> --- a/drivers/tty/serial/8250/8250_port.c
> +++ b/drivers/tty/serial/8250/8250_port.c
> @@ -354,22 +354,6 @@ static void default_serial_dl_write(struct uart_8250_port *up, u32 value)
> serial_out(up, UART_DLM, value >> 8 & 0xff);
> }
>
> -#ifdef CONFIG_HAS_IOPORT
> -static u32 hub6_serial_in(struct uart_port *p, unsigned int offset)
> -{
> - offset = offset << p->regshift;
> - outb(p->hub6 - 1 + offset, p->iobase);
> - return inb(p->iobase + 1);
> -}
> -
> -static void hub6_serial_out(struct uart_port *p, unsigned int offset, u32 value)
> -{
> - offset = offset << p->regshift;
> - outb(p->hub6 - 1 + offset, p->iobase);
> - outb(value, p->iobase + 1);
> -}
> -#endif /* CONFIG_HAS_IOPORT */
> -
> static u32 mem_serial_in(struct uart_port *p, unsigned int offset)
> {
> offset = offset << p->regshift;
> @@ -450,13 +434,6 @@ static void set_io_from_upio(struct uart_port *p)
> up->dl_write = default_serial_dl_write;
>
> switch (p->iotype) {
> -#ifdef CONFIG_HAS_IOPORT
> - case UPIO_HUB6:
> - p->serial_in = hub6_serial_in;
> - p->serial_out = hub6_serial_out;
> - break;
> -#endif
> -
> case UPIO_MEM:
> p->serial_in = mem_serial_in;
> p->serial_out = mem_serial_out;
> diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
> index 82e761b8298a..9917b7e1bb26 100644
> --- a/drivers/tty/serial/8250/Kconfig
> +++ b/drivers/tty/serial/8250/Kconfig
> @@ -208,9 +208,9 @@ config SERIAL_8250_EXTENDED
> depends on SERIAL_8250
> help
> If you wish to use any non-standard features of the standard "dumb"
> - driver, say Y here. This includes HUB6 support, shared serial
> - interrupts, special multiport support, support for more than the
> - four COM 1/2/3/4 boards, etc.
> + driver, say Y here. This includes shared serial interrupts, special
> + multiport support, support for more than the four COM 1/2/3/4 boards,
> + etc.
>
> Note that the answer to this question won't directly affect the
> kernel: saying N will just cause the configurator to skip all
> @@ -303,15 +303,6 @@ config SERIAL_8250_EXAR_ST16C554
> To compile this driver as a module, choose M here: the module
> will be called 8250_exar_st16c554.
>
> -config SERIAL_8250_HUB6
> - bool "Support Hub6 cards"
> - depends on SERIAL_8250_MANY_PORTS && ISA
> - help
> - Say Y here if you have a HUB6 serial board.
> -
> - To compile this driver as a module, choose M here: the module
> - will be called 8250_hub6.
> -
> config SERIAL_8250_PCI1XXXX
> tristate "Microchip 8250 based serial port"
> depends on SERIAL_8250 && PCI
> diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
> index 5ff2ba414e13..d241ce486953 100644
> --- a/drivers/tty/serial/8250/Makefile
> +++ b/drivers/tty/serial/8250/Makefile
> @@ -7,7 +7,6 @@ obj-$(CONFIG_SERIAL_8250) += 8250.o
> 8250-y := 8250_core.o
> 8250-y += 8250_platform.o
> 8250-$(CONFIG_SERIAL_8250_PNP) += 8250_pnp.o
> -8250-$(CONFIG_SERIAL_8250_HUB6) += 8250_hub6.o
>
> obj-$(CONFIG_SERIAL_8250) += 8250_base.o
> 8250_base-y := 8250_port.o
> diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
> index c3880259e3bc..9c40ccee0c82 100644
> --- a/drivers/tty/serial/atmel_serial.c
> +++ b/drivers/tty/serial/atmel_serial.c
> @@ -2448,8 +2448,6 @@ static int atmel_verify_port(struct uart_port *port, struct serial_struct *ser)
> ret = -EINVAL;
> if (port->iobase != ser->port)
> ret = -EINVAL;
> - if (ser->hub6 != 0)
> - ret = -EINVAL;
> return ret;
> }
>
> diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
> index c8575c965203..6e1248840022 100644
> --- a/drivers/tty/serial/fsl_lpuart.c
> +++ b/drivers/tty/serial/fsl_lpuart.c
> @@ -2432,8 +2432,6 @@ static int lpuart_verify_port(struct uart_port *port, struct serial_struct *ser)
> ret = -EINVAL;
> if (port->iobase != ser->port)
> ret = -EINVAL;
> - if (ser->hub6 != 0)
> - ret = -EINVAL;
> return ret;
> }
>
> diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
> index 986fefb45c63..d89be62e3852 100644
> --- a/drivers/tty/serial/imx.c
> +++ b/drivers/tty/serial/imx.c
> @@ -1936,8 +1936,6 @@ imx_uart_verify_port(struct uart_port *port, struct serial_struct *ser)
> ret = -EINVAL;
> if (port->iobase != ser->port)
> ret = -EINVAL;
> - if (ser->hub6 != 0)
> - ret = -EINVAL;
> return ret;
> }
>
> diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
> index 472ec39caf27..240009333fb5 100644
> --- a/drivers/tty/serial/mpc52xx_uart.c
> +++ b/drivers/tty/serial/mpc52xx_uart.c
> @@ -1339,8 +1339,7 @@ mpc52xx_uart_verify_port(struct uart_port *port, struct serial_struct *ser)
> if ((ser->irq != port->irq) ||
> (ser->io_type != UPIO_MEM) ||
> (ser->baud_base != port->uartclk) ||
> - (ser->iomem_base != (void *)port->mapbase) ||
> - (ser->hub6 != 0))
> + (ser->iomem_base != (void *)port->mapbase))
> return -EINVAL;
>
> return 0;
> diff --git a/drivers/tty/serial/sa1100.c b/drivers/tty/serial/sa1100.c
> index 72b1bb76415c..ee5f3960d1e4 100644
> --- a/drivers/tty/serial/sa1100.c
> +++ b/drivers/tty/serial/sa1100.c
> @@ -556,8 +556,6 @@ sa1100_verify_port(struct uart_port *port, struct serial_struct *ser)
> ret = -EINVAL;
> if (sport->port.iobase != ser->port)
> ret = -EINVAL;
> - if (ser->hub6 != 0)
> - ret = -EINVAL;
> return ret;
> }
>
> diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
> index 9eea8d1a0e8a..15d8c3ed6edc 100644
> --- a/drivers/tty/serial/serial_core.c
> +++ b/drivers/tty/serial/serial_core.c
> @@ -812,7 +812,7 @@ static int uart_get_info(struct tty_port *port, struct serial_struct *retinfo)
> ASYNC_CLOSING_WAIT_NONE :
> jiffies_to_msecs(port->closing_wait) / 10;
> retinfo->custom_divisor = uport->custom_divisor;
> - retinfo->hub6 = uport->hub6;
> + retinfo->hub6 = 0;
> retinfo->io_type = uport->iotype;
> retinfo->iomem_reg_shift = uport->regshift;
> retinfo->iomem_base = (void *)(unsigned long)uport->mapbase;
> @@ -834,13 +834,12 @@ static int uart_change_port(struct uart_port *uport,
> unsigned long new_port)
> {
> unsigned long old_iobase, old_mapbase;
> - unsigned int old_type, old_iotype, old_hub6, old_shift;
> + unsigned int old_type, old_iotype, old_shift;
> int retval;
>
> old_iobase = uport->iobase;
> old_mapbase = uport->mapbase;
> old_type = uport->type;
> - old_hub6 = uport->hub6;
> old_iotype = uport->iotype;
> old_shift = uport->regshift;
>
> @@ -849,7 +848,6 @@ static int uart_change_port(struct uart_port *uport,
>
> uport->iobase = new_port;
> uport->type = new_info->type;
> - uport->hub6 = new_info->hub6;
> uport->iotype = new_info->io_type;
> uport->regshift = new_info->iomem_reg_shift;
> uport->mapbase = (unsigned long)new_info->iomem_base;
> @@ -867,7 +865,6 @@ static int uart_change_port(struct uart_port *uport,
> */
> uport->iobase = old_iobase;
> uport->type = old_type;
> - uport->hub6 = old_hub6;
> uport->iotype = old_iotype;
> uport->regshift = old_shift;
> uport->mapbase = old_mapbase;
> @@ -924,7 +921,6 @@ static int uart_set_info(struct tty_struct *tty, struct tty_port *port,
> change_port = !(uport->flags & UPF_FIXED_PORT)
> && (new_port != uport->iobase ||
> (unsigned long)new_info->iomem_base != uport->mapbase ||
> - new_info->hub6 != uport->hub6 ||
> new_info->io_type != uport->iotype ||
> new_info->iomem_reg_shift != uport->regshift ||
> new_info->type != uport->type);
> @@ -954,6 +950,10 @@ static int uart_set_info(struct tty_struct *tty, struct tty_port *port,
> goto check_and_exit;
> }
>
> + /* hub6 is no longer support */
> + if (new_info->hub6 != 0)
> + return -EINVAL;
> +
> if (change_irq || change_port) {
> retval = security_locked_down(LOCKDOWN_TIOCSSERIAL);
> if (retval)
> @@ -2010,7 +2010,6 @@ bool uart_iotype_io(enum uart_iotype iotype)
> {
> switch (iotype) {
> case UPIO_PORT:
> - case UPIO_HUB6:
> return true;
> default:
> return false;
> @@ -2538,10 +2537,7 @@ void uart_get_ioinfos(struct uart_port *port, char *buf, size_t size)
> if (uart_iotype_mmio(port->iotype)) {
> scnprintf(buf, size, " MMIO%s:%pa", uart_get_mmio_width(port), &port->mapbase);
> } else if (uart_iotype_io(port->iotype)) {
> - if (port->iotype == UPIO_PORT)
> - scnprintf(buf, size, " I/O:0x%lx", port->iobase);
> - else if (port->iotype == UPIO_HUB6)
> - scnprintf(buf, size, " I/O:0x%lx, offset 0x%x", port->iobase, port->hub6);
> + scnprintf(buf, size, " I/O:0x%lx", port->iobase);
> }
With this simplification, you can now remove the {} braces...
> }
> EXPORT_SYMBOL(uart_get_ioinfos);
> diff --git a/drivers/tty/serial/sunsu.c b/drivers/tty/serial/sunsu.c
> index 4ff3e5c41dab..f43b802add12 100644
> --- a/drivers/tty/serial/sunsu.c
> +++ b/drivers/tty/serial/sunsu.c
> @@ -106,10 +106,6 @@ static unsigned int serial_in(struct uart_sunsu_port *up, int offset)
> offset <<= up->port.regshift;
>
> switch (up->port.iotype) {
> - case UPIO_HUB6:
> - outb(up->port.hub6 - 1 + offset, up->port.iobase);
> - return inb(up->port.iobase + 1);
> -
> case UPIO_MEM:
> return readb(up->port.membase + offset);
Maybe change to a simple if/else?
if (up->port.iotype == UPIO_MEM)
return readb(up->port.membase + offset);
else
return inb(up->port.iobase + offset);
>
> @@ -136,11 +132,6 @@ static void serial_out(struct uart_sunsu_port *up, int offset, int value)
> offset <<= up->port.regshift;
>
> switch (up->port.iotype) {
> - case UPIO_HUB6:
> - outb(up->port.hub6 - 1 + offset, up->port.iobase);
> - outb(value, up->port.iobase + 1);
> - break;
> -
> case UPIO_MEM:
> writeb(value, up->port.membase + offset);
> break;
Similar here:
if (up->port.iotype == UPIO_MEM)
writeb(value, up->port.membase + offset);
else
outb(value, up->port.iobase + offset);
> diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c
> index a072b75dbaf2..4066cc99fe1a 100644
> --- a/drivers/tty/serial/xilinx_uartps.c
> +++ b/drivers/tty/serial/xilinx_uartps.c
> @@ -1079,8 +1079,6 @@ static int cdns_uart_verify_port(struct uart_port *port,
> return -EINVAL;
> if (port->iobase != ser->port)
> return -EINVAL;
> - if (ser->hub6 != 0)
> - return -EINVAL;
> return 0;
> }
>
> diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
> index d91c0477be9d..d55bce4d4709 100644
> --- a/include/linux/serial_8250.h
> +++ b/include/linux/serial_8250.h
> @@ -41,7 +41,6 @@ struct plat_serial8250_port {
> void *private_data;
> unsigned char regshift; /* register shift */
> unsigned char iotype; /* UPIO_* */
> - unsigned char hub6;
> unsigned char has_sysrq; /* supports magic SysRq */
> unsigned int type; /* If UPF_FIXED_TYPE */
> upf_t flags; /* UPF_* flags */
> @@ -75,7 +74,6 @@ enum {
> PLAT8250_DEV_ACCENT,
> PLAT8250_DEV_BOCA,
> PLAT8250_DEV_EXAR_ST16C554,
> - PLAT8250_DEV_HUB6,
> PLAT8250_DEV_AU1X00,
> PLAT8250_DEV_SM501,
> };
> diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
> index 4eeb8253752a..ca8d009e5c36 100644
> --- a/include/linux/serial_core.h
> +++ b/include/linux/serial_core.h
> @@ -430,7 +430,6 @@ typedef unsigned int __bitwise upstat_t;
> enum uart_iotype {
> UPIO_UNKNOWN = -1,
> UPIO_PORT = SERIAL_IO_PORT, /* 8b I/O port access */
> - UPIO_HUB6 = SERIAL_IO_HUB6, /* Hub6 ISA card */
> UPIO_MEM = SERIAL_IO_MEM, /* driver-specific */
> UPIO_MEM32 = SERIAL_IO_MEM32, /* 32b little endian */
> UPIO_AU = SERIAL_IO_AU, /* Au1x00 and RT288x type IO */
> @@ -590,7 +589,6 @@ struct uart_port {
> unsigned char has_sysrq;
> unsigned char sysrq_seq; /* index in sysrq_toggle_seq */
>
> - unsigned char hub6; /* this should be in the 8250 driver */
> unsigned char suspended;
> unsigned char console_reinit;
> const char *name; /* port name */
> --
> 2.53.0
>
>
>
--
Hugo Villeneuve
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 1/2] tty: serial: remove hub6 multiport support
2026-10-16 16:48 ` Hugo Villeneuve
@ 2026-10-16 17:12 ` Arnd Bergmann
2026-10-16 17:16 ` Hugo Villeneuve
0 siblings, 1 reply; 14+ messages in thread
From: Arnd Bergmann @ 2026-10-16 17:12 UTC (permalink / raw)
To: Hugo Villeneuve, Arnd Bergmann
Cc: Greg Kroah-Hartman, Jiri Slaby, Andy Shevchenko,
Uwe Kleine-König, Hugo Villeneuve, linux-kernel,
linux-serial, linux-arm-kernel, imx
On Fri, Oct 16, 2026, at 18:48, Hugo Villeneuve wrote:
> On Fri, 16 Oct 2026 14:59:47 +0200
>> - scnprintf(buf, size, " I/O:0x%lx, offset 0x%x", port->iobase, port->hub6);
>> + scnprintf(buf, size, " I/O:0x%lx", port->iobase);
>> }
>
> With this simplification, you can now remove the {} braces...
Done
>> diff --git a/drivers/tty/serial/sunsu.c b/drivers/tty/serial/sunsu.c
>> index 4ff3e5c41dab..f43b802add12 100644
>> --- a/drivers/tty/serial/sunsu.c
>> +++ b/drivers/tty/serial/sunsu.c
>> @@ -106,10 +106,6 @@ static unsigned int serial_in(struct uart_sunsu_port *up, int offset)
>> offset <<= up->port.regshift;
>>
>> switch (up->port.iotype) {
>> - case UPIO_HUB6:
>> - outb(up->port.hub6 - 1 + offset, up->port.iobase);
>> - return inb(up->port.iobase + 1);
>> -
>> case UPIO_MEM:
>> return readb(up->port.membase + offset);
>
> Maybe change to a simple if/else?
>
> if (up->port.iotype == UPIO_MEM)
> return readb(up->port.membase + offset);
> else
> return inb(up->port.iobase + offset);
>
I think I'd rather not change sunsu.c any more than necessary.
Arnd
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 1/2] tty: serial: remove hub6 multiport support
2026-10-16 17:12 ` Arnd Bergmann
@ 2026-10-16 17:16 ` Hugo Villeneuve
0 siblings, 0 replies; 14+ messages in thread
From: Hugo Villeneuve @ 2026-10-16 17:16 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Arnd Bergmann, Greg Kroah-Hartman, Jiri Slaby, Andy Shevchenko,
Uwe Kleine-König, Hugo Villeneuve, linux-kernel,
linux-serial, linux-arm-kernel, imx
On Fri, 16 Oct 2026 19:12:19 +0200
"Arnd Bergmann" <arnd@arndb.de> wrote:
> On Fri, Oct 16, 2026, at 18:48, Hugo Villeneuve wrote:
> > On Fri, 16 Oct 2026 14:59:47 +0200
>
> >> - scnprintf(buf, size, " I/O:0x%lx, offset 0x%x", port->iobase, port->hub6);
> >> + scnprintf(buf, size, " I/O:0x%lx", port->iobase);
> >> }
> >
> > With this simplification, you can now remove the {} braces...
>
> Done
>
> >> diff --git a/drivers/tty/serial/sunsu.c b/drivers/tty/serial/sunsu.c
> >> index 4ff3e5c41dab..f43b802add12 100644
> >> --- a/drivers/tty/serial/sunsu.c
> >> +++ b/drivers/tty/serial/sunsu.c
> >> @@ -106,10 +106,6 @@ static unsigned int serial_in(struct uart_sunsu_port *up, int offset)
> >> offset <<= up->port.regshift;
> >>
> >> switch (up->port.iotype) {
> >> - case UPIO_HUB6:
> >> - outb(up->port.hub6 - 1 + offset, up->port.iobase);
> >> - return inb(up->port.iobase + 1);
> >> -
> >> case UPIO_MEM:
> >> return readb(up->port.membase + offset);
> >
> > Maybe change to a simple if/else?
> >
> > if (up->port.iotype == UPIO_MEM)
> > return readb(up->port.membase + offset);
> > else
> > return inb(up->port.iobase + offset);
> >
>
> I think I'd rather not change sunsu.c any more than necessary.
Ok
--
Hugo Villeneuve
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 1/2] tty: serial: remove hub6 multiport support
2026-10-16 16:16 ` Arnd Bergmann
@ 2026-10-16 17:17 ` Hugo Villeneuve
0 siblings, 0 replies; 14+ messages in thread
From: Hugo Villeneuve @ 2026-10-16 17:17 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Arnd Bergmann, Greg Kroah-Hartman, Jiri Slaby, Andy Shevchenko,
Uwe Kleine-König, Hugo Villeneuve, linux-kernel,
linux-serial, linux-arm-kernel, imx
Hi Arnd,
On Fri, 16 Oct 2026 18:16:20 +0200
"Arnd Bergmann" <arnd@arndb.de> wrote:
> On Fri, Oct 16, 2026, at 17:56, Hugo Villeneuve wrote:
> > On Fri, 16 Oct 2026 14:59:47 +0200
>
> >> retinfo->custom_divisor = uport->custom_divisor;
> >> - retinfo->hub6 = uport->hub6;
> >> + retinfo->hub6 = 0;
> >
> > Would a comment here help?
> >
> > retinfo->hub6 = 0; /* No longer supported */
>
> Good idea, added.
>
> >> @@ -924,7 +921,6 @@ static int uart_set_info(struct tty_struct *tty, struct tty_port *port,
> >> change_port = !(uport->flags & UPF_FIXED_PORT)
> >> && (new_port != uport->iobase ||
> >> (unsigned long)new_info->iomem_base != uport->mapbase ||
> >> - new_info->hub6 != uport->hub6 ||
> >
> > Maybe keep this so that change_port is true if someone sets hub6 to a
> > value other than zero (see below)?
>
> Right, this would be fairly harmless as nothing looks at the field
> afterwards but it makes sense for consistency.
>
> I've moved the hub6 check up before change_port now to behave the
> same way for regular users and root:
Yes that works too.
Reviewed-by: Hugo Villeneuve <hvilleneuve@dimonoff.com>
>
> @@ -935,6 +935,11 @@ static int uart_set_info(struct tty_struct *tty, struct tty_port *port,
> if (uartclk == 0)
> return -EINVAL;
> }
> +
> + /* hub6 is no longer supported */
> + if (new_info->hub6 != 0)
> + return -EINVAL;
> +
> if (!capable(CAP_SYS_ADMIN)) {
> if (change_irq || change_port ||
> (new_info->baud_base != uport->uartclk / 16) ||
> @@ -950,10 +955,6 @@ static int uart_set_info(struct tty_struct *tty, struct tty_port *port,
> goto check_and_exit;
> }
>
> - /* hub6 is no longer supported */
> - if (new_info->hub6 != 0)
> - return -EINVAL;
> -
> if (change_irq || change_port) {
> retval = security_locked_down(LOCKDOWN_TIOCSSERIAL);
> if (retval)
>
> Thanks for taking a look!
>
> Arnd
>
--
Hugo Villeneuve
^ permalink raw reply [flat|nested] 14+ messages in thread
* Re: [PATCH 1/2] tty: serial: remove hub6 multiport support
2026-10-16 12:59 [PATCH 1/2] tty: serial: remove hub6 multiport support Arnd Bergmann
` (5 preceding siblings ...)
2026-10-16 16:48 ` Hugo Villeneuve
@ 2026-10-16 18:28 ` Frank Li
6 siblings, 0 replies; 14+ messages in thread
From: Frank Li @ 2026-10-16 18:28 UTC (permalink / raw)
To: Arnd Bergmann
Cc: Greg Kroah-Hartman, Jiri Slaby, Andy Shevchenko,
Uwe Kleine-König (The Capable Hub), Hugo Villeneuve,
Arnd Bergmann, linux-kernel, linux-serial, linux-arm-kernel, imx
On Fri, Oct 16, 2026 at 02:59:47PM +0200, Arnd Bergmann wrote:
> From: Arnd Bergmann <arnd@arndb.de>
>
> hub6 support was added in linux-0.99 and the hardware was already old at
> the time, being discontinued in 1990. The code for it has always been a
> mess since it adds another dimension to the I/O addressing in the driver
> that has leaked into many individual files.
>
> Hugo and Uwe have attempted several times this year alone to isolate
> the hub6 handling into the 8250_hub6.c file, but I feel that none of
> this has been a real improvement over the original standalone loadable
> module support.
>
> Any machine that would have used this ISA card in practice is likely
> 30 to 40 years old, and with i486 support now removed, it is clearly
> safe to just kill this all off. The only bit that has to remain
> is the ioctl interface, to ensure the serial_struct field is always
> zero.
>
> Link: https://mirrors.nycbug.org/pub/The_Unix_Archive/Unix_Usenet/comp.unix.sysv386/1990-December/007174.html
> Fixes: a300273c458c ("serial: 8250: hub6: Add cleanup code")
> Fixes: c526404a4a92 ("serial: 8250: Fix corner case for port matching")
> Fixes: 7ab80d1e7243 ("serial: 8250: fix compile error with hub6_match_port() when compiled as a module")
> Fixes: da7b5fd4e17f ("serial: 8250_hub6: add missing include for hub6_match_port()")
> Fixes: 3d406299d882 ("serial: 8250_hub6: add hub6_match_port()")
> Signed-off-by: Arnd Bergmann <arnd@arndb.de>
> ---
> drivers/tty/serial/8250/8250.h | 15 -------
> drivers/tty/serial/8250/8250_core.c | 2 -
> drivers/tty/serial/8250/8250_hub6.c | 60 -------------------------
> drivers/tty/serial/8250/8250_platform.c | 11 +----
> drivers/tty/serial/8250/8250_port.c | 23 ----------
> drivers/tty/serial/8250/Kconfig | 15 ++-----
> drivers/tty/serial/8250/Makefile | 1 -
> drivers/tty/serial/atmel_serial.c | 2 -
> drivers/tty/serial/fsl_lpuart.c | 2 -
> drivers/tty/serial/imx.c | 2 -
For freescale part.
Acked-by: Frank Li <Frank.Li@nxp.com>
> drivers/tty/serial/mpc52xx_uart.c | 3 +-
> drivers/tty/serial/sa1100.c | 2 -
> drivers/tty/serial/serial_core.c | 18 +++-----
> drivers/tty/serial/sunsu.c | 9 ----
> drivers/tty/serial/xilinx_uartps.c | 2 -
> include/linux/serial_8250.h | 2 -
> include/linux/serial_core.h | 2 -
> 17 files changed, 12 insertions(+), 159 deletions(-)
> delete mode 100644 drivers/tty/serial/8250/8250_hub6.c
>
> diff --git a/drivers/tty/serial/8250/8250.h b/drivers/tty/serial/8250/8250.h
> index 21ed9c41b751..75afeb8c0cef 100644
> --- a/drivers/tty/serial/8250/8250.h
> +++ b/drivers/tty/serial/8250/8250.h
> @@ -323,14 +323,6 @@ static inline int serial8250_pnp_init(void) { return 0; }
> static inline void serial8250_pnp_exit(void) { }
> #endif
>
> -#ifdef CONFIG_SERIAL_8250_HUB6
> -int serial8250_hub6_init(void);
> -void serial8250_hub6_exit(void);
> -#else
> -static inline int serial8250_hub6_init(void) { return 0; }
> -static inline void serial8250_hub6_exit(void) { }
> -#endif
> -
> #ifdef CONFIG_SERIAL_8250_RSA
> void univ8250_rsa_support(struct uart_ops *ops, const struct uart_ops *core_ops);
> void rsa_enable(struct uart_8250_port *up);
> @@ -351,13 +343,6 @@ int fintek_8250_probe(struct uart_8250_port *uart);
> static inline int fintek_8250_probe(struct uart_8250_port *uart) { return 0; }
> #endif
>
> -#if IS_ENABLED(CONFIG_SERIAL_8250_HUB6)
> -bool hub6_match_port(const struct uart_port *port1, const struct uart_port *port2);
> -#else
> -static inline bool hub6_match_port(const struct uart_port *port1, const struct uart_port *port2)
> -{ return false; }
> -#endif
> -
> #ifdef CONFIG_ARCH_OMAP1
> #include <linux/soc/ti/omap1-soc.h>
> static inline int is_omap1_8250(struct uart_8250_port *pt)
> diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
> index 42319843cb5b..96c99f0ae683 100644
> --- a/drivers/tty/serial/8250/8250_core.c
> +++ b/drivers/tty/serial/8250/8250_core.c
> @@ -686,8 +686,6 @@ static bool serial8250_match_port(const struct uart_port *port1,
> return false;
> else if (port1->iotype == UPIO_PORT)
> return port1->iobase == port2->iobase;
> - else if (port1->iotype == UPIO_HUB6)
> - return hub6_match_port(port1, port2);
> else if (uart_iotype_mmio(port1->iotype))
> return port1->mapbase == port2->mapbase;
> else
> diff --git a/drivers/tty/serial/8250/8250_hub6.c b/drivers/tty/serial/8250/8250_hub6.c
> deleted file mode 100644
> index 848d9723ac56..000000000000
> --- a/drivers/tty/serial/8250/8250_hub6.c
> +++ /dev/null
> @@ -1,60 +0,0 @@
> -// SPDX-License-Identifier: GPL-2.0
> -/*
> - * Copyright (C) 2005 Russell King.
> - * Data taken from include/asm-i386/serial.h
> - */
> -#include <linux/module.h>
> -#include <linux/init.h>
> -#include <linux/serial_8250.h>
> -
> -#include "8250.h"
> -
> -#define HUB6(card, port) \
> - { \
> - .iobase = 0x302, \
> - .irq = 3, \
> - .uartclk = 1843200, \
> - .iotype = UPIO_HUB6, \
> - .flags = UPF_BOOT_AUTOCONF, \
> - .hub6 = (card) << 6 | (port) << 3 | 1, \
> - }
> -
> -static struct plat_serial8250_port hub6_data[] = {
> - HUB6(0, 0),
> - HUB6(0, 1),
> - HUB6(0, 2),
> - HUB6(0, 3),
> - HUB6(0, 4),
> - HUB6(0, 5),
> - HUB6(1, 0),
> - HUB6(1, 1),
> - HUB6(1, 2),
> - HUB6(1, 3),
> - HUB6(1, 4),
> - HUB6(1, 5),
> - { },
> -};
> -
> -static struct platform_device hub6_device = {
> - .name = "serial8250",
> - .id = PLAT8250_DEV_HUB6,
> - .dev = {
> - .platform_data = hub6_data,
> - },
> -};
> -
> -bool hub6_match_port(const struct uart_port *port1, const struct uart_port *port2)
> -{
> - return port1->iobase == port2->iobase && port1->hub6 == port2->hub6;
> -}
> -EXPORT_SYMBOL_GPL(hub6_match_port);
> -
> -int __init serial8250_hub6_init(void)
> -{
> - return platform_device_register(&hub6_device);
> -}
> -
> -void serial8250_hub6_exit(void)
> -{
> - platform_device_unregister(&hub6_device);
> -}
> diff --git a/drivers/tty/serial/8250/8250_platform.c b/drivers/tty/serial/8250/8250_platform.c
> index 7ce7ad295fae..8aa769085bfa 100644
> --- a/drivers/tty/serial/8250/8250_platform.c
> +++ b/drivers/tty/serial/8250/8250_platform.c
> @@ -86,7 +86,6 @@ static void __init __serial8250_isa_init_ports(void)
> port->irqflags = 0;
> port->uartclk = old_serial_port[i].baud_base * 16;
> port->flags = old_serial_port[i].flags;
> - port->hub6 = 0;
> port->membase = old_serial_port[i].iomem_base;
> port->iotype = old_serial_port[i].io_type;
> port->regshift = old_serial_port[i].iomem_reg_shift;
> @@ -169,7 +168,6 @@ static int serial8250_probe_platform(struct platform_device *dev, struct plat_se
> uart->port.flags = p->flags;
> uart->port.mapbase = p->mapbase;
> uart->port.mapsize = p->mapsize;
> - uart->port.hub6 = p->hub6;
> uart->port.has_sysrq = p->has_sysrq;
> uart->port.private_data = p->private_data;
> uart->port.type = p->type;
> @@ -317,14 +315,10 @@ static int __init serial8250_init(void)
> if (ret)
> goto unreg_uart_drv;
>
> - ret = serial8250_hub6_init();
> - if (ret)
> - goto unreg_pnp;
> -
> serial8250_isa_devs = platform_device_alloc("serial8250", PLAT8250_DEV_LEGACY);
> if (!serial8250_isa_devs) {
> ret = -ENOMEM;
> - goto unreg_hub6;
> + goto unreg_pnp;
> }
>
> ret = platform_device_add(serial8250_isa_devs);
> @@ -340,8 +334,6 @@ static int __init serial8250_init(void)
> platform_device_del(serial8250_isa_devs);
> put_dev:
> platform_device_put(serial8250_isa_devs);
> -unreg_hub6:
> - serial8250_hub6_exit();
> unreg_pnp:
> serial8250_pnp_exit();
> unreg_uart_drv:
> @@ -369,7 +361,6 @@ static void __exit serial8250_exit(void)
> platform_driver_unregister(&serial8250_isa_driver);
> platform_device_unregister(isa_dev);
>
> - serial8250_hub6_exit();
> serial8250_pnp_exit();
>
> #ifdef CONFIG_SPARC
> diff --git a/drivers/tty/serial/8250/8250_port.c b/drivers/tty/serial/8250/8250_port.c
> index 36b2b0a2c05c..3593e7209879 100644
> --- a/drivers/tty/serial/8250/8250_port.c
> +++ b/drivers/tty/serial/8250/8250_port.c
> @@ -354,22 +354,6 @@ static void default_serial_dl_write(struct uart_8250_port *up, u32 value)
> serial_out(up, UART_DLM, value >> 8 & 0xff);
> }
>
> -#ifdef CONFIG_HAS_IOPORT
> -static u32 hub6_serial_in(struct uart_port *p, unsigned int offset)
> -{
> - offset = offset << p->regshift;
> - outb(p->hub6 - 1 + offset, p->iobase);
> - return inb(p->iobase + 1);
> -}
> -
> -static void hub6_serial_out(struct uart_port *p, unsigned int offset, u32 value)
> -{
> - offset = offset << p->regshift;
> - outb(p->hub6 - 1 + offset, p->iobase);
> - outb(value, p->iobase + 1);
> -}
> -#endif /* CONFIG_HAS_IOPORT */
> -
> static u32 mem_serial_in(struct uart_port *p, unsigned int offset)
> {
> offset = offset << p->regshift;
> @@ -450,13 +434,6 @@ static void set_io_from_upio(struct uart_port *p)
> up->dl_write = default_serial_dl_write;
>
> switch (p->iotype) {
> -#ifdef CONFIG_HAS_IOPORT
> - case UPIO_HUB6:
> - p->serial_in = hub6_serial_in;
> - p->serial_out = hub6_serial_out;
> - break;
> -#endif
> -
> case UPIO_MEM:
> p->serial_in = mem_serial_in;
> p->serial_out = mem_serial_out;
> diff --git a/drivers/tty/serial/8250/Kconfig b/drivers/tty/serial/8250/Kconfig
> index 82e761b8298a..9917b7e1bb26 100644
> --- a/drivers/tty/serial/8250/Kconfig
> +++ b/drivers/tty/serial/8250/Kconfig
> @@ -208,9 +208,9 @@ config SERIAL_8250_EXTENDED
> depends on SERIAL_8250
> help
> If you wish to use any non-standard features of the standard "dumb"
> - driver, say Y here. This includes HUB6 support, shared serial
> - interrupts, special multiport support, support for more than the
> - four COM 1/2/3/4 boards, etc.
> + driver, say Y here. This includes shared serial interrupts, special
> + multiport support, support for more than the four COM 1/2/3/4 boards,
> + etc.
>
> Note that the answer to this question won't directly affect the
> kernel: saying N will just cause the configurator to skip all
> @@ -303,15 +303,6 @@ config SERIAL_8250_EXAR_ST16C554
> To compile this driver as a module, choose M here: the module
> will be called 8250_exar_st16c554.
>
> -config SERIAL_8250_HUB6
> - bool "Support Hub6 cards"
> - depends on SERIAL_8250_MANY_PORTS && ISA
> - help
> - Say Y here if you have a HUB6 serial board.
> -
> - To compile this driver as a module, choose M here: the module
> - will be called 8250_hub6.
> -
> config SERIAL_8250_PCI1XXXX
> tristate "Microchip 8250 based serial port"
> depends on SERIAL_8250 && PCI
> diff --git a/drivers/tty/serial/8250/Makefile b/drivers/tty/serial/8250/Makefile
> index 5ff2ba414e13..d241ce486953 100644
> --- a/drivers/tty/serial/8250/Makefile
> +++ b/drivers/tty/serial/8250/Makefile
> @@ -7,7 +7,6 @@ obj-$(CONFIG_SERIAL_8250) += 8250.o
> 8250-y := 8250_core.o
> 8250-y += 8250_platform.o
> 8250-$(CONFIG_SERIAL_8250_PNP) += 8250_pnp.o
> -8250-$(CONFIG_SERIAL_8250_HUB6) += 8250_hub6.o
>
> obj-$(CONFIG_SERIAL_8250) += 8250_base.o
> 8250_base-y := 8250_port.o
> diff --git a/drivers/tty/serial/atmel_serial.c b/drivers/tty/serial/atmel_serial.c
> index c3880259e3bc..9c40ccee0c82 100644
> --- a/drivers/tty/serial/atmel_serial.c
> +++ b/drivers/tty/serial/atmel_serial.c
> @@ -2448,8 +2448,6 @@ static int atmel_verify_port(struct uart_port *port, struct serial_struct *ser)
> ret = -EINVAL;
> if (port->iobase != ser->port)
> ret = -EINVAL;
> - if (ser->hub6 != 0)
> - ret = -EINVAL;
> return ret;
> }
>
> diff --git a/drivers/tty/serial/fsl_lpuart.c b/drivers/tty/serial/fsl_lpuart.c
> index c8575c965203..6e1248840022 100644
> --- a/drivers/tty/serial/fsl_lpuart.c
> +++ b/drivers/tty/serial/fsl_lpuart.c
> @@ -2432,8 +2432,6 @@ static int lpuart_verify_port(struct uart_port *port, struct serial_struct *ser)
> ret = -EINVAL;
> if (port->iobase != ser->port)
> ret = -EINVAL;
> - if (ser->hub6 != 0)
> - ret = -EINVAL;
> return ret;
> }
>
> diff --git a/drivers/tty/serial/imx.c b/drivers/tty/serial/imx.c
> index 986fefb45c63..d89be62e3852 100644
> --- a/drivers/tty/serial/imx.c
> +++ b/drivers/tty/serial/imx.c
> @@ -1936,8 +1936,6 @@ imx_uart_verify_port(struct uart_port *port, struct serial_struct *ser)
> ret = -EINVAL;
> if (port->iobase != ser->port)
> ret = -EINVAL;
> - if (ser->hub6 != 0)
> - ret = -EINVAL;
> return ret;
> }
>
> diff --git a/drivers/tty/serial/mpc52xx_uart.c b/drivers/tty/serial/mpc52xx_uart.c
> index 472ec39caf27..240009333fb5 100644
> --- a/drivers/tty/serial/mpc52xx_uart.c
> +++ b/drivers/tty/serial/mpc52xx_uart.c
> @@ -1339,8 +1339,7 @@ mpc52xx_uart_verify_port(struct uart_port *port, struct serial_struct *ser)
> if ((ser->irq != port->irq) ||
> (ser->io_type != UPIO_MEM) ||
> (ser->baud_base != port->uartclk) ||
> - (ser->iomem_base != (void *)port->mapbase) ||
> - (ser->hub6 != 0))
> + (ser->iomem_base != (void *)port->mapbase))
> return -EINVAL;
>
> return 0;
> diff --git a/drivers/tty/serial/sa1100.c b/drivers/tty/serial/sa1100.c
> index 72b1bb76415c..ee5f3960d1e4 100644
> --- a/drivers/tty/serial/sa1100.c
> +++ b/drivers/tty/serial/sa1100.c
> @@ -556,8 +556,6 @@ sa1100_verify_port(struct uart_port *port, struct serial_struct *ser)
> ret = -EINVAL;
> if (sport->port.iobase != ser->port)
> ret = -EINVAL;
> - if (ser->hub6 != 0)
> - ret = -EINVAL;
> return ret;
> }
>
> diff --git a/drivers/tty/serial/serial_core.c b/drivers/tty/serial/serial_core.c
> index 9eea8d1a0e8a..15d8c3ed6edc 100644
> --- a/drivers/tty/serial/serial_core.c
> +++ b/drivers/tty/serial/serial_core.c
> @@ -812,7 +812,7 @@ static int uart_get_info(struct tty_port *port, struct serial_struct *retinfo)
> ASYNC_CLOSING_WAIT_NONE :
> jiffies_to_msecs(port->closing_wait) / 10;
> retinfo->custom_divisor = uport->custom_divisor;
> - retinfo->hub6 = uport->hub6;
> + retinfo->hub6 = 0;
> retinfo->io_type = uport->iotype;
> retinfo->iomem_reg_shift = uport->regshift;
> retinfo->iomem_base = (void *)(unsigned long)uport->mapbase;
> @@ -834,13 +834,12 @@ static int uart_change_port(struct uart_port *uport,
> unsigned long new_port)
> {
> unsigned long old_iobase, old_mapbase;
> - unsigned int old_type, old_iotype, old_hub6, old_shift;
> + unsigned int old_type, old_iotype, old_shift;
> int retval;
>
> old_iobase = uport->iobase;
> old_mapbase = uport->mapbase;
> old_type = uport->type;
> - old_hub6 = uport->hub6;
> old_iotype = uport->iotype;
> old_shift = uport->regshift;
>
> @@ -849,7 +848,6 @@ static int uart_change_port(struct uart_port *uport,
>
> uport->iobase = new_port;
> uport->type = new_info->type;
> - uport->hub6 = new_info->hub6;
> uport->iotype = new_info->io_type;
> uport->regshift = new_info->iomem_reg_shift;
> uport->mapbase = (unsigned long)new_info->iomem_base;
> @@ -867,7 +865,6 @@ static int uart_change_port(struct uart_port *uport,
> */
> uport->iobase = old_iobase;
> uport->type = old_type;
> - uport->hub6 = old_hub6;
> uport->iotype = old_iotype;
> uport->regshift = old_shift;
> uport->mapbase = old_mapbase;
> @@ -924,7 +921,6 @@ static int uart_set_info(struct tty_struct *tty, struct tty_port *port,
> change_port = !(uport->flags & UPF_FIXED_PORT)
> && (new_port != uport->iobase ||
> (unsigned long)new_info->iomem_base != uport->mapbase ||
> - new_info->hub6 != uport->hub6 ||
> new_info->io_type != uport->iotype ||
> new_info->iomem_reg_shift != uport->regshift ||
> new_info->type != uport->type);
> @@ -954,6 +950,10 @@ static int uart_set_info(struct tty_struct *tty, struct tty_port *port,
> goto check_and_exit;
> }
>
> + /* hub6 is no longer support */
> + if (new_info->hub6 != 0)
> + return -EINVAL;
> +
> if (change_irq || change_port) {
> retval = security_locked_down(LOCKDOWN_TIOCSSERIAL);
> if (retval)
> @@ -2010,7 +2010,6 @@ bool uart_iotype_io(enum uart_iotype iotype)
> {
> switch (iotype) {
> case UPIO_PORT:
> - case UPIO_HUB6:
> return true;
> default:
> return false;
> @@ -2538,10 +2537,7 @@ void uart_get_ioinfos(struct uart_port *port, char *buf, size_t size)
> if (uart_iotype_mmio(port->iotype)) {
> scnprintf(buf, size, " MMIO%s:%pa", uart_get_mmio_width(port), &port->mapbase);
> } else if (uart_iotype_io(port->iotype)) {
> - if (port->iotype == UPIO_PORT)
> - scnprintf(buf, size, " I/O:0x%lx", port->iobase);
> - else if (port->iotype == UPIO_HUB6)
> - scnprintf(buf, size, " I/O:0x%lx, offset 0x%x", port->iobase, port->hub6);
> + scnprintf(buf, size, " I/O:0x%lx", port->iobase);
> }
> }
> EXPORT_SYMBOL(uart_get_ioinfos);
> diff --git a/drivers/tty/serial/sunsu.c b/drivers/tty/serial/sunsu.c
> index 4ff3e5c41dab..f43b802add12 100644
> --- a/drivers/tty/serial/sunsu.c
> +++ b/drivers/tty/serial/sunsu.c
> @@ -106,10 +106,6 @@ static unsigned int serial_in(struct uart_sunsu_port *up, int offset)
> offset <<= up->port.regshift;
>
> switch (up->port.iotype) {
> - case UPIO_HUB6:
> - outb(up->port.hub6 - 1 + offset, up->port.iobase);
> - return inb(up->port.iobase + 1);
> -
> case UPIO_MEM:
> return readb(up->port.membase + offset);
>
> @@ -136,11 +132,6 @@ static void serial_out(struct uart_sunsu_port *up, int offset, int value)
> offset <<= up->port.regshift;
>
> switch (up->port.iotype) {
> - case UPIO_HUB6:
> - outb(up->port.hub6 - 1 + offset, up->port.iobase);
> - outb(value, up->port.iobase + 1);
> - break;
> -
> case UPIO_MEM:
> writeb(value, up->port.membase + offset);
> break;
> diff --git a/drivers/tty/serial/xilinx_uartps.c b/drivers/tty/serial/xilinx_uartps.c
> index a072b75dbaf2..4066cc99fe1a 100644
> --- a/drivers/tty/serial/xilinx_uartps.c
> +++ b/drivers/tty/serial/xilinx_uartps.c
> @@ -1079,8 +1079,6 @@ static int cdns_uart_verify_port(struct uart_port *port,
> return -EINVAL;
> if (port->iobase != ser->port)
> return -EINVAL;
> - if (ser->hub6 != 0)
> - return -EINVAL;
> return 0;
> }
>
> diff --git a/include/linux/serial_8250.h b/include/linux/serial_8250.h
> index d91c0477be9d..d55bce4d4709 100644
> --- a/include/linux/serial_8250.h
> +++ b/include/linux/serial_8250.h
> @@ -41,7 +41,6 @@ struct plat_serial8250_port {
> void *private_data;
> unsigned char regshift; /* register shift */
> unsigned char iotype; /* UPIO_* */
> - unsigned char hub6;
> unsigned char has_sysrq; /* supports magic SysRq */
> unsigned int type; /* If UPF_FIXED_TYPE */
> upf_t flags; /* UPF_* flags */
> @@ -75,7 +74,6 @@ enum {
> PLAT8250_DEV_ACCENT,
> PLAT8250_DEV_BOCA,
> PLAT8250_DEV_EXAR_ST16C554,
> - PLAT8250_DEV_HUB6,
> PLAT8250_DEV_AU1X00,
> PLAT8250_DEV_SM501,
> };
> diff --git a/include/linux/serial_core.h b/include/linux/serial_core.h
> index 4eeb8253752a..ca8d009e5c36 100644
> --- a/include/linux/serial_core.h
> +++ b/include/linux/serial_core.h
> @@ -430,7 +430,6 @@ typedef unsigned int __bitwise upstat_t;
> enum uart_iotype {
> UPIO_UNKNOWN = -1,
> UPIO_PORT = SERIAL_IO_PORT, /* 8b I/O port access */
> - UPIO_HUB6 = SERIAL_IO_HUB6, /* Hub6 ISA card */
> UPIO_MEM = SERIAL_IO_MEM, /* driver-specific */
> UPIO_MEM32 = SERIAL_IO_MEM32, /* 32b little endian */
> UPIO_AU = SERIAL_IO_AU, /* Au1x00 and RT288x type IO */
> @@ -590,7 +589,6 @@ struct uart_port {
> unsigned char has_sysrq;
> unsigned char sysrq_seq; /* index in sysrq_toggle_seq */
>
> - unsigned char hub6; /* this should be in the 8250 driver */
> unsigned char suspended;
> unsigned char console_reinit;
> const char *name; /* port name */
> --
> 2.53.0
>
^ permalink raw reply [flat|nested] 14+ messages in thread
end of thread, other threads:[~2026-10-16 18:28 UTC | newest]
Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-10-16 12:59 [PATCH 1/2] tty: serial: remove hub6 multiport support Arnd Bergmann
2026-10-16 12:59 ` [PATCH 2/2] [v2] serial: 8250: remove obsolete and broken PORT_RSA support Arnd Bergmann
2026-10-16 13:14 ` Arnd Bergmann
2026-10-16 13:28 ` [PATCH 1/2] tty: serial: remove hub6 multiport support Andy Shevchenko
2026-10-16 14:41 ` Arnd Bergmann
2026-10-16 13:32 ` Andy Shevchenko
2026-10-16 14:10 ` Hugo Villeneuve
2026-10-16 15:56 ` Hugo Villeneuve
2026-10-16 16:16 ` Arnd Bergmann
2026-10-16 17:17 ` Hugo Villeneuve
2026-10-16 16:48 ` Hugo Villeneuve
2026-10-16 17:12 ` Arnd Bergmann
2026-10-16 17:16 ` Hugo Villeneuve
2026-10-16 18:28 ` Frank Li
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox