aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorVadim Fedorenko <vadim.fedorenko@linux.dev>2026-06-08 15:59:52 +0000
committerJakub Kicinski <kuba@kernel.org>2026-06-09 19:26:56 -0700
commit627366c51145a07f675b1800fb5ea2ec960bd900 (patch)
tree990be156d92cb46ee485603636a17cde5e1fb1c9
parent7f2fcff15e99bb852f6967396ed12b38376e2c8d (diff)
ptp: ocp: fix resource freeing order
Commit a60fc3294a37 ("ptp: rework ptp_clock_unregister() to disable events") added a call to ptp_disable_all_events() which changes the configuration of pins if they support EXTTS events. In ptp_ocp_detach() pins resources are freed before ptp_clock_unregister() and it leads to use-after-free during driver removal. Fix it by changing the order of free/unregister calls. To avoid irq handler running on the other core while ptp device unregistering, call synchronize_irq() after HW is configured to stop producing irqs and no irqs are in-flight. Fixes: a60fc3294a37 ("ptp: rework ptp_clock_unregister() to disable events") Signed-off-by: Vadim Fedorenko <vadim.fedorenko@linux.dev> Link: https://patch.msgid.link/20260608155952.240304-1-vadim.fedorenko@linux.dev Signed-off-by: Jakub Kicinski <kuba@kernel.org>
-rw-r--r--drivers/ptp/ptp_ocp.c24
1 files changed, 21 insertions, 3 deletions
diff --git a/drivers/ptp/ptp_ocp.c b/drivers/ptp/ptp_ocp.c
index beacc2ffb166..735385539b9f 100644
--- a/drivers/ptp/ptp_ocp.c
+++ b/drivers/ptp/ptp_ocp.c
@@ -2479,8 +2479,13 @@ ptp_ocp_ts_enable(void *priv, u32 req, bool enable)
iowrite32(1, &reg->intr_mask);
iowrite32(1, &reg->intr);
} else {
+ int irq_vec = pci_irq_vector(bp->pdev, ext->irq_vec);
+
iowrite32(0, &reg->intr_mask);
iowrite32(0, &reg->enable);
+ ioread32(&reg->intr_mask);
+ if (irq_vec > 0)
+ synchronize_irq(irq_vec);
}
return 0;
@@ -4867,6 +4872,22 @@ ptp_ocp_detach(struct ptp_ocp *bp)
ptp_ocp_detach_sysfs(bp);
ptp_ocp_attr_group_del(bp);
timer_delete_sync(&bp->watchdog);
+ /* Disable interrupts on all timestampers */
+ if (bp->ts0)
+ ptp_ocp_ts_enable(bp->ts0, 0, false);
+ if (bp->ts1)
+ ptp_ocp_ts_enable(bp->ts1, 0, false);
+ if (bp->ts2)
+ ptp_ocp_ts_enable(bp->ts2, 0, false);
+ if (bp->ts3)
+ ptp_ocp_ts_enable(bp->ts3, 0, false);
+ if (bp->ts4)
+ ptp_ocp_ts_enable(bp->ts4, 0, false);
+ if (bp->pps)
+ ptp_ocp_ts_enable(bp->pps, ~0, false);
+ if (bp->ptp)
+ ptp_clock_unregister(bp->ptp);
+ kfree(bp->ptp_info.pin_config);
ptp_ocp_unregister_ext(bp->ts0);
ptp_ocp_unregister_ext(bp->ts1);
ptp_ocp_unregister_ext(bp->ts2);
@@ -4884,9 +4905,6 @@ ptp_ocp_detach(struct ptp_ocp *bp)
clk_hw_unregister_fixed_rate(bp->i2c_clk);
if (bp->n_irqs)
pci_free_irq_vectors(bp->pdev);
- if (bp->ptp)
- ptp_clock_unregister(bp->ptp);
- kfree(bp->ptp_info.pin_config);
device_unregister(&bp->dev);
}