[PATCH net 1/2] net: fec: don't leave a stale PTP clock pointer after unregister

From: Shengzhuo Wei

Date: Thu Sep 03 2026 - 16:18:17 EST


fec_drv_remove() calls fec_ptp_stop() before unregister_netdev(), and
fec_ptp_stop() leaves fep->ptp_clock set after ptp_clock_unregister().
An ethtool -T issued while the netdev is still registered then reaches
fec_enet_get_ts_info(), which passes the stale pointer to
ptp_clock_index() after the clock structure has been freed.

Query the PHC index through ptp_clock_index_by_dev() instead. The lookup
holds a reference to the matching PTP class device while reading its index,
so concurrent unregister cannot free it underneath the lookup. It returns
-1 once no clock is registered. Clear fep->ptp_clock after unregistering
it as well, so the driver state no longer retains the invalid pointer.

Fixes: 32cba57ba74b ("net: fec: introduce fec_ptp_stop and use in probe fail path")
Cc: stable@xxxxxxxxxxxxxxx
Assisted-by: GLM:5.3
Signed-off-by: Shengzhuo Wei <me@xxxxxxxx>
---
drivers/net/ethernet/freescale/fec_main.c | 3 +--
drivers/net/ethernet/freescale/fec_ptp.c | 4 +++-
2 files changed, 4 insertions(+), 3 deletions(-)

diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c
index 794ec427b0ee..0606559d495c 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -3337,8 +3337,7 @@ static int fec_enet_get_ts_info(struct net_device *ndev,
SOF_TIMESTAMPING_TX_HARDWARE |
SOF_TIMESTAMPING_RX_HARDWARE |
SOF_TIMESTAMPING_RAW_HARDWARE;
- if (fep->ptp_clock)
- info->phc_index = ptp_clock_index(fep->ptp_clock);
+ info->phc_index = ptp_clock_index_by_dev(&fep->pdev->dev);

info->tx_types = (1 << HWTSTAMP_TX_OFF) |
(1 << HWTSTAMP_TX_ON);
diff --git a/drivers/net/ethernet/freescale/fec_ptp.c b/drivers/net/ethernet/freescale/fec_ptp.c
index 56801c2009d5..0036549974fd 100644
--- a/drivers/net/ethernet/freescale/fec_ptp.c
+++ b/drivers/net/ethernet/freescale/fec_ptp.c
@@ -861,6 +861,8 @@ void fec_ptp_stop(struct platform_device *pdev)

cancel_delayed_work_sync(&fep->time_keep);
hrtimer_cancel(&fep->perout_timer);
- if (fep->ptp_clock)
+ if (fep->ptp_clock) {
ptp_clock_unregister(fep->ptp_clock);
+ fep->ptp_clock = NULL;
+ }
}

--
2.47.3