serial: 8250: make port operations work on struct uart_8250_port
Subsystems (23)
Jiri Slaby (SUSE)
maintainerv2 cover serial: 8250: make port operations work on struct uart_8250_port
Hi,
the 8250 port operations work on line numbers. serial8250_register_8250_port() returns a line, and drivers pass it back to serial8250_unregister_port(), serial8250_suspend_port() and serial8250_resume_port(). Many drivers also convert it back to the port using serial8250_get_port() whenever they need the port itself.
The last patch switches this interface to struct uart_8250_port. serial8250_register_8250_port() now returns the port (or an ERR_PTR()), and the other operations take it. All users are converted, and serial8250_get_port() is no longer exported.
The first patch is a preparatory cleanup. It splits serial8250_register_8250_port() into a helper, so that the function no longer mixes guard() with goto-based error handling -- Sashiko.
The second patch is a trivial exar cleanup.
While doing the conversion, we (me, Claude and Sashiko) found three bugs in how drivers handle a line that is not set (yet). Patches 3-5 fix them separately, so that they can go to stable:
* 8250_exar: pci_xr17v35x_exit() looks up the GPIO platform device via port 0, which need not exist when its registration failed. The GPIO device is now stored in struct exar8250.
* 8250_lpss: the probe error path calls ehl_serial_exit(), which clears the dma pointer of serial8250_ports[0] (usually the console) when no port was registered.
* 8250_omap: the IRQ handler can run before probe stores priv->line, and then it uses serial8250_get_port(-ENODEV).
The conversion also fixes two latent issues: CIR ports (registration used to return 0, so callers operated on ttyS0) and 8250_acorn (a port on line 0 was never unregistered).
[v2]
* new patch 1: drop the err label from serial8250_register_8250_port()
* new patches 2-3: exar cleanup and fix of the GPIO device lookup (reported by Sashiko)
* 8250_lpss: no declaration in the middle of a function (Ilpo)
* conversion: include err.h (Ilpo)
Link to v1: https://lore.kernel.org/all/ef47d676a44346e058f29a00c8701484db722831.1791524724.git.jirislaby@kernel.org/
Jiri Slaby (SUSE) (6):
serial: 8250: drop err label from serial8250_register_8250_port()
serial: 8250_exar: remove useless void * casts
serial: 8250_exar: store the GPIO platform device in struct exar8250
serial: 8250_lpss: do not touch uninitialized line in
ehl_serial_exit()
serial: 8250_omap: set priv->line before enabling the IRQ
serial: 8250: make port operations work on struct uart_8250_port
drivers/ptp/ptp_ocp.c | 36 +++--- drivers/tty/serial/8250/8250_acorn.c | 5 +- drivers/tty/serial/8250/8250_airoha.c | 23 ++-- drivers/tty/serial/8250/8250_aspeed_vuart.c | 13 +- drivers/tty/serial/8250/8250_bcm2835aux.c | 20 +-- drivers/tty/serial/8250/8250_bcm7271.c | 33 +++-- drivers/tty/serial/8250/8250_core.c | 128 ++++++++++---------- drivers/tty/serial/8250/8250_dfl.c | 22 ++-- drivers/tty/serial/8250/8250_dw.c | 13 +- drivers/tty/serial/8250/8250_dwlib.h | 2 +- drivers/tty/serial/8250/8250_em.c | 26 ++-- drivers/tty/serial/8250/8250_exar.c | 59 +++++---- drivers/tty/serial/8250/8250_fsl.c | 24 ++-- drivers/tty/serial/8250/8250_hp300.c | 27 ++--- drivers/tty/serial/8250/8250_ingenic.c | 11 +- drivers/tty/serial/8250/8250_ioc3.c | 26 ++-- drivers/tty/serial/8250/8250_keba.c | 13 +- drivers/tty/serial/8250/8250_loongson.c | 20 +-- drivers/tty/serial/8250/8250_lpc18xx.c | 11 +- drivers/tty/serial/8250/8250_lpss.c | 17 +-- drivers/tty/serial/8250/8250_men_mcb.c | 14 +-- drivers/tty/serial/8250/8250_mid.c | 13 +- drivers/tty/serial/8250/8250_mtk.c | 19 +-- drivers/tty/serial/8250/8250_mxpcie.c | 13 +- drivers/tty/serial/8250/8250_ni.c | 12 +- drivers/tty/serial/8250/8250_of.c | 25 ++-- drivers/tty/serial/8250/8250_omap.c | 41 +++---- drivers/tty/serial/8250/8250_parisc.c | 14 +-- drivers/tty/serial/8250/8250_pci.c | 21 ++-- drivers/tty/serial/8250/8250_pci1xxxx.c | 41 +++---- drivers/tty/serial/8250/8250_pericom.c | 15 +-- drivers/tty/serial/8250/8250_platform.c | 23 ++-- drivers/tty/serial/8250/8250_pnp.c | 21 ++-- drivers/tty/serial/8250/8250_pxa.c | 17 +-- drivers/tty/serial/8250/8250_tegra.c | 20 +-- drivers/tty/serial/8250/8250_uniphier.c | 21 ++-- drivers/tty/serial/8250/serial_cs.c | 15 ++- include/linux/serial_8250.h | 8 +- 38 files changed, 417 insertions(+), 465 deletions(-)
Signature · 1 line
2.56.0
Jiri Slaby (SUSE)
maintainerPATCH v2 1/6 serial: 8250: drop err label from serial8250_register_8250_port()
serial8250_register_8250_port() holds serial_mutex using guard(), but still uses goto-based error handling. Mixing the two is discouraged by the cleanup guidelines.
Move the part of the function which configures the found port into a new helper: __serial8250_register_8250_port(). It returns an int and uses plain returns on failures. The caller now resets uart->port.dev on failure at a single place, so the err label can go.
While at it, simplify the mctrl_gpio_init() error handling: return PTR_ERR() directly and drop the else branch.
No functional change intended.
--- drivers/tty/serial/8250/8250_core.c | 98 +++++++++++++++-------------- 1 file changed, 52 insertions(+), 46 deletions(-)
drivers/tty/serial/8250/8250_core.c +52 -46
@@ -743,46 +743,12 @@ static void serial_8250_overrun_backoff_work(struct work_struct *work)serial_out (up,UART_IER , up->ier); } -/** -* serial8250_register_8250_port - register a serial port -* @up: serial port template -* -* Configure the serial port specified by the request. If the -* port exists and is in use, it is hung up and unregistered -* first. -* -* The port is then probed and if necessary the IRQ is autodetected -* If this fails an error is returned. -* -* On success the port is ready to use and the line number is returned. -*/ -int serial8250_register_8250_port (const struct uart_8250_port *up) +static int __serial8250_register_8250_port (struct uart_8250_port *uart, +const struct uart_8250_port *up) { -struct uart_8250_port *uart;bool cons_flow;int ret; -if (up->port.uartclk ==0 ) -return -EINVAL ; - -guard (mutex)(&serial_mutex); - - uart =serial8250_find_match_or_unused (&up->port); -if (!uart) { -/* -* If the port is past the initial isa ports, initialize a new -* port and increment nr_uarts accordingly. -*/ - uart =serial8250_setup_port (nr_uarts); -if (!uart) -return -ENOSPC ; - nr_uarts++; - } - -/* Check if it is CIR already. We check this below again, see there why. */ -if (uart->port.type ==PORT_8250_CIR ) -return -ENODEV ; -/* Preserve specified console flow control. */ cons_flow =uart_cons_flow_enabled (&uart->port);
@@ -826,7 +792,7 @@ int serial8250_register_8250_port(const struct uart_8250_port *up) uart->port.dev = up->port.dev; ret =uart_get_rs485_mode (&uart->port);if (ret) - goto err; +return ret; }if (up->port.flags &UPF_FIXED_TYPE )
@@ -838,12 +804,10 @@ int serial8250_register_8250_port(const struct uart_8250_port *up)*/ if (uart->port.dev && !has_acpi_companion (uart->port.dev)) {struct mctrl_gpios *gpios =mctrl_gpio_init (&uart->port,0 ); -if (IS_ERR (gpios)) { - ret =PTR_ERR (gpios); - goto err; - }else { - uart->gpios = gpios; - } +if (IS_ERR (gpios)) +return PTR_ERR (gpios); + + uart->gpios = gpios; }serial8250_set_defaults (uart);
@@ -900,7 +864,7 @@ int serial8250_register_8250_port(const struct uart_8250_port *up) ret =uart_add_one_port (&serial8250_reg, &uart->port);if (ret) - goto err; +return ret; ret = uart->port.line; }else {
@@ -927,9 +891,51 @@ int serial8250_register_8250_port(const struct uart_8250_port *up) }return ret; +} + +/** +* serial8250_register_8250_port - register a serial port +* @up: serial port template +* +* Configure the serial port specified by the request. If the +* port exists and is in use, it is hung up and unregistered +* first. +* +* The port is then probed and if necessary the IRQ is autodetected +* If this fails an error is returned. +* +* On success the port is ready to use and the line number is returned. +*/ +int serial8250_register_8250_port (const struct uart_8250_port *up) +{ +struct uart_8250_port *uart; +int ret; + +if (up->port.uartclk ==0 ) +return -EINVAL ; + +guard (mutex)(&serial_mutex); + + uart =serial8250_find_match_or_unused (&up->port); +if (!uart) { +/* +* If the port is past the initial isa ports, initialize a new +* port and increment nr_uarts accordingly. +*/ + uart =serial8250_setup_port (nr_uarts); +if (!uart) +return -ENOSPC ; + nr_uarts++; + } + +/* Check if it is CIR already. We check this below again, see there why. */ +if (uart->port.type ==PORT_8250_CIR ) +return -ENODEV ; + + ret =__serial8250_register_8250_port (uart, up); +if (ret <0 ) + uart->port.dev =NULL ; -err: - uart->port.dev =NULL ;return ret; }EXPORT_SYMBOL (serial8250_register_8250_port);
Signature · 1 line
2.56.0
[email protected]
AI reviewRe: [PATCH v2 1/6] serial: 8250: drop err label from serial8250_register_8250_port()
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider: - [High] tty: serial: 8250: missing cancel_delayed_work_sync() for overrun_backoff - [High] tty: serial…
Thank you for your contribution! Sashiko AI review found 2 potential issue(s) to consider:
- [High] tty: serial: 8250: missing cancel_delayed_work_sync() for overrun_backoff
- [High] tty: serial: 8250: workqueue list corruption via INIT_DELAYED_WORK() --
commit c4166af59c093eb0e0aed408aac8356ad1cf88f2
Author: Jiri Slaby (SUSE) <[email protected]>
serial: 8250: drop err label from serial8250_register_8250_port()
This commit refactors serial8250_register_8250_port() to eliminate goto-based error handling while holding a guard() lock. The port configuration logic is moved into a new helper, __serial8250_register_8250_port(), which returns an int and uses plain returns on failures. The caller then handles resetting uart->port.dev in a single place.
drivers/tty/serial/8250/8250_core.c static void serial_8250_overrun_backoff_work(struct work_struct *work) · line 744
Quoted 7 lines
drivers/tty/serial/8250/8250_core.c +0
-0@@ -743,46 +743,12 @@ static void serial_8250_overrun_backoff_work(struct work_struct *work)serial_out (up,UART_IER , up->ier); }
[Severity: High]
Can this background work access hardware registers after the port is unregistered?
When a port is removed (such as during hot-unplug or driver unbind), it appears there is no matching cancel_delayed_work_sync() for the overrun_backoff work.
If the device memory is unmapped and the delayed work executes, will this serial_out() trigger a synchronous external abort or use-after-free?
[ ... ]
drivers/tty/serial/8250/8250_core.c int serial8250_register_8250_port(const struct uart_8250_port *up) · line 894
Quoted 5 lines
drivers/tty/serial/8250/8250_core.c +1
-0@@ -927,9 +891,51 @@ int serial8250_register_8250_port(const struct uart_8250_port *up) }return ret; +}
[Severity: High]
Does this new helper unconditionally re-initialize the delayed work without checking if it is already pending?
If a device is unbound and then rebound while the overrun_backoff work is still pending, __serial8250_register_8250_port() is called again. Towards the end of the helper, the work is initialized:
if (up->overrun_backoff_time_ms > 0) {
...
INIT_DELAYED_WORK(&uart->overrun_backoff,
serial_8250_overrun_backoff_work);
}Re-initializing an active delayed work item with INIT_DELAYED_WORK() calls INIT_LIST_HEAD() on its list nodes.
Can this corrupt the timer or workqueue linked lists if the work is still active from a previous registration?
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=1
Jiri Slaby (SUSE)
maintainerPATCH v2 2/6 serial: 8250_exar: remove useless void * casts
In reply to Jiri Slaby (SUSE)port->private_data is a void pointer. There is no need to cast it when assigning to or from struct exar8250 pointers. So drop the casts.
--- drivers/tty/serial/8250/8250_exar.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-)
drivers/tty/serial/8250/8250_exar.c +2 -2
@@ -799,7 +799,7 @@ static int cti_rs485_config_mpio_tristate(struct uart_port *port,struct ktermios *termios, struct serial_rs485 *rs485) { - struct exar8250 *priv = (struct exar8250 *)port->private_data; + struct exar8250 *priv = port->private_data;int ret; ret =generic_rs485_config (port, termios, rs485);
@@ -837,7 +837,7 @@ static int cti_port_setup_common(struct exar8250 *priv,if (ret)return ret; - port->port.private_data = (void *)priv; + port->port.private_data = priv; port->port.pm = exar_pm; port->port.shutdown = exar_shutdown;
Signature · 1 line
2.56.0
[email protected]
AI reviewRe: [PATCH v2 2/6] serial: 8250_exar: remove useless void * casts
Sashiko has reviewed this patch and found no issues. It looks great!
Quoted 4 lines
port->private_datais a void pointer. There is no need to cast it when assigning to or from struct exar8250 pointers. So drop the casts.Signed-off-by Jiri Slaby (SUSE) <[email protected]>
Sashiko has reviewed this patch and found no issues. It looks great!
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=2
Jiri Slaby (SUSE)
maintainerPATCH v2 3/6 serial: 8250_exar: store the GPIO platform device in struct exar8250
In reply to Jiri Slaby (SUSE)The GPIO platform device is registered via platform->register_gpio() when port 0 is being set up. It is stored to port->port.private_data of the on-stack uart template (and from there it is copied into every registered port). pci_xr17v35x_exit() then fetches it back by serial8250_get_port(priv->line[0]).
But port 0 does not have to exist at that point. If serial8250_register_8250_port() fails for port 0, priv->line[0] holds a negative error code. The probe still succeeds (it only breaks the loop), so on unbind, priv->line[0] (a negative value) is passed to serial8250_get_port(). The GPIO device is never unregistered and a bogus port is accessed.
The same problem would also occur after the planned conversion of serial8250_register_8250_port() to return a uart port instead of a line. As Sashiko pointed out in that case:
If board->setup() fails for the first port (i=0) in exar_pci_probe(), priv->uport[0] remains NULL. If serial8250_register_8250_port() fails, it returns an ERR_PTR. In either case, the loop breaks and probe returns success. When the device is later unbound, pci_xr17v35x_exit() unconditionally passes priv->uport[0] to platform->unregister_gpio(), which will dereference it without checking for validity.
The GPIO device belongs to the PCI device, not to any particular port. So store it in a new struct exar8250::gpio member. Pass priv to both ->register_gpio() and ->unregister_gpio(), so that pci_xr17v35x_exit() does not need to look up any port at all.
---
[v2] this is new in v2
--- drivers/tty/serial/8250/8250_exar.c | 36 ++++++++++++++--------------- 1 file changed, 18 insertions(+), 18 deletions(-)
drivers/tty/serial/8250/8250_exar.c +18 -18
@@ -231,8 +231,9 @@ struct exar8250_platform {int (*rs485_config)(struct uart_port *port,struct ktermios *termios,struct serial_rs485 *rs485);const struct serial_rs485 *rs485_supported; -int (*register_gpio)(struct pci_dev *pcidev,struct uart_8250_port *port); -void (*unregister_gpio)(struct uart_8250_port *port); +int (*register_gpio)(struct exar8250 *priv,struct pci_dev *pcidev, +struct uart_8250_port *port); +void (*unregister_gpio)(struct exar8250 *priv); };/**
@@ -256,6 +257,7 @@ struct exar8250 {struct exar8250_board *board;struct eeprom_93cx6 eeprom;void __iomem *virt; +struct platform_device *gpio;int line[]; };
@@ -1167,22 +1169,21 @@ static const struct software_node exar_gpio_node = { .properties = exar_gpio_properties, }; -static int xr17v35x_register_gpio (struct pci_dev *pcidev,struct uart_8250_port *port) +static int xr17v35x_register_gpio (struct exar8250 *priv,struct pci_dev *pcidev, +struct uart_8250_port *port) {if (pcidev->vendor ==PCI_VENDOR_ID_EXAR ) - port->port.private_data = -__xr17v35x_register_gpio (pcidev, &exar_gpio_node); + priv->gpio =__xr17v35x_register_gpio (pcidev, &exar_gpio_node);return 0 ; } -static void xr17v35x_unregister_gpio (struct uart_8250_port *port) +static void xr17v35x_unregister_gpio (struct exar8250 *priv) { -if (!port->port.private_data) -return ; - -__xr17v35x_unregister_gpio (port->port.private_data); - port->port.private_data =NULL ; +if (priv->gpio) { +__xr17v35x_unregister_gpio (priv->gpio); + priv->gpio =NULL ; + } } static int sealevel_rs485_config(struct uart_port *port, struct ktermios *termios,
@@ -1279,8 +1280,9 @@ static const struct software_node iot2040_gpio_node = { .properties = iot2040_gpio_properties, }; -static int iot2040_register_gpio (struct pci_dev *pcidev, -struct uart_8250_port *port) +static int iot2040_register_gpio (struct exar8250 *priv, +struct pci_dev *pcidev, +struct uart_8250_port *port) {u8 __iomem *p = port->port.membase;
@@ -1289,8 +1291,7 @@ static int iot2040_register_gpio(struct pci_dev *pcidev,writeb (IOT2040_UARTS_ENABLE , p +UART_EXAR_MPIOLVL_15_8 );writeb (IOT2040_UARTS_GPIO_HI_MODE , p +UART_EXAR_MPIOSEL_15_8 ); - port->port.private_data = -__xr17v35x_register_gpio (pcidev, &iot2040_gpio_node); + priv->gpio =__xr17v35x_register_gpio (pcidev, &iot2040_gpio_node);return 0 ; }
@@ -1367,7 +1368,7 @@ pci_xr17v35x_setup(struct exar8250 *priv, struct pci_dev *pcidev,/* Setup Multipurpose Input/Output pins. */ setup_gpio (pcidev, p); - ret = platform->register_gpio (pcidev, port); + ret = platform->register_gpio (priv, pcidev, port); }return ret;
@@ -1377,9 +1378,8 @@ static void pci_xr17v35x_exit(struct pci_dev *pcidev) {const struct exar8250_platform *platform =exar_get_platform ();struct exar8250 *priv =pci_get_drvdata (pcidev); -struct uart_8250_port *port =serial8250_get_port (priv->line[0 ]); - platform->unregister_gpio (port); + platform->unregister_gpio (priv); }static inline void exar_misc_clear (struct exar8250 *priv)
Signature · 1 line
2.56.0
[email protected]
AI reviewRe: [PATCH v2 3/6] serial: 8250_exar: store the GPIO platform device in struct exar8250
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [High] tty: 8250_exar: missing IS_ERR check causes invalid pointer deref --
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] tty: 8250_exar: missing IS_ERR check causes invalid pointer deref --
commit 6cdc2bc96a13008a8cfba8cca844ee2bb25786e6
Author: Jiri Slaby (SUSE) <[email protected]>
serial: 8250_exar: store the GPIO platform device in struct exar8250
The GPIO platform device is now stored in struct exar8250::gpio instead of port->port.private_data to fix an issue where port 0 might not exist on unbind. The platform->register_gpio() and platform->unregister_gpio() callbacks are updated to take priv as an argument.
Quoted 4 lines
drivers/tty/serial/8250/8250_exar.c +0
-0
[ ... ]
drivers/tty/serial/8250/8250_exar.c static const struct software_node exar_gpio_node = { · line 1176
Quoted 12 lines
drivers/tty/serial/8250/8250_exar.c +3
-3@@ -1167,22 +1169,21 @@ static const struct software_node exar_gpio_node = { .properties = exar_gpio_properties, }; -static int xr17v35x_register_gpio (struct pci_dev *pcidev,struct uart_8250_port *port) +static int xr17v35x_register_gpio (struct exar8250 *priv,struct pci_dev *pcidev, +struct uart_8250_port *port) {if (pcidev->vendor ==PCI_VENDOR_ID_EXAR ) - port->port.private_data = -__xr17v35x_register_gpio (pcidev, &exar_gpio_node); + priv->gpio =__xr17v35x_register_gpio (pcidev, &exar_gpio_node);
[Severity: High]
Does __xr17v35x_register_gpio() return an ERR_PTR if platform_device_register_full() fails?
If it does, we might be storing an error pointer directly into priv->gpio in xr17v35x_register_gpio() without validating it with IS_ERR(). Because the error is ignored, the device probe successfully continues.
drivers/tty/serial/8250/8250_exar.c static const struct software_node exar_gpio_node = { · line 1183
Quoted 13 lines
drivers/tty/serial/8250/8250_exar.c +2
-6return 0 ; } -static void xr17v35x_unregister_gpio (struct uart_8250_port *port) +static void xr17v35x_unregister_gpio (struct exar8250 *priv) { -if (!port->port.private_data) -return ; - -__xr17v35x_unregister_gpio (port->port.private_data); - port->port.private_data =NULL ; +if (priv->gpio) {
[Severity: High]
Later, during module unload or device unbind, we evaluate if (priv->gpio) here in xr17v35x_unregister_gpio().
Since an ERR_PTR is not NULL, the condition passes and the error pointer is passed to __xr17v35x_unregister_gpio().
Inside, device_remove_software_node(&pdev->dev) attempts to dereference the invalid pointer, resulting in a crash. Could we add an IS_ERR check when assigning priv->gpio, or check for it here?
Quoted 4 lines
drivers/tty/serial/8250/8250_exar.c +3
-0+__xr17v35x_unregister_gpio (priv->gpio); + priv->gpio =NULL ; + } }
[ ... ]
drivers/tty/serial/8250/8250_exar.c static int iot2040_register_gpio(struct pci_dev *pcidev, · line 1294
Quoted 7 lines
drivers/tty/serial/8250/8250_exar.c +1
-2@@ -1289,8 +1291,7 @@ static int iot2040_register_gpio(struct pci_dev *pcidev,writeb (IOT2040_UARTS_ENABLE , p +UART_EXAR_MPIOLVL_15_8 );writeb (IOT2040_UARTS_GPIO_HI_MODE , p +UART_EXAR_MPIOSEL_15_8 ); - port->port.private_data = -__xr17v35x_register_gpio (pcidev, &iot2040_gpio_node); + priv->gpio =__xr17v35x_register_gpio (pcidev, &iot2040_gpio_node);
[Severity: High]
This looks like the same concern as above in xr17v35x_register_gpio(). If __xr17v35x_register_gpio() fails and returns an error pointer, we'll store it here in iot2040_register_gpio() unchecked.
Quoted 3 lines
drivers/tty/serial/8250/8250_exar.c +0
-0return 0 ; }
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=3
Jiri Slaby (SUSE)
maintainerPATCH v2 4/6 serial: 8250_lpss: do not touch uninitialized line in ehl_serial_exit()
In reply to Jiri Slaby (SUSE)lpss8250_probe() calls lpss->board->exit() on its error path. For the EHL board, that is ehl_serial_exit() and it does:
serial8250_get_port(lpss->data.line)->dma = NULL;
But when lpss8250_dma_setup() or serial8250_register_8250_port() fails, lpss->data.line was never assigned. As lpss is kzalloc()ed, line is 0 and ehl_serial_exit() clears the dma pointer of an unrelated port -- serial8250_ports[0], i.e. ttyS0, which is often the console.
Initialize lpss->data.line to -1 in probe and skip the clearing in ehl_serial_exit() if no port was registered.
-- pick
Cc: Andy Shevchenko <[email protected]>
Cc: [email protected]
[v2] no declaration in the middle of a function (Ilpo)
--- drivers/tty/serial/8250/8250_lpss.c | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-)
drivers/tty/serial/8250/8250_lpss.c +4 -3
@@ -183,9 +183,8 @@ static int ehl_serial_setup(struct lpss8250 *lpss, struct uart_port *port)static void ehl_serial_exit (struct lpss8250 *lpss) { -struct uart_8250_port *up =serial8250_get_port (lpss->data.line); - - up->dma =NULL ; +if (lpss->data.line >=0 ) +serial8250_get_port (lpss->data.line)->dma =NULL ; }#ifdef CONFIG_SERIAL_8250_DMA
@@ -329,6 +328,8 @@ static int lpss8250_probe(struct pci_dev *pdev, const struct pci_device_id *id)return ret; lpss->board = (struct lpss8250_board *)id->driver_data; +/* for tests in lpss->board->exit() */ + lpss->data.line =-1 ;memset (&uart,0 ,sizeof (struct uart_8250_port ));
Signature · 1 line
2.56.0
Andy Shevchenko
reviewerRe: [PATCH v2 4/6] serial: 8250_lpss: do not touch uninitialized line in ehl_serial_exit()
Quoted 11 lines · Jiri Slaby (SUSE)
lpss8250_probe()callslpss->board->exit()on its error path. For the EHL board, that isehl_serial_exit()and it does:
serial8250_get_port(lpss->data.line)->dma = NULL;But when
lpss8250_dma_setup()orserial8250_register_8250_port()fails,lpss->data.linewas never assigned. As lpss is kzalloc()ed, line is 0 andehl_serial_exit()clears the dma pointer of an unrelated port -- serial8250_ports[0], i.e. ttyS0, which is often the console.Initialize
lpss->data.lineto -1 in probe and skip the clearing inehl_serial_exit()if no port was registered.
Thanks for the catch and the fix, my comments below.
Quoted 11 lines
Fixes 5318f70da7e8 ("serial: 8250_lpss: Balance reference count for PCI DMA device")Signed-off-by Jiri Slaby (SUSE) <[email protected]>Assisted-by LLMCc "Ilpo Järvinen" <[email protected]>-- pick
Cc: Andy Shevchenko <[email protected]>
Cc: [email protected][v2] no declaration in the middle of a function (Ilpo)
---
Hmm... Something went wrong with the Cc list, I would expect to see
---
Cc: "Ilpo Järvinen" <[email protected]>
Cc: Andy Shevchenko <[email protected]>
Cc: [email protected]
[v2] no declaration in the middle of a function (Ilpo)
---
...
drivers/tty/serial/8250/8250_lpss.c static int ehl_serial_setup(struct lpss8250 *lpss, struct uart_port *port) · line 187
Quoted 7 lines
static void
ehl_serial_exit(struct lpss8250 *lpss){drivers/tty/serial/8250/8250_lpss.c +2
-3-struct uart_8250_port *up =serial8250_get_port (lpss->data.line); - - up->dma =NULL ; +if (lpss->data.line >=0 ) +serial8250_get_port (lpss->data.line)->dma =NULL ;
I would rather make it more readable by splitting the operations.
struct uart_8250_port *up; if (lpss->data.line < 0) return; up = serial8250_get_port(lpss->data.line); up->dma = NULL;
Quoted 1 line
}
Signature · 2 lines
With Best Regards, Andy Shevchenko
[email protected]
AI reviewRe: [PATCH v2 4/6] serial: 8250_lpss: do not touch uninitialized line in ehl_serial_exit()
In reply to Jiri Slaby (SUSE)Sashiko has reviewed this patch and found no issues. It looks great!
Quoted 9 lines
lpss8250_probe()callslpss->board->exit()on its error path. For the EHL board, that isehl_serial_exit()and it does:
serial8250_get_port(lpss->data.line)->dma = NULL;But when
lpss8250_dma_setup()orserial8250_register_8250_port()fails,lpss->data.linewas never assigned. As lpss is kzalloc()ed, line is 0 andehl_serial_exit()clears the dma pointer of an unrelated port -- serial8250_ports[0], i.e. ttyS0, which is often the console.
Quoted 5 lines
Initialize
lpss->data.lineto -1 in probe and skip the clearing inehl_serial_exit()if no port was registered.Fixes 5318f70da7e8 ("serial: 8250_lpss: Balance reference count for PCI DMA device")Signed-off-by Jiri Slaby (SUSE) <[email protected]>
Sashiko has reviewed this patch and found no issues. It looks great!
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=4
Jiri Slaby (SUSE)
maintainerPATCH v2 5/6 serial: 8250_omap: set priv->line before enabling the IRQ
In reply to Jiri Slaby (SUSE)omap8250_irq() is requested in omap8250_probe() with IRQ_NOAUTOEN and enabled only in omap_8250_startup(). The handler obtains the port by serial8250_get_port(priv->line), but probe stores priv->line only after serial8250_register_8250_port() returns.
The port becomes visible to userspace already inside serial8250_register_8250_port() (uart_add_one_port()). So it can be opened -- and the IRQ enabled -- before probe stores the line. An interrupt in that window makes the handler call serial8250_get_port(-ENODEV) and dereference a pointer outside of serial8250_ports[].
Store the line in omap_8250_startup() before enable_irq(), so the handler never runs with an unset line. Keep the assignment in probe too, as remove and the system PM callbacks rely on it even when the port was never opened.
---
Cc: [email protected]
--- drivers/tty/serial/8250/8250_omap.c | 3 +++ 1 file changed, 3 insertions(+)
drivers/tty/serial/8250/8250_omap.c +3 -0
@@ -711,6 +711,9 @@ static int omap_8250_startup(struct uart_port *port)struct uart_8250_dma *dma = &priv->omap8250_dma;int ret; +/* ISR and runtime PM need the line; probe sets it only after registration */ + priv->line = port->line; +#ifdef CONFIG_PM up->capabilities |=UART_CAP_RPM ;#endif
Signature · 1 line
2.56.0
[email protected]
AI reviewRe: [PATCH v2 5/6] serial: 8250_omap: set priv->line before enabling the IRQ
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [Low] serial: 8250_omap: data race on priv->line assignment --
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [Low] serial: 8250_omap: data race on priv->line assignment
--
commit 5147cae847c38d599a30c92bc983c41140a1abad
Author: Jiri Slaby (SUSE) <[email protected]>
serial: 8250_omap: set priv->line before enabling the IRQ
This commit fixes an issue where the IRQ handler could dereference an unset priv->line if an interrupt occurs before omap8250_probe() stores it. It stores port->line into priv->line in omap_8250_startup() before enabling the IRQ to ensure the handler always sees a valid line number.
drivers/tty/serial/8250/8250_omap.c static int omap_8250_startup(struct uart_port *port) · line 716
Quoted 11 lines
drivers/tty/serial/8250/8250_omap.c +3
-0@@ -711,6 +711,9 @@ static int omap_8250_startup(struct uart_port *port)struct uart_8250_dma *dma = &priv->omap8250_dma;int ret; +/* ISR and runtime PM need the line; probe sets it only after registration */ + priv->line = port->line; +
[Severity: Low]
Does this new assignment introduce a data race regression on the unannotated priv->line variable?
In omap8250_probe(), serial8250_register_8250_port() is called, which exposes the TTY device to userspace. A concurrent userspace open() can then immediately trigger omap_8250_startup() on another CPU, which executes this new assignment:
priv->line = port->line;
Meanwhile, the original omap8250_probe() execution resumes and writes to the same variable:
priv->line = ret;
This can result in a write-write data race between omap_8250_startup() and omap8250_probe(). Furthermore, since omap_8250_startup() also enables the IRQ, omap8250_irq() can fire and perform an unannotated read:
struct uart_8250_port *up = serial8250_get_port(priv->line);
While functionally benign since both paths write the same aligned value, this creates unannotated read-write and write-write races that constitute undefined behavior under C11/LKMM and will trigger KCSAN warnings.
Could WRITE_ONCE() and READ_ONCE() be used to safely handle these concurrent accesses?
Quoted 3 lines
drivers/tty/serial/8250/8250_omap.c +0
-0#ifdef CONFIG_PM up->capabilities |=UART_CAP_RPM ;#endif
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=5
Jiri Slaby (SUSE)
maintainerPATCH v2 6/6 serial: 8250: make port operations work on struct uart_8250_port
In reply to Jiri Slaby (SUSE)serial8250_register_8250_port() returns a line number and the other port operations (serial8250_unregister_port(), serial8250_suspend_port(), serial8250_resume_port()) accept it. Many drivers then convert the line back to the port using serial8250_get_port() anyway.
Switch the interface to struct uart_8250_port:
* serial8250_register_8250_port() now returns the registered port, or an ERR_PTR() on failure.
* serial8250_unregister_port(), serial8250_suspend_port() and serial8250_resume_port() accept the port.
Convert all users accordingly. Drivers store the port pointer instead of the line number. Several drivers kept a private struct only to hold the line (airoha, dfl, em, fsl, ioc3); these are dropped and the port is stored as drvdata directly.
This also fixes two latent issues:
* For a CIR port, serial8250_register_8250_port() used to return 0. Callers stored this as the line, so a later unregister/suspend/resume operated on ttyS0. Now the CIR port itself is returned.
* 8250_acorn checked ports[i] > 0 on removal, so a port registered as line 0 was never unregistered.
There are no more users of serial8250_get_port() outside of the 8250 core, so drop its EXPORT.
---
Cc: Vadim Fedorenko <[email protected]>
Cc: Richard Cochran <[email protected]>
Cc: Andrew Lunn <[email protected]>
Cc: "David S. Miller" <[email protected]>
Cc: Eric Dumazet <[email protected]>
Cc: Jakub Kicinski <[email protected]>
Cc: Paolo Abeni <[email protected]>
Cc: Joel Stanley <[email protected]>
Cc: Andrew Jeffery <[email protected]>
Cc: Ryan Chen <[email protected]>
Cc: Billy Tsai <[email protected]>
Cc: Florian Fainelli <[email protected]>
Cc: Broadcom internal kernel review list <[email protected]>
Cc: Ray Jui <[email protected]>
Cc: Scott Branden <[email protected]>
Cc: Al Cooper <[email protected]>
Cc: Andy Shevchenko <[email protected]>
Cc: Paul Cercueil <[email protected]>
Cc: Matthias Brugger <[email protected]>
Cc: AngeloGioacchino Del Regno <[email protected]>
Cc: Chaitanya Vadrevu <[email protected]>
Cc: "James E.J. Bottomley" <[email protected]>
Cc: Helge Deller <[email protected]>
Cc: Kumaravel Thiagarajan <[email protected]>
Cc: Thierry Reding <[email protected]>
Cc: Jonathan Hunter <[email protected]>
Cc: Kunihiko Hayashi <[email protected]>
Cc: Masami Hiramatsu <[email protected]>
Cc: Kees Cook <[email protected]>
Cc: "Gustavo A. R. Silva" <[email protected]>
Cc: "Uwe Kleine-König (The Capable Hub)" <[email protected]>
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
[v2] include err.h (Ilpo)
--- drivers/ptp/ptp_ocp.c | 36 +++++++++--------- drivers/tty/serial/8250/8250_acorn.c | 5 ++- drivers/tty/serial/8250/8250_airoha.c | 23 ++++------- drivers/tty/serial/8250/8250_aspeed_vuart.c | 13 ++++--- drivers/tty/serial/8250/8250_bcm2835aux.c | 20 +++++----- drivers/tty/serial/8250/8250_bcm7271.c | 33 ++++++++-------- drivers/tty/serial/8250/8250_core.c | 40 +++++++++----------- drivers/tty/serial/8250/8250_dfl.c | 22 ++++------- drivers/tty/serial/8250/8250_dw.c | 13 ++++--- drivers/tty/serial/8250/8250_dwlib.h | 2 +- drivers/tty/serial/8250/8250_em.c | 26 ++++--------- drivers/tty/serial/8250/8250_exar.c | 19 +++++----- drivers/tty/serial/8250/8250_fsl.c | 24 ++++-------- drivers/tty/serial/8250/8250_hp300.c | 27 ++++++------- drivers/tty/serial/8250/8250_ingenic.c | 11 +++--- drivers/tty/serial/8250/8250_ioc3.c | 26 +++++-------- drivers/tty/serial/8250/8250_keba.c | 13 +++---- drivers/tty/serial/8250/8250_loongson.c | 20 +++++----- drivers/tty/serial/8250/8250_lpc18xx.c | 11 +++--- drivers/tty/serial/8250/8250_lpss.c | 18 ++++----- drivers/tty/serial/8250/8250_men_mcb.c | 14 +++---- drivers/tty/serial/8250/8250_mid.c | 13 ++++--- drivers/tty/serial/8250/8250_mtk.c | 19 +++++----- drivers/tty/serial/8250/8250_mxpcie.c | 13 ++++--- drivers/tty/serial/8250/8250_ni.c | 12 +++--- drivers/tty/serial/8250/8250_of.c | 25 ++++++------ drivers/tty/serial/8250/8250_omap.c | 42 ++++++++++----------- drivers/tty/serial/8250/8250_parisc.c | 14 +++---- drivers/tty/serial/8250/8250_pci.c | 21 +++++------ drivers/tty/serial/8250/8250_pci1xxxx.c | 41 ++++++++++---------- drivers/tty/serial/8250/8250_pericom.c | 15 ++++---- drivers/tty/serial/8250/8250_platform.c | 23 +++++------ drivers/tty/serial/8250/8250_pnp.c | 21 +++++------ drivers/tty/serial/8250/8250_pxa.c | 17 +++++---- drivers/tty/serial/8250/8250_tegra.c | 20 +++++----- drivers/tty/serial/8250/8250_uniphier.c | 21 +++++------ drivers/tty/serial/8250/serial_cs.c | 15 ++++---- include/linux/serial_8250.h | 8 ++-- 38 files changed, 349 insertions(+), 407 deletions(-)
drivers/ptp/ptp_ocp.c +19 -17
@@ -344,7 +344,7 @@ struct ptp_ocp_signal { };struct ptp_ocp_serial_port { -int line; +struct uart_8250_port *uport;int baud; };
@@ -2629,7 +2629,7 @@ ptp_ocp_register_ext(struct ptp_ocp *bp, struct ocp_resource *r)return err; } -static int +static struct uart_8250_port *ptp_ocp_serial_line (struct ptp_ocp *bp,struct ocp_resource *r) {struct pci_dev *pdev = bp->pdev;
@@ -2657,9 +2657,11 @@ ptp_ocp_register_serial(struct ptp_ocp *bp, struct ocp_resource *r)struct ptp_ocp_serial_port *p = (struct ptp_ocp_serial_port *)r->extra;struct ptp_ocp_serial_port port = {}; - port.line =ptp_ocp_serial_line (bp, r); -if (port.line <0 ) -return port.line; +struct uart_8250_port *uport =ptp_ocp_serial_line (bp, r); +if (IS_ERR (uport)) +return PTR_ERR (uport); + + port.uport = uport;if (p) port.baud = p->baud;
@@ -3804,7 +3806,7 @@ ptp_ocp_tty_show(struct device *dev, struct device_attribute *attr, char *buf)* as a device path (e.g., "/dev/ttyS4"), and adding a newline would * break those applications. Do not add a newline to this output. */ -return sysfs_emit (buf,"ttyS%d" , bp->port[(uintptr_t )ea->var].line); +return sysfs_emit (buf,"ttyS%d" , bp->port[(uintptr_t )ea->var].uport->port.line); } static umode_t
@@ -3821,7 +3823,7 @@ ptp_ocp_timecard_tty_is_visible(struct kobject *kobj, struct attribute *attr, in dattr = container_of(attr, struct device_attribute, attr); ea = container_of(dattr, struct dev_ext_attribute, attr); port = &bp->port[(uintptr_t )ea->var]; -return port->line ==-1 ?0 :0444 ; +return port->uport ?0444 :0 ; }#define EXT_TTY_ATTR_RO (_name, _val) \
@@ -5287,9 +5289,9 @@ ptp_ocp_summary_show(struct seq_file *s, void *data)seq_printf (s,"%7s: /dev/ptp%d\n" ,"PTP" ,ptp_clock_index (bp->ptp));for (i =0 ; i < __PORT_COUNT; i++) { -if (bp->port[i].line !=-1 ) +if (bp->port[i].uport)seq_printf (s,"%7s: /dev/ttyS%d\n" ,ptp_ocp_tty_port_name (i), - bp->port[i].line); + bp->port[i].uport->port.line); }memset (sma_val,0xff ,sizeof (sma_val));
@@ -5613,7 +5615,7 @@ ptp_ocp_device_init(struct ptp_ocp *bp, struct pci_dev *pdev)spin_lock_init (&bp->lock);for (i =0 ; i < __PORT_COUNT; i++) - bp->port[i].line =-1 ; + bp->port[i].uport =NULL ; bp->pdev = pdev;
@@ -5702,10 +5704,10 @@ ptp_ocp_phc_info(struct ptp_ocp *bp) }static void -ptp_ocp_serial_info (struct device *dev,const char *name,int port,int baud) +ptp_ocp_serial_info (struct device *dev,const char *name,struct uart_8250_port *port,int baud) { -if (port !=-1 ) -dev_info (dev,"%5s: /dev/ttyS%-2d @ %6d\n" , name, port, baud); +if (port) +dev_info (dev,"%5s: /dev/ttyS%-2d @ %6d\n" , name, port->port.line, baud); } static void
@@ -5723,14 +5725,14 @@ ptp_ocp_info(struct ptp_ocp *bp)ptp_ocp_phc_info (bp);for (i =0 ; i < __PORT_COUNT; i++) { -if (i ==PORT_NMEA && bp->nmea_out && bp->port[PORT_NMEA ].line !=-1 ) { +if (i ==PORT_NMEA && bp->nmea_out && bp->port[PORT_NMEA ].uport) { bp->port[PORT_NMEA ].baud =-1 ; reg =ioread32 (&bp->nmea_out->uart_baud);if (reg <ARRAY_SIZE (nmea_baud)) bp->port[PORT_NMEA ].baud = nmea_baud[reg]; } -ptp_ocp_serial_info (dev,ptp_ocp_tty_port_name (i), bp->port[i].line, +ptp_ocp_serial_info (dev,ptp_ocp_tty_port_name (i), bp->port[i].uport, bp->port[i].baud); } }
@@ -5778,8 +5780,8 @@ ptp_ocp_detach(struct ptp_ocp *bp)for (i =0 ; i <4 ; i++)ptp_ocp_unregister_ext (bp->signal_out[i]);for (i =0 ; i < __PORT_COUNT; i++) -if (bp->port[i].line !=-1 ) -serial8250_unregister_port (bp->port[i].line); +if (bp->port[i].uport) +serial8250_unregister_port (bp->port[i].uport);platform_device_unregister (bp->spi_flash);platform_device_unregister (bp->i2c_ctrl);if (bp->i2c_clk)
drivers/tty/serial/8250/8250_acorn.c +3 -2
@@ -8,6 +8,7 @@#include <linux/types.h> #include <linux/tty.h> #include <linux/serial_core.h> +#include <linux/err.h> #include <linux/errno.h> #include <linux/ioport.h> #include <linux/slab.h>
@@ -31,7 +32,7 @@ struct serial_card_type {struct serial_card_info {unsigned int num_ports; -int ports[MAX_PORTS ]; +struct uart_8250_port *ports[MAX_PORTS ];void __iomem *vaddr; };
@@ -85,7 +86,7 @@ static void serial_card_remove(struct expansion_card *ec)ecard_set_drvdata (ec,NULL );for (i =0 ; i < info->num_ports; i++) -if (info->ports[i] >0 ) +if (!IS_ERR_OR_NULL (info->ports[i]))serial8250_unregister_port (info->ports[i]);kfree (info);
drivers/tty/serial/8250/8250_airoha.c +7 -16
@@ -10,6 +10,7 @@#include <linux/array_size.h> #include <linux/bits.h> #include <linux/bitfield.h> +#include <linux/err.h> #include <linux/errno.h> #include <linux/math64.h> #include <linux/module.h>
@@ -28,10 +29,6 @@#define UART_AIROHA_XYD_X GENMASK(31, 16)#define UART_AIROHA_XYD_Y GENMASK(15, 0) -struct airoha_8250_priv { -int line; -}; -#define UART_BRD_20M 0x0001#define XINDIV_CLOCK (20 * HZ_PER_MHZ)
@@ -119,7 +116,6 @@ static int airoha_8250_probe(struct platform_device *pdev) {struct uart_8250_port uart = { };struct device *dev = &pdev->dev; -struct airoha_8250_priv *priv;struct resource *res;int ret;
@@ -127,10 +123,6 @@ static int airoha_8250_probe(struct platform_device *pdev)if (!res)return dev_err_probe (dev, -EINVAL ,"invalid address\n" ); - priv =devm_kzalloc (dev,sizeof (*priv),GFP_KERNEL ); -if (!priv) -return -ENOMEM ; - uart.port.dev = dev;if (device_is_compatible (dev,"airoha,an7581-hsuart" )) uart.port.type =UART_PORT_AIROHA_HS ;
@@ -147,21 +139,20 @@ static int airoha_8250_probe(struct platform_device *pdev)if (ret)return ret; - ret =serial8250_register_8250_port (&uart); -if (ret <0 ) -return ret; +struct uart_8250_port *uport =serial8250_register_8250_port (&uart); +if (IS_ERR (uport)) +return PTR_ERR (uport); - priv->line = ret; -platform_set_drvdata (pdev, priv); +platform_set_drvdata (pdev, uport);return 0 ; }static void airoha_8250_remove (struct platform_device *ofdev) { -struct airoha_8250_priv *priv =platform_get_drvdata (ofdev); +struct uart_8250_port *uport =platform_get_drvdata (ofdev); -serial8250_unregister_port (priv->line); +serial8250_unregister_port (uport); }static const struct of_device_id airoha_8250_dt_ids[] = {
drivers/tty/serial/8250/8250_aspeed_vuart.c +7 -6
@@ -6,6 +6,7 @@* Copyright (C) 2006 Arnd Bergmann <[email protected]>, IBM Corp. */ #include <linux/device.h> +#include <linux/err.h> #include <linux/module.h> #include <linux/of_address.h> #include <linux/of_irq.h>
@@ -34,7 +35,6 @@struct aspeed_vuart {struct device *dev; -int line;struct timer_list unthrottle_timer;struct uart_8250_port *port; };
@@ -484,12 +484,13 @@ static int aspeed_vuart_probe(struct platform_device *pdev)if (of_property_read_bool (np,"auto-flow-control" )) port.capabilities |=UART_CAP_AFE ; - rc =serial8250_register_8250_port (&port); -if (rc <0 ) +struct uart_8250_port *uport =serial8250_register_8250_port (&port); +if (IS_ERR (uport)) { + rc =PTR_ERR (uport); goto err_sysfs_remove; + } - vuart->line = rc; - vuart->port =serial8250_get_port (vuart->line); + vuart->port = uport; rc = of_parse_phandle_with_fixed_args( np, "aspeed,sirq-polarity-sense", 2, 0,
@@ -553,7 +554,7 @@ static void aspeed_vuart_remove(struct platform_device *pdev)timer_delete_sync (&vuart->unthrottle_timer);aspeed_vuart_set_enabled (vuart, false); -serial8250_unregister_port (vuart->line); +serial8250_unregister_port (vuart->port);sysfs_remove_group (&vuart->dev->kobj, &aspeed_vuart_attr_group); }
drivers/tty/serial/8250/8250_bcm2835aux.c +10 -10
@@ -14,6 +14,7 @@#include <linux/clk.h> #include <linux/console.h> +#include <linux/err.h> #include <linux/io.h> #include <linux/module.h> #include <linux/of.h>
@@ -37,12 +38,12 @@/** * struct bcm2835aux_data - driver private data of BCM2835 auxiliary UART * @clk: clock producer of the port's uartclk -* @line: index of the port's serial8250_ports[] entry +* @uport: the underlying uart_8250_port * @cntl: cached copy of CNTL register */ struct bcm2835aux_data {struct clk *clk; -int line; +struct uart_8250_port *uport;u32 cntl; };
@@ -157,12 +158,12 @@ static int bcm2835aux_serial_probe(struct platform_device *pdev) up.port.uartclk *=2 ;/* register the port */ - ret =serial8250_register_8250_port (&up); -if (ret <0 ) { + data->uport =serial8250_register_8250_port (&up); +if (IS_ERR (data->uport)) { + ret =PTR_ERR (data->uport);dev_err_probe (&pdev->dev, ret,"unable to register 8250 port\n" ); goto dis_clk; } - data->line = ret;return 0 ;
@@ -177,7 +178,7 @@ static void bcm2835aux_serial_remove(struct platform_device *pdev) {struct bcm2835aux_data *data =platform_get_drvdata (pdev); -serial8250_unregister_port (data->line); +serial8250_unregister_port (data->uport);clk_disable_unprepare (data->clk);device_remove_software_node (&pdev->dev); }
@@ -217,12 +218,11 @@ MODULE_DEVICE_TABLE(acpi, bcm2835aux_serial_acpi_match);static bool bcm2835aux_can_disable_clock (struct device *dev) {struct bcm2835aux_data *data =dev_get_drvdata (dev); -struct uart_8250_port *up =serial8250_get_port (data->line);if (device_may_wakeup (dev))return false; -if (uart_console (&up->port) && !console_suspend_enabled) +if (uart_console (&data->uport->port) && !console_suspend_enabled)return false;return true;
@@ -232,7 +232,7 @@ static int bcm2835aux_suspend(struct device *dev) {struct bcm2835aux_data *data =dev_get_drvdata (dev); -serial8250_suspend_port (data->line); +serial8250_suspend_port (data->uport);if (!bcm2835aux_can_disable_clock (dev))return 0 ;
@@ -252,7 +252,7 @@ static int bcm2835aux_resume(struct device *dev)return ret; } -serial8250_resume_port (data->line); +serial8250_resume_port (data->uport);return 0 ; }
drivers/tty/serial/8250/8250_bcm7271.c +15 -18
@@ -13,6 +13,7 @@#include <linux/module.h> #include <linux/types.h> #include <linux/tty.h> +#include <linux/err.h> #include <linux/errno.h> #include <linux/device.h> #include <linux/io.h>
@@ -204,13 +205,12 @@ static const u32 brcmstb_rate_table_7278[] = { };struct brcmuart_priv { -int line;struct clk *baud_mux_clk;unsigned long default_mux_rate;u32 real_rates[ARRAY_SIZE (brcmstb_rate_table)];const u32 *rate_table;ktime_t char_wait; -struct uart_port *up; +struct uart_8250_port *uport;struct hrtimer hrt;bool shutdown;bool dma_enabled;
@@ -839,8 +839,8 @@ static int brcmuart_handle_irq(struct uart_port *p)static enum hrtimer_restart brcmuart_hrtimer_func (struct hrtimer *t) { struct brcmuart_priv *priv = container_of(t, struct brcmuart_priv, hrt); -struct uart_port *p = priv->up; -struct uart_8250_port *up =up_to_u8250p (p); +struct uart_8250_port *up = priv->uport; +struct uart_port *p = &up->port;unsigned int status;unsigned long flags;
@@ -953,7 +953,6 @@ static int brcmuart_probe(struct platform_device *pdev) {struct resource *regs;const struct of_device_id *of_id =NULL ; -struct uart_8250_port *new_port;struct device *dev = &pdev->dev;struct brcmuart_priv *priv;struct clk *baud_mux_clk;
@@ -1083,14 +1082,12 @@ static int brcmuart_probe(struct platform_device *pdev) } } - ret =serial8250_register_8250_port (&up); -if (ret <0 ) { + priv->uport =serial8250_register_8250_port (&up); +if (IS_ERR (priv->uport)) { + ret =PTR_ERR (priv->uport);dev_err_probe (dev, ret,"unable to register 8250 port\n" ); goto err; } - priv->line = ret; - new_port =serial8250_get_port (ret); - priv->up = &new_port->port;if (priv->dma_enabled) { dma_irq =platform_get_irq_byname (pdev,"dma" );if (dma_irq <0 ) {
@@ -1098,7 +1095,7 @@ static int brcmuart_probe(struct platform_device *pdev) goto err1; } ret =devm_request_irq (dev, dma_irq, brcmuart_isr, -IRQF_SHARED ,"uart DMA irq" , &new_port->port); +IRQF_SHARED ,"uart DMA irq" , &priv->uport->port);if (ret) goto err1; }
@@ -1107,7 +1104,7 @@ static int brcmuart_probe(struct platform_device *pdev)return 0 ; err1: -serial8250_unregister_port (priv->line); +serial8250_unregister_port (priv->uport); err:brcmuart_free_bufs (dev, priv); release_dma:
@@ -1121,7 +1118,7 @@ static void brcmuart_remove(struct platform_device *pdev)struct brcmuart_priv *priv =platform_get_drvdata (pdev);debugfs_remove_recursive (priv->debugfs_dir); -serial8250_unregister_port (priv->line); +serial8250_unregister_port (priv->uport);hrtimer_cancel (&priv->hrt);brcmuart_free_bufs (&pdev->dev, priv);if (priv->dma_enabled)
@@ -1131,7 +1128,7 @@ static void brcmuart_remove(struct platform_device *pdev)static int __maybe_unused brcmuart_suspend (struct device *dev) {struct brcmuart_priv *priv =dev_get_drvdata (dev); -struct uart_8250_port *up =serial8250_get_port (priv->line); +struct uart_8250_port *up = priv->uport;struct uart_port *port = &up->port;unsigned long flags;
@@ -1144,7 +1141,7 @@ static int __maybe_unused brcmuart_suspend(struct device *dev) port->mctrl &= ~TIOCM_RTS ;uart_port_unlock_irqrestore (port, flags); -serial8250_suspend_port (priv->line); +serial8250_suspend_port (up);clk_disable_unprepare (priv->baud_mux_clk);return 0 ;
@@ -1153,7 +1150,7 @@ static int __maybe_unused brcmuart_suspend(struct device *dev)static int __maybe_unused brcmuart_resume (struct device *dev) {struct brcmuart_priv *priv =dev_get_drvdata (dev); -struct uart_8250_port *up =serial8250_get_port (priv->line); +struct uart_8250_port *up = priv->uport;struct uart_port *port = &up->port;unsigned long flags;int ret;
@@ -1175,9 +1172,9 @@ static int __maybe_unused brcmuart_resume(struct device *dev)return (-EBUSY ); }brcmuart_init_dma_hardware (priv); -start_rx_dma (serial8250_get_port (priv->line)); +start_rx_dma (up); } -serial8250_resume_port (priv->line); +serial8250_resume_port (up);if (priv->saved_mctrl &TIOCM_RTS ) {/* Restore RTS */
drivers/tty/serial/8250/8250_core.c +17 -23
@@ -16,6 +16,7 @@#include <linux/hashtable.h> #include <linux/module.h> #include <linux/moduleparam.h> +#include <linux/err.h> #include <linux/ioport.h> #include <linux/init.h> #include <linux/console.h>
@@ -333,7 +334,6 @@ struct uart_8250_port *serial8250_get_port(int line) {return &serial8250_ports[line]; } -EXPORT_SYMBOL_GPL (serial8250_get_port);static inline void serial8250_apply_quirks (struct uart_8250_port *up) {
@@ -600,13 +600,12 @@ int __init early_serial_setup(struct uart_port *port)/** * serial8250_suspend_port - suspend one serial port -* @line: serial line number +* @up: serial port * * Suspend one serial port. */ -void serial8250_suspend_port (int line) +void serial8250_suspend_port (struct uart_8250_port *up) { -struct uart_8250_port *up = &serial8250_ports[line];struct uart_port *port = &up->port;if (uart_console (port)) {
@@ -630,13 +629,12 @@ EXPORT_SYMBOL(serial8250_suspend_port);/** * serial8250_resume_port - resume one serial port -* @line: serial line number +* @up: serial port * * Resume one serial port. */ -void serial8250_resume_port (int line) +void serial8250_resume_port (struct uart_8250_port *up) { -struct uart_8250_port *up = &serial8250_ports[line];struct uart_port *port = &up->port; up->canary =0 ;
@@ -865,16 +863,12 @@ static int __serial8250_register_8250_port(struct uart_8250_port *uart, &uart->port);if (ret)return ret; - - ret = uart->port.line; }else {dev_info (uart->port.dev,"skipping CIR port at 0x%lx / 0x%llx, IRQ %d\n" , uart->port.iobase, (unsigned long long )uart->port.mapbase, uart->port.irq); - - ret =0 ; }if (!uart->lsr_save_mask)
@@ -890,7 +884,7 @@ static int __serial8250_register_8250_port(struct uart_8250_port *uart, uart->overrun_backoff_time_ms =0 ; } -return ret; +return 0 ; }/**
@@ -906,13 +900,13 @@ static int __serial8250_register_8250_port(struct uart_8250_port *uart,* * On success the port is ready to use and the line number is returned. */ -int serial8250_register_8250_port (const struct uart_8250_port *up) +struct uart_8250_port *serial8250_register_8250_port (const struct uart_8250_port *up) {struct uart_8250_port *uart;int ret;if (up->port.uartclk ==0 ) -return -EINVAL ; +return ERR_PTR (-EINVAL );guard (mutex)(&serial_mutex);
@@ -924,33 +918,33 @@ int serial8250_register_8250_port(const struct uart_8250_port *up)*/ uart =serial8250_setup_port (nr_uarts);if (!uart) -return -ENOSPC ; +return ERR_PTR (-ENOSPC ); nr_uarts++; }/* Check if it is CIR already. We check this below again, see there why. */ if (uart->port.type ==PORT_8250_CIR ) -return -ENODEV ; +return ERR_PTR (-ENODEV ); ret =__serial8250_register_8250_port (uart, up); -if (ret <0 ) +if (ret <0 ) { uart->port.dev =NULL ; +return ERR_PTR (ret); + } -return ret; +return uart; }EXPORT_SYMBOL (serial8250_register_8250_port);/** * serial8250_unregister_port - remove a 16x50 serial port at runtime -* @line: serial line number +* @uart: port * * Remove one serial port. This may not be called from interrupt * context. We hand the port back to the our control. */ -void serial8250_unregister_port (int line) +void serial8250_unregister_port (struct uart_8250_port *uart) { -struct uart_8250_port *uart = &serial8250_ports[line]; -guard (mutex)(&serial_mutex);if (uart->em485) {
@@ -963,7 +957,7 @@ void serial8250_unregister_port(int line) uart->port.flags &= ~UPF_BOOT_AUTOCONF ; uart->port.type =PORT_UNKNOWN ; uart->port.dev = &serial8250_isa_devs->dev; - uart->port.port_id = line; + uart->port.port_id = uart->port.line; uart->capabilities =0 ;serial8250_init_port (uart);serial8250_apply_quirks (uart);
drivers/tty/serial/8250/8250_dfl.c +7 -15
@@ -12,6 +12,7 @@#include <linux/bitfield.h> #include <linux/device.h> #include <linux/dfl.h> +#include <linux/err.h> #include <linux/errno.h> #include <linux/ioport.h> #include <linux/module.h>
@@ -27,10 +28,6 @@#define DFHv1_PARAM_REG_LAYOUT_WIDTH GENMASK_ULL(63, 32)#define DFHv1_PARAM_REG_LAYOUT_SHIFT GENMASK_ULL(31, 0) -struct dfl_uart { -int line; -}; -static int dfh_get_u64_param_val (struct dfl_device *dfl_dev,int param_id,u64 *pval) {size_t psize;
@@ -109,7 +106,6 @@ static int dfl_uart_probe(struct dfl_device *dfl_dev) {struct device *dev = &dfl_dev->dev;struct uart_8250_port uart = { }; -struct dfl_uart *dfluart;int ret; uart.port.flags =UPF_IOREMAP ;
@@ -123,24 +119,20 @@ static int dfl_uart_probe(struct dfl_device *dfl_dev)if (dfl_dev->num_irqs ==1 ) uart.port.irq = dfl_dev->irqs[0 ]; - dfluart =devm_kzalloc (dev,sizeof (*dfluart),GFP_KERNEL ); -if (!dfluart) -return -ENOMEM ; - - dfluart->line =serial8250_register_8250_port (&uart); -if (dfluart->line <0 ) -return dev_err_probe (dev, dfluart->line,"unable to register 8250 port.\n" ); +struct uart_8250_port *uport =serial8250_register_8250_port (&uart); +if (IS_ERR (uport)) +return dev_err_probe (dev,PTR_ERR (uport),"unable to register 8250 port.\n" ); -dev_set_drvdata (dev, dfluart); +dev_set_drvdata (dev, uport);return 0 ; }static void dfl_uart_remove (struct dfl_device *dfl_dev) { -struct dfl_uart *dfluart =dev_get_drvdata (&dfl_dev->dev); +struct uart_8250_port *uport =dev_get_drvdata (&dfl_dev->dev); -serial8250_unregister_port (dfluart->line); +serial8250_unregister_port (uport); }#define FME_FEATURE_ID_UART 0x24
drivers/tty/serial/8250/8250_dw.c +7 -6
@@ -15,6 +15,7 @@#include <linux/clk.h> #include <linux/delay.h> #include <linux/device.h> +#include <linux/err.h> #include <linux/io.h> #include <linux/lockdep.h> #include <linux/module.h>
@@ -774,9 +775,9 @@ static int dw8250_probe(struct platform_device *pdev) up->dma = &data->data.dma; } - data->data.line =serial8250_register_8250_port (up); -if (data->data.line <0 ) -return data->data.line; + data->data.uport =serial8250_register_8250_port (up); +if (IS_ERR (data->data.uport)) +return PTR_ERR (data->data.uport);platform_set_drvdata (pdev, data);
@@ -792,7 +793,7 @@ static void dw8250_remove(struct platform_device *pdev)pm_runtime_get_sync (dev); -serial8250_unregister_port (data->data.line); +serial8250_unregister_port (data->data.uport);pm_runtime_disable (dev);pm_runtime_put_noidle (dev);
@@ -802,7 +803,7 @@ static int dw8250_suspend(struct device *dev) {struct dw8250_data *data =dev_get_drvdata (dev); -serial8250_suspend_port (data->data.line); +serial8250_suspend_port (data->data.uport);return 0 ; }
@@ -811,7 +812,7 @@ static int dw8250_resume(struct device *dev) {struct dw8250_data *data =dev_get_drvdata (dev); -serial8250_resume_port (data->data.line); +serial8250_resume_port (data->data.uport);return 0 ; }
drivers/tty/serial/8250/8250_dwlib.h +1 -1
@@ -80,7 +80,7 @@struct dw8250_port_data {/* Port properties */ -int line; +struct uart_8250_port *uport;/* DMA operations */ struct uart_8250_dma dma;
drivers/tty/serial/8250/8250_em.c +8 -18
@@ -6,6 +6,7 @@*/ #include <linux/device.h> +#include <linux/err.h> #include <linux/io.h> #include <linux/module.h> #include <linux/serial_8250.h>
@@ -28,10 +29,6 @@#define UART_HCR0_EM_SW_RESET BIT(7)/* SW Reset */ -struct serial8250_em_priv { -int line; -}; -static void serial8250_em_serial_out_helper (struct uart_port *p,int offset,int value) {
@@ -151,12 +148,11 @@ static void serial8250_em_serial_dl_write(struct uart_8250_port *up, u32 value)static int serial8250_em_probe (struct platform_device *pdev) { -struct serial8250_em_priv *priv;struct device *dev = &pdev->dev;struct uart_8250_port up;struct resource *regs;struct clk *sclk; -int irq, ret; +int irq; irq =platform_get_irq (pdev,0 );if (irq <0 )
@@ -166,10 +162,6 @@ static int serial8250_em_probe(struct platform_device *pdev)if (!regs)return dev_err_probe (dev, -EINVAL ,"missing registers\n" ); - priv =devm_kzalloc (dev,sizeof (*priv),GFP_KERNEL ); -if (!priv) -return -ENOMEM ; - sclk =devm_clk_get_enabled (dev,"sclk" );if (IS_ERR (sclk))return dev_err_probe (dev,PTR_ERR (sclk),"unable to get clock\n" );
@@ -180,7 +172,6 @@ static int serial8250_em_probe(struct platform_device *pdev) up.port.type =PORT_16750 ; up.port.flags =UPF_FIXED_PORT |UPF_IOREMAP |UPF_FIXED_TYPE ; up.port.dev = dev; - up.port.private_data = priv; up.port.uartclk =clk_get_rate (sclk);
@@ -190,20 +181,19 @@ static int serial8250_em_probe(struct platform_device *pdev) up.dl_read = serial8250_em_serial_dl_read; up.dl_write = serial8250_em_serial_dl_write; - ret =serial8250_register_8250_port (&up); -if (ret <0 ) -return dev_err_probe (dev, ret,"unable to register 8250 port\n" ); +struct uart_8250_port *uport =serial8250_register_8250_port (&up); +if (IS_ERR (uport)) +return dev_err_probe (dev,PTR_ERR (uport),"unable to register 8250 port\n" ); - priv->line = ret; -platform_set_drvdata (pdev, priv); +platform_set_drvdata (pdev, uport);return 0 ; }static void serial8250_em_remove (struct platform_device *pdev) { -struct serial8250_em_priv *priv =platform_get_drvdata (pdev); +struct uart_8250_port *up =platform_get_drvdata (pdev); -serial8250_unregister_port (priv->line); +serial8250_unregister_port (up); }static const struct of_device_id serial8250_em_dt_ids[] = {
drivers/tty/serial/8250/8250_exar.c +9 -10
@@ -12,6 +12,7 @@#include <linux/device.h> #include <linux/dmi.h> #include <linux/eeprom_93cx6.h> +#include <linux/err.h> #include <linux/interrupt.h> #include <linux/io.h> #include <linux/math.h>
@@ -258,7 +259,7 @@ struct exar8250 {struct eeprom_93cx6 eeprom;void __iomem *virt;struct platform_device *gpio; -int line[]; +struct uart_8250_port *uport[]; }; static inline void exar_write_reg(struct exar8250 *priv,
@@ -1460,7 +1461,7 @@ exar_pci_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)if (nr_ports ==0 )return dev_err_probe (&pcidev->dev, -ENODEV ,"failed to get number of ports\n" ); - priv =devm_kzalloc (&pcidev->dev,struct_size (priv, line, nr_ports),GFP_KERNEL ); + priv =devm_kzalloc (&pcidev->dev,struct_size (priv, uport, nr_ports),GFP_KERNEL );if (!priv)return -ENOMEM ;
@@ -1500,9 +1501,9 @@ exar_pci_probe(struct pci_dev *pcidev, const struct pci_device_id *ent)dev_dbg (&pcidev->dev,"Setup PCI port: port %lx, irq %d, type %d\n" , uart.port.iobase, uart.port.irq, uart.port.iotype); - priv->line[i] =serial8250_register_8250_port (&uart); -if (priv->line[i] <0 ) { -dev_err_probe (&pcidev->dev, priv->line[i], + priv->uport[i] =serial8250_register_8250_port (&uart); +if (IS_ERR (priv->uport[i])) { +dev_err_probe (&pcidev->dev,PTR_ERR (priv->uport[i]),"Couldn't register serial port %lx, type %d, irq %d\n" , uart.port.iobase, uart.port.iotype, uart.port.irq);break ;
@@ -1519,7 +1520,7 @@ static void exar_pci_remove(struct pci_dev *pcidev)unsigned int i;for (i =0 ; i < priv->nr; i++) -serial8250_unregister_port (priv->line[i]); +serial8250_unregister_port (priv->uport[i]);/* Ensure that every init quirk is properly torn down */ if (priv->board->exit)
@@ -1532,8 +1533,7 @@ static int exar_suspend(struct device *dev)unsigned int i;for (i =0 ; i < priv->nr; i++) -if (priv->line[i] >=0 ) -serial8250_suspend_port (priv->line[i]); +serial8250_suspend_port (priv->uport[i]);return 0 ; }
@@ -1546,8 +1546,7 @@ static int exar_resume(struct device *dev)exar_misc_clear (priv);for (i =0 ; i < priv->nr; i++) -if (priv->line[i] >=0 ) -serial8250_resume_port (priv->line[i]); +serial8250_resume_port (priv->uport[i]);return 0 ; }
drivers/tty/serial/8250/8250_fsl.c +8 -16
@@ -18,6 +18,7 @@*/ #include <linux/acpi.h> +#include <linux/err.h> #include <linux/serial_reg.h> #include <linux/serial_8250.h>
@@ -99,14 +100,9 @@ int fsl8250_handle_irq(struct uart_port *port)EXPORT_SYMBOL_GPL (fsl8250_handle_irq);#ifdef CONFIG_ACPI -struct fsl8250_data { -int line; -}; -static int fsl8250_acpi_probe (struct platform_device *pdev) { -struct fsl8250_data *data; -struct uart_8250_port port8250; +struct uart_8250_port *uport, port8250;struct device *dev = &pdev->dev;struct resource *regs;
@@ -148,23 +144,19 @@ static int fsl8250_acpi_probe(struct platform_device *pdev)if (!port8250.port.membase)return -ENOMEM ; - data =devm_kzalloc (dev,sizeof (*data),GFP_KERNEL ); -if (!data) -return -ENOMEM ; - - data->line =serial8250_register_8250_port (&port8250); -if (data->line <0 ) -return data->line; + uport =serial8250_register_8250_port (&port8250); +if (IS_ERR (uport)) +return PTR_ERR (uport); -platform_set_drvdata (pdev, data); +platform_set_drvdata (pdev, uport);return 0 ; }static void fsl8250_acpi_remove (struct platform_device *pdev) { -struct fsl8250_data *data =platform_get_drvdata (pdev); +struct uart_8250_port *uport =platform_get_drvdata (pdev); -serial8250_unregister_port (data->line); +serial8250_unregister_port (uport); }static const struct acpi_device_id fsl_8250_acpi_id[] = {
drivers/tty/serial/8250/8250_hp300.c +11 -16
@@ -7,6 +7,7 @@* by Kars de Jong <[email protected]>, May 2004. */ #include <linux/module.h> +#include <linux/err.h> #include <linux/init.h> #include <linux/string.h> #include <linux/kernel.h>
@@ -27,7 +28,7 @@#ifdef CONFIG_HPAPCI struct hp300_port {struct hp300_port *next;/* next port */ -int line;/* line (tty) number */ +struct uart_8250_port *uport; };static struct hp300_port *hp300_ports;
@@ -157,8 +158,7 @@ int __init hp300_setup_serial_console(void)static int hpdca_init_one (struct dio_dev *d,const struct dio_device_id *ent) { -struct uart_8250_port uart; -int line; +struct uart_8250_port *uport, uart;#ifdef CONFIG_SERIAL_8250_CONSOLE if (hp300_uart_scode == d->scode) {
@@ -177,9 +177,8 @@ static int hpdca_init_one(struct dio_dev *d, uart.port.membase = (char *)(uart.port.mapbase +DIO_VIRADDRBASE ); uart.port.regshift =1 ; uart.port.dev = &d->dev; - line =serial8250_register_8250_port (&uart); - -if (line <0 ) { + uport =serial8250_register_8250_port (&uart); +if (IS_ERR (uport)) {dev_notice (&d->dev,"8250_hp300: register_serial() DCA scode %d irq %d failed\n" , d->scode, uart.port.irq);
@@ -188,7 +187,7 @@ static int hpdca_init_one(struct dio_dev *d,/* Enable board-interrupts */ out_8 (d->resource.start +DIO_VIRADDRBASE +DCA_IC ,DCA_IC_IE ); -dio_set_drvdata (d, (void *)line); +dio_set_drvdata (d, uport);/* Reset the DCA */ out_8 (d->resource.start +DIO_VIRADDRBASE +DCA_ID ,0xff );
@@ -204,7 +203,6 @@ static int __init hp300_8250_init(void) {static int called;#ifdef CONFIG_HPAPCI -int line;unsigned long base;struct uart_8250_port uart;struct hp300_port *port;
@@ -259,9 +257,8 @@ static int __init hp300_8250_init(void) uart.port.membase = (char *)(base +DIO_VIRADDRBASE ); uart.port.regshift =2 ; - line =serial8250_register_8250_port (&uart); - -if (line <0 ) { + port->uport =serial8250_register_8250_port (&uart); +if (IS_ERR (port->uport)) {dev_notice (uart.port.dev,"8250_hp300: register_serial() APCI %d irq %d failed\n" , i, uart.port.irq);
@@ -269,7 +266,6 @@ static int __init hp300_8250_init(void)continue ; } - port->line = line; port->next = hp300_ports; hp300_ports = port;
@@ -287,14 +283,13 @@ static int __init hp300_8250_init(void)#ifdef CONFIG_HPDCA static void hpdca_remove_one (struct dio_dev *d) { -int line; +struct uart_8250_port *uport =dio_get_drvdata (d); - line = (int )dio_get_drvdata (d);if (d->resource.start) {/* Disable board-interrupts */ out_8 (d->resource.start +DIO_VIRADDRBASE +DCA_IC ,0 ); } -serial8250_unregister_port (line); +serial8250_unregister_port (uport); }#endif
@@ -304,7 +299,7 @@ static void __exit hp300_8250_exit(void)struct hp300_port *port, *to_free;for (port = hp300_ports; port; ) { -serial8250_unregister_port (port->line); +serial8250_unregister_port (port->uport); to_free = port; port = port->next;kfree (to_free);
drivers/tty/serial/8250/8250_ingenic.c +6 -5
@@ -8,6 +8,7 @@#include <linux/clk.h> #include <linux/console.h> +#include <linux/err.h> #include <linux/io.h> #include <linux/libfdt.h> #include <linux/module.h>
@@ -29,7 +30,7 @@ struct ingenic_uart_config {struct ingenic_uart_data {struct clk *clk_module;struct clk *clk_baud; -int line; +struct uart_8250_port *uport; };static const struct of_device_id of_match[];
@@ -297,9 +298,9 @@ static int ingenic_uart_probe(struct platform_device *pdev) } uart.port.uartclk =clk_get_rate (data->clk_baud); - data->line =serial8250_register_8250_port (&uart); -if (data->line <0 ) { - err = data->line; + data->uport =serial8250_register_8250_port (&uart); +if (IS_ERR (data->uport)) { + err =PTR_ERR (data->uport); goto out_disable_baudclk; }
@@ -318,7 +319,7 @@ static void ingenic_uart_remove(struct platform_device *pdev) {struct ingenic_uart_data *data =platform_get_drvdata (pdev); -serial8250_unregister_port (data->line); +serial8250_unregister_port (data->uport);clk_disable_unprepare (data->clk_module);clk_disable_unprepare (data->clk_baud); }
drivers/tty/serial/8250/8250_ioc3.c +9 -17
@@ -9,6 +9,7 @@*/ #include <linux/module.h> +#include <linux/err.h> #include <linux/errno.h> #include <linux/io.h> #include <linux/platform_device.h>
@@ -17,10 +18,6 @@#define IOC3_UARTCLK (22000000 / 3) -struct ioc3_8250_data { -int line; -}; -static u32 ioc3_serial_in (struct uart_port *p,unsigned int offset) {return readb (p->membase + (offset ^3 ));
@@ -33,20 +30,15 @@ static void ioc3_serial_out(struct uart_port *p, unsigned int offset, u32 value)static int serial8250_ioc3_probe (struct platform_device *pdev) { -struct ioc3_8250_data *data; -struct uart_8250_port up; +struct uart_8250_port *uport, up;struct resource *r;void __iomem *membase; -int irq, line; +int irq; r =platform_get_resource (pdev,IORESOURCE_MEM ,0 );if (!r)return -ENODEV ; - data =devm_kzalloc (&pdev->dev,sizeof (*data),GFP_KERNEL ); -if (!data) -return -ENOMEM ; - membase =devm_ioremap (&pdev->dev, r->start,resource_size (r));if (!membase)return -ENOMEM ;
@@ -67,19 +59,19 @@ static int serial8250_ioc3_probe(struct platform_device *pdev) up.port.mapbase = r->start; up.port.serial_in = ioc3_serial_in; up.port.serial_out = ioc3_serial_out; - line =serial8250_register_8250_port (&up); -if (line <0 ) -return line; + uport =serial8250_register_8250_port (&up); +if (IS_ERR (uport)) +return PTR_ERR (uport); -platform_set_drvdata (pdev, data); +platform_set_drvdata (pdev, uport);return 0 ; }static void serial8250_ioc3_remove (struct platform_device *pdev) { -struct ioc3_8250_data *data =platform_get_drvdata (pdev); +struct uart_8250_port *uport =platform_get_drvdata (pdev); -serial8250_unregister_port (data->line); +serial8250_unregister_port (uport); }static struct platform_driver serial8250_ioc3_driver = {
drivers/tty/serial/8250/8250_keba.c +5 -8
@@ -62,7 +62,7 @@ enum kuart_mode {struct kuart {struct keba_uart_auxdev *auxdev;void __iomem *base; -unsigned int line; +struct uart_8250_port *uport;unsigned int flags;u8 capability;
@@ -174,7 +174,6 @@ static int kuart_probe(struct auxiliary_device *auxdev,struct uart_8250_port uart = {};struct resource res;struct kuart *kuart; -int retval; kuart =devm_kzalloc (dev,sizeof (*kuart),GFP_KERNEL );if (!kuart)
@@ -250,12 +249,10 @@ static int kuart_probe(struct auxiliary_device *auxdev, } } - retval =serial8250_register_8250_port (&uart); -if (retval <0 ) -return dev_err_probe (&auxdev->dev, retval, + kuart->uport =serial8250_register_8250_port (&uart); +if (IS_ERR (kuart->uport)) +return dev_err_probe (&auxdev->dev,PTR_ERR (kuart->uport),"UART registration failed!\n" ); - kuart->line = retval; -return 0 ; }
@@ -266,7 +263,7 @@ static void kuart_remove(struct auxiliary_device *auxdev)if (kuart->flags &KUART_USE_CAPABILITY )kuart_set_phy_mode (kuart,KUART_MODE_NONE ); -serial8250_unregister_port (kuart->line); +serial8250_unregister_port (kuart->uport); }static const struct auxiliary_device_id kuart_devtype_aux[] = {
drivers/tty/serial/8250/8250_loongson.c +10 -10
@@ -10,6 +10,7 @@#include <linux/clk.h> #include <linux/console.h> #include <linux/module.h> +#include <linux/err.h> #include <linux/io.h> #include <linux/property.h> #include <linux/math.h>
@@ -43,7 +44,7 @@ static const struct loongson_uart_ddata ls2k1500_uart_data = { };struct loongson_uart_priv { -int line; +struct uart_8250_port *uport;struct clk *clk;struct resource *res;struct reset_control *rst;
@@ -160,13 +161,12 @@ static int loongson_uart_probe(struct platform_device *pdev)if (ret)return ret; - ret =serial8250_register_8250_port (&uart); -if (ret <0 ) { + priv->uport =serial8250_register_8250_port (&uart); +if (IS_ERR (priv->uport)) {reset_control_assert (priv->rst); -return ret; +return PTR_ERR (priv->uport); } - priv->line = ret;platform_set_drvdata (pdev, priv);return 0 ;
@@ -176,16 +176,16 @@ static void loongson_uart_remove(struct platform_device *pdev) {struct loongson_uart_priv *priv =platform_get_drvdata (pdev); -serial8250_unregister_port (priv->line); +serial8250_unregister_port (priv->uport);reset_control_assert (priv->rst); }static int loongson_uart_suspend (struct device *dev) {struct loongson_uart_priv *priv =dev_get_drvdata (dev); -struct uart_8250_port *up =serial8250_get_port (priv->line); +struct uart_8250_port *up = priv->uport; -serial8250_suspend_port (priv->line); +serial8250_suspend_port (up);if (!uart_console (&up->port) || console_suspend_enabled)clk_disable_unprepare (priv->clk);
@@ -196,7 +196,7 @@ static int loongson_uart_suspend(struct device *dev)static int loongson_uart_resume (struct device *dev) {struct loongson_uart_priv *priv =dev_get_drvdata (dev); -struct uart_8250_port *up =serial8250_get_port (priv->line); +struct uart_8250_port *up = priv->uport;int ret;if (!uart_console (&up->port) || console_suspend_enabled) {
@@ -205,7 +205,7 @@ static int loongson_uart_resume(struct device *dev)return ret; } -serial8250_resume_port (priv->line); +serial8250_resume_port (up);return 0 ; }
drivers/tty/serial/8250/8250_lpc18xx.c +6 -5
@@ -10,6 +10,7 @@*/ #include <linux/clk.h> +#include <linux/err.h> #include <linux/io.h> #include <linux/module.h> #include <linux/of.h>
@@ -29,7 +30,7 @@ struct lpc18xx_uart_data {struct uart_8250_dma dma;struct clk *clk_uart;struct clk *clk_reg; -int line; +struct uart_8250_port *uport; }; static int lpc18xx_rs485_config(struct uart_port *port, struct ktermios *termios,
@@ -160,13 +161,13 @@ static int lpc18xx_serial_probe(struct platform_device *pdev) uart.dma->rxconf.src_maxburst =1 ; uart.dma->txconf.dst_maxburst =1 ; - ret =serial8250_register_8250_port (&uart); -if (ret <0 ) { + data->uport =serial8250_register_8250_port (&uart); +if (IS_ERR (data->uport)) { + ret =PTR_ERR (data->uport);dev_err (&pdev->dev,"unable to register 8250 port\n" ); goto dis_uart_clk; } - data->line = ret;platform_set_drvdata (pdev, data);return 0 ;
@@ -182,7 +183,7 @@ static void lpc18xx_serial_remove(struct platform_device *pdev) {struct lpc18xx_uart_data *data =platform_get_drvdata (pdev); -serial8250_unregister_port (data->line); +serial8250_unregister_port (data->uport);clk_disable_unprepare (data->clk_uart);clk_disable_unprepare (data->clk_reg); }
drivers/tty/serial/8250/8250_lpss.c +9 -9
@@ -7,6 +7,7 @@*/ #include <linux/bitops.h> +#include <linux/err.h> #include <linux/module.h> #include <linux/pci.h> #include <linux/rational.h>
@@ -183,8 +184,8 @@ static int ehl_serial_setup(struct lpss8250 *lpss, struct uart_port *port)static void ehl_serial_exit (struct lpss8250 *lpss) { -if (lpss->data.line >=0 ) -serial8250_get_port (lpss->data.line)->dma =NULL ; +if (lpss->data.uport) + lpss->data.uport->dma =NULL ; }#ifdef CONFIG_SERIAL_8250_DMA
@@ -328,8 +329,6 @@ static int lpss8250_probe(struct pci_dev *pdev, const struct pci_device_id *id)return ret; lpss->board = (struct lpss8250_board *)id->driver_data; -/* for tests in lpss->board->exit() */ - lpss->data.line =-1 ;memset (&uart,0 ,sizeof (struct uart_8250_port ));
@@ -357,11 +356,12 @@ static int lpss8250_probe(struct pci_dev *pdev, const struct pci_device_id *id)if (ret) goto err_exit; - ret =serial8250_register_8250_port (&uart); -if (ret <0 ) +struct uart_8250_port *uport =serial8250_register_8250_port (&uart); +if (IS_ERR (uport)) { + ret =PTR_ERR (uport); goto err_exit; - - lpss->data.line = ret; + } + lpss->data.uport = uport;pci_set_drvdata (pdev, lpss);return 0 ;
@@ -376,7 +376,7 @@ static void lpss8250_remove(struct pci_dev *pdev) {struct lpss8250 *lpss =pci_get_drvdata (pdev); -serial8250_unregister_port (lpss->data.line); +serial8250_unregister_port (lpss->data.uport); lpss->board->exit (lpss);pci_free_irq_vectors (pdev);
drivers/tty/serial/8250/8250_men_mcb.c +7 -7
@@ -2,6 +2,7 @@#include <linux/device.h> #include <linux/kernel.h> #include <linux/module.h> +#include <linux/err.h> #include <linux/io.h> #include <linux/mcb.h> #include <linux/serial.h>
@@ -42,7 +43,7 @@struct serial_8250_men_mcb_data {int num_ports; -int line[MEN_Z025_MAX_UARTS ]; +struct uart_8250_port *uport[MEN_Z025_MAX_UARTS ];unsigned int offset[MEN_Z025_MAX_UARTS ]; };
@@ -218,14 +219,13 @@ static int serial_8250_men_mcb_probe(struct mcb_device *mdev, + data->offset[i];/* ok, register the port */ - res =serial8250_register_8250_port (&uart); -if (res <0 ) { + data->uport[i] =serial8250_register_8250_port (&uart); +if (IS_ERR (data->uport[i])) {dev_err (&mdev->dev,"unable to register UART port\n" ); -return res; +return PTR_ERR (data->uport[i]); } - data->line[i] = res; -dev_info (&mdev->dev,"found MCB UART: ttyS%d\n" , data->line[i]); +dev_info (&mdev->dev,"found MCB UART: ttyS%d\n" , data->uport[i]->port.line); }return 0 ;
@@ -240,7 +240,7 @@ static void serial_8250_men_mcb_remove(struct mcb_device *mdev)return ;for (i =0 ; i < data->num_ports; i++) -serial8250_unregister_port (data->line[i]); +serial8250_unregister_port (data->uport[i]); }static const struct mcb_device_id serial_8250_men_mcb_ids[] = {
drivers/tty/serial/8250/8250_mid.c +7 -6
@@ -8,6 +8,7 @@#include <linux/bitops.h> #include <linux/cleanup.h> +#include <linux/err.h> #include <linux/module.h> #include <linux/pci.h> #include <linux/rational.h>
@@ -41,7 +42,7 @@ struct mid8250_board { };struct mid8250 { -int line; +struct uart_8250_port *uport;int dma_index;struct pci_dev *dma_dev;struct uart_8250_dma dma;
@@ -335,11 +336,11 @@ static int mid8250_probe(struct pci_dev *pdev, const struct pci_device_id *id)if (ret) goto err; - ret =serial8250_register_8250_port (&uart); -if (ret <0 ) + mid->uport =serial8250_register_8250_port (&uart); +if (IS_ERR (mid->uport)) { + ret =PTR_ERR (mid->uport); goto err; - - mid->line = ret; + }pci_set_drvdata (pdev, mid);return 0 ;
@@ -354,7 +355,7 @@ static void mid8250_remove(struct pci_dev *pdev) {struct mid8250 *mid =pci_get_drvdata (pdev); -serial8250_unregister_port (mid->line); +serial8250_unregister_port (mid->uport);if (mid->board->exit) mid->board->exit (mid);
drivers/tty/serial/8250/8250_mtk.c +10 -9
@@ -6,6 +6,7 @@* Author: Matthias Brugger <[email protected]> */ #include <linux/clk.h> +#include <linux/err.h> #include <linux/io.h> #include <linux/module.h> #include <linux/of.h>
@@ -68,7 +69,7 @@ enum dma_rx_status {#endif struct mtk8250_data { -int line; +struct uart_8250_port *uport;unsigned int rx_pos;unsigned int clk_count;struct clk *uart_clk;
@@ -431,7 +432,7 @@ mtk8250_set_termios(struct uart_port *port, struct ktermios *termios,static int __maybe_unused mtk8250_runtime_suspend (struct device *dev) {struct mtk8250_data *data =dev_get_drvdata (dev); -struct uart_8250_port *up =serial8250_get_port (data->line); +struct uart_8250_port *up = data->uport;/* wait until UART in idle status */ while
@@ -587,9 +588,9 @@ static int mtk8250_probe(struct platform_device *pdev)platform_set_drvdata (pdev, data); - data->line =serial8250_register_8250_port (&uart); -if (data->line <0 ) -return data->line; + data->uport =serial8250_register_8250_port (&uart); +if (IS_ERR (data->uport)) +return PTR_ERR (data->uport); data->rx_wakeup_irq =platform_get_irq_optional (pdev,1 );
@@ -605,7 +606,7 @@ static void mtk8250_remove(struct platform_device *pdev)pm_runtime_get_sync (&pdev->dev); -serial8250_unregister_port (data->line); +serial8250_unregister_port (data->uport);pm_runtime_disable (&pdev->dev);pm_runtime_put_noidle (&pdev->dev);
@@ -617,7 +618,7 @@ static int __maybe_unused mtk8250_suspend(struct device *dev)int irq = data->rx_wakeup_irq;int err; -serial8250_suspend_port (data->line); +serial8250_suspend_port (data->uport);pinctrl_pm_select_sleep_state (dev);if (irq >=0 ) {
@@ -627,7 +628,7 @@ static int __maybe_unused mtk8250_suspend(struct device *dev)"failed to enable irq wake on IRQ %d: %d\n" , irq, err);pinctrl_pm_select_default_state (dev); -serial8250_resume_port (data->line); +serial8250_resume_port (data->uport);return err; } }
@@ -644,7 +645,7 @@ static int __maybe_unused mtk8250_resume(struct device *dev)disable_irq_wake (irq);pinctrl_pm_select_default_state (dev); -serial8250_resume_port (data->line); +serial8250_resume_port (data->uport);return 0 ; }
drivers/tty/serial/8250/8250_mxpcie.c +7 -6
@@ -9,6 +9,7 @@#include <linux/bits.h> #include <linux/device.h> #include <linux/dev_printk.h> +#include <linux/err.h> #include <linux/io.h> #include <linux/ioport.h> #include <linux/module.h>
@@ -102,7 +103,7 @@#define MOXA_ODD_RS_MASK GENMASK(7, 4)struct mxpcie8250_port { -int line; +struct uart_8250_port *uport;u8 rx_trig_level; };
@@ -572,12 +573,12 @@ static int mxpcie8250_probe(struct pci_dev *pdev, const struct pci_device_id *iddev_dbg (dev,"Setup PCI port: port %lx, irq %d, type %d\n" , up.port.iobase, up.port.irq, up.port.iotype); - priv->port[i].line =serial8250_register_8250_port (&up); -if (priv->port[i].line <0 ) { + priv->port[i].uport =serial8250_register_8250_port (&up); +if (IS_ERR (priv->port[i].uport)) {dev_err (dev, -"Couldn't register serial port %lx, irq %d, type %d, error %d\n" , +"Couldn't register serial port %lx, irq %d, type %d, error %pe\n" , up.port.iobase, up.port.irq, - up.port.iotype, priv->port[i].line); + up.port.iotype, priv->port[i].uport);break ; } priv->port[i].rx_trig_level =MOXA_PUART_RX_TRIG_DEFAULT ;
@@ -592,7 +593,7 @@ static void mxpcie8250_remove(struct pci_dev *pdev)struct mxpcie8250 *priv =pci_get_drvdata (pdev);for (unsigned int i =0 ; i < priv->nr; i++) -serial8250_unregister_port (priv->port[i].line); +serial8250_unregister_port (priv->port[i].uport); }static const struct pci_device_id mxpcie8250_pci_ids[] = {
drivers/tty/serial/8250/8250_ni.c +6 -6
@@ -14,6 +14,7 @@#include <linux/bits.h> #include <linux/clk.h> #include <linux/device.h> +#include <linux/err.h> #include <linux/io.h> #include <linux/init.h> #include <linux/module.h>
@@ -73,7 +74,7 @@ struct ni16550_device_info { };struct ni16550_data { -int line; +struct uart_8250_port *uport;struct clk *clk; };
@@ -383,10 +384,9 @@ static int ni16550_probe(struct platform_device *pdev)ni16550_rs485_setup (&uart->port); } - ret =serial8250_register_8250_port (uart); -if (ret <0 ) -return ret; - data->line = ret; + data->uport =serial8250_register_8250_port (uart); +if (IS_ERR (data->uport)) +return PTR_ERR (data->uport);platform_set_drvdata (pdev, data);return 0 ;
@@ -396,7 +396,7 @@ static void ni16550_remove(struct platform_device *pdev) {struct ni16550_data *data =platform_get_drvdata (pdev); -serial8250_unregister_port (data->line); +serial8250_unregister_port (data->uport); }/* NI 16550 RS-485 Interface */
drivers/tty/serial/8250/8250_of.c +13 -12
@@ -8,6 +8,7 @@#include <linux/align.h> #include <linux/bits.h> #include <linux/console.h> +#include <linux/err.h> #include <linux/math.h> #include <linux/module.h> #include <linux/slab.h>
@@ -28,7 +29,7 @@ struct of_serial_info {struct clk *bus_clk;struct reset_control *rst;int type; -int line; +struct uart_8250_port *uport;struct notifier_block clk_notifier; };
@@ -71,11 +72,10 @@ static int of_platform_serial_clk_notifier_cb(struct notifier_block *nb, unsigne void *data) {struct of_serial_info *info =clk_nb_to_info (nb); -struct uart_8250_port *port8250 =serial8250_get_port (info->line);struct clk_notifier_data *ndata = data;if (event ==POST_RATE_CHANGE ) { -serial8250_update_uartclk (&port8250->port, ndata->new_rate); +serial8250_update_uartclk (&info->uport->port, ndata->new_rate);return NOTIFY_OK ; }
@@ -292,12 +292,13 @@ static int of_platform_serial_probe(struct platform_device *ofdev) &port8250.overrun_backoff_time_ms) != 0) port8250.overrun_backoff_time_ms =0 ; - ret =serial8250_register_8250_port (&port8250); -if (ret <0 ) + info->uport =serial8250_register_8250_port (&port8250); +if (IS_ERR (info->uport)) { + ret =PTR_ERR (info->uport); goto err_dispose; + } info->type = port_type; - info->line = ret;platform_set_drvdata (ofdev, info);if (info->clk) {
@@ -311,7 +312,7 @@ static int of_platform_serial_probe(struct platform_device *ofdev)return 0 ; err_unregister: -serial8250_unregister_port (info->line); +serial8250_unregister_port (info->uport); err_dispose:pm_runtime_put_sync (&ofdev->dev);pm_runtime_disable (&ofdev->dev);
@@ -330,7 +331,7 @@ static void of_platform_serial_remove(struct platform_device *ofdev)if (info->clk)clk_notifier_unregister (info->clk, &info->clk_notifier); -serial8250_unregister_port (info->line); +serial8250_unregister_port (info->uport);reset_control_assert (info->rst);pm_runtime_put_sync (&ofdev->dev);
@@ -342,10 +343,10 @@ static void of_platform_serial_remove(struct platform_device *ofdev)static int of_serial_suspend (struct device *dev) {struct of_serial_info *info =dev_get_drvdata (dev); -struct uart_8250_port *port8250 =serial8250_get_port (info->line); +struct uart_8250_port *port8250 = info->uport;struct uart_port *port = &port8250->port; -serial8250_suspend_port (info->line); +serial8250_suspend_port (port8250);if (!uart_console (port) || console_suspend_enabled) {pm_runtime_put_sync (dev);
@@ -358,7 +359,7 @@ static int of_serial_suspend(struct device *dev)static int of_serial_resume (struct device *dev) {struct of_serial_info *info =dev_get_drvdata (dev); -struct uart_8250_port *port8250 =serial8250_get_port (info->line); +struct uart_8250_port *port8250 = info->uport;struct uart_port *port = &port8250->port;if (!uart_console (port) || console_suspend_enabled) {
@@ -367,7 +368,7 @@ static int of_serial_resume(struct device *dev)clk_prepare_enable (info->clk); } -serial8250_resume_port (info->line); +serial8250_resume_port (port8250);return 0 ; }
drivers/tty/serial/8250/8250_omap.c +19 -23
129 lines not on this page · raw message
drivers/tty/serial/8250/8250_parisc.c +7 -7
@@ -5,6 +5,7 @@* (c) Copyright Matthew Wilcox <[email protected]> 2001-2002 */ +#include <linux/err.h> #include <linux/errno.h> #include <linux/init.h> #include <linux/interrupt.h>
@@ -22,9 +23,8 @@static int __init serial_init_chip (struct parisc_device *dev) { -struct uart_8250_port uart; +struct uart_8250_port *uport, uart;unsigned long address; -int err;#if defined(CONFIG_64BIT ) && defined(CONFIG_IOSAPIC )if (!dev->irq && (dev->id.sversion ==0xad ))
@@ -64,13 +64,13 @@ static int __init serial_init_chip(struct parisc_device *dev) uart.port.flags =UPF_BOOT_AUTOCONF ; uart.port.dev = &dev->dev; - err =serial8250_register_8250_port (&uart); -if (err <0 ) { + uport =serial8250_register_8250_port (&uart); +if (IS_ERR (uport)) {dev_warn (&dev->dev, -"serial8250_register_8250_port returned error %d\n" , - err); +"serial8250_register_8250_port returned error %pe\n" , + uport);iounmap (uart.port.membase); -return err; +return PTR_ERR (uport); }return 0 ;
drivers/tty/serial/8250/8250_pci.c +10 -11
@@ -20,6 +20,7 @@#include <linux/8250_pci.h> #include <linux/bitops.h> #include <linux/bitfield.h> +#include <linux/err.h> #include <asm/byteorder.h> #include <asm/io.h>
@@ -116,7 +117,7 @@ struct serial_private {unsigned int nr;struct pci_serial_quirk *quirk;const struct pciserial_board *board; -int line[]; +struct uart_8250_port *uport[]; };#define PCI_DEVICE_ID_HPE_PCI_SERIAL 0x37e
@@ -4028,7 +4029,7 @@ pciserial_init_ports(struct pci_dev *dev, const struct pciserial_board *board) nr_ports = rc; } - priv =kzalloc_flex (*priv, line, nr_ports); + priv =kzalloc_flex (*priv, uport, nr_ports);if (!priv) { priv =ERR_PTR (-ENOMEM ); goto err_deinit;
@@ -4071,12 +4072,12 @@ pciserial_init_ports(struct pci_dev *dev, const struct pciserial_board *board)pci_dbg (dev,"Setup PCI port: port %lx, irq %d, type %d\n" , uart.port.iobase, uart.port.irq, uart.port.iotype); - priv->line[i] =serial8250_register_8250_port (&uart); -if (priv->line[i] <0 ) { + priv->uport[i] =serial8250_register_8250_port (&uart); +if (IS_ERR (priv->uport[i])) {pci_err (dev, -"Couldn't register serial port %lx, irq %d, type %d, error %d\n" , +"Couldn't register serial port %lx, irq %d, type %d, error %pe\n" , uart.port.iobase, uart.port.irq, - uart.port.iotype, priv->line[i]); + uart.port.iotype, priv->uport[i]);break ; } }
@@ -4098,7 +4099,7 @@ static void pciserial_detach_ports(struct serial_private *priv)int i;for (i =0 ; i < priv->nr; i++) -serial8250_unregister_port (priv->line[i]); +serial8250_unregister_port (priv->uport[i]);/* * Find the exit quirks.
@@ -4120,8 +4121,7 @@ void pciserial_suspend_ports(struct serial_private *priv)int i;for (i =0 ; i < priv->nr; i++) -if (priv->line[i] >=0 ) -serial8250_suspend_port (priv->line[i]); +serial8250_suspend_port (priv->uport[i]);/* * Ensure that every init quirk is properly torn down
@@ -4142,8 +4142,7 @@ void pciserial_resume_ports(struct serial_private *priv) priv->quirk->init (priv->dev);for (i =0 ; i < priv->nr; i++) -if (priv->line[i] >=0 ) -serial8250_resume_port (priv->line[i]); +serial8250_resume_port (priv->uport[i]); }EXPORT_SYMBOL_GPL (pciserial_resume_ports);
drivers/tty/serial/8250/8250_pci1xxxx.c +20 -21
105 lines not on this page · raw message
drivers/tty/serial/8250/8250_pericom.c +8 -7
@@ -2,6 +2,7 @@/* Driver for Pericom UART */ #include <linux/bits.h> +#include <linux/err.h> #include <linux/module.h> #include <linux/overflow.h> #include <linux/pci.h>
@@ -45,7 +46,7 @@struct pericom8250 {void __iomem *virt;unsigned int nr; -int line[]; +struct uart_8250_port *uport[]; }; static void pericom_do_set_divisor(struct uart_port *port, unsigned int baud,
@@ -102,7 +103,7 @@ static int pericom8250_probe(struct pci_dev *pdev, const struct pci_device_id *ielse nr =1 ; - pericom =devm_kzalloc (&pdev->dev,struct_size (pericom, line, nr),GFP_KERNEL ); + pericom =devm_kzalloc (&pdev->dev,struct_size (pericom, uport, nr),GFP_KERNEL );if (!pericom)return -ENOMEM ;
@@ -127,12 +128,12 @@ static int pericom8250_probe(struct pci_dev *pdev, const struct pci_device_id *idev_dbg (&pdev->dev,"Setup PCI port: port %lx, irq %d, type %d\n" , uart.port.iobase, uart.port.irq, uart.port.iotype); - pericom->line[i] =serial8250_register_8250_port (&uart); -if (pericom->line[i] <0 ) { + pericom->uport[i] =serial8250_register_8250_port (&uart); +if (IS_ERR (pericom->uport[i])) {dev_err (&pdev->dev, -"Couldn't register serial port %lx, irq %d, type %d, error %d\n" , +"Couldn't register serial port %lx, irq %d, type %d, error %pe\n" , uart.port.iobase, uart.port.irq, - uart.port.iotype, pericom->line[i]); + uart.port.iotype, pericom->uport[i]);break ; } }
@@ -148,7 +149,7 @@ static void pericom8250_remove(struct pci_dev *pdev)unsigned int i;for (i =0 ; i < pericom->nr; i++) -serial8250_unregister_port (pericom->line[i]); +serial8250_unregister_port (pericom->uport[i]); }static const struct pci_device_id pericom8250_pci_ids[] = {
drivers/tty/serial/8250/8250_platform.c +10 -13
@@ -11,6 +11,7 @@#include <linux/acpi.h> #include <linux/array_size.h> #include <linux/cleanup.h> +#include <linux/err.h> #include <linux/io.h> #include <linux/module.h> #include <linux/moduleparam.h>
@@ -109,7 +110,7 @@ static int serial8250_probe_acpi(struct platform_device *pdev) {struct device *dev = &pdev->dev;struct resource *regs; -int ret, line; +int ret; struct uart_8250_port *uart __free(kfree) = kzalloc_obj(*uart);if (!uart)
@@ -145,16 +146,12 @@ static int serial8250_probe_acpi(struct platform_device *pdev)if (ret)return ret; - line =serial8250_register_8250_port (uart); -if (line <0 ) -return line; - -return 0 ; +return PTR_ERR_OR_ZERO (serial8250_register_8250_port (uart)); }static int serial8250_probe_platform (struct platform_device *dev,struct plat_serial8250_port *p) { -int ret, i; +int i; struct uart_8250_port *uart __free(kfree) = kzalloc_obj(*uart);if (!uart)
@@ -191,12 +188,12 @@ static int serial8250_probe_platform(struct platform_device *dev, struct plat_seif (share_irqs) uart->port.irqflags |=IRQF_SHARED ; - ret =serial8250_register_8250_port (uart); -if (ret <0 ) { +struct uart_8250_port *uport =serial8250_register_8250_port (uart); +if (IS_ERR (uport)) {dev_err (&dev->dev,"unable to register port at index %d " -"(IO%lx MEM%llx IRQ%d): %d\n" , i, +"(IO%lx MEM%llx IRQ%d): %pe\n" , i, p->iobase, (unsigned long long )p->mapbase, - p->irq, ret); + p->irq, uport); } }return 0 ;
@@ -238,7 +235,7 @@ static void serial8250_remove(struct platform_device *dev)struct uart_8250_port *up =serial8250_get_port (i);if (up->port.dev == &dev->dev) -serial8250_unregister_port (i); +serial8250_unregister_port (up); } }
@@ -264,7 +261,7 @@ static int serial8250_resume(struct platform_device *dev)struct uart_8250_port *up =serial8250_get_port (i);if (up->port.type !=PORT_UNKNOWN && up->port.dev == &dev->dev) -serial8250_resume_port (i); +serial8250_resume_port (up); }return 0 ;
drivers/tty/serial/8250/8250_pnp.c +10 -11
@@ -8,6 +8,7 @@* * Ported to the Linux PnP Layer - (C) Adam Belay. */ +#include <linux/err.h> #include <linux/module.h> #include <linux/pci.h> #include <linux/pm.h>
@@ -436,7 +437,6 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) {struct uart_8250_port uart, *port;int ret, flags = dev_id->driver_data; -long line;if (flags &UNKNOWN_DEV ) { ret =serial_pnp_guess_board (dev);
@@ -477,39 +477,38 @@ serial_pnp_probe(struct pnp_dev *dev, const struct pnp_device_id *dev_id) uart.port.iobase, (unsigned long long )uart.port.mapbase, (unsigned long long)uart.port.mapsize, uart.port.irq, uart.port.iotype); - line =serial8250_register_8250_port (&uart); -if (line <0 || (flags &CIR_PORT )) + port =serial8250_register_8250_port (&uart); +if (IS_ERR (port) || (flags &CIR_PORT ))return -ENODEV ; - port =serial8250_get_port (line);if (uart_console (&port->port)) dev->capabilities |=PNP_CONSOLE ; -pnp_set_drvdata (dev, (void *)line); +pnp_set_drvdata (dev, port);return 0 ; }static void serial_pnp_remove (struct pnp_dev *dev) { -long line = (long )pnp_get_drvdata (dev); +struct uart_8250_port *uport =pnp_get_drvdata (dev); dev->capabilities &= ~PNP_CONSOLE ; -serial8250_unregister_port (line); +serial8250_unregister_port (uport); }static int serial_pnp_suspend (struct device *dev) { -long line = (long )dev_get_drvdata (dev); +struct uart_8250_port *uport =dev_get_drvdata (dev); -serial8250_suspend_port (line); +serial8250_suspend_port (uport);return 0 ; }static int serial_pnp_resume (struct device *dev) { -long line = (long )dev_get_drvdata (dev); +struct uart_8250_port *uport =dev_get_drvdata (dev); -serial8250_resume_port (line); +serial8250_resume_port (uport);return 0 ; }
drivers/tty/serial/8250/8250_pxa.c +9 -8
@@ -11,6 +11,7 @@*/ #include <linux/device.h> +#include <linux/err.h> #include <linux/init.h> #include <linux/io.h> #include <linux/module.h>
@@ -26,7 +27,7 @@#include "8250.h" struct pxa8250_data { -int line; +struct uart_8250_port *uport;struct clk *clk; };
@@ -34,7 +35,7 @@ static int __maybe_unused serial_pxa_suspend(struct device *dev) {struct pxa8250_data *data =dev_get_drvdata (dev); -serial8250_suspend_port (data->line); +serial8250_suspend_port (data->uport);return 0 ; }
@@ -43,7 +44,7 @@ static int __maybe_unused serial_pxa_resume(struct device *dev) {struct pxa8250_data *data =dev_get_drvdata (dev); -serial8250_resume_port (data->line); +serial8250_resume_port (data->uport);return 0 ; }
@@ -128,11 +129,11 @@ static int serial_pxa_probe(struct platform_device *pdev) uart.tx_loadsz =32 ; uart.dl_write = serial_pxa_dl_write; - ret =serial8250_register_8250_port (&uart); -if (ret <0 ) + data->uport =serial8250_register_8250_port (&uart); +if (IS_ERR (data->uport)) { + ret =PTR_ERR (data->uport); goto err_clk; - - data->line = ret; + }platform_set_drvdata (pdev, data);
@@ -147,7 +148,7 @@ static void serial_pxa_remove(struct platform_device *pdev) {struct pxa8250_data *data =platform_get_drvdata (pdev); -serial8250_unregister_port (data->line); +serial8250_unregister_port (data->uport);clk_unprepare (data->clk); }
drivers/tty/serial/8250/8250_tegra.c +11 -9
@@ -9,6 +9,7 @@#include <linux/clk.h> #include <linux/console.h> #include <linux/delay.h> +#include <linux/err.h> #include <linux/io.h> #include <linux/module.h> #include <linux/of.h>
@@ -20,7 +21,7 @@struct tegra_uart {struct clk *clk;struct reset_control *rst; -int line; +struct uart_8250_port *uport; };static void tegra_uart_handle_break (struct uart_port *p)
@@ -103,12 +104,13 @@ static int tegra_uart_probe(struct platform_device *pdev)if (ret) goto err_clkdisable; - ret =serial8250_register_8250_port (&port8250); -if (ret <0 ) + uart->uport =serial8250_register_8250_port (&port8250); +if (IS_ERR (uart->uport)) { + ret =PTR_ERR (uart->uport); goto err_ctrl_assert; + }platform_set_drvdata (pdev, uart); - uart->line = ret;return 0 ;
@@ -124,7 +126,7 @@ static void tegra_uart_remove(struct platform_device *pdev) {struct tegra_uart *uart =platform_get_drvdata (pdev); -serial8250_unregister_port (uart->line); +serial8250_unregister_port (uart->uport);reset_control_assert (uart->rst);clk_disable_unprepare (uart->clk); }
@@ -133,10 +135,10 @@ static void tegra_uart_remove(struct platform_device *pdev)static int tegra_uart_suspend (struct device *dev) {struct tegra_uart *uart =dev_get_drvdata (dev); -struct uart_8250_port *port8250 =serial8250_get_port (uart->line); +struct uart_8250_port *port8250 = uart->uport;struct uart_port *port = &port8250->port; -serial8250_suspend_port (uart->line); +serial8250_suspend_port (port8250);if (!uart_console (port) || console_suspend_enabled)clk_disable_unprepare (uart->clk);
@@ -147,13 +149,13 @@ static int tegra_uart_suspend(struct device *dev)static int tegra_uart_resume (struct device *dev) {struct tegra_uart *uart =dev_get_drvdata (dev); -struct uart_8250_port *port8250 =serial8250_get_port (uart->line); +struct uart_8250_port *port8250 = uart->uport;struct uart_port *port = &port8250->port;if (!uart_console (port) || console_suspend_enabled)clk_prepare_enable (uart->clk); -serial8250_resume_port (uart->line); +serial8250_resume_port (port8250);return 0 ; }
drivers/tty/serial/8250/8250_uniphier.c +10 -11
@@ -5,6 +5,7 @@#include <linux/clk.h> #include <linux/console.h> +#include <linux/err.h> #include <linux/io.h> #include <linux/module.h> #include <linux/of.h>
@@ -31,7 +32,7 @@#define UNIPHIER_UART_DLR (9 << (UNIPHIER_UART_REGSHIFT))struct uniphier8250_priv { -int line; +struct uart_8250_port *uport;struct clk *clk;spinlock_t atomic_write_lock; };
@@ -212,11 +213,9 @@ static int uniphier_uart_probe(struct platform_device *pdev) up.dl_read = uniphier_serial_dl_read; up.dl_write = uniphier_serial_dl_write; - ret =serial8250_register_8250_port (&up); -if (ret <0 ) -return dev_err_probe (dev, ret,"failed to register 8250 port\n" ); - - priv->line = ret; + priv->uport =serial8250_register_8250_port (&up); +if (IS_ERR (priv->uport)) +return dev_err_probe (dev,PTR_ERR (priv->uport),"failed to register 8250 port\n" );platform_set_drvdata (pdev, priv);
@@ -227,15 +226,15 @@ static void uniphier_uart_remove(struct platform_device *pdev) {struct uniphier8250_priv *priv =platform_get_drvdata (pdev); -serial8250_unregister_port (priv->line); +serial8250_unregister_port (priv->uport); }static int __maybe_unused uniphier_uart_suspend (struct device *dev) {struct uniphier8250_priv *priv =dev_get_drvdata (dev); -struct uart_8250_port *up =serial8250_get_port (priv->line); +struct uart_8250_port *up = priv->uport; -serial8250_suspend_port (priv->line); +serial8250_suspend_port (up);if (!uart_console (&up->port) || console_suspend_enabled)clk_disable_unprepare (priv->clk);
@@ -246,7 +245,7 @@ static int __maybe_unused uniphier_uart_suspend(struct device *dev)static int __maybe_unused uniphier_uart_resume (struct device *dev) {struct uniphier8250_priv *priv =dev_get_drvdata (dev); -struct uart_8250_port *up =serial8250_get_port (priv->line); +struct uart_8250_port *up = priv->uport;int ret;if (!uart_console (&up->port) || console_suspend_enabled) {
@@ -255,7 +254,7 @@ static int __maybe_unused uniphier_uart_resume(struct device *dev)return ret; } -serial8250_resume_port (priv->line); +serial8250_resume_port (up);return 0 ; }
drivers/tty/serial/8250/serial_cs.c +7 -8
@@ -34,6 +34,7 @@#include <linux/module.h> #include <linux/moduleparam.h> +#include <linux/err.h> #include <linux/kernel.h> #include <linux/ptrace.h> #include <linux/slab.h>
@@ -86,7 +87,7 @@ struct serial_info {int manfid;int prodid;int c950ctrl; -int line[4 ]; +struct uart_8250_port *uport[4 ];const struct serial_quirk *quirk; };
@@ -266,7 +267,7 @@ static void serial_remove(struct pcmcia_device *link)* Recheck to see if the device is still configured. */ for (i =0 ; i < info->ndev; i++) -serial8250_unregister_port (info->line[i]); +serial8250_unregister_port (info->uport[i]);if (!info->slave)pcmcia_disable_device (link);
@@ -278,7 +279,7 @@ static int serial_suspend(struct pcmcia_device *link)int i;for (i =0 ; i < info->ndev; i++) -serial8250_suspend_port (info->line[i]); +serial8250_suspend_port (info->uport[i]);return 0 ; }
@@ -289,7 +290,7 @@ static int serial_resume(struct pcmcia_device *link)int i;for (i =0 ; i < info->ndev; i++) -serial8250_resume_port (info->line[i]); +serial8250_resume_port (info->uport[i]);if (info->quirk && info->quirk->wakeup) info->quirk->wakeup (link);
@@ -347,7 +348,6 @@ static int setup_serial(struct pcmcia_device *handle, struct serial_info *info, unsigned int iobase, int irq) {struct uart_8250_port uart; -int line;memset (&uart,0 ,sizeof (uart)); uart.port.iobase = iobase;
@@ -361,14 +361,13 @@ static int setup_serial(struct pcmcia_device *handle, struct serial_info *info,if (info->quirk && info->quirk->setup) info->quirk->setup (handle, &uart); - line =serial8250_register_8250_port (&uart); -if (line <0 ) { + info->uport[info->ndev] =serial8250_register_8250_port (&uart); +if (IS_ERR (info->uport[info->ndev])) {pr_err ("serial_cs: serial8250_register_8250_port() at 0x%04lx, irq %d failed\n" , (unsigned long )iobase, irq);return -EINVAL ; } - info->line[info->ndev] = line; info->ndev++;return 0 ;
include/linux/serial_8250.h +4 -4
@@ -186,10 +186,10 @@ static inline struct uart_8250_port *up_to_u8250p(struct uart_port *up) return container_of(up, struct uart_8250_port, port); } -int serial8250_register_8250_port (const struct uart_8250_port *); -void serial8250_unregister_port (int line); -void serial8250_suspend_port (int line); -void serial8250_resume_port (int line); +struct uart_8250_port *serial8250_register_8250_port (const struct uart_8250_port *); +void serial8250_unregister_port (struct uart_8250_port *); +void serial8250_suspend_port (struct uart_8250_port *); +void serial8250_resume_port (struct uart_8250_port *);int early_serial_setup (struct uart_port *port);int early_serial8250_setup (struct earlycon_device *device,const char *options);
Signature · 1 line
2.56.0
Andy Shevchenko
reviewerQuoted 23 lines · Jiri Slaby (SUSE)
serial8250_register_8250_port()returns a line number and the other port operations (serial8250_unregister_port(),serial8250_suspend_port(),serial8250_resume_port()) accept it. Many drivers then convert the line back to the port usingserial8250_get_port()anyway.Switch the interface to struct
uart_8250_port:
*serial8250_register_8250_port()now returns the registered port, or anERR_PTR()on failure.
*serial8250_unregister_port(),serial8250_suspend_port()andserial8250_resume_port()accept the port.Convert all users accordingly. Drivers store the port pointer instead of the line number. Several drivers kept a private struct only to hold the line (airoha, dfl, em, fsl, ioc3); these are dropped and the port is stored as drvdata directly.
This also fixes two latent issues:
* For a CIR port,serial8250_register_8250_port()used to return 0. Callers stored this as the line, so a later unregister/suspend/resume operated on ttyS0. Now the CIR port itself is returned.
* 8250_acorn checked ports[i] > 0 on removal, so a port registered as line 0 was never unregistered.
Quoted 6 lines
There are no more users of
serial8250_get_port()outside of the 8250 core, so drop its EXPORT.Signed-off-by Jiri Slaby (SUSE) <[email protected]>Cc "Ilpo Järvinen" <[email protected]>
Why not having Ilpo's Cc in the below list?
Quoted 46 lines
Assisted-by LLM---
Cc: Vadim Fedorenko <[email protected]>
Cc: Richard Cochran <[email protected]>
Cc: Andrew Lunn <[email protected]>
Cc: "David S. Miller" <[email protected]>
Cc: Eric Dumazet <[email protected]>
Cc: Jakub Kicinski <[email protected]>
Cc: Paolo Abeni <[email protected]>
Cc: Joel Stanley <[email protected]>
Cc: Andrew Jeffery <[email protected]>
Cc: Ryan Chen <[email protected]>
Cc: Billy Tsai <[email protected]>
Cc: Florian Fainelli <[email protected]>
Cc: Broadcom internal kernel review list <[email protected]>
Cc: Ray Jui <[email protected]>
Cc: Scott Branden <[email protected]>
Cc: Al Cooper <[email protected]>
Cc: Andy Shevchenko <[email protected]>
Cc: Paul Cercueil <[email protected]>
Cc: Matthias Brugger <[email protected]>
Cc: AngeloGioacchino Del Regno <[email protected]>
Cc: Chaitanya Vadrevu <[email protected]>
Cc: "James E.J. Bottomley" <[email protected]>
Cc: Helge Deller <[email protected]>
Cc: Kumaravel Thiagarajan <[email protected]>
Cc: Thierry Reding <[email protected]>
Cc: Jonathan Hunter <[email protected]>
Cc: Kunihiko Hayashi <[email protected]>
Cc: Masami Hiramatsu <[email protected]>
Cc: Kees Cook <[email protected]>
Cc: "Gustavo A. R. Silva" <[email protected]>
Cc: "Uwe Kleine-König (The Capable Hub)" <[email protected]>
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected]
Cc: [email protected][v2] include
err.h(Ilpo)
---
...
drivers/ptp/ptp_ocp.c ptp_ocp_summary_show(struct seq_file *s, void *data) · line 5291
Quoted 2 lines
drivers/ptp/ptp_ocp.c +0
-0seq_printf (s,"%7s: /dev/ptp%d\n" ,"PTP" ,ptp_clock_index (bp->ptp));for (i =0 ; i < __PORT_COUNT; i++) {
What about
struct uart_8250_port *uport = bp->port[i].uport;
here and use it accordingly in the below code?
Quoted 6 lines
drivers/ptp/ptp_ocp.c +2
-2-if (bp->port[i].line !=-1 ) +if (bp->port[i].uport)seq_printf (s,"%7s: /dev/ttyS%d\n" ,ptp_ocp_tty_port_name (i), - bp->port[i].line); + bp->port[i].uport->port.line); }
...
drivers/ptp/ptp_ocp.c ptp_ocp_detach(struct ptp_ocp *bp) · line 5784
Quoted 5 lines
drivers/ptp/ptp_ocp.c +2
-2for (i =0 ; i < __PORT_COUNT; i++) -if (bp->port[i].line !=-1 ) -serial8250_unregister_port (bp->port[i].line); +if (bp->port[i].uport) +serial8250_unregister_port (bp->port[i].uport);
Since it takes a pointer now, make it error pointer and NULL-aware
if (IS_ERR_OR_NULL(...)) return;
there. With that being done, all this redundant NULL-checks will gone.
...
drivers/tty/serial/8250/8250_acorn.c static void serial_card_remove(struct expansion_card *ec) · line 90
Quoted 8 lines
static void
serial_card_remove(struct expansion_card *ec)drivers/tty/serial/8250/8250_acorn.c +1
-1ecard_set_drvdata (ec,NULL );for (i =0 ; i < info->num_ports; i++) -if (info->ports[i] >0 ) +if (!IS_ERR_OR_NULL (info->ports[i]))serial8250_unregister_port (info->ports[i]);
See my point?
...
drivers/tty/serial/8250/8250_aspeed_vuart.c static int aspeed_vuart_probe(struct platform_device *pdev) · line 491
Quoted 12 lines
static int
aspeed_vuart_probe(struct platform_device *pdev)drivers/tty/serial/8250/8250_aspeed_vuart.c +4
-2if (of_property_read_bool (np,"auto-flow-control" )) port.capabilities |=UART_CAP_AFE ; - rc =serial8250_register_8250_port (&port); -if (rc <0 ) +struct uart_8250_port *uport =serial8250_register_8250_port (&port); +if (IS_ERR (uport)) { + rc =PTR_ERR (uport); goto err_sysfs_remove; + }
You can get rid of these {} by using PTR_ERR_OR_ZERO(). Also do not define variables in the middle of the code (it's only allowed for auto cleanup variables and for-loop iterators).
...
I stopped here, I believe there are many similar cases which may be amended in the same way as pointed out above.
Signature · 2 lines
With Best Regards, Andy Shevchenko
Jiri Slaby
maintainerQuoted 24 lines · Andy Shevchenko
Quoted 23 lines · Jiri Slaby (SUSE)
serial8250_register_8250_port()returns a line number and the other port operations (serial8250_unregister_port(),serial8250_suspend_port(),serial8250_resume_port()) accept it. Many drivers then convert the line back to the port usingserial8250_get_port()anyway.Switch the interface to struct
uart_8250_port:
*serial8250_register_8250_port()now returns the registered port, or anERR_PTR()on failure.
*serial8250_unregister_port(),serial8250_suspend_port()andserial8250_resume_port()accept the port.Convert all users accordingly. Drivers store the port pointer instead of the line number. Several drivers kept a private struct only to hold the line (airoha, dfl, em, fsl, ioc3); these are dropped and the port is stored as drvdata directly.
This also fixes two latent issues:
* For a CIR port,serial8250_register_8250_port()used to return 0. Callers stored this as the line, so a later unregister/suspend/resume operated on ttyS0. Now the CIR port itself is returned.
* 8250_acorn checked ports[i] > 0 on removal, so a port registered as line 0 was never unregistered.
Quoted 8 lines
Quoted 6 lines
There are no more users of
serial8250_get_port()outside of the 8250 core, so drop its EXPORT.Signed-off-by Jiri Slaby (SUSE) <[email protected]>Cc "Ilpo Järvinen" <[email protected]>Why not having Ilpo's Cc in the below list?
He commented on the v1. Now you will be listed here as well.
Quoted 16 lines
drivers/tty/serial/8250/8250_aspeed_vuart.c static int aspeed_vuart_probe(struct platform_device *pdev) · line 491
Quoted 12 lines
static int
aspeed_vuart_probe(struct platform_device *pdev)if (of_property_read_bool(np, "auto-flow-control")) port.capabilities |= UART_CAP_AFE;drivers/tty/serial/8250/8250_aspeed_vuart.c +4
-2- rc =serial8250_register_8250_port (&port); -if (rc <0 ) +struct uart_8250_port *uport =serial8250_register_8250_port (&port); +if (IS_ERR (uport)) { + rc =PTR_ERR (uport); goto err_sysfs_remove; + }You can get rid of these {} by using
PTR_ERR_OR_ZERO().
Quoted 3 lines
Also do not define
variables in the middle of the code (it's only allowed for auto cleanup variables and for-loop iterators).
Why, actually? First, it is used in the kernel quite a few times already [1]. Second, while it is sort of c++ism (and I like to use modern c++), it makes the life of the variable a lot more obvious.
[1] eg. see output of: rg -U -C 5 '}\n+\s+struct .*\*.*=' drivers/
thanks,
Signature · 2 lines
js suse labs
Andy Shevchenko
reviewerQuoted 2 lines · Jiri Slaby
Quoted 1 line · Andy Shevchenko
On Tue, Oct 13, 2026 at 08:48:51AM +0200, Jiri Slaby (SUSE) wrote:
...
Quoted 12 lines
Quoted 11 lines
drivers/tty/serial/8250/8250_aspeed_vuart.c static int aspeed_vuart_probe(struct platform_device *pdev) · line 491
Quoted 7 lines
drivers/tty/serial/8250/8250_aspeed_vuart.c +4
-2- rc =serial8250_register_8250_port (&port); -if (rc <0 ) +struct uart_8250_port *uport =serial8250_register_8250_port (&port); +if (IS_ERR (uport)) { + rc =PTR_ERR (uport); goto err_sysfs_remove; + }Also do not define
variables in the middle of the code (it's only allowed for auto cleanup variables and for-loop iterators).
Quoted 1 line
Why, actually?
Because it's the style. Linus also told it many times (I am tired to repeat this, I leave it to you to find his words on lore.kernel.org).
Quoted 5 lines
First, it is used in the kernel quite a few times already
[1]. Second, while it is sort of c++ism (and I like to use modern c++), it makes the life of the variable a lot more obvious.[1] eg. see output of: rg -U -C 5 '}\n+\s+struct .*\*.*='
drivers/
(you made me to install something I haven't heard about, it's better to use
git grep though)
Note excluded __free() if I get regexp correctly
$ rg -U -l '}\n+\s+struct .*\*[^)]*=' drivers/ | less drivers/ufs/host/ufs-qcom.c drivers/dma/xilinx/xilinx_dma.c drivers/dma/idxd/init.c drivers/media/platform/raspberrypi/rp1-cfe/csi2.c drivers/gpib/agilent_82357a/agilent_82357a.c drivers/gpib/ni_usb/ni_usb_gpib.c drivers/tty/serial/samsung_tty.c drivers/s390/scsi/zfcp_scsi.c drivers/gpio/gpiolib-shared.c drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_irq.c drivers/gpu/drm/amd/display/amdgpu_dm/amdgpu_dm_dmub.c drivers/gpu/drm/msm/disp/dpu1/dpu_kms.c drivers/gpu/drm/msm/msm_gem_vma.c drivers/gpu/drm/amd/display/dc/clk_mgr/clk_mgr.c drivers/gpu/drm/amd/amdgpu/amdgpu_psp.c
So, less than dozen of drivers doing wrong is not an argument, try something better. But thanks, I will check and address this in some of the above.
Signature · 2 lines
With Best Regards, Andy Shevchenko
Jiri Slaby
maintainerQuoted 14 lines · Andy Shevchenko
Quoted 2 lines · Jiri Slaby
Quoted 1 line · Andy Shevchenko
On Tue, Oct 13, 2026 at 08:48:51AM +0200, Jiri Slaby (SUSE) wrote:
...
Quoted 8 lines
Quoted 7 lines
Quoted 7 lines
drivers/tty/serial/8250/8250_aspeed_vuart.c +4
-2- rc =serial8250_register_8250_port (&port); -if (rc <0 ) +struct uart_8250_port *uport =serial8250_register_8250_port (&port); +if (IS_ERR (uport)) { + rc =PTR_ERR (uport); goto err_sysfs_remove; + }
Quoted 7 lines
Quoted 5 lines
Quoted 3 lines
Also do not define
variables in the middle of the code (it's only allowed for auto cleanup variables and for-loop iterators).Why, actually?
Because it's the style.
There is no hard style though. It varies across subsystems.
Quoted 1 line
Linus also told it many times
Which is neither an argument. Linus is wrong at times ("Link:" use as an example).
All in all, I do not insist on this at all. It's easier to read and follow the code for me. Not necessarily the case for others...
Quoted 8 lines
Quoted 5 lines
First, it is used in the kernel quite a few times already
[1]. Second, while it is sort of c++ism (and I like to use modern c++), it makes the life of the variable a lot more obvious.[1] eg. see output of: rg -U -C 5 '}\n+\s+struct .*\*.*='
drivers/(you made me to install something I haven't heard about, it's better to use
git grepthough)
rg is order of magnitude faster (searches in parallel). More importantly in this case, supports multiline matches. (And respects .git ignores.)
Quoted 4 lines
Note excluded
__free()if I get regexp correctly$ rg -U -l '}\n+\s+struct .*\*[^)]*=' drivers/ | less drivers/ufs/host/ufs-qcom.c
...
Quoted 4 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.cSo, less than dozen of drivers doing wrong is not an argument, try something better. But thanks, I will check and address this in some of the above.
Well, it's only an example of a declaration after a previous opening brace "{" -- this one turned out to be easy to search for. There is a lot of more, of course. kernel/ included.
thanks,
Signature · 2 lines
js suse labs
Andy Shevchenko
reviewerQuoted 4 lines · Jiri Slaby
Quoted 3 lines · Andy Shevchenko
Quoted 2 lines · Jiri Slaby
Quoted 1 line · Andy Shevchenko
On Tue, Oct 13, 2026 at 08:48:51AM +0200, Jiri Slaby (SUSE) wrote:
...
Quoted 12 lines
Quoted 12 lines
Quoted 12 lines
Quoted 11 lines
drivers/tty/serial/8250/8250_aspeed_vuart.c static int aspeed_vuart_probe(struct platform_device *pdev) · line 491
Quoted 7 lines
drivers/tty/serial/8250/8250_aspeed_vuart.c +4
-2- rc =serial8250_register_8250_port (&port); -if (rc <0 ) +struct uart_8250_port *uport =serial8250_register_8250_port (&port); +if (IS_ERR (uport)) { + rc =PTR_ERR (uport); goto err_sysfs_remove; + }Also do not define
variables in the middle of the code (it's only allowed for auto cleanup variables and for-loop iterators).
Quoted 5 lines
Quoted 3 lines
Quoted 1 line
Why, actually?
Because it's the style.
There is no hard style though. It varies across subsystems.
The keyword is *slightly*. I do not see much of deviation in style in the subsystem maintainer-XXX.rst. Do you?
Quoted 4 lines
Quoted 1 line
Linus also told it many times
Which is neither an argument. Linus is wrong at times ("Link:" use as an example).
Link is different, it wasn't about the code. So, for coding style we have stricter rules.
Quoted 7 lines
All in all, I do not insist on this at all. It's easier to read and follow the code for me. Not necessarily the case for others...
Quoted 4 lines
Quoted 4 lines
First, it is used in the kernel quite a few times already
[1]. Second, while it is sort of c++ism (and I like to use modern c++), it makes the life of the variable a lot more obvious.
Quoted 7 lines
Quoted 4 lines
Quoted 1 line
[1] eg. see output of: rg -U -C 5 '}\n+\s+struct .*\*.*='
drivers/(you made me to install something I haven't heard about, it's better to use
git grepthough)rg is order of magnitude faster (searches in parallel). More importantly in this case, supports multiline matches. (And respects .git ignores.)
Isn't git grep fast enough due to looking into index and not into the files? rg may not look at the Git index, right? So I may not to use an arbitrary hash without checking it out first.
Quoted 5 lines
Quoted 4 lines
Note excluded
__free()if I get regexp correctly$ rg -U -l '}\n+\s+struct .*\*[^)]*=' drivers/ | less drivers/ufs/host/ufs-qcom.c...
Quoted 8 lines
Quoted 4 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.cSo, less than dozen of drivers doing wrong is not an argument, try something better. But thanks, I will check and address this in some of the above.
Well, it's only an example of a declaration after a previous opening brace "{" -- this one turned out to be easy to search for. There is a lot of more, of course.
kernel/included.
Please, provide a better search line, I will look at that. For now it's just a hypothetical assumption, I am afraid.
Signature · 2 lines
With Best Regards, Andy Shevchenko
Jiri Slaby
maintainerQuoted 9 lines · Andy Shevchenko
Quoted 9 lines
Quoted 8 lines
Quoted 5 lines
First, it is used in the kernel quite a few times already
[1]. Second, while it is sort of c++ism (and I like to use modern c++), it makes the life of the variable a lot more obvious.[1] eg. see output of: rg -U -C 5 '}\n+\s+struct .*\*.*='
drivers/(you made me to install something I haven't heard about, it's better to use
git grepthough)
Quoted 6 lines
Quoted 2 lines
rg is order of magnitude faster (searches in parallel). More importantly in this case, supports multiline matches. (And respects .git ignores.)
Isn't
git grepfast enough due to looking into index and not into the files?rgmay not look at the Git index, right? So I may not to use an arbitrary hash without checking it out first.
Of course rg is not git grep.
Quoted 10 lines
Quoted 10 lines
Quoted 4 lines
Note excluded
__free()if I get regexp correctly$ rg -U -l '}\n+\s+struct .*\*[^)]*=' drivers/ | less drivers/ufs/host/ufs-qcom.c...
Quoted 4 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.cSo, less than dozen of drivers doing wrong is not an argument, try something better. But thanks, I will check and address this in some of the above.
Quoted 6 lines
Quoted 3 lines
Well, it's only an example of a declaration after a previous opening brace "{" -- this one turned out to be easy to search for. There is a lot of more, of course.
kernel/included.Please, provide a better search line, I will look at that. For now it's just a hypothetical assumption, I am afraid.
I am not much into writing a semi-parser at this point :D. This'd be a task eg. for clang's ASTMatcher.
thanks,
Signature · 2 lines
js suse labs
Hi Jiri,
Quoted 36 lines
Date: 2026-10-13 12:15:35+0200
From: Jiri Slaby <[email protected]>Quoted 9 lines · Andy Shevchenko
Quoted 9 lines
Quoted 8 lines
Quoted 5 lines
First, it is used in the kernel quite a few times already
[1]. Second, while it is sort of c++ism (and I like to use modern c++), it makes the life of the variable a lot more obvious.[1] eg. see output of: rg -U -C 5 '}\n+\s+struct .*\*.*='
drivers/(you made me to install something I haven't heard about, it's better to use
git grepthough)Quoted 6 lines
Quoted 2 lines
rg is order of magnitude faster (searches in parallel). More importantly in this case, supports multiline matches. (And respects .git ignores.)
Isn't
git grepfast enough due to looking into index and not into the files?rgmay not look at the Git index, right? So I may not to use an arbitrary hash without checking it out first.Of course rg is not git grep.
Quoted 14 lines
Quoted 13 lines
Quoted 4 lines
Note excluded
__free()if I get regexp correctly$ rg -U -l '}\n+\s+struct .*\*[^)]*=' drivers/ | less drivers/ufs/host/ufs-qcom.c...
Quoted 4 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.cSo, less than dozen of drivers doing wrong is not an argument, try something better. But thanks, I will check and address this in some of the above.
Well, it's only an example of a declaration after a previous opening brace "{" -- this one turned out to be easy to search for. There is a lot of more, of course.
kernel/included.
Quoted 5 lines
Quoted 2 lines
Please, provide a better search line, I will look at that. For now it's just a hypothetical assumption, I am afraid.
I am not much into writing a semi-parser at this point :D. This'd be a task eg. for clang's ASTMatcher.
You may check grepc(1) --provided in man-pages.git--, which does have some code for searching different kinds of code. You may need to tweak some regex produced by the backend grepc_c(1), but it should be possible.
Cheers,
Alex
Quoted 6 lines
thanks,
Signature · 2 lines
js suse labs
Signature · 1 line
<https://www.alejandro-colomar.es>
Hi Jiri,
Quoted 40 lines
Date: 2026-10-13 11:39:00+0200
From: Jiri Slaby <[email protected]>Quoted 14 lines · Andy Shevchenko
Quoted 2 lines · Jiri Slaby
Quoted 1 line · Andy Shevchenko
On Tue, Oct 13, 2026 at 08:48:51AM +0200, Jiri Slaby (SUSE) wrote:
...
Quoted 8 lines
Quoted 7 lines
Quoted 7 lines
drivers/tty/serial/8250/8250_aspeed_vuart.c +4
-2- rc =serial8250_register_8250_port (&port); -if (rc <0 ) +struct uart_8250_port *uport =serial8250_register_8250_port (&port); +if (IS_ERR (uport)) { + rc =PTR_ERR (uport); goto err_sysfs_remove; + }Quoted 7 lines
Quoted 5 lines
Quoted 3 lines
Also do not define
variables in the middle of the code (it's only allowed for auto cleanup variables and for-loop iterators).Why, actually?
Because it's the style.
There is no hard style though. It varies across subsystems.
Quoted 1 line
Linus also told it many times
Which is neither an argument. Linus is wrong at times ("Link:" use as an example).
All in all, I do not insist on this at all. It's easier to read and follow the code for me. Not necessarily the case for others...
Quoted 4 lines
Quoted 4 lines
First, it is used in the kernel quite a few times already
[1]. Second, while it is sort of c++ism (and I like to use modern c++), it makes the life of the variable a lot more obvious.
Quoted 7 lines
Quoted 4 lines
Quoted 1 line
[1] eg. see output of: rg -U -C 5 '}\n+\s+struct .*\*.*='
drivers/(you made me to install something I haven't heard about, it's better to use
git grepthough)rg is order of magnitude faster (searches in parallel). More importantly in this case, supports multiline matches. (And respects .git ignores.)
Is that really true?
alx@debian:~/src/linux/linux/master$ time \ find * -type f \ | grep '\.[ch]' \ | sort \ | xargs grep -n ARRAY_SIZE /dev/null \ | wc -l; 58852
real 0m1.022s user 0m0.726s sys 0m0.358s alx@debian:~/src/linux/linux/master$ time \ git ls-files \ | grep '\.[ch]' \ | xargs grep -n ARRAY_SIZE /dev/null \ | wc -l; 58854 real 0m0.923s user 0m0.650s sys 0m0.333s
There seems to be a difference of two occurences, which is due to symlinks:
alx@debian:~/src/linux/linux/master$ diff -u \
<(find * -type f \
| grep '\.[ch]' \
| sort \
| xargs grep -n ARRAY_SIZE /dev/null) \
<(git ls-files \
| grep '\.[ch]' \
| xargs grep -n ARRAY_SIZE /dev/null);
--- /dev/fd/63 2026-10-13 12:40:11.675302047 +0200
+++ /dev/fd/62 2026-10-13 12:40:11.675302047 +0200
@@ -57769,6 +57769,7 @@
tools/testing/selftests/bpf/benchs/bench_sockmap.c:128: for (i = 0; i < ARRAY_SIZE(ctx.fds); i++) {
tools/testing/selftests/bpf/bpf_util.h:69:#ifndef ARRAY_SIZE
tools/testing/selftests/bpf/bpf_util.h:70:# define ARRAY_SIZE(x) (sizeof(x) / sizeof((x)[0]))
+tools/testing/selftests/bpf/disasm.c:23: BUILD_BUG_ON(ARRAY_SIZE(func_id_str) != __BPF_FUNC_MAX_ID);
tools/testing/selftests/bpf/map_tests/lpm_trie_map_basic_ops.c:1006: const char *sorted_keys[ARRAY_SIZE(keys)];
tools/testing/selftests/bpf/map_tests/lpm_trie_map_basic_ops.c:1012: fd = lpm_trie_create(sizeof(key), sizeof(value), ARRAY_SIZE(keys));
tools/testing/selftests/bpf/map_tests/lpm_trie_map_basic_ops.c:1014: for (i = 0; i < ARRAY_SIZE(keys); i++) {
@@ -58786,6 +58787,7 @@
tools/testing/selftests/vfio/lib/drivers/dsa/dsa.c:215: dsa->max_copies_per_batch = min(dsa->max_copies_per_batch, ARRAY_SIZE(dsa->copy));
tools/testing/selftests/vfio/lib/drivers/dsa/dsa.c:340: for (i = 0; i < ARRAY_SIZE(dsa->copy); i++) {
tools/testing/selftests/vfio/lib/drivers/dsa/dsa.c:349: for (i = 0; i < ARRAY_SIZE(dsa->batch) && count; i++) {
+tools/testing/selftests/vfio/lib/drivers/igb/e1000_82575.h:240:#define E1000_VLVF_ARRAY_SIZE 32
tools/testing/selftests/vfio/lib/drivers/nv_falcon/hw.h:249:#define VERIFIED_GPU_MAP_SIZE ARRAY_SIZE(verified_gpu_map)
tools/testing/selftests/vfio/lib/iommu.c:59: for (i = 0; i < ARRAY_SIZE(iommu_modes); i++) {
tools/testing/selftests/vfio/lib/sysfs.c:48: VFIO_ASSERT_GT(read(fd, buf, ARRAY_SIZE(buf)), 0);And here goes rg(1):
alx@debian:~/src/linux/linux/master$ time rg -n ARRAY_SIZE | wc -l 58957
real 0m0.512s user 0m0.490s sys 0m0.974s
It's around 50% faster, which I wouldn't call orders of magnitude. rg(1) inherits the bogus design of find(1) in trying to filter the file names with multiple subtly different options. grep(1) can do that much better, and by using a pipe, you have a dedicated process (often in a dedicated CPU) for that task, which is likely more efficient.
And here's plain grep(1):
alx@debian:~/src/linux/linux/master$ time grep -r -n ARRAY_SIZE \ | wc -l 58957
real 0m1.140s user 0m0.663s sys 0m0.489s
Multiline matches are also supported by pcre2grep(1), BTW, which uses PCRE2, which are way more useful than that.
pcre2grep(1) is itself a bit slower than grep(1) --especially if you try very complex regexes--:
alx@debian:~/src/linux/linux/master$ time \ find * -type f \ | grep '\.[ch]' \ | sort \ | xargs pcre2grep -n ARRAY_SIZE /dev/null \ | wc -l; 58852
real 0m1.857s user 0m1.408s sys 0m0.516s
But if you pre-filter the files with a simpler regex, then it comes back to usual time:
alx@debian:~/src/linux/linux/master$ time \ find * -type f \ | grep '\.[ch]' \ | sort \ | xargs grep -l ARRAY_SIZE \ | xargs pcre2grep -n ARRAY_SIZE /dev/null \ | wc -l; 58852
real 0m0.919s user 0m0.830s sys 0m0.462s
Have a lovely day!
Alex
Quoted 19 lines
Quoted 4 lines
Note excluded
__free()if I get regexp correctly$ rg -U -l '}\n+\s+struct .*\*[^)]*=' drivers/ | less drivers/ufs/host/ufs-qcom.c...
Quoted 4 lines
drivers/gpu/drm/amd/amdgpu/amdgpu_psp.cSo, less than dozen of drivers doing wrong is not an argument, try something better. But thanks, I will check and address this in some of the above.
Well, it's only an example of a declaration after a previous opening brace "{" -- this one turned out to be easy to search for. There is a lot of more, of course.
kernel/included.thanks,
Signature · 2 lines
js suse labs
Signature · 1 line
<https://www.alejandro-colomar.es>
Jiri Slaby
maintainerQuoted 8 lines · Alejandro Colomar
alx@debian:~/src/linux/linux/master$ time rg -n ARRAY_SIZE | wc -l 58957real 0m0.512s user 0m0.490s sys 0m0.974sIt's around 50% faster, which I wouldn't call orders of magnitude.
If you pipe rg's output somewhere, it no longer works in parallel.
Are we really about to discuss this?
Signature · 2 lines
js suse labs
Andy Shevchenko
reviewerQuoted 11 lines · Jiri Slaby
Quoted 8 lines · Alejandro Colomar
alx@debian:~/src/linux/linux/master$ time rg -n ARRAY_SIZE | wc -l 58957real 0m0.512s user 0m0.490s sys 0m0.974sIt's around 50% faster, which I wouldn't call orders of magnitude.
If you pipe rg's output somewhere, it no longer works in parallel.
Ha-ha! It means it's useless, as it outputs (as of your example) directly to the console without any pager, so one can't simply look backwards (it's limited by the terminal emulator scroll-back buffer).
Quoted 1 line
Are we really about to discuss this?
Up to you, I think git grep wins anyway by several reasons (at lest for me).
Signature · 2 lines
With Best Regards, Andy Shevchenko
[email protected]
AI reviewThank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider: - [High] tty: serial: 8250_hp300: NULL pointer dereference on hpdca device removal --
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] tty: serial: 8250_hp300: NULL pointer dereference on hpdca device removal --
commit f913317bfee3afed5e144530ca60f25858464754
Author: Jiri Slaby (SUSE) <[email protected]> Date: Tue Oct 13 06:48:51 2026 +0000
serial: 8250: make port operations work on struct uart_8250_port
This commit switches the interface of port operations to use struct uart_8250_port instead of the line number, returning the registered port or an ERR_PTR() on failure. It updates all drivers to store the port pointer instead of the line number.
Quoted 4 lines
drivers/tty/serial/8250/8250_hp300.c +0
-0
[ ... ]
Quoted 12 lines
drivers/tty/serial/8250/8250_hp300.c +2
-3@@ -177,9 +177,8 @@ static int hpdca_init_one(struct dio_dev *d, uart.port.membase = (char *)(uart.port.mapbase +DIO_VIRADDRBASE ); uart.port.regshift =1 ; uart.port.dev = &d->dev; - line =serial8250_register_8250_port (&uart); - -if (line <0 ) { + uport =serial8250_register_8250_port (&uart); +if (IS_ERR (uport)) {dev_notice (&d->dev,"8250_hp300: register_serial() DCA scode %d irq %d failed\n" , d->scode, uart.port.irq);
drivers/tty/serial/8250/8250_hp300.c static int hpdca_init_one(struct dio_dev *d, · line 193
Quoted 10 lines
drivers/tty/serial/8250/8250_hp300.c +1
-1return 0 ; }/* Enable board-interrupts */ out_8 (d->resource.start +DIO_VIRADDRBASE +DCA_IC ,DCA_IC_IE ); -dio_set_drvdata (d, (void *)line); +dio_set_drvdata (d, uport);/* Reset the DCA */ out_8 (d->resource.start +DIO_VIRADDRBASE +DCA_ID ,0xff );
[Severity: High]
If serial8250_register_8250_port() fails here and returns an ERR_PTR, this function logs a warning and returns 0 (success). In this failure path, dio_set_drvdata() is skipped, leaving the device's driver data as NULL.
Because the driver returns 0, the device is considered successfully bound. When the device is later removed, hpdca_remove_one() is called:
Quoted 6 lines
drivers/tty/serial/8250/8250_hp300.c +1
-1@@ -287,14 +283,13 @@ static int __init hp300_8250_init(void)#ifdef CONFIG_HPDCA static void hpdca_remove_one (struct dio_dev *d) { -int line; +struct uart_8250_port *uport =dio_get_drvdata (d);
drivers/tty/serial/8250/8250_hp300.c static int __init hp300_8250_init(void) · line 294
Quoted 10 lines
drivers/tty/serial/8250/8250_hp300.c +1
-2- line = (int )dio_get_drvdata (d);if (d->resource.start) {/* Disable board-interrupts */ out_8 (d->resource.start +DIO_VIRADDRBASE +DCA_IC ,0 ); } - serial8250_unregister_port(line); + serial8250_unregister_port(uport); }#endif
Will this lead to a NULL pointer dereference?
If the registration failed during probe, uport will be NULL here. Since serial8250_unregister_port() unconditionally dereferences the pointer (e.g., checking uart->em485), passing NULL will cause a kernel panic.
Should the failure path in hpdca_init_one() return an error code instead of 0, or should hpdca_remove_one() check for a valid uport before unregistering?
Note: This replaces a prior bug where passing an uninitialized 0 line number caused the driver to erroneously unregister ttyS0 instead of crashing.
Signature · 1 line
Sashiko AI review · https://sashiko.dev/#/patchset/[email protected]?part=6
Jiri Slaby
maintainerQuoted 20 lines · On 14. 10. 26, 8:49, [email protected] wrote:
Thank you for your contribution! Sashiko AI review found 1 potential issue(s) to consider:
- [High] tty: serial: 8250_hp300: NULL pointer dereference on hpdca device removal --commit
f913317bfee3afed5e144530ca60f25858464754Author: Jiri Slaby (SUSE) <[email protected]> Date: Tue Oct 13 06:48:51 2026 +0000serial: 8250: make port operations work on struct
uart_8250_portThis commit switches the interface of port operations to use struct
uart_8250_portinstead of the line number, returning the registered port or anERR_PTR()on failure. It updates all drivers to store the port pointer instead of the line number.Quoted 4 lines
drivers/tty/serial/8250/8250_hp300.c +0
-0[ ... ]
Quoted 13 lines
Quoted 12 lines
drivers/tty/serial/8250/8250_hp300.c +2
-3@@ -177,9 +177,8 @@ static int hpdca_init_one(struct dio_dev *d, uart.port.membase = (char *)(uart.port.mapbase +DIO_VIRADDRBASE ); uart.port.regshift =1 ; uart.port.dev = &d->dev; - line =serial8250_register_8250_port (&uart); - -if (line <0 ) { + uport =serial8250_register_8250_port (&uart); +if (IS_ERR (uport)) {dev_notice (&d->dev,"8250_hp300: register_serial() DCA scode %d irq %d failed\n" , d->scode, uart.port.irq);Quoted 1 line
return 0;
Am I hallucinating or you do? I have:
return -ENOMEM;
on that line.
Quoted 48 lines
drivers/tty/serial/8250/8250_hp300.c static int hpdca_init_one(struct dio_dev *d, · line 193
Quoted 9 lines
} /* Enable board-interrupts */ out_8(d->resource.start + DIO_VIRADDRBASE + DCA_IC, DCA_IC_IE);drivers/tty/serial/8250/8250_hp300.c +1
-1-dio_set_drvdata (d, (void *)line); +dio_set_drvdata (d, uport);/* Reset the DCA */ out_8 (d->resource.start +DIO_VIRADDRBASE +DCA_ID ,0xff );[Severity: High]
Ifserial8250_register_8250_port()fails here and returns anERR_PTR, this function logs a warning and returns 0 (success). In this failure path,dio_set_drvdata()is skipped, leaving the device's driver data as NULL.Because the driver returns 0, the device is considered successfully bound. When the device is later removed,
hpdca_remove_one()is called:Quoted 6 lines
drivers/tty/serial/8250/8250_hp300.c +1
-1@@ -287,14 +283,13 @@ static int __init hp300_8250_init(void)#ifdef CONFIG_HPDCA static void hpdca_remove_one (struct dio_dev *d) { -int line; +struct uart_8250_port *uport =dio_get_drvdata (d);drivers/tty/serial/8250/8250_hp300.c static int __init hp300_8250_init(void) · line 294
Quoted 10 lines
drivers/tty/serial/8250/8250_hp300.c +1
-2- line = (int )dio_get_drvdata (d);if (d->resource.start) {/* Disable board-interrupts */ out_8 (d->resource.start +DIO_VIRADDRBASE +DCA_IC ,0 ); } - serial8250_unregister_port(line); + serial8250_unregister_port(uport); }#endif Will this lead to a NULL pointer dereference?
If the registration failed during probe, uport will be NULL here. Since
serial8250_unregister_port()unconditionally dereferences the pointer (e.g., checkinguart->em485), passing NULL will cause a kernel panic.Should the failure path in
hpdca_init_one()return an error code instead of 0, or shouldhpdca_remove_one()check for a valid uport before unregistering?Note: This replaces a prior bug where passing an uninitialized 0 line number caused the driver to erroneously unregister ttyS0 instead of crashing.
Signature · 2 lines
js suse labs