From 1fadd469b628e5857ff2e7a42c4c5aa394cd3229 Mon Sep 17 00:00:00 2001 From: "Bastien Curutchet (Schneider Electric)" Date: Fri, 25 Sep 2026 13:38:47 +0200 Subject: [PATCH] net: dsa: microchip: fully save the periodic output request When a periodic output is initialized, its period and start time are stored to initialize it back in case of restart. These information aren't enough if the request contains flags or targets a pin that isn't the first output of the switch. At restarts, these two arguments are always set to 0. The 'flag issue' isn't concrete so far because the driver doesn't advertise any .supported_perout_flags so any flag request gets rejected by the upper layer. I don't know if other switches use non-zero indexes but the KSZ8463 has twelve periodic outputs, so this index has to also be saved from now on. Save the full request when a periodic output is successfully started. Use the saved request when the periodic output is restarted. Signed-off-by: Bastien Curutchet (Schneider Electric) Link: https://patch.msgid.link/20260925-ksz-perout-v4-1-d675bd21ce49@bootlin.com Signed-off-by: Jakub Kicinski --- drivers/net/dsa/microchip/ksz_ptp.c | 33 ++++++++++++++++------------- drivers/net/dsa/microchip/ksz_ptp.h | 3 +-- 2 files changed, 19 insertions(+), 17 deletions(-) diff --git a/drivers/net/dsa/microchip/ksz_ptp.c b/drivers/net/dsa/microchip/ksz_ptp.c index 39cc70d65900..47cf397481d5 100644 --- a/drivers/net/dsa/microchip/ksz_ptp.c +++ b/drivers/net/dsa/microchip/ksz_ptp.c @@ -189,6 +189,7 @@ static int ksz_ptp_enable_perout(struct ksz_device *dev, { struct ksz_ptp_data *ptp_data = &dev->ptp_data; u64 req_pulse_width_ns; + struct timespec64 tmp; u64 cycle_width_ns; u64 pulse_width_ns; int pin = 0; @@ -222,13 +223,9 @@ static int ksz_ptp_enable_perout(struct ksz_device *dev, return 0; } - ptp_data->perout_target_time_first.tv_sec = request->start.sec; - ptp_data->perout_target_time_first.tv_nsec = request->start.nsec; - - ptp_data->perout_period.tv_sec = request->period.sec; - ptp_data->perout_period.tv_nsec = request->period.nsec; - - cycle_width_ns = timespec64_to_ns(&ptp_data->perout_period); + tmp.tv_sec = request->period.sec; + tmp.tv_nsec = request->period.nsec; + cycle_width_ns = timespec64_to_ns(&tmp); if ((cycle_width_ns & TRIG_CYCLE_WIDTH_M) != cycle_width_ns) return -EINVAL; @@ -249,9 +246,10 @@ static int ksz_ptp_enable_perout(struct ksz_device *dev, if (ret) return ret; + tmp.tv_sec = request->start.sec; + tmp.tv_nsec = request->start.nsec; ret = ksz_ptp_configure_perout(dev, cycle_width_ns, pulse_width_ns, - &ptp_data->perout_target_time_first, - pin); + &tmp, pin); if (ret) return ret; @@ -263,6 +261,8 @@ static int ksz_ptp_enable_perout(struct ksz_device *dev, if (ret) return ret; + memcpy(&ptp_data->perout_request, request, + sizeof(struct ptp_perout_request)); ptp_data->tou_mode = KSZ_PTP_TOU_PEROUT; return 0; @@ -763,6 +763,7 @@ static int ksz_ptp_restart_perout(struct ksz_device *dev) struct ptp_perout_request request; struct timespec64 next; struct timespec64 now; + struct timespec64 tmp; unsigned int count; int ret; @@ -773,10 +774,14 @@ static int ksz_ptp_restart_perout(struct ksz_device *dev) return ret; now_ns = timespec64_to_ns(&now); - first_ns = timespec64_to_ns(&ptp_data->perout_target_time_first); + tmp.tv_sec = ptp_data->perout_request.start.sec; + tmp.tv_nsec = ptp_data->perout_request.start.nsec; + first_ns = timespec64_to_ns(&tmp); /* Calculate next perout event based on start time and period */ - period_ns = timespec64_to_ns(&ptp_data->perout_period); + tmp.tv_sec = ptp_data->perout_request.period.sec; + tmp.tv_nsec = ptp_data->perout_request.period.nsec; + period_ns = timespec64_to_ns(&tmp); if (first_ns < now_ns) { count = div_u64(now_ns - first_ns, period_ns); @@ -791,12 +796,10 @@ static int ksz_ptp_restart_perout(struct ksz_device *dev) /* Restart periodic output signal */ next = ns_to_timespec64(next_ns); + memcpy(&request, &ptp_data->perout_request, + sizeof(struct ptp_perout_request)); request.start.sec = next.tv_sec; request.start.nsec = next.tv_nsec; - request.period.sec = ptp_data->perout_period.tv_sec; - request.period.nsec = ptp_data->perout_period.tv_nsec; - request.index = 0; - request.flags = 0; return ksz_ptp_enable_perout(dev, &request, 1); } diff --git a/drivers/net/dsa/microchip/ksz_ptp.h b/drivers/net/dsa/microchip/ksz_ptp.h index 7067ec9bd1e6..eb3827203b96 100644 --- a/drivers/net/dsa/microchip/ksz_ptp.h +++ b/drivers/net/dsa/microchip/ksz_ptp.h @@ -29,8 +29,7 @@ struct ksz_ptp_data { spinlock_t clock_lock; struct timespec64 clock_time; enum ksz_ptp_tou_mode tou_mode; - struct timespec64 perout_target_time_first; /* start of first pulse */ - struct timespec64 perout_period; + struct ptp_perout_request perout_request; }; int ksz_ptp_clock_register(struct dsa_switch *ds);