tty: serial: handle HAS_IOPORT dependencies

In a future patch HAS_IOPORT=n will disable inb()/outb() and friends at
compile time. We thus need to add HAS_IOPORT as dependency for those
drivers using them unconditionally. Some 8250 serial drivers support
MMIO only use, so fence only the parts requiring I/O ports and print an
error message if a device can't be supported with the current
configuration.

Co-developed-by: Arnd Bergmann <arnd@kernel.org>
Signed-off-by: Arnd Bergmann <arnd@kernel.org>
Acked-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Reviewed-by: Maciej W. Rozycki <macro@orcam.me.uk>
Signed-off-by: Niklas Schnelle <schnelle@linux.ibm.com>
Signed-off-by: Arnd Bergmann <arnd@arndb.de>
This commit is contained in:
Niklas Schnelle 2024-10-24 19:54:43 +02:00 committed by Arnd Bergmann
parent f663c6ae36
commit 7c7e6c8924
No known key found for this signature in database
GPG Key ID: 60AB47FFC9095227
9 changed files with 89 additions and 10 deletions

View File

@ -220,7 +220,7 @@ config MOXA_INTELLIO
config MOXA_SMARTIO config MOXA_SMARTIO
tristate "Moxa SmartIO support v. 2.0" tristate "Moxa SmartIO support v. 2.0"
depends on SERIAL_NONSTANDARD && PCI depends on SERIAL_NONSTANDARD && PCI && HAS_IOPORT
help help
Say Y here if you have a Moxa SmartIO multiport serial card and/or Say Y here if you have a Moxa SmartIO multiport serial card and/or
want to help develop a new version of this driver. want to help develop a new version of this driver.
@ -302,7 +302,7 @@ config GOLDFISH_TTY_EARLY_CONSOLE
config IPWIRELESS config IPWIRELESS
tristate "IPWireless 3G UMTS PCMCIA card support" tristate "IPWireless 3G UMTS PCMCIA card support"
depends on PCMCIA && NETDEVICES depends on PCMCIA && NETDEVICES && HAS_IOPORT
select PPP select PPP
help help
This is a driver for 3G UMTS PCMCIA card from IPWireless company. In This is a driver for 3G UMTS PCMCIA card from IPWireless company. In

View File

@ -46,8 +46,10 @@ static unsigned int serial8250_early_in(struct uart_port *port, int offset)
return readl(port->membase + offset); return readl(port->membase + offset);
case UPIO_MEM32BE: case UPIO_MEM32BE:
return ioread32be(port->membase + offset); return ioread32be(port->membase + offset);
#ifdef CONFIG_HAS_IOPORT
case UPIO_PORT: case UPIO_PORT:
return inb(port->iobase + offset); return inb(port->iobase + offset);
#endif
default: default:
return 0; return 0;
} }
@ -70,9 +72,11 @@ static void serial8250_early_out(struct uart_port *port, int offset, int value)
case UPIO_MEM32BE: case UPIO_MEM32BE:
iowrite32be(value, port->membase + offset); iowrite32be(value, port->membase + offset);
break; break;
#ifdef CONFIG_HAS_IOPORT
case UPIO_PORT: case UPIO_PORT:
outb(value, port->iobase + offset); outb(value, port->iobase + offset);
break; break;
#endif
} }
} }

View File

@ -964,6 +964,9 @@ static int pci_ite887x_init(struct pci_dev *dev)
struct resource *iobase = NULL; struct resource *iobase = NULL;
u32 miscr, uartbar, ioport; u32 miscr, uartbar, ioport;
if (!IS_ENABLED(CONFIG_HAS_IOPORT))
return serial_8250_warn_need_ioport(dev);
/* search for the base-ioport */ /* search for the base-ioport */
for (i = 0; i < ARRAY_SIZE(inta_addr); i++) { for (i = 0; i < ARRAY_SIZE(inta_addr); i++) {
iobase = request_region(inta_addr[i], ITE_887x_IOSIZE, iobase = request_region(inta_addr[i], ITE_887x_IOSIZE,
@ -1514,6 +1517,9 @@ static int pci_quatech_init(struct pci_dev *dev)
const struct pci_device_id *match; const struct pci_device_id *match;
bool amcc = false; bool amcc = false;
if (!IS_ENABLED(CONFIG_HAS_IOPORT))
return serial_8250_warn_need_ioport(dev);
match = pci_match_id(quatech_cards, dev); match = pci_match_id(quatech_cards, dev);
if (match) if (match)
amcc = match->driver_data; amcc = match->driver_data;
@ -1538,6 +1544,9 @@ static int pci_quatech_setup(struct serial_private *priv,
const struct pciserial_board *board, const struct pciserial_board *board,
struct uart_8250_port *port, int idx) struct uart_8250_port *port, int idx)
{ {
if (!IS_ENABLED(CONFIG_HAS_IOPORT))
return serial_8250_warn_need_ioport(priv->dev);
/* Needed by pci_quatech calls below */ /* Needed by pci_quatech calls below */
port->port.iobase = pci_resource_start(priv->dev, FL_GET_BASE(board->flags)); port->port.iobase = pci_resource_start(priv->dev, FL_GET_BASE(board->flags));
/* Set up the clocking */ /* Set up the clocking */
@ -1655,6 +1664,9 @@ static int pci_fintek_setup(struct serial_private *priv,
u8 config_base; u8 config_base;
u16 iobase; u16 iobase;
if (!IS_ENABLED(CONFIG_HAS_IOPORT))
return serial_8250_warn_need_ioport(pdev);
config_base = 0x40 + 0x08 * idx; config_base = 0x40 + 0x08 * idx;
/* Get the io address from configuration space */ /* Get the io address from configuration space */
@ -1686,6 +1698,9 @@ static int pci_fintek_init(struct pci_dev *dev)
u8 config_base; u8 config_base;
struct serial_private *priv = pci_get_drvdata(dev); struct serial_private *priv = pci_get_drvdata(dev);
if (!IS_ENABLED(CONFIG_HAS_IOPORT))
return serial_8250_warn_need_ioport(dev);
if (!(pci_resource_flags(dev, 5) & IORESOURCE_IO) || if (!(pci_resource_flags(dev, 5) & IORESOURCE_IO) ||
!(pci_resource_flags(dev, 4) & IORESOURCE_IO) || !(pci_resource_flags(dev, 4) & IORESOURCE_IO) ||
!(pci_resource_flags(dev, 3) & IORESOURCE_IO)) !(pci_resource_flags(dev, 3) & IORESOURCE_IO))
@ -1864,6 +1879,9 @@ static int kt_serial_setup(struct serial_private *priv,
const struct pciserial_board *board, const struct pciserial_board *board,
struct uart_8250_port *port, int idx) struct uart_8250_port *port, int idx)
{ {
if (!IS_ENABLED(CONFIG_HAS_IOPORT))
return serial_8250_warn_need_ioport(priv->dev);
port->port.flags |= UPF_BUG_THRE; port->port.flags |= UPF_BUG_THRE;
port->port.serial_in = kt_serial_in; port->port.serial_in = kt_serial_in;
port->port.handle_break = kt_handle_break; port->port.handle_break = kt_handle_break;
@ -1884,6 +1902,9 @@ pci_wch_ch353_setup(struct serial_private *priv,
const struct pciserial_board *board, const struct pciserial_board *board,
struct uart_8250_port *port, int idx) struct uart_8250_port *port, int idx)
{ {
if (!IS_ENABLED(CONFIG_HAS_IOPORT))
return serial_8250_warn_need_ioport(priv->dev);
port->port.flags |= UPF_FIXED_TYPE; port->port.flags |= UPF_FIXED_TYPE;
port->port.type = PORT_16550A; port->port.type = PORT_16550A;
return pci_default_setup(priv, board, port, idx); return pci_default_setup(priv, board, port, idx);
@ -1894,6 +1915,9 @@ pci_wch_ch355_setup(struct serial_private *priv,
const struct pciserial_board *board, const struct pciserial_board *board,
struct uart_8250_port *port, int idx) struct uart_8250_port *port, int idx)
{ {
if (!IS_ENABLED(CONFIG_HAS_IOPORT))
return serial_8250_warn_need_ioport(priv->dev);
port->port.flags |= UPF_FIXED_TYPE; port->port.flags |= UPF_FIXED_TYPE;
port->port.type = PORT_16550A; port->port.type = PORT_16550A;
return pci_default_setup(priv, board, port, idx); return pci_default_setup(priv, board, port, idx);
@ -1904,6 +1928,9 @@ pci_wch_ch38x_setup(struct serial_private *priv,
const struct pciserial_board *board, const struct pciserial_board *board,
struct uart_8250_port *port, int idx) struct uart_8250_port *port, int idx)
{ {
if (!IS_ENABLED(CONFIG_HAS_IOPORT))
return serial_8250_warn_need_ioport(priv->dev);
port->port.flags |= UPF_FIXED_TYPE; port->port.flags |= UPF_FIXED_TYPE;
port->port.type = PORT_16850; port->port.type = PORT_16850;
return pci_default_setup(priv, board, port, idx); return pci_default_setup(priv, board, port, idx);
@ -1918,6 +1945,8 @@ static int pci_wch_ch38x_init(struct pci_dev *dev)
int max_port; int max_port;
unsigned long iobase; unsigned long iobase;
if (!IS_ENABLED(CONFIG_HAS_IOPORT))
return serial_8250_warn_need_ioport(dev);
switch (dev->device) { switch (dev->device) {
case 0x3853: /* 8 ports */ case 0x3853: /* 8 ports */
@ -1937,6 +1966,11 @@ static void pci_wch_ch38x_exit(struct pci_dev *dev)
{ {
unsigned long iobase; unsigned long iobase;
if (!IS_ENABLED(CONFIG_HAS_IOPORT)) {
serial_8250_warn_need_ioport(dev);
return;
}
iobase = pci_resource_start(dev, 0); iobase = pci_resource_start(dev, 0);
outb(0x0, iobase + CH384_XINT_ENABLE_REG); outb(0x0, iobase + CH384_XINT_ENABLE_REG);
} }
@ -2052,6 +2086,9 @@ static int pci_moxa_init(struct pci_dev *dev)
unsigned int i, num_ports = moxa_get_nports(device); unsigned int i, num_ports = moxa_get_nports(device);
u8 val, init_mode = MOXA_RS232; u8 val, init_mode = MOXA_RS232;
if (!IS_ENABLED(CONFIG_HAS_IOPORT))
return serial_8250_warn_need_ioport(dev);
if (!(pci_moxa_supported_rs(dev) & MOXA_SUPP_RS232)) { if (!(pci_moxa_supported_rs(dev) & MOXA_SUPP_RS232)) {
init_mode = MOXA_RS422; init_mode = MOXA_RS422;
} }
@ -2084,6 +2121,9 @@ pci_moxa_setup(struct serial_private *priv,
unsigned int bar = FL_GET_BASE(board->flags); unsigned int bar = FL_GET_BASE(board->flags);
int offset; int offset;
if (!IS_ENABLED(CONFIG_HAS_IOPORT))
return serial_8250_warn_need_ioport(priv->dev);
if (board->num_ports == 4 && idx == 3) if (board->num_ports == 4 && idx == 3)
offset = 7 * board->uart_offset; offset = 7 * board->uart_offset;
else else

View File

@ -12,6 +12,14 @@
#include "8250.h" #include "8250.h"
#include "8250_pcilib.h" #include "8250_pcilib.h"
int serial_8250_warn_need_ioport(struct pci_dev *dev)
{
dev_warn(&dev->dev,
"Serial port not supported because of missing I/O resource\n");
return -ENXIO;
}
int serial8250_pci_setup_port(struct pci_dev *dev, struct uart_8250_port *port, int serial8250_pci_setup_port(struct pci_dev *dev, struct uart_8250_port *port,
u8 bar, unsigned int offset, int regshift) u8 bar, unsigned int offset, int regshift)
{ {
@ -27,12 +35,14 @@ int serial8250_pci_setup_port(struct pci_dev *dev, struct uart_8250_port *port,
port->port.mapbase = pci_resource_start(dev, bar) + offset; port->port.mapbase = pci_resource_start(dev, bar) + offset;
port->port.membase = pcim_iomap_table(dev)[bar] + offset; port->port.membase = pcim_iomap_table(dev)[bar] + offset;
port->port.regshift = regshift; port->port.regshift = regshift;
} else { } else if (IS_ENABLED(CONFIG_HAS_IOPORT)) {
port->port.iotype = UPIO_PORT; port->port.iotype = UPIO_PORT;
port->port.iobase = pci_resource_start(dev, bar) + offset; port->port.iobase = pci_resource_start(dev, bar) + offset;
port->port.mapbase = 0; port->port.mapbase = 0;
port->port.membase = NULL; port->port.membase = NULL;
port->port.regshift = 0; port->port.regshift = 0;
} else {
return serial_8250_warn_need_ioport(dev);
} }
return 0; return 0;
} }

View File

@ -13,3 +13,5 @@ struct uart_8250_port;
int serial8250_pci_setup_port(struct pci_dev *dev, struct uart_8250_port *port, u8 bar, int serial8250_pci_setup_port(struct pci_dev *dev, struct uart_8250_port *port, u8 bar,
unsigned int offset, int regshift); unsigned int offset, int regshift);
int serial_8250_warn_need_ioport(struct pci_dev *dev);

View File

@ -338,6 +338,7 @@ static void default_serial_dl_write(struct uart_8250_port *up, u32 value)
serial_out(up, UART_DLM, value >> 8 & 0xff); serial_out(up, UART_DLM, value >> 8 & 0xff);
} }
#ifdef CONFIG_HAS_IOPORT
static unsigned int hub6_serial_in(struct uart_port *p, int offset) static unsigned int hub6_serial_in(struct uart_port *p, int offset)
{ {
offset = offset << p->regshift; offset = offset << p->regshift;
@ -351,6 +352,7 @@ static void hub6_serial_out(struct uart_port *p, int offset, int value)
outb(p->hub6 - 1 + offset, p->iobase); outb(p->hub6 - 1 + offset, p->iobase);
outb(value, p->iobase + 1); outb(value, p->iobase + 1);
} }
#endif /* CONFIG_HAS_IOPORT */
static unsigned int mem_serial_in(struct uart_port *p, int offset) static unsigned int mem_serial_in(struct uart_port *p, int offset)
{ {
@ -400,6 +402,7 @@ static unsigned int mem32be_serial_in(struct uart_port *p, int offset)
return ioread32be(p->membase + offset); return ioread32be(p->membase + offset);
} }
#ifdef CONFIG_HAS_IOPORT
static unsigned int io_serial_in(struct uart_port *p, int offset) static unsigned int io_serial_in(struct uart_port *p, int offset)
{ {
offset = offset << p->regshift; offset = offset << p->regshift;
@ -411,6 +414,15 @@ static void io_serial_out(struct uart_port *p, int offset, int value)
offset = offset << p->regshift; offset = offset << p->regshift;
outb(value, p->iobase + offset); outb(value, p->iobase + offset);
} }
#endif
static unsigned int no_serial_in(struct uart_port *p, int offset)
{
return (unsigned int)-1;
}
static void no_serial_out(struct uart_port *p, int offset, int value)
{
}
static int serial8250_default_handle_irq(struct uart_port *port); static int serial8250_default_handle_irq(struct uart_port *port);
@ -422,10 +434,12 @@ static void set_io_from_upio(struct uart_port *p)
up->dl_write = default_serial_dl_write; up->dl_write = default_serial_dl_write;
switch (p->iotype) { switch (p->iotype) {
#ifdef CONFIG_HAS_IOPORT
case UPIO_HUB6: case UPIO_HUB6:
p->serial_in = hub6_serial_in; p->serial_in = hub6_serial_in;
p->serial_out = hub6_serial_out; p->serial_out = hub6_serial_out;
break; break;
#endif
case UPIO_MEM: case UPIO_MEM:
p->serial_in = mem_serial_in; p->serial_in = mem_serial_in;
@ -446,11 +460,16 @@ static void set_io_from_upio(struct uart_port *p)
p->serial_in = mem32be_serial_in; p->serial_in = mem32be_serial_in;
p->serial_out = mem32be_serial_out; p->serial_out = mem32be_serial_out;
break; break;
#ifdef CONFIG_HAS_IOPORT
default: case UPIO_PORT:
p->serial_in = io_serial_in; p->serial_in = io_serial_in;
p->serial_out = io_serial_out; p->serial_out = io_serial_out;
break; break;
#endif
default:
WARN(1, "Unsupported UART type %x\n", p->iotype);
p->serial_in = no_serial_in;
p->serial_out = no_serial_out;
} }
/* Remember loaded iotype */ /* Remember loaded iotype */
up->cur_iotype = p->iotype; up->cur_iotype = p->iotype;
@ -1174,7 +1193,7 @@ static void autoconfig(struct uart_8250_port *up)
*/ */
scratch = serial_in(up, UART_IER); scratch = serial_in(up, UART_IER);
serial_out(up, UART_IER, 0); serial_out(up, UART_IER, 0);
#ifdef __i386__ #if defined(__i386__) && defined(CONFIG_HAS_IOPORT)
outb(0xff, 0x080); outb(0xff, 0x080);
#endif #endif
/* /*
@ -1183,7 +1202,7 @@ static void autoconfig(struct uart_8250_port *up)
*/ */
scratch2 = serial_in(up, UART_IER) & UART_IER_ALL_INTR; scratch2 = serial_in(up, UART_IER) & UART_IER_ALL_INTR;
serial_out(up, UART_IER, UART_IER_ALL_INTR); serial_out(up, UART_IER, UART_IER_ALL_INTR);
#ifdef __i386__ #if defined(__i386__) && defined(CONFIG_HAS_IOPORT)
outb(0, 0x080); outb(0, 0x080);
#endif #endif
scratch3 = serial_in(up, UART_IER) & UART_IER_ALL_INTR; scratch3 = serial_in(up, UART_IER) & UART_IER_ALL_INTR;

View File

@ -72,7 +72,7 @@ config SERIAL_8250_16550A_VARIANTS
config SERIAL_8250_FINTEK config SERIAL_8250_FINTEK
bool "Support for Fintek variants" bool "Support for Fintek variants"
depends on SERIAL_8250 depends on SERIAL_8250 && HAS_IOPORT
help help
Selecting this option will add support for the RS232 and RS485 Selecting this option will add support for the RS232 and RS485
capabilities of the Fintek F81216A LPC to 4 UART as well similar capabilities of the Fintek F81216A LPC to 4 UART as well similar
@ -163,7 +163,7 @@ config SERIAL_8250_HP300
config SERIAL_8250_CS config SERIAL_8250_CS
tristate "8250/16550 PCMCIA device support" tristate "8250/16550 PCMCIA device support"
depends on PCMCIA && SERIAL_8250 depends on PCMCIA && SERIAL_8250 && HAS_IOPORT
help help
Say Y here to enable support for 16-bit PCMCIA serial devices, Say Y here to enable support for 16-bit PCMCIA serial devices,
including serial port cards, modems, and the modem functions of including serial port cards, modems, and the modem functions of

View File

@ -877,7 +877,7 @@ config SERIAL_TXX9_STDSERIAL
config SERIAL_JSM config SERIAL_JSM
tristate "Digi International NEO and Classic PCI Support" tristate "Digi International NEO and Classic PCI Support"
depends on PCI depends on PCI && HAS_IOPORT
select SERIAL_CORE select SERIAL_CORE
help help
This is a driver for Digi International's Neo and Classic series This is a driver for Digi International's Neo and Classic series

View File

@ -505,7 +505,11 @@ struct uart_port {
* The remaining bits are serial-core specific and not modifiable by * The remaining bits are serial-core specific and not modifiable by
* userspace. * userspace.
*/ */
#ifdef CONFIG_HAS_IOPORT
#define UPF_FOURPORT ((__force upf_t) ASYNC_FOURPORT /* 1 */ ) #define UPF_FOURPORT ((__force upf_t) ASYNC_FOURPORT /* 1 */ )
#else
#define UPF_FOURPORT 0
#endif
#define UPF_SAK ((__force upf_t) ASYNC_SAK /* 2 */ ) #define UPF_SAK ((__force upf_t) ASYNC_SAK /* 2 */ )
#define UPF_SPD_HI ((__force upf_t) ASYNC_SPD_HI /* 4 */ ) #define UPF_SPD_HI ((__force upf_t) ASYNC_SPD_HI /* 4 */ )
#define UPF_SPD_VHI ((__force upf_t) ASYNC_SPD_VHI /* 5 */ ) #define UPF_SPD_VHI ((__force upf_t) ASYNC_SPD_VHI /* 5 */ )