[PATCH net] ptp: netc: fix potential interrupt storm caused by incorrect unbind order

wei.fang@oss.nxp.com posted 1 patch 14 hours ago
drivers/ptp/ptp_netc.c | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
[PATCH net] ptp: netc: fix potential interrupt storm caused by incorrect unbind order
Posted by wei.fang@oss.nxp.com 14 hours ago
From: Wei Fang <wei.fang@nxp.com>

In netc_timer_remove(), hardware interrupts are disabled by clearing
TMR_TEMASK before ptp_clock_unregister() is called. This may cause a
race condition during driver unbind that could leave hardware interrupts
active. For example, a concurrent PTP_CLK_REQ_EXTTS ioctl can re-enable
TMR_TEMASK after it has been cleared, leaving a pending hardware
interrupt when the driver unbinds.

Since the NETC Timer does not support PCIe FLR, hardware state is not
reset during probe. When the driver is rebound and the IRQ is registered,
the pending interrupt fires immediately. At that point priv->tmr_emask
is still zero, so netc_timer_isr() does not clear the interrupt status
and unconditionally returns IRQ_HANDLED, resulting in an uninterruptible
infinite interrupt storm.

Therefore, move ptp_clock_unregister() before the register writes that
clear NETC_TMR_TEMASK and NETC_TMR_CTRL. This guarantees that no
in-flight or concurrent ioctl can re-enable hardware interrupts, so no
pending interrupt is left when the driver unbinds.

Fixes: 671e266835b8 ("ptp: netc: add periodic pulse output support")
Reported-by: Sashiko <sashiko-bot@kernel.org>
Closes: https://sashiko.dev/#/patchset/20260720012508.23227-1-wei.fang%40oss.nxp.com
Signed-off-by: Wei Fang <wei.fang@nxp.com>
---
 drivers/ptp/ptp_netc.c | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/drivers/ptp/ptp_netc.c b/drivers/ptp/ptp_netc.c
index 5e381c354d74..3bab86afe8e2 100644
--- a/drivers/ptp/ptp_netc.c
+++ b/drivers/ptp/ptp_netc.c
@@ -1019,9 +1019,9 @@ static void netc_timer_remove(struct pci_dev *pdev)
 {
 	struct netc_timer *priv = pci_get_drvdata(pdev);
 
+	ptp_clock_unregister(priv->clock);
 	netc_timer_wr(priv, NETC_TMR_TEMASK, 0);
 	netc_timer_wr(priv, NETC_TMR_CTRL, 0);
-	ptp_clock_unregister(priv->clock);
 	netc_timer_free_msix_irq(priv);
 	netc_timer_pci_remove(pdev);
 }
-- 
2.34.1
Re: [PATCH net] ptp: netc: fix potential interrupt storm caused by incorrect unbind order
Posted by Vadim Fedorenko 10 hours ago
On 24/07/2026 07:51, wei.fang@oss.nxp.com wrote:
> From: Wei Fang <wei.fang@nxp.com>
> 
> In netc_timer_remove(), hardware interrupts are disabled by clearing
> TMR_TEMASK before ptp_clock_unregister() is called. This may cause a
> race condition during driver unbind that could leave hardware interrupts
> active. For example, a concurrent PTP_CLK_REQ_EXTTS ioctl can re-enable
> TMR_TEMASK after it has been cleared, leaving a pending hardware
> interrupt when the driver unbinds.
> 
> Since the NETC Timer does not support PCIe FLR, hardware state is not
> reset during probe. When the driver is rebound and the IRQ is registered,
> the pending interrupt fires immediately. At that point priv->tmr_emask
> is still zero, so netc_timer_isr() does not clear the interrupt status
> and unconditionally returns IRQ_HANDLED, resulting in an uninterruptible
> infinite interrupt storm.
> 
> Therefore, move ptp_clock_unregister() before the register writes that
> clear NETC_TMR_TEMASK and NETC_TMR_CTRL. This guarantees that no
> in-flight or concurrent ioctl can re-enable hardware interrupts, so no
> pending interrupt is left when the driver unbinds.
> 
> Fixes: 671e266835b8 ("ptp: netc: add periodic pulse output support")
> Reported-by: Sashiko <sashiko-bot@kernel.org>
> Closes: https://sashiko.dev/#/patchset/20260720012508.23227-1-wei.fang%40oss.nxp.com
> Signed-off-by: Wei Fang <wei.fang@nxp.com>
> ---
>   drivers/ptp/ptp_netc.c | 2 +-
>   1 file changed, 1 insertion(+), 1 deletion(-)
> 
> diff --git a/drivers/ptp/ptp_netc.c b/drivers/ptp/ptp_netc.c
> index 5e381c354d74..3bab86afe8e2 100644
> --- a/drivers/ptp/ptp_netc.c
> +++ b/drivers/ptp/ptp_netc.c
> @@ -1019,9 +1019,9 @@ static void netc_timer_remove(struct pci_dev *pdev)
>   {
>   	struct netc_timer *priv = pci_get_drvdata(pdev);
>   
> +	ptp_clock_unregister(priv->clock);
>   	netc_timer_wr(priv, NETC_TMR_TEMASK, 0);
>   	netc_timer_wr(priv, NETC_TMR_CTRL, 0);
> -	ptp_clock_unregister(priv->clock);
>   	netc_timer_free_msix_irq(priv);
>   	netc_timer_pci_remove(pdev);
>   }

Reviewed-by: Vadim Fedorenko <vadim.fedorenko@linux.dev>