[PATCH 3/3] serial: 8250: make port operations work on struct uart_8250_port

Ilpo Järvinen ilpo.jarvinen at linux.intel.com
Fri Oct 9 04:25:36 PDT 2026


On Fri, 9 Oct 2026, Jiri Slaby (SUSE) wrote:

> 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.
> 
> Signed-off-by: Jiri Slaby (SUSE) <jirislaby at kernel.org>
> Assisted-by: LLM
> ---
> Cc: Vadim Fedorenko <vadim.fedorenko at linux.dev>
> Cc: Richard Cochran <richardcochran at gmail.com>
> Cc: Andrew Lunn <andrew+netdev at lunn.ch>
> Cc: "David S. Miller" <davem at davemloft.net>
> Cc: Eric Dumazet <edumazet at kernel.org>
> Cc: Jakub Kicinski <kuba at kernel.org>
> Cc: Paolo Abeni <pabeni at redhat.com>
> Cc: Joel Stanley <joel at jms.id.au>
> Cc: Andrew Jeffery <andrew at codeconstruct.com.au>
> Cc: Ryan Chen <ryan_chen at aspeedtech.com>
> Cc: Billy Tsai <billy_tsai at aspeedtech.com>
> Cc: Florian Fainelli <florian.fainelli at broadcom.com>
> Cc: Broadcom internal kernel review list <bcm-kernel-feedback-list at broadcom.com>
> Cc: Ray Jui <rjui at broadcom.com>
> Cc: Scott Branden <sbranden at broadcom.com>
> Cc: Al Cooper <alcooperx at gmail.com>
> Cc: "Ilpo Järvinen" <ilpo.jarvinen at linux.intel.com>
> Cc: Andy Shevchenko <andriy.shevchenko at linux.intel.com>
> Cc: Paul Cercueil <paul at crapouillou.net>
> Cc: Matthias Brugger <matthias.bgg at gmail.com>
> Cc: AngeloGioacchino Del Regno <angelogioacchino.delregno at collabora.com>
> Cc: Chaitanya Vadrevu <chaitanya.vadrevu at emerson.com>
> Cc: "James E.J. Bottomley" <James.Bottomley at HansenPartnership.com>
> Cc: Helge Deller <deller at gmx.de>
> Cc: Kumaravel Thiagarajan <kumaravel.thiagarajan at microchip.com>
> Cc: Thierry Reding <thierry.reding at kernel.org>
> Cc: Jonathan Hunter <jonathanh at nvidia.com>
> Cc: Kunihiko Hayashi <hayashi.kunihiko at socionext.com>
> Cc: Masami Hiramatsu <mhiramat at kernel.org>
> Cc: Kees Cook <kees at kernel.org>
> Cc: "Gustavo A. R. Silva" <gustavoars at kernel.org>
> Cc: "Uwe Kleine-König (The Capable Hub)" <u.kleine-koenig at baylibre.com>
> Cc: netdev at vger.kernel.org
> Cc: linux-serial at vger.kernel.org
> Cc: linux-arm-kernel at lists.infradead.org
> Cc: linux-aspeed at lists.ozlabs.org
> Cc: linux-rpi-kernel at lists.infradead.org
> Cc: linux-mips at vger.kernel.org
> Cc: linux-mediatek at lists.infradead.org
> Cc: linux-parisc at vger.kernel.org
> Cc: linux-tegra at vger.kernel.org
> Cc: linux-hardening at vger.kernel.org
> ---
>  drivers/ptp/ptp_ocp.c                       | 36 +++++++++---------
>  drivers/tty/serial/8250/8250_acorn.c        |  5 ++-
>  drivers/tty/serial/8250/8250_airoha.c       | 22 +++--------
>  drivers/tty/serial/8250/8250_aspeed_vuart.c | 12 +++---
>  drivers/tty/serial/8250/8250_bcm2835aux.c   | 19 +++++-----
>  drivers/tty/serial/8250/8250_bcm7271.c      | 32 +++++++---------
>  drivers/tty/serial/8250/8250_core.c         | 37 +++++++------------
>  drivers/tty/serial/8250/8250_dfl.c          | 21 +++--------
>  drivers/tty/serial/8250/8250_dw.c           | 12 +++---
>  drivers/tty/serial/8250/8250_dwlib.h        |  2 +-
>  drivers/tty/serial/8250/8250_em.c           | 25 ++++---------
>  drivers/tty/serial/8250/8250_exar.c         | 21 +++++------
>  drivers/tty/serial/8250/8250_fsl.c          | 23 ++++--------
>  drivers/tty/serial/8250/8250_hp300.c        | 27 ++++++--------
>  drivers/tty/serial/8250/8250_ingenic.c      | 10 ++---
>  drivers/tty/serial/8250/8250_ioc3.c         | 25 ++++---------
>  drivers/tty/serial/8250/8250_keba.c         | 13 +++----
>  drivers/tty/serial/8250/8250_loongson.c     | 19 +++++-----
>  drivers/tty/serial/8250/8250_lpc18xx.c      | 10 ++---
>  drivers/tty/serial/8250/8250_lpss.c         | 21 ++++-------
>  drivers/tty/serial/8250/8250_men_mcb.c      | 13 +++----
>  drivers/tty/serial/8250/8250_mid.c          | 12 +++---
>  drivers/tty/serial/8250/8250_mtk.c          | 18 ++++-----
>  drivers/tty/serial/8250/8250_mxpcie.c       | 13 ++++---
>  drivers/tty/serial/8250/8250_ni.c           | 11 +++---
>  drivers/tty/serial/8250/8250_of.c           | 24 ++++++------
>  drivers/tty/serial/8250/8250_omap.c         | 41 +++++++++------------
>  drivers/tty/serial/8250/8250_parisc.c       | 13 +++----
>  drivers/tty/serial/8250/8250_pci.c          | 21 +++++------
>  drivers/tty/serial/8250/8250_pci1xxxx.c     | 40 ++++++++++----------
>  drivers/tty/serial/8250/8250_pericom.c      | 14 +++----
>  drivers/tty/serial/8250/8250_platform.c     | 22 +++++------
>  drivers/tty/serial/8250/8250_pnp.c          | 20 +++++-----
>  drivers/tty/serial/8250/8250_pxa.c          | 16 ++++----
>  drivers/tty/serial/8250/8250_tegra.c        | 19 +++++-----
>  drivers/tty/serial/8250/8250_uniphier.c     | 20 +++++-----
>  drivers/tty/serial/8250/serial_cs.c         | 14 +++----
>  include/linux/serial_8250.h                 |  8 ++--
>  38 files changed, 319 insertions(+), 412 deletions(-)
> 
> diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c
> index 2802989e8494..609cee1d2c80 100644
> --- a/drivers/ptp/ptp_ocp.c
> +++ b/drivers/ptp/ptp_ocp.c
> @@ -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)
> diff --git a/drivers/tty/serial/8250/8250_acorn.c b/drivers/tty/serial/8250/8250_acorn.c
> index fb596262b9c7..d0696668493a 100644
> --- a/drivers/tty/serial/8250/8250_acorn.c
> +++ b/drivers/tty/serial/8250/8250_acorn.c
> @@ -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);
> diff --git a/drivers/tty/serial/8250/8250_airoha.c b/drivers/tty/serial/8250/8250_airoha.c
> index fe72a39561c2..44aeb427d5c8 100644
> --- a/drivers/tty/serial/8250/8250_airoha.c
> +++ b/drivers/tty/serial/8250/8250_airoha.c
> @@ -28,10 +28,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 +115,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 +122,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 +138,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[] = {
> diff --git a/drivers/tty/serial/8250/8250_aspeed_vuart.c b/drivers/tty/serial/8250/8250_aspeed_vuart.c
> index 26fc0464f1cc..604e4946fd1d 100644
> --- a/drivers/tty/serial/8250/8250_aspeed_vuart.c
> +++ b/drivers/tty/serial/8250/8250_aspeed_vuart.c
> @@ -34,7 +34,6 @@
>  
>  struct aspeed_vuart {
>  	struct device		*dev;
> -	int			line;
>  	struct timer_list	unthrottle_timer;
>  	struct uart_8250_port	*port;
>  };
> @@ -484,12 +483,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 +553,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);
>  }
>  
> diff --git a/drivers/tty/serial/8250/8250_bcm2835aux.c b/drivers/tty/serial/8250/8250_bcm2835aux.c
> index 0609582a62f7..78b40bf1363b 100644
> --- a/drivers/tty/serial/8250/8250_bcm2835aux.c
> +++ b/drivers/tty/serial/8250/8250_bcm2835aux.c
> @@ -37,12 +37,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 +157,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 +177,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 +217,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 +231,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 +251,7 @@ static int bcm2835aux_resume(struct device *dev)
>  			return ret;
>  	}
>  
> -	serial8250_resume_port(data->line);
> +	serial8250_resume_port(data->uport);
>  
>  	return 0;
>  }
> diff --git a/drivers/tty/serial/8250/8250_bcm7271.c b/drivers/tty/serial/8250/8250_bcm7271.c
> index 5f1140f05150..ff75b0df41f4 100644
> --- a/drivers/tty/serial/8250/8250_bcm7271.c
> +++ b/drivers/tty/serial/8250/8250_bcm7271.c
> @@ -204,13 +204,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 +838,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 +952,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 +1081,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 +1094,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 +1103,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 +1117,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 +1127,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 +1140,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 +1149,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 +1171,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 */
> diff --git a/drivers/tty/serial/8250/8250_core.c b/drivers/tty/serial/8250/8250_core.c
> index 11424fef7c08..6ca6b3bed80f 100644
> --- a/drivers/tty/serial/8250/8250_core.c
> +++ b/drivers/tty/serial/8250/8250_core.c
> @@ -333,7 +333,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 +599,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 +628,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;
> @@ -754,16 +751,16 @@ static void serial_8250_overrun_backoff_work(struct work_struct *work)
>   *	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.
> + *	On success, the port is returned as ready to use.
>   */
> -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;
>  	bool cons_flow;
>  	int ret;
>  
>  	if (up->port.uartclk == 0)
> -		return -EINVAL;
> +		return ERR_PTR(-EINVAL);
>  
>  	guard(mutex)(&serial_mutex);
>  
> @@ -775,13 +772,13 @@ 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);
>  
>  	/* Preserve specified console flow control. */
>  	cons_flow = uart_cons_flow_enabled(&uart->port);
> @@ -901,16 +898,12 @@ int serial8250_register_8250_port(const struct uart_8250_port *up)
>  					&uart->port);
>  		if (ret)
>  			goto err;
> -
> -		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)
> @@ -926,25 +919,23 @@ int serial8250_register_8250_port(const struct uart_8250_port *up)
>  		uart->overrun_backoff_time_ms = 0;
>  	}
>  
> -	return ret;
> +	return uart;
>  
>  err:
>  	uart->port.dev = NULL;
> -	return ret;
> +	return ERR_PTR(ret);
>  }
>  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) {
> @@ -957,7 +948,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);
> diff --git a/drivers/tty/serial/8250/8250_dfl.c b/drivers/tty/serial/8250/8250_dfl.c
> index 475ca340948c..13d361ddfc4b 100644
> --- a/drivers/tty/serial/8250/8250_dfl.c
> +++ b/drivers/tty/serial/8250/8250_dfl.c
> @@ -27,10 +27,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 +105,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 +118,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
> diff --git a/drivers/tty/serial/8250/8250_dw.c b/drivers/tty/serial/8250/8250_dw.c
> index 0ab558230370..c259a940654f 100644
> --- a/drivers/tty/serial/8250/8250_dw.c
> +++ b/drivers/tty/serial/8250/8250_dw.c
> @@ -774,9 +774,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);

Add err.h.

>  
>  	platform_set_drvdata(pdev, data);
>  
> @@ -792,7 +792,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 +802,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 +811,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;
>  }
> diff --git a/drivers/tty/serial/8250/8250_dwlib.h b/drivers/tty/serial/8250/8250_dwlib.h
> index ee7a07fac0f6..39fcb1b323ad 100644
> --- a/drivers/tty/serial/8250/8250_dwlib.h
> +++ b/drivers/tty/serial/8250/8250_dwlib.h
> @@ -80,7 +80,7 @@
>  
>  struct dw8250_port_data {
>  	/* Port properties */
> -	int			line;
> +	struct uart_8250_port *uport;
>  
>  	/* DMA operations */
>  	struct uart_8250_dma	dma;
> diff --git a/drivers/tty/serial/8250/8250_em.c b/drivers/tty/serial/8250/8250_em.c
> index 32d077da076a..68c70f857e8d 100644
> --- a/drivers/tty/serial/8250/8250_em.c
> +++ b/drivers/tty/serial/8250/8250_em.c
> @@ -28,10 +28,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 +147,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 +161,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 +171,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 +180,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[] = {
> diff --git a/drivers/tty/serial/8250/8250_exar.c b/drivers/tty/serial/8250/8250_exar.c
> index 836792e861bf..453e843b78ca 100644
> --- a/drivers/tty/serial/8250/8250_exar.c
> +++ b/drivers/tty/serial/8250/8250_exar.c
> @@ -256,7 +256,7 @@ struct exar8250 {
>  	struct exar8250_board	*board;
>  	struct eeprom_93cx6	eeprom;
>  	void __iomem		*virt;
> -	int			line[];
> +	struct uart_8250_port	*uport[];
>  };
>  
>  static inline void exar_write_reg(struct exar8250 *priv,
> @@ -1377,9 +1377,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->uport[0]);
>  }
>  
>  static inline void exar_misc_clear(struct exar8250 *priv)
> @@ -1460,7 +1459,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 +1499,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 +1518,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 +1531,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 +1544,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;
>  }
> diff --git a/drivers/tty/serial/8250/8250_fsl.c b/drivers/tty/serial/8250/8250_fsl.c
> index 649ae5c8304d..d4ba391e321b 100644
> --- a/drivers/tty/serial/8250/8250_fsl.c
> +++ b/drivers/tty/serial/8250/8250_fsl.c
> @@ -99,14 +99,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 +143,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[] = {
> diff --git a/drivers/tty/serial/8250/8250_hp300.c b/drivers/tty/serial/8250/8250_hp300.c
> index 59ec0c7377a1..c0227ec873c8 100644
> --- a/drivers/tty/serial/8250/8250_hp300.c
> +++ b/drivers/tty/serial/8250/8250_hp300.c
> @@ -27,7 +27,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 +157,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 +176,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 +186,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 +202,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;
> @@ -226,6 +223,7 @@ static int __init hp300_8250_init(void)
>  			return -ENODEV;
>  		return 0;
>  	}
> +
>  	/* These models have the Frodo chip.
>  	 * Port 0 is reserved for the Apollo Domain keyboard.
>  	 * Port 1 is either the console or the DCA.
> @@ -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);
> diff --git a/drivers/tty/serial/8250/8250_ingenic.c b/drivers/tty/serial/8250/8250_ingenic.c
> index 94542fc143c2..8fedddeb38d9 100644
> --- a/drivers/tty/serial/8250/8250_ingenic.c
> +++ b/drivers/tty/serial/8250/8250_ingenic.c
> @@ -29,7 +29,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 +297,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 +318,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);
>  }
> diff --git a/drivers/tty/serial/8250/8250_ioc3.c b/drivers/tty/serial/8250/8250_ioc3.c
> index 28e28076782b..0ddc5e24567b 100644
> --- a/drivers/tty/serial/8250/8250_ioc3.c
> +++ b/drivers/tty/serial/8250/8250_ioc3.c
> @@ -17,10 +17,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 +29,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 +58,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 = {
> diff --git a/drivers/tty/serial/8250/8250_keba.c b/drivers/tty/serial/8250/8250_keba.c
> index 5b791b6eefd0..c53ca05a57d7 100644
> --- a/drivers/tty/serial/8250/8250_keba.c
> +++ b/drivers/tty/serial/8250/8250_keba.c
> @@ -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[] = {
> diff --git a/drivers/tty/serial/8250/8250_loongson.c b/drivers/tty/serial/8250/8250_loongson.c
> index 19acb2c6b611..f65e0813d84a 100644
> --- a/drivers/tty/serial/8250/8250_loongson.c
> +++ b/drivers/tty/serial/8250/8250_loongson.c
> @@ -43,7 +43,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 +160,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 +175,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 +195,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 +204,7 @@ static int loongson_uart_resume(struct device *dev)
>  			return ret;
>  	}
>  
> -	serial8250_resume_port(priv->line);
> +	serial8250_resume_port(up);
>  
>  	return 0;
>  }
> diff --git a/drivers/tty/serial/8250/8250_lpc18xx.c b/drivers/tty/serial/8250/8250_lpc18xx.c
> index 6c0489c9c253..9002951db02b 100644
> --- a/drivers/tty/serial/8250/8250_lpc18xx.c
> +++ b/drivers/tty/serial/8250/8250_lpc18xx.c
> @@ -29,7 +29,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 +160,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 +182,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);
>  }
> diff --git a/drivers/tty/serial/8250/8250_lpss.c b/drivers/tty/serial/8250/8250_lpss.c
> index c5257847a94c..115b97556360 100644
> --- a/drivers/tty/serial/8250/8250_lpss.c
> +++ b/drivers/tty/serial/8250/8250_lpss.c
> @@ -183,12 +183,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)
> -		return;
> -
> -	struct uart_8250_port *up = serial8250_get_port(lpss->data.line);
> -
> -	up->dma = NULL;
> +	if (lpss->data.uport)
> +		lpss->data.uport->dma = NULL;
>  }
>  
>  #ifdef CONFIG_SERIAL_8250_DMA
> @@ -332,8 +328,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));
>  
> @@ -361,11 +355,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);

Add err.h

Some other cases had the include added so you might want to check all the 
files you're adding IS_ERR/PTR_ERR() to if they already have err.h or not.

--
 i.


More information about the Linux-mediatek mailing list