From: Sasha Levin <sashal@kernel.org>
To: stable@vger.kernel.org
Cc: "Jiri Slaby (SUSE)" <jirislaby@kernel.org>,
Greg Kroah-Hartman <gregkh@linuxfoundation.org>,
Sasha Levin <sashal@kernel.org>
Subject: [PATCH 6.6.y 4/4] serial: 8250_exar: store the GPIO platform device in struct exar8250
Date: Tue, 10 Nov 2026 15:21:02 -0500 [thread overview]
Message-ID: <20261110202051.3754797-4-sashal@kernel.org> (raw)
In-Reply-To: <20261110202051.3754797-1-sashal@kernel.org>
From: "Jiri Slaby (SUSE)" <jirislaby@kernel.org>
[ Upstream commit 33d337816e00994daaf670243186d9e537ee090d ]
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.
Signed-off-by: Jiri Slaby (SUSE) <jirislaby@kernel.org>
Fixes: d0aeaa83f0b0 ("serial: exar: split out the exar code from 8250_pci")
Link: https://lore.kernel.org/all/sashiko-outbox-166269@kernel.org/
Assisted-by: LLM
Cc: stable@vger.kernel.org
Link: https://patch.msgid.link/03a8b5c71614fc672fef1e55c083bda6c73b5bf3.1791873876.git.jirislaby@kernel.org
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
Signed-off-by: Sasha Levin <sashal@kernel.org>
---
drivers/tty/serial/8250/8250_exar.c | 36 ++++++++++++++---------------
1 file changed, 18 insertions(+), 18 deletions(-)
diff --git a/drivers/tty/serial/8250/8250_exar.c b/drivers/tty/serial/8250/8250_exar.c
index aa72d252c6bcb..c15cf3cc87144 100644
--- a/drivers/tty/serial/8250/8250_exar.c
+++ b/drivers/tty/serial/8250/8250_exar.c
@@ -169,8 +169,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);
};
/**
@@ -194,6 +195,7 @@ struct exar8250 {
unsigned int nr;
struct exar8250_board *board;
void __iomem *virt;
+ struct platform_device *gpio;
int line[];
};
@@ -452,22 +454,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 generic_rs485_config(struct uart_port *port, struct ktermios *termios,
@@ -550,8 +551,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;
@@ -560,8 +562,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;
}
@@ -635,7 +636,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;
@@ -645,9 +646,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)
--
2.53.0
prev parent reply other threads:[~2026-11-10 20:21 UTC|newest]
Thread overview: 5+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-11-07 10:34 FAILED: patch "[PATCH] serial: 8250_exar: store the GPIO platform device in struct exar8250" failed to apply to 6.6-stable tree Sasha Levin
2026-11-10 20:20 ` [PATCH 6.6.y 1/4] serial: 8250_exar: Clear interrupts before registering handler Sasha Levin
2026-11-10 20:21 ` [PATCH 6.6.y 2/4] serial: exar: add optional board_init function Sasha Levin
2026-11-10 20:21 ` [PATCH 6.6.y 3/4] serial: exar: fix checkpach warnings Sasha Levin
2026-11-10 20:21 ` Sasha Levin [this message]
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261110202051.3754797-4-sashal@kernel.org \
--to=sashal@kernel.org \
--cc=gregkh@linuxfoundation.org \
--cc=jirislaby@kernel.org \
--cc=stable@vger.kernel.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.