[PATCH] PCI: rockchip-ep: disable link training work on remove
From: Fan Wu
Date: Mon Aug 10 2026 - 22:54:47 EST
The endpoint driver has no .remove callback, so on unbind the
link_training work can keep running after the devm-allocated ep is freed,
causing a use-after-free. Add a .remove() callback that disables the
worker.
This issue was found by an in-house static analysis tool.
Fixes: bd6e61df4b2e ("PCI: rockchip-ep: Improve link training")
Cc: stable@xxxxxxxxxxxxxxx
Assisted-by: Codex:gpt-5.6
Signed-off-by: Fan Wu <fanwu01@xxxxxxxxxx>
---
drivers/pci/controller/pcie-rockchip-ep.c | 21 +++++++++++++++++++++
1 file changed, 21 insertions(+)
diff --git a/drivers/pci/controller/pcie-rockchip-ep.c b/drivers/pci/controller/pcie-rockchip-ep.c
index 7994613..fbc2470 100644
--- a/drivers/pci/controller/pcie-rockchip-ep.c
+++ b/drivers/pci/controller/pcie-rockchip-ep.c
@@ -860,6 +860,7 @@ static int rockchip_pcie_ep_probe(struct platform_device *pdev)
}
ep->epc = epc;
+ platform_set_drvdata(pdev, ep);
epc_set_drvdata(epc, ep);
err = rockchip_pcie_ep_get_resources(rockchip, ep);
@@ -899,12 +900,32 @@ err_exit_ob_mem:
return err;
}
+static void rockchip_pcie_ep_remove(struct platform_device *pdev)
+{
+ struct rockchip_pcie_ep *ep = platform_get_drvdata(pdev);
+ struct rockchip_pcie *rockchip = &ep->rockchip;
+
+ if (rockchip->perst_gpio) {
+ ep->perst_asserted = true;
+ disable_irq(ep->perst_irq);
+ }
+
+ /* Disable, not cancel like .stop(): a racing .start() cannot re-arm it. */
+ disable_delayed_work_sync(&ep->link_training);
+
+ rockchip_pcie_write(rockchip,
+ PCIE_CLIENT_CONF_DISABLE |
+ PCIE_CLIENT_LINK_TRAIN_DISABLE,
+ PCIE_CLIENT_CONFIG);
+}
+
static struct platform_driver rockchip_pcie_ep_driver = {
.driver = {
.name = "rockchip-pcie-ep",
.of_match_table = rockchip_pcie_ep_of_match,
},
.probe = rockchip_pcie_ep_probe,
+ .remove = rockchip_pcie_ep_remove,
};
builtin_platform_driver(rockchip_pcie_ep_driver);
--
2.34.1