[PATCH v2 2/3] serial: 8250_mxpcie: only unregister the ports that were registered
From: Linmao Li
Date: Tue Sep 01 2026 - 00:17:01 EST
When serial8250_register_8250_port() fails the loop stops and the probe
keeps the ports registered so far, like pciserial_init_ports() in
8250_pci.c this driver was split from. What the split lost is that
function's priv->nr: mxpcie8250_remove() walks all num_ports entries,
but the ones the loop never reached keep the zero devm_kzalloc() left
there, and the one that failed keeps a negative error code.
serial8250_unregister_port() checks neither, so removal unregisters
line 0 - a port this driver does not own - and indexes
serial8250_ports[] with a negative line number.
Record how many ports were registered and unregister only those.
Fixes: 0481a041e956 ("serial: 8250: split Moxa PCIe serial board support out of 8250_pci")
Signed-off-by: Linmao Li <lilinmao@xxxxxxxxxx>
---
v2: keep the ports that registered successfully and restore only the
missing count; v1 failed the probe instead (Andy Shevchenko).
drivers/tty/serial/8250/8250_mxpcie.c | 7 +++++--
1 file changed, 5 insertions(+), 2 deletions(-)
diff --git a/drivers/tty/serial/8250/8250_mxpcie.c b/drivers/tty/serial/8250/8250_mxpcie.c
index c0e3517d4e4e..ef2516ec16da 100644
--- a/drivers/tty/serial/8250/8250_mxpcie.c
+++ b/drivers/tty/serial/8250/8250_mxpcie.c
@@ -109,6 +109,7 @@ struct mxpcie8250_port {
struct mxpcie8250 {
unsigned int supp_rs;
unsigned int num_ports;
+ unsigned int nr; /* ports actually registered */
void __iomem *bar1_base; /* UART registers (MMIO) */
void __iomem *bar2_base; /* UIR / GPIO / CPLD (IO) */
struct mxpcie8250_port port[] __counted_by(num_ports);
@@ -517,6 +518,7 @@ static int mxpcie8250_probe(struct pci_dev *pdev, const struct pci_device_id *id
struct mxpcie8250 *priv;
unsigned short device = pdev->device;
unsigned int num_ports;
+ unsigned int i;
int ret;
ret = pcim_enable_device(pdev);
@@ -564,7 +566,7 @@ static int mxpcie8250_probe(struct pci_dev *pdev, const struct pci_device_id *id
up.port.handle_irq = mxpcie8250_handle_irq;
up.port.break_ctl = mxpcie8250_break_ctl;
- for (unsigned int i = 0; i < num_ports; i++) {
+ for (i = 0; i < num_ports; i++) {
mxpcie8250_setup_port(pdev, priv, &up, i);
dev_dbg(dev, "Setup PCI port: port %lx, irq %d, type %d\n",
@@ -580,6 +582,7 @@ static int mxpcie8250_probe(struct pci_dev *pdev, const struct pci_device_id *id
}
priv->port[i].rx_trig_level = MOXA_PUART_RX_TRIG_DEFAULT;
}
+ priv->nr = i;
return 0;
}
@@ -588,7 +591,7 @@ static void mxpcie8250_remove(struct pci_dev *pdev)
{
struct mxpcie8250 *priv = pci_get_drvdata(pdev);
- for (unsigned int i = 0; i < priv->num_ports; i++)
+ for (unsigned int i = 0; i < priv->nr; i++)
serial8250_unregister_port(priv->port[i].line);
}
--
2.25.1