From: Alex Austin <alex.austin@amd.com>
To: <netdev@vger.kernel.org>
Cc: <andrew+netdev@lunn.ch>, <bhutchings@solarflare.com>,
<davem@davemloft.net>, <ecree.xilinx@gmail.com>,
<edumazet@kernel.org>, <kuba@kernel.org>,
<linux-kernel@vger.kernel.org>, <linux-net-drivers@amd.com>,
<pabeni@redhat.com>, <richardcochran@gmail.com>,
<smhodgson@solarflare.com>, <alucero@amd.com>,
<pieter.jansen-van-vuuren@amd.com>,
Alex Austin <alex.austin@amd.com>,
Alejandro Lucero <alucerop@amd.com>
Subject: [PATCH net 2/2] sfc: ptp: avoid racing PPS timestamp updates
Date: Fri, 9 Oct 2026 19:32:40 +0100 [thread overview]
Message-ID: <20261009183240.1898762-3-alex.austin@amd.com> (raw)
In-Reply-To: <20261009183240.1898762-1-alex.austin@amd.com>
efx_ptp_pps_worker() can race with SIOCHWTSTAMP via
efx_ptp_change_mode(). After the worker completes synchronization, the
ioctl can start another synchronization and update host_time_pps while
the worker copies it into the PPS event. This can report a partially
updated timestamp. Serializing synchronization transactions alone does
not protect this copy, which happens after phc_lock is released.
Fixes: 7c236c43b838 ("sfc: Add support for IEEE-1588 PTP")
Signed-off-by: Alex Austin <alex.austin@amd.com>
Reviewed-by: Alejandro Lucero <alucerop@amd.com>
Reviewed-by: Pieter Jansen van Vuuren <pieter.jansen-van-vuuren@amd.com>
---
drivers/net/ethernet/sfc/ptp.c | 34 ++++++++++++++++++++++++----------
1 file changed, 24 insertions(+), 10 deletions(-)
diff --git a/drivers/net/ethernet/sfc/ptp.c b/drivers/net/ethernet/sfc/ptp.c
index ac9951f..103df1f 100644
--- a/drivers/net/ethernet/sfc/ptp.c
+++ b/drivers/net/ethernet/sfc/ptp.c
@@ -205,6 +205,14 @@ struct efx_ptp_timeset {
u32 window; /* Derived: end - start, allowing for wrap */
};
+/**
+ * struct efx_ptp_sync_result - Result of host and MC synchronisation
+ * @host_time_pps: Host time at the NIC top of second
+ */
+struct efx_ptp_sync_result {
+ struct pps_event_time host_time_pps;
+};
+
/**
* struct efx_ptp_rxfilter - Filter for PTP packets
* @list: Node of the list where the filter is added
@@ -268,7 +276,6 @@ struct efx_ptp_rxfilter {
* @evt_frag_idx: Current fragment number
* @evt_code: Last event code
* @start: Address at which MC indicates ready for synchronisation
- * @host_time_pps: Host time at last PPS
* @adjfreq_ppb_shift: Shift required to convert scaled parts-per-billion
* frequency adjustment into a fixed point fractional nanosecond format.
* @current_adjfreq: Current ppb adjustment.
@@ -329,7 +336,6 @@ struct efx_ptp_data {
int evt_frag_idx;
int evt_code;
struct efx_buffer start;
- struct pps_event_time host_time_pps;
unsigned int adjfreq_ppb_shift;
s64 current_adjfreq;
struct ptp_clock *phc_clock;
@@ -911,7 +917,8 @@ static void efx_ptp_read_timeset(MCDI_DECLARE_STRUCT_PTR(data),
static int
efx_ptp_process_times(struct efx_nic *efx, MCDI_DECLARE_STRUCT_PTR(synch_buf),
size_t response_length,
- const struct pps_event_time *last_time)
+ const struct pps_event_time *last_time,
+ struct efx_ptp_sync_result *result)
{
unsigned number_readings =
MCDI_VAR_ARRAY_LEN(response_length,
@@ -989,6 +996,10 @@ efx_ptp_process_times(struct efx_nic *efx, MCDI_DECLARE_STRUCT_PTR(synch_buf),
"PTP bad synchronisation seconds\n");
return -EAGAIN;
}
+
+ if (!result)
+ return 0;
+
delta.tv_sec = (last_sec - start_sec) & 1;
delta.tv_nsec =
last_time->ts_real.tv_nsec -
@@ -1005,14 +1016,15 @@ efx_ptp_process_times(struct efx_nic *efx, MCDI_DECLARE_STRUCT_PTR(synch_buf),
delta.tv_nsec += ktime_to_timespec64(mc_time).tv_nsec;
/* Set PPS timestamp to match NIC top of second */
- ptp->host_time_pps = *last_time;
- pps_sub_ts(&ptp->host_time_pps, delta);
+ result->host_time_pps = *last_time;
+ pps_sub_ts(&result->host_time_pps, delta);
return 0;
}
/* Synchronize times between the host and the MC */
-static int efx_ptp_synchronize(struct efx_nic *efx, unsigned int num_readings)
+static int efx_ptp_synchronize(struct efx_nic *efx, unsigned int num_readings,
+ struct efx_ptp_sync_result *result)
{
struct efx_ptp_data *ptp = efx->ptp_data;
MCDI_DECLARE_BUF(synch_buf, MC_CMD_PTP_OUT_SYNCHRONIZE_LENMAX);
@@ -1061,7 +1073,7 @@ static int efx_ptp_synchronize(struct efx_nic *efx, unsigned int num_readings)
&response_length);
if (rc == 0) {
rc = efx_ptp_process_times(efx, synch_buf, response_length,
- &last_time);
+ &last_time, result);
if (rc == 0)
++ptp->good_syncs;
else
@@ -1494,14 +1506,15 @@ static void efx_ptp_pps_worker(struct work_struct *work)
{
struct efx_ptp_data *ptp =
container_of(work, struct efx_ptp_data, pps_work);
+ struct efx_ptp_sync_result result = {};
struct efx_nic *efx = ptp->efx;
struct ptp_clock_event ptp_evt;
- if (efx_ptp_synchronize(efx, PTP_SYNC_ATTEMPTS))
+ if (efx_ptp_synchronize(efx, PTP_SYNC_ATTEMPTS, &result))
return;
ptp_evt.type = PTP_CLOCK_PPSUSR;
- ptp_evt.pps_times = ptp->host_time_pps;
+ ptp_evt.pps_times = result.host_time_pps;
ptp_clock_event(ptp->phc_clock, &ptp_evt);
}
@@ -1837,7 +1850,8 @@ int efx_ptp_change_mode(struct efx_nic *efx, bool enable_wanted,
rc = efx_ptp_start(efx);
if (rc == 0) {
rc = efx_ptp_synchronize(efx,
- PTP_SYNC_ATTEMPTS * 2);
+ PTP_SYNC_ATTEMPTS * 2,
+ NULL);
if (rc != 0)
efx_ptp_stop(efx);
}
--
2.34.1
next prev parent reply other threads:[~2026-10-09 18:33 UTC|newest]
Thread overview: 4+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-10-09 18:32 [PATCH net 0/2] sfc: fix PTP synchronization races Alex Austin
2026-10-09 18:32 ` [PATCH net 1/2] sfc: ptp: serialize host and MC synchronization transactions Alex Austin
2026-10-09 18:32 ` Alex Austin [this message]
2026-10-09 18:35 ` [PATCH net 0/2] sfc: fix PTP synchronization races netdev-bot+sinfo
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=20261009183240.1898762-3-alex.austin@amd.com \
--to=alex.austin@amd.com \
--cc=alucero@amd.com \
--cc=alucerop@amd.com \
--cc=andrew+netdev@lunn.ch \
--cc=bhutchings@solarflare.com \
--cc=davem@davemloft.net \
--cc=ecree.xilinx@gmail.com \
--cc=edumazet@kernel.org \
--cc=kuba@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=linux-net-drivers@amd.com \
--cc=netdev@vger.kernel.org \
--cc=pabeni@redhat.com \
--cc=pieter.jansen-van-vuuren@amd.com \
--cc=richardcochran@gmail.com \
--cc=smhodgson@solarflare.com \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox
all inboxes | Powered by JetHome®