| From 80d4609008e6d696a279e39ae7458c916fcd44c1 Mon Sep 17 00:00:00 2001 |
| From: Yannick Vignon <yannick.vignon@nxp.com> |
| Date: Thu, 3 Feb 2022 17:00:25 +0100 |
| Subject: net: stmmac: ensure PTP time register reads are consistent |
| |
| From: Yannick Vignon <yannick.vignon@nxp.com> |
| |
| commit 80d4609008e6d696a279e39ae7458c916fcd44c1 upstream. |
| |
| Even if protected from preemption and interrupts, a small time window |
| remains when the 2 register reads could return inconsistent values, |
| each time the "seconds" register changes. This could lead to an about |
| 1-second error in the reported time. |
| |
| Add logic to ensure the "seconds" and "nanoseconds" values are consistent. |
| |
| Fixes: 92ba6888510c ("stmmac: add the support for PTP hw clock driver") |
| Signed-off-by: Yannick Vignon <yannick.vignon@nxp.com> |
| Reviewed-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk> |
| Link: https://lore.kernel.org/r/20220203160025.750632-1-yannick.vignon@oss.nxp.com |
| Signed-off-by: Jakub Kicinski <kuba@kernel.org> |
| Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org> |
| --- |
| drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c | 17 +++++++++++------ |
| 1 file changed, 11 insertions(+), 6 deletions(-) |
| |
| --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c |
| +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c |
| @@ -142,15 +142,20 @@ static int adjust_systime(void __iomem * |
| |
| static void get_systime(void __iomem *ioaddr, u64 *systime) |
| { |
| - u64 ns; |
| + u64 ns, sec0, sec1; |
| |
| - /* Get the TSSS value */ |
| - ns = readl(ioaddr + PTP_STNSR); |
| - /* Get the TSS and convert sec time value to nanosecond */ |
| - ns += readl(ioaddr + PTP_STSR) * 1000000000ULL; |
| + /* Get the TSS value */ |
| + sec1 = readl_relaxed(ioaddr + PTP_STSR); |
| + do { |
| + sec0 = sec1; |
| + /* Get the TSSS value */ |
| + ns = readl_relaxed(ioaddr + PTP_STNSR); |
| + /* Get the TSS value */ |
| + sec1 = readl_relaxed(ioaddr + PTP_STSR); |
| + } while (sec0 != sec1); |
| |
| if (systime) |
| - *systime = ns; |
| + *systime = ns + (sec1 * 1000000000ULL); |
| } |
| |
| const struct stmmac_hwtimestamp stmmac_ptp = { |