Thread (1 message) 1 message, 1 author, 22h ago

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

From: Wei Fang (OSS) <hidden>
Date: 2026-07-27 04:46:55
Also in: imx, sashiko-reviews

quoted
diff --git a/drivers/ptp/ptp_netc.c b/drivers/ptp/ptp_netc.c
index 5e381c354d746..3bab86afe8e23 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)
quoted
 {
 	struct netc_timer *priv = pci_get_drvdata(pdev);

+	ptp_clock_unregister(priv->clock);
+	netc_timer_wr(priv, NETC_TMR_TEMASK, 0);
[Severity: High]
Does moving ptp_clock_unregister() before masking hardware interrupts
introduce a use-after-free regression in the interrupt handler?
That is indeed a problem, I will fix it in next version.
If EXTTS events are configured, ptp_clock_unregister() drops the final
device reference and frees priv->clock if no file descriptors are open.

Because the hardware interrupt mask (NETC_TMR_TEMASK) is not cleared until
the next instruction, and free_irq() has not yet been called, the hardware
can still fire an EXTTS interrupt.

If this occurs, the ISR netc_timer_isr() processes the event and
unconditionally dereferences the freed clock object:

netc_timer_isr() -> netc_timer_handle_etts_event() {
    ...
    ptp_clock_event(priv->clock, &event);
    ...
}
quoted
 	netc_timer_wr(priv, NETC_TMR_CTRL, 0);
-	ptp_clock_unregister(priv->clock);
 	netc_timer_free_msix_irq(priv);
 	netc_timer_pci_remove(pdev);
 }
[Severity: High]
This isn't a bug introduced by this patch, but can the driver encounter a
hard lockup during probe on kexec or an unclean shutdown?

Because the NETC timer does not support PCIe FLR, hardware registers
retain their state. In netc_timer_probe(), the driver requests the IRQ via
netc_timer_init_msix_irq() before resetting the hardware state.

If the hardware has a pending interrupt, it fires immediately upon
request_irq(). At this point, priv->tmr_emask is 0.

The ISR netc_timer_isr() masks the hardware status with priv->tmr_emask
and writes 0 back to the Write-1-to-Clear (W1C) register, failing to clear
the pending hardware interrupt:

netc_timer_isr() {
    ...
    tmr_event = netc_timer_rd(priv, NETC_TMR_TEVENT);
    tmr_event &= priv->tmr_emask;
    /* Clear interrupts status */
    netc_timer_wr(priv, NETC_TMR_TEVENT, tmr_event);
    ...
}

The ISR then defeats the kernel's spurious interrupt detection by
unconditionally returning IRQ_HANDLED, causing the interrupt controller to
re-invoke the ISR in an infinite loop:

netc_timer_isr() {
    ...
    return IRQ_HANDLED;
}

--
Sashiko AI
review · https://sashiko.dev/#/patchset/20260724065116.521893-1-wei.fang@
oss.nxp.com?part=1
Keyboard shortcuts
hback out one level
jnext message in thread
kprevious message in thread
ldrill in
Escclose help / fold thread tree
?toggle this help