Re: [PATCH 1/1] tty: serial: handle HAS_IOPORT dependencies

From: Arnd Bergmann
Date: Fri Oct 04 2024 - 08:49:26 EST


On Fri, Oct 4, 2024, at 10:09, Niklas Schnelle wrote:

> I'm working on a new proposal for 8250 now. Basically I think we can
> put the warning/error in serial8250_pci_setup_port(). And then for
> those 8250_pci.c "sub drivers" that require I/O ports instead of just
> ifdeffing out their setup/init/exit we can define anything but setup to
> NULL and setup to pci_default_setup() such that the latter will find
> the I/O port BAR via FL_GET_BASE() and subsequently cause the error
> print in serial8250_pci_setup_port(). It's admittedly a bit odd but it
> also keeps the #ifdefs to just around the code that wouldn't compile.

Right, makes sense.

> One thing I'm not happy with yet is the handling around
> is_upf_fourport(port) in 8250_pci.c. With !HAS_IOPORT this is defined
> as false. With that it makes sure that inb_p()/outb_p() aren't called
> but I think this only works because the compiler usually drops the dead
> if clause. I think there were previous discussions around this but I
> think just like IS_ENABLED() checks this isn't quite correct.

Not sure what you mean, we rely on dead code elimination in all
kinds of places. The only bit to be aware of is that normal
'inline' functions may not get constant-folded all the time,
but anything that is either a macro or __always_inline does
work.

I just verified that the version below does what Maciej
suggested with IS_ENABLED() in 8250-pci, and this works fine.

Arnd

diff --git a/drivers/tty/serial/8250/8250_pci.c b/drivers/tty/serial/8250/8250_pci.c
index 6709b6a5f301..784190824aad 100644
--- a/drivers/tty/serial/8250/8250_pci.c
+++ b/drivers/tty/serial/8250/8250_pci.c
@@ -928,6 +928,14 @@ static int pci_netmos_init(struct pci_dev *dev)
return num_serial;
}

+static int serial_8250_need_ioport(struct pci_dev *dev)
+{
+ dev_warn(&dev->dev,
+ "Serial port not supported because of missing I/O resource\n");
+
+ return -ENXIO;
+}
+
/*
* These chips are available with optionally one parallel port and up to
* two serial ports. Unfortunately they all have the same product id.
@@ -964,6 +972,9 @@ static int pci_ite887x_init(struct pci_dev *dev)
struct resource *iobase = NULL;
u32 miscr, uartbar, ioport;

+ if (!IS_ENABLED(CONFIG_HAS_IOPORT))
+ return serial_8250_need_ioport(dev);
+
/* search for the base-ioport */
for (i = 0; i < ARRAY_SIZE(inta_addr); i++) {
iobase = request_region(inta_addr[i], ITE_887x_IOSIZE,
@@ -1049,6 +1060,10 @@ static int pci_ite887x_init(struct pci_dev *dev)
static void pci_ite887x_exit(struct pci_dev *dev)
{
u32 ioport;
+
+ if (!IS_ENABLED(CONFIG_HAS_IOPORT))
+ serial_8250_need_ioport(dev);
+
/* the ioport is bit 0-15 in POSIO0R */
pci_read_config_dword(dev, ITE_887x_POSIO0, &ioport);
ioport &= 0xffff;
@@ -1514,6 +1529,9 @@ static int pci_quatech_init(struct pci_dev *dev)
const struct pci_device_id *match;
bool amcc = false;

+ if (!IS_ENABLED(CONFIG_HAS_IOPORT))
+ return serial_8250_need_ioport(dev);
+
match = pci_match_id(quatech_cards, dev);
if (match)
amcc = match->driver_data;
@@ -1538,6 +1556,9 @@ static int pci_quatech_setup(struct serial_private *priv,
const struct pciserial_board *board,
struct uart_8250_port *port, int idx)
{
+ if (!IS_ENABLED(CONFIG_HAS_IOPORT))
+ return serial_8250_need_ioport(dev);
+
/* Needed by pci_quatech calls below */
port->port.iobase = pci_resource_start(priv->dev, FL_GET_BASE(board->flags));
/* Set up the clocking */
@@ -1864,6 +1885,9 @@ static int kt_serial_setup(struct serial_private *priv,
const struct pciserial_board *board,
struct uart_8250_port *port, int idx)
{
+ if (!IS_ENABLED(CONFIG_HAS_IOPORT))
+ return serial_8250_need_ioport(dev);
+
port->port.flags |= UPF_BUG_THRE;
port->port.serial_in = kt_serial_in;
port->port.handle_break = kt_handle_break;
@@ -1918,6 +1942,8 @@ static int pci_wch_ch38x_init(struct pci_dev *dev)
int max_port;
unsigned long iobase;

+ if (!IS_ENABLED(CONFIG_HAS_IOPORT))
+ return serial_8250_need_ioport(dev);

switch (dev->device) {
case 0x3853: /* 8 ports */
@@ -1937,6 +1963,9 @@ static void pci_wch_ch38x_exit(struct pci_dev *dev)
{
unsigned long iobase;

+ if (!IS_ENABLED(CONFIG_HAS_IOPORT))
+ serial_8250_need_ioport(dev);
+
iobase = pci_resource_start(dev, 0);
outb(0x0, iobase + CH384_XINT_ENABLE_REG);
}
@@ -2052,6 +2081,9 @@ static int pci_moxa_init(struct pci_dev *dev)
unsigned int i, num_ports = moxa_get_nports(device);
u8 val, init_mode = MOXA_RS232;

+ if (!IS_ENABLED(CONFIG_HAS_IOPORT))
+ return serial_8250_need_ioport(dev);
+
if (!(pci_moxa_supported_rs(dev) & MOXA_SUPP_RS232)) {
init_mode = MOXA_RS422;
}
@@ -2084,6 +2116,9 @@ pci_moxa_setup(struct serial_private *priv,
unsigned int bar = FL_GET_BASE(board->flags);
int offset;

+ if (!IS_ENABLED(CONFIG_HAS_IOPORT))
+ return serial_8250_need_ioport(dev);
+
if (board->num_ports == 4 && idx == 3)
offset = 7 * board->uart_offset;
else