Patch "igc: Handle PPS start time programming for past time values" has been added to the 6.1-stable tree

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This is a note to let you know that I've just added the patch titled

    igc: Handle PPS start time programming for past time values

to the 6.1-stable tree which can be found at:
    http://www.kernel.org/git/?p=linux/kernel/git/stable/stable-queue.git;a=summary

The filename of the patch is:
     igc-handle-pps-start-time-programming-for-past-time-.patch
and it can be found in the queue-6.1 subdirectory.

If you, or anyone else, feels it should not be added to the stable tree,
please let <stable@xxxxxxxxxxxxxxx> know about it.



commit b724b2e932ce9dbc5f882562c96c8e3186e26a77
Author: Aravindhan Gunasekaran <aravindhan.gunasekaran@xxxxxxxxx>
Date:   Thu Jun 15 12:00:43 2023 +0530

    igc: Handle PPS start time programming for past time values
    
    [ Upstream commit 84a192e46106355de1a314d709e657231d4b1026 ]
    
    I225/6 hardware can be programmed to start PPS output once
    the time in Target Time registers is reached. The time
    programmed in these registers should always be into future.
    Only then PPS output is triggered when SYSTIM register
    reaches the programmed value. There are two modes in i225/6
    hardware to program PPS, pulse and clock mode.
    
    There were issues reported where PPS is not generated when
    start time is in past.
    
    Example 1, "echo 0 0 0 2 0 > /sys/class/ptp/ptp0/period"
    
    In the current implementation, a value of '0' is programmed
    into Target time registers and PPS output is in pulse mode.
    Eventually an interrupt which is triggered upon SYSTIM
    register reaching Target time is not fired. Thus no PPS
    output is generated.
    
    Example 2, "echo 0 0 0 1 0 > /sys/class/ptp/ptp0/period"
    
    Above case, a value of '0' is programmed into Target time
    registers and PPS output is in clock mode. Here, HW tries to
    catch-up the current time by incrementing Target Time
    register. This catch-up time seem to vary according to
    programmed PPS period time as per the HW design. In my
    experiments, the delay ranged between few tens of seconds to
    few minutes. The PPS output is only generated after the
    Target time register reaches current time.
    
    In my experiments, I also observed PPS stopped working with
    below test and could not recover until module is removed and
    loaded again.
    
    1) echo 0 <future time> 0 1 0 > /sys/class/ptp/ptp1/period
    2) echo 0 0 0 1 0 > /sys/class/ptp/ptp1/period
    3) echo 0 0 0 1 0 > /sys/class/ptp/ptp1/period
    
    After this PPS did not work even if i re-program with proper
    values. I could only get this back working by reloading the
    driver.
    
    This patch takes care of calculating and programming
    appropriate future time value into Target Time registers.
    
    Fixes: 5e91c72e560c ("igc: Fix PPS delta between two synchronized end-points")
    Signed-off-by: Aravindhan Gunasekaran <aravindhan.gunasekaran@xxxxxxxxx>
    Reviewed-by: Muhammad Husaini Zulkifli <muhammad.husaini.zulkifli@xxxxxxxxx>
    Tested-by: Naama Meir <naamax.meir@xxxxxxxxxxxxxxx>
    Signed-off-by: Tony Nguyen <anthony.l.nguyen@xxxxxxxxx>
    Signed-off-by: Sasha Levin <sashal@xxxxxxxxxx>

diff --git a/drivers/net/ethernet/intel/igc/igc_ptp.c b/drivers/net/ethernet/intel/igc/igc_ptp.c
index 4e10ced736dbb..d96cdccdc1e1e 100644
--- a/drivers/net/ethernet/intel/igc/igc_ptp.c
+++ b/drivers/net/ethernet/intel/igc/igc_ptp.c
@@ -356,16 +356,35 @@ static int igc_ptp_feature_enable_i225(struct ptp_clock_info *ptp,
 			tsim &= ~IGC_TSICR_TT0;
 		}
 		if (on) {
+			struct timespec64 safe_start;
 			int i = rq->perout.index;
 
 			igc_pin_perout(igc, i, pin, use_freq);
-			igc->perout[i].start.tv_sec = rq->perout.start.sec;
+			igc_ptp_read(igc, &safe_start);
+
+			/* PPS output start time is triggered by Target time(TT)
+			 * register. Programming any past time value into TT
+			 * register will cause PPS to never start. Need to make
+			 * sure we program the TT register a time ahead in
+			 * future. There isn't a stringent need to fire PPS out
+			 * right away. Adding +2 seconds should take care of
+			 * corner cases. Let's say if the SYSTIML is close to
+			 * wrap up and the timer keeps ticking as we program the
+			 * register, adding +2seconds is safe bet.
+			 */
+			safe_start.tv_sec += 2;
+
+			if (rq->perout.start.sec < safe_start.tv_sec)
+				igc->perout[i].start.tv_sec = safe_start.tv_sec;
+			else
+				igc->perout[i].start.tv_sec = rq->perout.start.sec;
 			igc->perout[i].start.tv_nsec = rq->perout.start.nsec;
 			igc->perout[i].period.tv_sec = ts.tv_sec;
 			igc->perout[i].period.tv_nsec = ts.tv_nsec;
-			wr32(trgttimh, rq->perout.start.sec);
+			wr32(trgttimh, (u32)igc->perout[i].start.tv_sec);
 			/* For now, always select timer 0 as source. */
-			wr32(trgttiml, rq->perout.start.nsec | IGC_TT_IO_TIMER_SEL_SYSTIM0);
+			wr32(trgttiml, (u32)(igc->perout[i].start.tv_nsec |
+					     IGC_TT_IO_TIMER_SEL_SYSTIM0));
 			if (use_freq)
 				wr32(freqout, ns);
 			tsauxc |= tsauxc_mask;



[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[Index of Archives]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]

  Powered by Linux