ucc_hdlc_probe() registers an HDLC netdev whose private pointer refers to
the separately allocated ucc_hdlc_private object. The remove path frees
that private object without unregistering or freeing the netdev, leaving
a registered device with a dangling private pointer.

Unregister the HDLC device before releasing hardware resources. This
closes an active interface through ndo_stop, which disables NAPI, stops
the UCC, and frees its IRQ. Then free the netdev before releasing its
private object.

Fixes: c19b6d246a35 ("drivers/net: support hdlc function for QE-UCC")
Cc: [email protected]
Co-developed-by: Ijae Kim <[email protected]>
Signed-off-by: Ijae Kim <[email protected]>
Signed-off-by: Myeonghun Pak <[email protected]>
---
 drivers/net/wan/fsl_ucc_hdlc.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/drivers/net/wan/fsl_ucc_hdlc.c b/drivers/net/wan/fsl_ucc_hdlc.c
index 809f21fb9..4c843c94c 100644
--- a/drivers/net/wan/fsl_ucc_hdlc.c
+++ b/drivers/net/wan/fsl_ucc_hdlc.c
@@ -1255,6 +1255,8 @@ static void ucc_hdlc_remove(struct platform_device *pdev)
 {
        struct ucc_hdlc_private *priv = dev_get_drvdata(&pdev->dev);
 
+       unregister_hdlc_device(priv->ndev);
+
        uhdlc_memclean(priv);
 
        if (priv->utdm && priv->utdm->si_regs) {
@@ -1266,6 +1268,7 @@ static void ucc_hdlc_remove(struct platform_device *pdev)
                iounmap(priv->utdm->siram);
                priv->utdm->siram = NULL;
        }
+       free_netdev(priv->ndev);
        kfree(priv);
 
        dev_info(&pdev->dev, "UCC based hdlc module removed\n");
-- 
2.47.1

Reply via email to