Commit 38427664 authored by Alessandro Rubini's avatar Alessandro Rubini

time: fix proto-ext-whiterabbit

Signed-off-by: Alessandro Rubini's avatarAlessandro Rubini <rubini@gnudd.com>
parent 8d4eba82
...@@ -73,9 +73,9 @@ static int wr_listening(struct pp_instance *ppi, unsigned char *pkt, int plen) ...@@ -73,9 +73,9 @@ static int wr_listening(struct pp_instance *ppi, unsigned char *pkt, int plen)
static int wr_handle_preq(struct pp_instance *ppi) static int wr_handle_preq(struct pp_instance *ppi)
{ {
ppi->received_ptp_header.correctionfield.msb = 0; /* FIXME: why do we save this fractional part? */
ppi->received_ptp_header.correctionfield.lsb = clear_time(&ppi->cField);
phase_to_cf_units(ppi->last_rcv_time.phase); ppi->cField.scaled_nsecs = ppi->last_rcv_time.scaled_nsecs & 0xffff;
return 0; return 0;
} }
...@@ -84,7 +84,7 @@ static int wr_master_msg(struct pp_instance *ppi, unsigned char *pkt, int plen, ...@@ -84,7 +84,7 @@ static int wr_master_msg(struct pp_instance *ppi, unsigned char *pkt, int plen,
{ {
MsgHeader *hdr = &ppi->received_ptp_header; MsgHeader *hdr = &ppi->received_ptp_header;
MsgSignaling wrsig_msg; MsgSignaling wrsig_msg;
TimeInternal *time = &ppi->last_rcv_time; struct pp_time *time = &ppi->last_rcv_time;
if (msgtype != PPM_NO_MESSAGE) if (msgtype != PPM_NO_MESSAGE)
pp_diag(ppi, ext, 2, "hook: %s\n", __func__); pp_diag(ppi, ext, 2, "hook: %s\n", __func__);
...@@ -93,9 +93,8 @@ static int wr_master_msg(struct pp_instance *ppi, unsigned char *pkt, int plen, ...@@ -93,9 +93,8 @@ static int wr_master_msg(struct pp_instance *ppi, unsigned char *pkt, int plen,
/* This case is modified from the default one */ /* This case is modified from the default one */
case PPM_DELAY_REQ: case PPM_DELAY_REQ:
hdr->correctionfield.msb = 0; /* there is no cField now, we pp_time includes it all */
hdr->correctionfield.lsb = clear_time(&hdr->cField);
phase_to_cf_units(ppi->last_rcv_time.phase);
msg_issue_delay_resp(ppi, time); /* no error check */ msg_issue_delay_resp(ppi, time); /* no error check */
msgtype = PPM_NO_MESSAGE; msgtype = PPM_NO_MESSAGE;
break; break;
...@@ -131,15 +130,12 @@ static int wr_new_slave(struct pp_instance *ppi, unsigned char *pkt, int plen) ...@@ -131,15 +130,12 @@ static int wr_new_slave(struct pp_instance *ppi, unsigned char *pkt, int plen)
static int wr_handle_resp(struct pp_instance *ppi) static int wr_handle_resp(struct pp_instance *ppi)
{ {
MsgHeader *hdr = &ppi->received_ptp_header; struct pp_time *ofm = &DSCUR(ppi)->offsetFromMaster;
TimeInternal correction_field;
TimeInternal *ofm = &DSCUR(ppi)->offsetFromMaster;
struct wr_dsport *wrp = WR_DSPOR(ppi); struct wr_dsport *wrp = WR_DSPOR(ppi);
pp_diag(ppi, ext, 2, "hook: %s\n", __func__); pp_diag(ppi, ext, 2, "hook: %s\n", __func__);
/* FIXME: check sub-nano relevance of correction filed */ /* This correction_field we received is already part of t4 */
cField_to_TimeInternal(&correction_field, hdr->correctionfield);
/* /*
* If no WR mode is on, run normal code, if T2/T3 are valid. * If no WR mode is on, run normal code, if T2/T3 are valid.
...@@ -147,7 +143,7 @@ static int wr_handle_resp(struct pp_instance *ppi) ...@@ -147,7 +143,7 @@ static int wr_handle_resp(struct pp_instance *ppi)
* we'll have the Unix time instead, marked by "correct" * we'll have the Unix time instead, marked by "correct"
*/ */
if (!wrp->wrModeOn) { if (!wrp->wrModeOn) {
if (!ppi->t2.correct || !ppi->t3.correct) { if (is_incorrect(&ppi->t2) || is_incorrect(&ppi->t3)) {
pp_diag(ppi, servo, 1, pp_diag(ppi, servo, 1,
"T2 or T3 incorrect, discarding tuple\n"); "T2 or T3 incorrect, discarding tuple\n");
return 0; return 0;
...@@ -156,13 +152,13 @@ static int wr_handle_resp(struct pp_instance *ppi) ...@@ -156,13 +152,13 @@ static int wr_handle_resp(struct pp_instance *ppi)
/* /*
* pps always on if offset less than 1 second, * pps always on if offset less than 1 second,
* until ve have a configurable threshold */ * until ve have a configurable threshold */
if (ofm->seconds) if (ofm->secs)
wrp->ops->enable_timing_output(ppi, 0); wrp->ops->enable_timing_output(ppi, 0);
else else
wrp->ops->enable_timing_output(ppi, 1); wrp->ops->enable_timing_output(ppi, 1);
} }
wr_servo_got_delay(ppi, hdr->correctionfield.lsb); wr_servo_got_delay(ppi);
wr_servo_update(ppi); wr_servo_update(ppi);
return 0; return 0;
} }
...@@ -206,14 +202,13 @@ static int wr_handle_announce(struct pp_instance *ppi) ...@@ -206,14 +202,13 @@ static int wr_handle_announce(struct pp_instance *ppi)
} }
static int wr_handle_followup(struct pp_instance *ppi, static int wr_handle_followup(struct pp_instance *ppi,
TimeInternal *precise_orig_timestamp, struct pp_time *precise_orig_timestamp,
TimeInternal *correction_field) struct pp_time *correction_field)
{ {
pp_diag(ppi, ext, 2, "hook: %s\n", __func__); pp_diag(ppi, ext, 2, "hook: %s\n", __func__);
if (!WR_DSPOR(ppi)->wrModeOn) if (!WR_DSPOR(ppi)->wrModeOn)
return 0; return 0;
precise_orig_timestamp->phase = 0;
wr_servo_got_sync(ppi, precise_orig_timestamp, wr_servo_got_sync(ppi, precise_orig_timestamp,
&ppi->t2); &ppi->t2);
...@@ -225,13 +220,8 @@ static int wr_handle_followup(struct pp_instance *ppi, ...@@ -225,13 +220,8 @@ static int wr_handle_followup(struct pp_instance *ppi,
static __attribute__((used)) int wr_handle_presp(struct pp_instance *ppi) static __attribute__((used)) int wr_handle_presp(struct pp_instance *ppi)
{ {
MsgHeader *hdr = &ppi->received_ptp_header;
TimeInternal correction_field;
struct wr_dsport *wrp = WR_DSPOR(ppi); struct wr_dsport *wrp = WR_DSPOR(ppi);
TimeInternal *ofm = &DSCUR(ppi)->offsetFromMaster; struct pp_time *ofm = &DSCUR(ppi)->offsetFromMaster;
/* FIXME: check sub-nano relevance of correction filed */
cField_to_TimeInternal(&correction_field, hdr->correctionfield);
/* /*
* If no WR mode is on, run normal code, if T2/T3 are valid. * If no WR mode is on, run normal code, if T2/T3 are valid.
...@@ -240,7 +230,7 @@ static __attribute__((used)) int wr_handle_presp(struct pp_instance *ppi) ...@@ -240,7 +230,7 @@ static __attribute__((used)) int wr_handle_presp(struct pp_instance *ppi)
*/ */
if (!wrp->wrModeOn) { if (!wrp->wrModeOn) {
if (!ppi->t3.correct || !ppi->t6.correct) { if (is_incorrect(&ppi->t3) || is_incorrect(&ppi->t6)) {
pp_diag(ppi, servo, 1, pp_diag(ppi, servo, 1,
"T3 or T6 incorrect, discarding tuple\n"); "T3 or T6 incorrect, discarding tuple\n");
return 0; return 0;
...@@ -249,7 +239,7 @@ static __attribute__((used)) int wr_handle_presp(struct pp_instance *ppi) ...@@ -249,7 +239,7 @@ static __attribute__((used)) int wr_handle_presp(struct pp_instance *ppi)
/* /*
* pps always on if offset less than 1 second, * pps always on if offset less than 1 second,
* until ve have a configurable threshold */ * until ve have a configurable threshold */
if (ofm->seconds) if (ofm->secs)
wrp->ops->enable_timing_output(ppi, 0); wrp->ops->enable_timing_output(ppi, 0);
else else
wrp->ops->enable_timing_output(ppi, 1); wrp->ops->enable_timing_output(ppi, 1);
......
...@@ -12,8 +12,7 @@ ...@@ -12,8 +12,7 @@
#include <ppsi/lib.h> #include <ppsi/lib.h>
#include "wr-constants.h" #include "wr-constants.h"
#define WRS_PPSI_SHMEM_VERSION 17 /* Changed definition of field mcast_addr of #define WRS_PPSI_SHMEM_VERSION 18 /* New pp_time everywhere */
* struct pp_instance */
/* /*
* This structure is used as extension-specific data in the DSPort * This structure is used as extension-specific data in the DSPort
...@@ -135,7 +134,7 @@ void wr_servo_reset(struct pp_instance *ppi); ...@@ -135,7 +134,7 @@ void wr_servo_reset(struct pp_instance *ppi);
void wr_servo_enable_tracking(int enable); void wr_servo_enable_tracking(int enable);
int wr_servo_got_sync(struct pp_instance *ppi, struct pp_time *t1, int wr_servo_got_sync(struct pp_instance *ppi, struct pp_time *t1,
struct pp_time *t2); struct pp_time *t2);
int wr_servo_got_delay(struct pp_instance *ppi, Integer32 cf); int wr_servo_got_delay(struct pp_instance *ppi);
int wr_servo_update(struct pp_instance *ppi); int wr_servo_update(struct pp_instance *ppi);
struct wr_servo_state { struct wr_servo_state {
......
...@@ -36,105 +36,78 @@ void wr_servo_enable_tracking(int enable) ...@@ -36,105 +36,78 @@ void wr_servo_enable_tracking(int enable)
/* my own timestamp arithmetic functions */ /* my own timestamp arithmetic functions */
static void dump_timestamp(struct pp_instance *ppi, char *what, TimeInternal ts) static void dump_timestamp(struct pp_instance *ppi, char *what,
struct pp_time ts)
{ {
pp_diag(ppi, servo, 2, "%s = %d:%d:%d\n", what, (int32_t)ts.seconds, pp_diag(ppi, servo, 2, "%s = %ld:%ld:%ld\n", what, (long)ts.secs,
ts.nanoseconds, ts.phase); (long)(ts.scaled_nsecs >> 16),
/* unlikely what we had earlier, third field is not phase */
((long)(ts.scaled_nsecs & 0xffff) * 1000 + 0x8000) >> 16);
} }
static int64_t ts_to_picos(TimeInternal ts) static int64_t ts_to_picos(struct pp_time *ts)
{ {
return ts.seconds * 1000000000000LL return ts->secs * PP_NSEC_PER_SEC
+ ts.nanoseconds * 1000LL + ((ts->scaled_nsecs * 1000 + 0x8000) >> 16);
+ ts.phase;
} }
static TimeInternal picos_to_ts(int64_t picos) static void picos_to_ts(int64_t picos, struct pp_time *ts)
{ {
uint64_t nsec, phase; uint64_t sec, nsec;
TimeInternal ts; int phase;
int sign = (picos < 0 ? -1 : 1);
picos *= sign;
nsec = picos; nsec = picos;
phase = __div64_32(&nsec, 1000); phase = __div64_32(&nsec, 1000);
sec = nsec;
ts.nanoseconds = __div64_32(&nsec, PP_NSEC_PER_SEC); ts->scaled_nsecs = __div64_32(&sec, PP_NSEC_PER_SEC) << 16;
ts.seconds = nsec; /* after the division */ ts->scaled_nsecs += (phase << 16) / 1000;
ts.phase = phase; ts->scaled_nsecs *= sign;
return ts; ts->secs = sec * sign;
}
static TimeInternal ts_add(TimeInternal a, TimeInternal b)
{
TimeInternal c;
c.phase = a.phase + b.phase;
c.nanoseconds = a.nanoseconds + b.nanoseconds;
c.seconds = a.seconds + b.seconds;
while (c.phase >= 1000) {
c.phase -= 1000;
c.nanoseconds++;
}
while (c.nanoseconds >= PP_NSEC_PER_SEC) {
c.nanoseconds -= PP_NSEC_PER_SEC;
c.seconds++;
}
return c;
}
static TimeInternal ts_sub(TimeInternal a, TimeInternal b)
{
TimeInternal c;
c.phase = a.phase - b.phase;
c.nanoseconds = a.nanoseconds - b.nanoseconds;
c.seconds = a.seconds - b.seconds;
while(c.phase < 0) {
c.phase += 1000;
c.nanoseconds--;
}
while(c.nanoseconds < 0) {
c.nanoseconds += PP_NSEC_PER_SEC;
c.seconds--;
}
return c;
} }
/* "Hardwarizes" the timestamp - e.g. makes the nanosecond field a multiple /* "Hardwarizes" the timestamp - e.g. makes the nanosecond field a multiple
* of 8ns cycles and puts the extra nanoseconds in the phase field */ * of 8/16ns cycles and puts the extra nanoseconds in the picos result */
static TimeInternal ts_hardwarize(TimeInternal ts, int clock_period_ps) static void ts_hardwarize(struct pp_time *time, int clock_period_ps,
int32_t *ticks, int32_t *picos)
{ {
int32_t q_threshold; int32_t s, ns, ps, clock_ns;
q_threshold = (clock_period_ps + 999) / 1000; /* clock_period_ps *must* be a multiple of 1000 -- assert()? */
clock_ns = clock_period_ps / 1000;
if (ts.nanoseconds > 0) {
int32_t extra_nsec = ts.nanoseconds % q_threshold; /*
* In pp_time, both sec/nsec are positive, or both negative.
if(extra_nsec) { * Only 0 secs can have positive or negative nsecs.
ts.nanoseconds -= extra_nsec; *
ts.phase += extra_nsec * 1000; * Here we need a positive count for both tick and picos. Or not.
} * The code here replicates what found in original WR code.
*/
s = time->secs; /* a difference: known to fit 32 bits (really?) */
ps = time->scaled_nsecs & 0xffff; /* fractional nano */
ps = (ps * 1000) >> 16; /* now picoseconds 0..999 -- positive*/
ns = time->scaled_nsecs >> 16;
if (ns > 0) {
ps += (ns % clock_ns) * 1000;
ns -= (ns % clock_ns);
} }
if (ns < 0) {
if (ts.nanoseconds < 0) { s--;
ts.nanoseconds += PP_NSEC_PER_SEC; ns += PP_NSEC_PER_SEC;
ts.seconds--;
} }
if (s == -1 && ns > 0) {
if (ts.seconds == -1 && ts.nanoseconds > 0) { s++;
ts.seconds++; ns -= PP_NSEC_PER_SEC;
ts.nanoseconds -= PP_NSEC_PER_SEC;
} }
if (ns < 0 && s == 0 && ns >= -clock_ns) {
if (ts.nanoseconds < 0 && ts.nanoseconds >= (-q_threshold) /* originally, ns was a multiple of clock_ns, code differs */
&& ts.seconds == 0) { ps += ns * 1000;
ts.nanoseconds += q_threshold; ns = 0;
ts.phase -= q_threshold * 1000;
} }
*ticks = ns;
return ts; *picos = ps;
} }
/* end my own timestamp arithmetic functions */ /* end my own timestamp arithmetic functions */
...@@ -219,18 +192,15 @@ int wr_servo_init(struct pp_instance *ppi) ...@@ -219,18 +192,15 @@ int wr_servo_init(struct pp_instance *ppi)
return 0; return 0;
} }
int wr_servo_got_sync(struct pp_instance *ppi, TimeInternal *t1, int wr_servo_got_sync(struct pp_instance *ppi, struct pp_time *t1,
TimeInternal *t2) struct pp_time *t2)
{ {
struct wr_servo_state *s = struct wr_servo_state *s =
&((struct wr_data *)ppi->ext_data)->servo_state; &((struct wr_data *)ppi->ext_data)->servo_state;
s->t1 = *t1; s->t1 = *t1;
s->t1.correct = 1;
s->t2 = *t2; s->t2 = *t2;
got_sync = 1; got_sync = 1;
return 0; return 0;
} }
...@@ -248,8 +218,6 @@ int wr_servo_got_delay(struct pp_instance *ppi) ...@@ -248,8 +218,6 @@ int wr_servo_got_delay(struct pp_instance *ppi)
if (CONFIG_HAS_P2P && ppi->mech == PP_P2P_MECH) { if (CONFIG_HAS_P2P && ppi->mech == PP_P2P_MECH) {
s->t5 = ppi->t5; s->t5 = ppi->t5;
s->t5.correct = 1;
s->t5.phase = 0;
s->t6 = ppi->t6; s->t6 = ppi->t6;
wr_p2p_delay(ppi, s); wr_p2p_delay(ppi, s);
...@@ -264,20 +232,28 @@ int wr_p2p_delay(struct pp_instance *ppi, struct wr_servo_state *s) ...@@ -264,20 +232,28 @@ int wr_p2p_delay(struct pp_instance *ppi, struct wr_servo_state *s)
uint64_t big_delta_fix; uint64_t big_delta_fix;
static int errcount; static int errcount;
if (!s->t3.correct || !s->t4.correct || if (is_incorrect(&s->t3) || is_incorrect(&s->t4)
!s->t5.correct || !s->t6.correct) { || is_incorrect(&s->t5) || is_incorrect(&s->t6)) {
errcount++; errcount++;
if (errcount > 5) /* a 2-3 in a row are expected */ if (errcount > 5) /* a 2-3 in a row are expected */
pp_error("%s: TimestampsIncorrect: %d %d %d %d\n", pp_error("%s: TimestampsIncorrect: %d %d %d %d\n",
__func__, s->t3.correct, s->t4.correct, __func__, !is_incorrect(&s->t3),
s->t5.correct, s->t6.correct); !is_incorrect(&s->t4), !is_incorrect(&s->t5),
!is_incorrect(&s->t6));
return 0; return 0;
} }
errcount = 0; errcount = 0;
s->update_count++; s->update_count++;
s->mu = ts_sub(ts_sub(s->t6, s->t3), ts_sub(s->t5, s->t4)); { /* avoid modifying stamps in place */
struct pp_time mtime, stime;
stime = s->t6; pp_time_sub(&stime, &s->t3);
mtime = s->t5; pp_time_sub(&mtime, &s->t4);
s->mu = stime; pp_time_sub(&s->mu, &mtime);
}
if (__PP_DIAG_ALLOW(ppi, pp_dt_servo, 1)) { if (__PP_DIAG_ALLOW(ppi, pp_dt_servo, 1)) {
dump_timestamp(ppi, "servo:t1", s->t1); dump_timestamp(ppi, "servo:t1", s->t1);
...@@ -289,30 +265,31 @@ int wr_p2p_delay(struct pp_instance *ppi, struct wr_servo_state *s) ...@@ -289,30 +265,31 @@ int wr_p2p_delay(struct pp_instance *ppi, struct wr_servo_state *s)
dump_timestamp(ppi, "->mdelay", s->mu); dump_timestamp(ppi, "->mdelay", s->mu);
} }
s->picos_mu = ts_to_picos(s->mu); s->picos_mu = ts_to_picos(&s->mu);
big_delta_fix = s->delta_tx_m + s->delta_tx_s big_delta_fix = s->delta_tx_m + s->delta_tx_s
+ s->delta_rx_m + s->delta_rx_s; + s->delta_rx_m + s->delta_rx_s;
s->delta_ms = s->delta_ms =
(((int64_t) (ts_to_picos(s->mu) - big_delta_fix) * (((int64_t) (ts_to_picos(&s->mu) - big_delta_fix) *
(int64_t) s->fiber_fix_alpha) >> FIX_ALPHA_FRACBITS) (int64_t) s->fiber_fix_alpha) >> FIX_ALPHA_FRACBITS)
+ ((ts_to_picos(s->mu) - big_delta_fix) >> 1) + ((ts_to_picos(&s->mu) - big_delta_fix) >> 1)
+ s->delta_tx_m + s->delta_rx_s; + s->delta_tx_m + s->delta_rx_s;
return 1; return 1;
} }
int wr_p2p_offset(struct pp_instance *ppi, int wr_p2p_offset(struct pp_instance *ppi,
struct wr_servo_state *s, TimeInternal *ts_offset_hw) struct wr_servo_state *s, struct pp_time *ts_offset)
{ {
TimeInternal ts_offset;
static int errcount; static int errcount;
struct pp_time time_ms;
if (!s->t1.correct || !s->t2.correct) { if (is_incorrect(&s->t1) || is_incorrect(&s->t2)) {
errcount++; errcount++;
if (errcount > 5) /* a 2-3 in a row are expected */ if (errcount > 5) /* a 2-3 in a row are expected */
pp_error("%s: TimestampsIncorrect: %d %d \n", pp_error("%s: TimestampsIncorrect: %d %d \n",
__func__, s->t1.correct, s->t2.correct); __func__, !is_incorrect(&s->t1),
!is_incorrect(&s->t2));
return 0; return 0;
} }
errcount = 0; errcount = 0;
...@@ -320,8 +297,10 @@ int wr_p2p_offset(struct pp_instance *ppi, ...@@ -320,8 +297,10 @@ int wr_p2p_offset(struct pp_instance *ppi,
s->update_count++; s->update_count++;
ts_offset = ts_add(ts_sub(s->t1, s->t2), picos_to_ts(s->delta_ms)); picos_to_ts(s->delta_ms, &time_ms);
*ts_offset_hw = ts_hardwarize(ts_offset, s->clock_period_ps); *ts_offset = s->t1;
pp_time_sub(ts_offset, &s->t2);
pp_time_add(ts_offset, &time_ms);
/* is it possible to calculate it in client, /* is it possible to calculate it in client,
* but then t1 and t2 require shmem locks */ * but then t1 and t2 require shmem locks */
...@@ -333,35 +312,41 @@ int wr_p2p_offset(struct pp_instance *ppi, ...@@ -333,35 +312,41 @@ int wr_p2p_offset(struct pp_instance *ppi,
} }
int wr_e2e_offset(struct pp_instance *ppi, int wr_e2e_offset(struct pp_instance *ppi,
struct wr_servo_state *s, TimeInternal *ts_offset_hw) struct wr_servo_state *s, struct pp_time *ts_offset)
{ {
struct wr_dsport *wrp = WR_DSPOR(ppi); struct wr_dsport *wrp = WR_DSPOR(ppi);
uint64_t big_delta_fix; uint64_t big_delta_fix;
uint64_t delay_ms_fix; uint64_t delay_ms_fix;
TimeInternal ts_offset;
static int errcount; static int errcount;
if(!s->t1.correct || !s->t2.correct || if (is_incorrect(&s->t1) || is_incorrect(&s->t2)
!s->t3.correct || !s->t4.correct) { || is_incorrect(&s->t3) || is_incorrect(&s->t4)) {
errcount++; errcount++;
if (errcount > 5) /* a 2-3 in a row are expected */ if (errcount > 5) /* a 2-3 in a row are expected */
pp_error("%s: TimestampsIncorrect: %d %d %d %d\n", pp_error("%s: TimestampsIncorrect: %d %d %d %d\n",
__func__, s->t1.correct, s->t2.correct, __func__, !is_incorrect(&s->t1),
s->t3.correct, s->t4.correct); !is_incorrect(&s->t2), !is_incorrect(&s->t3),
!is_incorrect(&s->t4));
return 0; return 0;
} }
if (wrp->ops->servo_hook) if (wrp->ops->servo_hook) /* FIXME: check this, missing in p2p */
wrp->ops->servo_hook(s, WR_SERVO_ENTER); wrp->ops->servo_hook(s, WR_SERVO_ENTER);
errcount = 0; errcount = 0;
s->update_count++; s->update_count++;
ppi->t_ops->get(ppi, &s->update_time); ppi->t_ops->get(ppi, &s->update_time); /* FIXME: missing in p2p */
got_sync = 0; got_sync = 0;
s->mu = ts_sub(ts_sub(s->t4, s->t1), ts_sub(s->t3, s->t2)); { /* avoid modifying stamps in place */
struct pp_time mtime, stime;
mtime = s->t4; pp_time_sub(&mtime, &s->t1);
stime = s->t3; pp_time_sub(&stime, &s->t2);
s->mu = mtime; pp_time_sub(&s->mu, &stime);
}
if (__PP_DIAG_ALLOW(ppi, pp_dt_servo, 1)) { if (__PP_DIAG_ALLOW(ppi, pp_dt_servo, 1)) {
dump_timestamp(ppi, "servo:t1", s->t1); dump_timestamp(ppi, "servo:t1", s->t1);
...@@ -371,7 +356,7 @@ int wr_e2e_offset(struct pp_instance *ppi, ...@@ -371,7 +356,7 @@ int wr_e2e_offset(struct pp_instance *ppi,
dump_timestamp(ppi, "->mdelay", s->mu); dump_timestamp(ppi, "->mdelay", s->mu);
} }
s->picos_mu = ts_to_picos(s->mu); s->picos_mu = ts_to_picos(&s->mu);
big_delta_fix = s->delta_tx_m + s->delta_tx_s big_delta_fix = s->delta_tx_m + s->delta_tx_s
+ s->delta_rx_m + s->delta_rx_s; + s->delta_rx_m + s->delta_rx_s;
...@@ -380,12 +365,20 @@ int wr_e2e_offset(struct pp_instance *ppi, ...@@ -380,12 +365,20 @@ int wr_e2e_offset(struct pp_instance *ppi,
s->picos_mu = big_delta_fix; s->picos_mu = big_delta_fix;
} }
delay_ms_fix = (((int64_t)(s->picos_mu - big_delta_fix) * (int64_t) s->fiber_fix_alpha) >> FIX_ALPHA_FRACBITS) delay_ms_fix = (((s->picos_mu - big_delta_fix)
+ ((s->picos_mu - big_delta_fix) >> 1) * s->fiber_fix_alpha) >> FIX_ALPHA_FRACBITS)
+ s->delta_tx_m + s->delta_rx_s; + ((s->picos_mu - big_delta_fix) >> 1)
+ s->delta_tx_m + s->delta_rx_s;
{ /* again, use temps to avoid modifying tx in place */
struct pp_time tmp = s->t1, tmp2;
ts_offset = ts_add(ts_sub(s->t1, s->t2), picos_to_ts(delay_ms_fix)); pp_time_sub(&tmp, &s->t2);
*ts_offset_hw = ts_hardwarize(ts_offset, s->clock_period_ps); picos_to_ts(delay_ms_fix, &tmp2);
pp_time_add(&tmp, &tmp2);
*ts_offset = tmp;
}
/* is it possible to calculate it in client, /* is it possible to calculate it in client,
* but then t1 and t2 require shmem locks */ * but then t1 and t2 require shmem locks */
...@@ -406,7 +399,9 @@ int wr_servo_update(struct pp_instance *ppi) ...@@ -406,7 +399,9 @@ int wr_servo_update(struct pp_instance *ppi)
int remaining_offset; int remaining_offset;
int64_t picos_mu_prev = 0; int64_t picos_mu_prev = 0;
TimeInternal ts_offset_hw /*, ts_phase_adjust */ ; struct pp_time ts_offset;
int32_t ts_offset_ticks;
int32_t ts_offset_picos;
if (!got_sync) if (!got_sync)
return 0; return 0;
...@@ -416,13 +411,20 @@ int wr_servo_update(struct pp_instance *ppi) ...@@ -416,13 +411,20 @@ int wr_servo_update(struct pp_instance *ppi)
picos_mu_prev = s->picos_mu; picos_mu_prev = s->picos_mu;
if (CONFIG_HAS_P2P && ppi->mech == PP_P2P_MECH) { if (CONFIG_HAS_P2P && ppi->mech == PP_P2P_MECH) {
if (!wr_p2p_offset(ppi, s, &ts_offset_hw)) if (!wr_p2p_offset(ppi, s, &ts_offset))
goto out; goto out;
} else { } else {
if (!wr_e2e_offset(ppi, s, &ts_offset_hw)) if (!wr_e2e_offset(ppi, s, &ts_offset))
goto out; goto out;
} }
ts_hardwarize(&ts_offset, s->clock_period_ps,
&ts_offset_ticks, &ts_offset_picos);
pp_diag(ppi, servo, 2, "offset_hw: %li.%09li (+%li)\n",
(long)ts_offset.secs, (long)ts_offset_ticks,
(long)ts_offset_picos);
if (wrp->ops->locking_poll(ppi, 0) != WR_SPLL_READY) { if (wrp->ops->locking_poll(ppi, 0) != WR_SPLL_READY) {
pp_diag(ppi, servo, 1, "PLL OutOfLock, should restart sync\n"); pp_diag(ppi, servo, 1, "PLL OutOfLock, should restart sync\n");
wrp->ops->enable_timing_output(ppi, 0); wrp->ops->enable_timing_output(ppi, 0);
...@@ -439,16 +441,12 @@ int wr_servo_update(struct pp_instance *ppi) ...@@ -439,16 +441,12 @@ int wr_servo_update(struct pp_instance *ppi)
} }
/* So, we didn't return. Choose the right state */ /* So, we didn't return. Choose the right state */
if (ts_offset_hw.seconds) /* so bad... */ if (ts_offset.secs) /* so bad... */
s->state = WR_SYNC_TAI; s->state = WR_SYNC_TAI;
else if (ts_offset_hw.nanoseconds) /* not that bad */ else if (ts_offset_ticks) /* not that bad */
s->state = WR_SYNC_NSEC; s->state = WR_SYNC_NSEC;
/* else, let the states below choose the sequence */ /* else, let the states below choose the sequence */
pp_diag(ppi, servo, 2, "offset_hw: %li.%09li (+%li)\n",
(long)ts_offset_hw.seconds, (long)ts_offset_hw.nanoseconds,
(long)ts_offset_hw.phase);
pp_diag(ppi, servo, 1, "wr_servo state: %s%s\n", pp_diag(ppi, servo, 1, "wr_servo state: %s%s\n",
servo_name[s->state], servo_name[s->state],
s->flags & WR_FLAG_WAIT_HW ? " (wait for hw)" : ""); s->flags & WR_FLAG_WAIT_HW ? " (wait for hw)" : "");
...@@ -458,7 +456,7 @@ int wr_servo_update(struct pp_instance *ppi) ...@@ -458,7 +456,7 @@ int wr_servo_update(struct pp_instance *ppi)
switch (s->state) { switch (s->state) {
case WR_SYNC_TAI: case WR_SYNC_TAI:
wrp->ops->adjust_counters(ts_offset_hw.seconds, 0); wrp->ops->adjust_counters(ts_offset.secs, 0);
s->flags |= WR_FLAG_WAIT_HW; s->flags |= WR_FLAG_WAIT_HW;
/* /*
* If nsec wrong, code above forces SYNC_NSEC, * If nsec wrong, code above forces SYNC_NSEC,
...@@ -469,16 +467,16 @@ int wr_servo_update(struct pp_instance *ppi) ...@@ -469,16 +467,16 @@ int wr_servo_update(struct pp_instance *ppi)
break; break;
case WR_SYNC_NSEC: case WR_SYNC_NSEC:
wrp->ops->adjust_counters(0, ts_offset_hw.nanoseconds); wrp->ops->adjust_counters(0, ts_offset_ticks);
s->flags |= WR_FLAG_WAIT_HW; s->flags |= WR_FLAG_WAIT_HW;
s->state = WR_SYNC_PHASE; s->state = WR_SYNC_PHASE;
break; break;
case WR_SYNC_PHASE: case WR_SYNC_PHASE:
pp_diag(ppi, servo, 2, "oldsetp %i, offset %i:%04i\n", pp_diag(ppi, servo, 2, "oldsetp %i, offset %i:%04i\n",
s->cur_setpoint, ts_offset_hw.nanoseconds, s->cur_setpoint, ts_offset_ticks,
ts_offset_hw.phase); ts_offset_picos);
s->cur_setpoint += ts_offset_hw.phase; s->cur_setpoint += ts_offset_picos;
wrp->ops->adjust_phase(s->cur_setpoint); wrp->ops->adjust_phase(s->cur_setpoint);
s->flags |= WR_FLAG_WAIT_HW; s->flags |= WR_FLAG_WAIT_HW;
...@@ -494,14 +492,14 @@ int wr_servo_update(struct pp_instance *ppi) ...@@ -494,14 +492,14 @@ int wr_servo_update(struct pp_instance *ppi)
*/ */
unix_time_ops.set(ppi, &ppi->t4); unix_time_ops.set(ppi, &ppi->t4);
pp_diag(ppi, time, 1, "system time set to %li TAI\n", pp_diag(ppi, time, 1, "system time set to %li TAI\n",
(long)ppi->t4.seconds); (long)ppi->t4.secs);
} }
break; break;
case WR_WAIT_OFFSET_STABLE: case WR_WAIT_OFFSET_STABLE:
/* ts_to_picos() below returns phase alone */ /* ts_to_picos() below returns phase alone */
remaining_offset = abs(ts_to_picos(ts_offset_hw)); remaining_offset = abs(ts_offset_picos);
if(remaining_offset < WR_SERVO_OFFSET_STABILITY_THRESHOLD) { if(remaining_offset < WR_SERVO_OFFSET_STABILITY_THRESHOLD) {
wrp->ops->enable_timing_output(ppi, 1); wrp->ops->enable_timing_output(ppi, 1);
s->delta_ms_prev = s->delta_ms; s->delta_ms_prev = s->delta_ms;
...@@ -520,14 +518,14 @@ int wr_servo_update(struct pp_instance *ppi) ...@@ -520,14 +518,14 @@ int wr_servo_update(struct pp_instance *ppi)
/* Can be disabled for manually tweaking and testing */ /* Can be disabled for manually tweaking and testing */
if(tracking_enabled) { if(tracking_enabled) {
if (abs(ts_offset_hw.phase) > if (abs(ts_offset_picos) >
2 * WR_SERVO_OFFSET_STABILITY_THRESHOLD) { 2 * WR_SERVO_OFFSET_STABILITY_THRESHOLD) {
s->state = WR_SYNC_PHASE; s->state = WR_SYNC_PHASE;
break; break;
} }
// adjust phase towards offset = 0 make ck0 0 // adjust phase towards offset = 0 make ck0 0
s->cur_setpoint += (ts_offset_hw.phase / 4); s->cur_setpoint += (ts_offset_picos / 4);
wrp->ops->adjust_phase(s->cur_setpoint); wrp->ops->adjust_phase(s->cur_setpoint);
pp_diag(ppi, time, 1, "adjust phase %i\n", pp_diag(ppi, time, 1, "adjust phase %i\n",
......
...@@ -52,8 +52,8 @@ static int slave_handle_response(struct pp_instance *ppi, unsigned char *pkt, ...@@ -52,8 +52,8 @@ static int slave_handle_response(struct pp_instance *ppi, unsigned char *pkt,
} }
ppi->t4 = resp.receiveTimestamp; ppi->t4 = resp.receiveTimestamp;
/* Save delay resp cf in ppi->cField */ pp_time_add(&ppi->t4, &hdr->cField);
ppi->cField = hdr->cField; /* FIXME: merge cField here? */ /* NOTE: older code was adding cField later, in hooks.handle_resp */
if (pp_hooks.handle_resp) if (pp_hooks.handle_resp)
e = pp_hooks.handle_resp(ppi); e = pp_hooks.handle_resp(ppi);
......
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