Commit 80d46090 authored by Yannick Vignon's avatar Yannick Vignon Committed by Jakub Kicinski

net: stmmac: ensure PTP time register reads are consistent

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: 92ba6888 ("stmmac: add the support for PTP hw clock driver")
Signed-off-by: default avatarYannick Vignon <yannick.vignon@nxp.com>
Reviewed-by: default avatarRussell King (Oracle) <rmk+kernel@armlinux.org.uk>
Link: https://lore.kernel.org/r/20220203160025.750632-1-yannick.vignon@oss.nxp.comSigned-off-by: default avatarJakub Kicinski <kuba@kernel.org>
parent 77b1b8b4
...@@ -145,15 +145,20 @@ static int adjust_systime(void __iomem *ioaddr, u32 sec, u32 nsec, ...@@ -145,15 +145,20 @@ static int adjust_systime(void __iomem *ioaddr, u32 sec, u32 nsec,
static void get_systime(void __iomem *ioaddr, u64 *systime) static void get_systime(void __iomem *ioaddr, u64 *systime)
{ {
u64 ns; u64 ns, sec0, sec1;
/* Get the TSSS value */ /* Get the TSS value */
ns = readl(ioaddr + PTP_STNSR); sec1 = readl_relaxed(ioaddr + PTP_STSR);
/* Get the TSS and convert sec time value to nanosecond */ do {
ns += readl(ioaddr + PTP_STSR) * 1000000000ULL; 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) if (systime)
*systime = ns; *systime = ns + (sec1 * 1000000000ULL);
} }
static void get_ptptime(void __iomem *ptpaddr, u64 *ptp_time) static void get_ptptime(void __iomem *ptpaddr, u64 *ptp_time)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment