Commit 0b031b22 authored by baujc's avatar baujc

Review of WR protocol implementation

- It has now its own state table
- The servo is shared with L1Sync extension. It means that servo
calculation is now following the new standard IEEE 1588
- It stay compatible with older versions of the switch. The correction
field value in the exchange messages are still not compliant with the
standard to keep the compatibility.
parent 621c3372
...@@ -84,6 +84,7 @@ endif ...@@ -84,6 +84,7 @@ endif
ifeq ($(CONFIG_HAS_EXT_L1SYNC),1) ifeq ($(CONFIG_HAS_EXT_L1SYNC),1)
include proto-ext-l1sync/Makefile include proto-ext-l1sync/Makefile
endif endif
include proto-ext-common/Makefile
include proto-standard/Makefile include proto-standard/Makefile
# ...and the TIME choice sets the default operations # ...and the TIME choice sets the default operations
......
D := proto-ext-common
INC_WRH_SERVO=$(shell test ".$(CONFIG_HAS_EXT_WR)" = ".1" -o \
".$(CONFIG_HAS_EXT_L1SYNC)" = ".1" \
&& echo -n "true")
ifeq ($(INC_WRH_SERVO),true)
OBJ-y += $D/wrh-servo.o
endif
/*
* Copyright (C) 2018 CERN (www.cern.ch)
* Author: Jean-Claude BAU & Maciej Lipinski
*
* Released according to the GNU LGPL, version 2.1 or any later version.
*/
#include <stdint.h>
#include <inttypes.h>
#include <ppsi/ppsi.h>
// #include "wrs-constants.h"
#include <libwr/shmem.h>
#include "../proto-standard/common-fun.h"
static const char *wrh_servo_state_name[] = {
[WRH_UNINITIALIZED] = "Uninitialized",
[WRH_SYNC_NSEC] = "SYNC_NSEC",
[WRH_SYNC_TAI] = "SYNC_SEC",
[WRH_SYNC_PHASE] = "SYNC_PHASE",
[WRH_TRACK_PHASE] = "TRACK_PHASE",
[WRH_WAIT_OFFSET_STABLE] = "WAIT_OFFSET_STABLE",
};
/* Enable tracking by default. Disabling the tracking is used for demos. */
static int wrh_tracking_enabled = 1;
/* prototypes */
static int __wrh_servo_update(struct pp_instance *ppi);
/* External data */
extern struct wrs_shm_head *ppsi_head;
extern struct pp_time faulty_stamps[6]; /* if unused, dropped at link time */
void wrh_servo_enable_tracking(int enable)
{
wrh_tracking_enabled = enable;
}
/*
* Update calibration data
*/
int wrh_update_correction_values(struct pp_instance *ppi)
{
wrh_servo_t *s = WRH_SRV(ppi);
pp_diag(ppi, ext, 2, "hook: %s -- ext %i\n", __func__, ppi->protocol_extension);
/* read the interesting values from HW (i.e. HAL)*/
if ( WRH_OPER()->read_calib_data(ppi,&s->clock_period_ps,NULL) != WRH_HW_CALIB_OK){
pp_diag(ppi, ext, 2, "hook: %s -- cannot read calib values\n",
__func__);
return -1;
}
pp_diag(ppi, ext, 2, "ML- Updated correction values: Clock period=%d [ps]\n",
s->clock_period_ps);
return 0;
}
int wrh_servo_init(struct pp_instance *ppi)
{
wrh_servo_t *s=WRH_SRV(ppi);
struct pp_servo *gs=SRV(ppi);
int ret=0;
pp_servo_init(ppi); // Initialize the standard servo data
/* shmem lock */
wrs_shm_write(ppsi_head, WRS_SHM_WRITE_BEGIN);
WRH_SERVO_RESET_DATA(s);
/* Update correction data in data sets*/
if (wrh_update_correction_values(ppi) != -1) {
/*
* Do not reset cur_setpoint, but trim it to be less than one tick.
* The softpll code uses the module anyways, but if we unplug-replug
* the fiber it will always increase, so don't scare the user
*/
if (s->cur_setpoint_ps > s->clock_period_ps)
s->cur_setpoint_ps %= s->clock_period_ps;
pp_diag(ppi, servo, 3, "%s.%d: Adjust_phase: %d\n",__func__,__LINE__,s->cur_setpoint_ps);
WRH_OPER()->adjust_phase(s->cur_setpoint_ps);
strcpy(gs->servo_state_name, wrh_servo_state_name[gs->state]);
gs->flags |= PP_SERVO_FLAG_VALID;
ppi->t_ops->get(ppi, &gs->update_time);
s->tracking_enabled = wrh_tracking_enabled;
gs->state = WRH_SYNC_TAI;
}
/* shmem unlock */
wrs_shm_write(ppsi_head, WRS_SHM_WRITE_END);
return ret;
}
void wrh_servo_reset(struct pp_instance *ppi)
{
if ( ppi->ext_enabled ) {
/* shmem lock */
wrs_shm_write(ppsi_head, WRS_SHM_WRITE_BEGIN);
ppi->flags = 0;
WRH_SERVO_RESET_DATA(WRH_SRV(ppi));
SRV(ppi)->state = WRH_UNINITIALIZED;
/* shmem unlock */
wrs_shm_write(ppsi_head, WRS_SHM_WRITE_END);
}
}
/**
* SYNC/FOLLOW_UP messages have been received: t1/t2 are available
*/
int wrh_servo_got_sync(struct pp_instance *ppi)
{
struct pp_servo *gs=SRV(ppi);
/* shmem lock */
wrs_shm_write(ppsi_head, WRS_SHM_WRITE_BEGIN);
gs->t1=ppi->t1;apply_faulty_stamp(ppi,1);
gs->t2=ppi->t2;apply_faulty_stamp(ppi,2);
if ( is_delayMechanismP2P(ppi) && gs->got_sync) {
gs->got_sync=0;
__wrh_servo_update(ppi);
}else {
gs->got_sync=1;
}
/* shmem unlock */
wrs_shm_write(ppsi_head, WRS_SHM_WRITE_END);
return 0;
}
/**
* DELAY_RESPONSE message has been received: t3/t4 are available
*/
int wrh_servo_got_resp(struct pp_instance *ppi)
{
struct pp_servo *gs=SRV(ppi);
int ret;
static int errcount=0;
if ( !gs->got_sync )
return 0; /* t1 & t2 not available yet */
gs->got_sync=0;
if ( is_timestamps_incorrect(ppi,&errcount,0xC /* mask=t3&t4 */) )
return 0;
wrs_shm_write(ppsi_head, WRS_SHM_WRITE_BEGIN);
gs->t3 = ppi->t3; apply_faulty_stamp(ppi,3);
gs->t4 = ppi->t4; apply_faulty_stamp(ppi,4);
ret=__wrh_servo_update(ppi);
wrs_shm_write(ppsi_head, WRS_SHM_WRITE_END);
return ret;
}
/**
* PDELAY_RESPONSE_FUP message has been received: t3/t4/t5/t6 are available
*/
int wrh_servo_got_presp(struct pp_instance *ppi)
{
struct pp_servo *gs=SRV(ppi);
static int errcount=0;
if ( is_timestamps_incorrect(ppi,&errcount,0x3C /* mask=&t3&t4&t5&t6 */) )
return 0;
wrs_shm_write(ppsi_head, WRS_SHM_WRITE_BEGIN);
gs->t3 = ppi->t3; apply_faulty_stamp(ppi,3);
gs->t4 = ppi->t4; apply_faulty_stamp(ppi,4);
gs->t5 = ppi->t5; apply_faulty_stamp(ppi,5);
gs->t6 = ppi->t6; apply_faulty_stamp(ppi,6);
gs->got_sync=1;
wrs_shm_write(ppsi_head, WRS_SHM_WRITE_END);
return 1;
}
static int __wrh_servo_update(struct pp_instance *ppi)
{
struct pp_servo *gs=SRV(ppi);
wrh_servo_t *s=WRH_SRV(ppi);
int remaining_offset;
int32_t offset_ticks;
int64_t prev_delayMM_ps = 0;
int locking_poll_ret;
struct pp_time offsetMS ;
int32_t offset_ps;
if ( gs->state==WRH_UNINITIALIZED )
return 0;
prev_delayMM_ps = s->delayMM_ps;
if ( !pp_servo_calculate_delays(ppi) )
return 0;
s->delayMM_ps=pp_time_to_picos(&gs->delayMM);
offsetMS=gs->offsetFromMaster;
s->offsetMS_ps=pp_time_to_picos(&offsetMS);
s->tracking_enabled = wrh_tracking_enabled;
// Servo updated
gs->update_count++;
ppi->t_ops->get(ppi, &gs->update_time);
if (!s->readyForSync )
return 1; /* We have to wait before to start the synchronization */
locking_poll_ret = WRH_OPER()->locking_poll(ppi);
if (locking_poll_ret != WRH_SPLL_READY
&& locking_poll_ret != WRH_SPLL_CALIB_NOT_READY) {
pp_diag(ppi, servo, 1, "PLL out of lock\n");
/* TODO check
* DSPOR(ppi)->doRestart = TRUE; */
}
/* After each action on the hardware, we must verify if it is over. */
if (!WRH_OPER()->adjust_in_progress()) {
gs->flags &= ~PP_SERVO_FLAG_WAIT_HW;
} else {
pp_diag(ppi, servo, 1, "servo:busy\n");
return 1;
}
/* So, we didn't return. Choose the right state */
if (offsetMS.secs) {/* so bad... */
gs->state = WRH_SYNC_TAI;
pp_diag(ppi, servo, 2, "offsetMS: %li sec ...\n",
(long)offsetMS.secs);
} else {
pp_time_hardwarize(&offsetMS, s->clock_period_ps,
&offset_ticks, &offset_ps);
pp_diag(ppi, servo, 2, "offsetMS: %li sec %09li ticks (%li ps)\n",
(long)offsetMS.secs, (long)offset_ticks,
(long)offset_ps);
if (offset_ticks) /* not that bad */
gs->state = WRH_SYNC_NSEC;
/* else, let the states below choose the sequence */
}
/* update string state name */
strcpy(gs->servo_state_name, wrh_servo_state_name[gs->state]);
pp_diag(ppi, servo, 1, "wrh_servo state: %s%s\n",
gs->servo_state_name,
gs->flags & PP_SERVO_FLAG_WAIT_HW ? " (wait for hw)" : "");
switch (gs->state) {
case WRH_SYNC_TAI:
WRH_OPER()->adjust_counters(offsetMS.secs, 0);
gs->flags |= PP_SERVO_FLAG_WAIT_HW;
/*
* If nsec wrong, code above forces SYNC_NSEC,
* Else, we must ensure we leave this status towards
* fine tuning
*/
gs->state = WRH_SYNC_PHASE;
break;
case WRH_SYNC_NSEC:
WRH_OPER()->adjust_counters(0, offset_ticks);
gs->flags |= PP_SERVO_FLAG_WAIT_HW;
gs->state = WRH_SYNC_PHASE;
break;
case WRH_SYNC_PHASE:
pp_diag(ppi, servo, 2, "oldsetp %i, offset %i:%04i\n",
s->cur_setpoint_ps, offset_ticks,
offset_ps);
s->cur_setpoint_ps += offset_ps;
pp_diag(ppi, servo, 3, "%s.%d: Adjust_phase: %d\n",__func__,__LINE__,s->cur_setpoint_ps);
WRH_OPER()->adjust_phase(s->cur_setpoint_ps);
gs->flags |= PP_SERVO_FLAG_WAIT_HW;
gs->state = WRH_WAIT_OFFSET_STABLE;
if (CONFIG_ARCH_IS_WRS) {
/*
* Now, let's fix system time. We pass here
* once only, so that's the best place to do
* it. We use current WR time.
* */
struct pp_time t;
ppi->t_ops->get(ppi,&t);
unix_time_ops.set(ppi, &t);
pp_diag(ppi, time, 1, "system time set to %s TAI\n",
time_to_string(&t));
}
break;
case WRH_WAIT_OFFSET_STABLE:
/* ts_to_picos() below returns phase alone */
remaining_offset = abs(pp_time_to_picos(&offsetMS));
if(remaining_offset < WRH_SERVO_OFFSET_STABILITY_THRESHOLD) {
WRH_OPER()->enable_timing_output(GLBS(ppi),1);
s->prev_delayMS_ps = s->delayMS_ps;
gs->state = WRH_TRACK_PHASE;
} else {
s->missed_iters++;
}
if (s->missed_iters >= 10) {
s->missed_iters = 0;
gs->state = WRH_SYNC_PHASE;
}
break;
case WRH_TRACK_PHASE:
s->skew_ps = s->delayMS_ps - s->prev_delayMS_ps;
/* Can be disabled for manually tweaking and testing */
if(wrh_tracking_enabled) {
if (abs(offset_ps) >
2 * WRH_SERVO_OFFSET_STABILITY_THRESHOLD) {
gs->state = WRH_SYNC_PHASE;
break;
}
// adjust phase towards offset = 0 make ck0 0
s->cur_setpoint_ps += (offset_ps / 4);
pp_diag(ppi, servo, 3, "%s.%d: Adjust_phase: %d\n",__func__,__LINE__,s->cur_setpoint_ps);
WRH_OPER()->adjust_phase(s->cur_setpoint_ps);
pp_diag(ppi, time, 1, "adjust phase %i\n",
s->cur_setpoint_ps);
s->prev_delayMS_ps = s->delayMS_ps;
}
break;
}
gs->servo_locked=gs->state==WRH_TRACK_PHASE;
/* Increase number of servo updates with state different than
* WRH_TRACK_PHASE. (Used by SNMP) */
if (gs->state != WRH_TRACK_PHASE)
s->n_err_state++;
/* Increase number of servo updates with offset exceeded
* SNMP_MAX_OFFSET_PS (Used by SNMP) */
if (abs(s->offsetMS_ps) > SNMP_MAX_OFFSET_PS)
s->n_err_offset++;
/* Increase number of servo updates with delta rtt exceeded
* SNMP_MAX_DELTA_RTT_PS (Used by SNMP) */
if (abs(prev_delayMM_ps - s->delayMM_ps) > SNMP_MAX_DELTA_RTT_PS)
s->n_err_delta_rtt++;
return 1;
}
...@@ -4,6 +4,5 @@ D := proto-ext-l1sync ...@@ -4,6 +4,5 @@ D := proto-ext-l1sync
OBJ-y += $D/l1e-hooks.o \ OBJ-y += $D/l1e-hooks.o \
$D/l1e-servo.o\
$D/l1e-msg.o\ $D/l1e-msg.o\
$D/l1e-state-machine.o $D/l1e-state-machine.o
\ No newline at end of file
...@@ -13,7 +13,9 @@ OBJ-y += $D/fsm-table.o \ ...@@ -13,7 +13,9 @@ OBJ-y += $D/fsm-table.o \
$D/state-wr-calibrated.o \ $D/state-wr-calibrated.o \
$D/state-wr-resp-calib-req.o \ $D/state-wr-resp-calib-req.o \
$D/state-wr-link-on.o \ $D/state-wr-link-on.o \
$D/state-wr-idle.o \
$D/wr-msg.o \ $D/wr-msg.o \
$D/wr-servo.o $D/wr-servo.o \
$D/wr-state-machine.o
OBJ-$(CONFIG_ABSCAL) += $D/state-wr-abscal.o OBJ-$(CONFIG_ABSCAL) += $D/state-wr-abscal.o
...@@ -6,30 +6,19 @@ ...@@ -6,30 +6,19 @@
*/ */
#include <ppsi/ppsi.h> #include <ppsi/ppsi.h>
/* We are entering WR handshake, as either master or slave */ void wr_reset_process(struct pp_instance *ppi, wr_role_t role) {
void wr_handshake_init(struct pp_instance *ppi, int mode_or_retry)
{
struct wr_dsport *wrp = WR_DSPOR(ppi); struct wr_dsport *wrp = WR_DSPOR(ppi);
switch(mode_or_retry) { wrp->wrStateTimeout = WR_DEFAULT_STATE_TIMEOUT_MS;
wrp->calPeriod = WR_DEFAULT_CAL_PERIOD;
case PPS_MASTER: wrp->wrMode = role;
wrp->wrMode = WR_MASTER; wrp->wrModeOn=FALSE;
ppi->next_state = WRS_M_LOCK; wrp->calibrated = !WR_DEFAULT_PHY_CALIBRATION_REQUIRED;
break; /* Reset parent data */
wrp->parentWrConfig = NON_WR;
case PPS_SLAVE: wrp->parentIsWRnode =
wrp->wrMode = WR_SLAVE; wrp->parentWrModeOn =
ppi->next_state = WRS_PRESENT; wrp->parentCalibrated = FALSE;
break;
default: /* retry: only called from below in this file */
if (wrp->wrMode == WR_MASTER)
ppi->next_state = WRS_M_LOCK;
else
ppi->next_state = WRS_PRESENT;
break;
}
} }
/* The handshake failed: go master or slave in normal PTP mode */ /* The handshake failed: go master or slave in normal PTP mode */
...@@ -39,15 +28,10 @@ void wr_handshake_fail(struct pp_instance *ppi) ...@@ -39,15 +28,10 @@ void wr_handshake_fail(struct pp_instance *ppi)
pp_diag(ppi, ext, 1, "Handshake failure: now non-wr %s\n", pp_diag(ppi, ext, 1, "Handshake failure: now non-wr %s\n",
wrp->wrMode == WR_MASTER ? "master" : "slave"); wrp->wrMode == WR_MASTER ? "master" : "slave");
if (wrp->wrMode == WR_MASTER) wrp->next_state=WRS_IDLE;
ppi->next_state = PPS_MASTER; wr_reset_process(ppi,WR_ROLE_NONE);
else wr_servo_reset(ppi);
ppi->next_state = PPS_SLAVE; lstate_set_link_perror(ppi);
wrp->wrMode =
wrp->parentWrConfig = NON_WR;
wrp->parentIsWRnode =
wrp->parentWrModeOn =
wrp->parentCalibrated = FALSE;
} }
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
* This is the WR state machine table. * This is the WR state machine table.
*/ */
#if 0
struct pp_state_table_item pp_state_table[] = { struct pp_state_table_item pp_state_table[] = {
{ PPS_INITIALIZING, "initializing", pp_initializing,}, { PPS_INITIALIZING, "initializing", pp_initializing,},
{ PPS_FAULTY, "faulty", pp_faulty,}, { PPS_FAULTY, "faulty", pp_faulty,},
...@@ -34,3 +35,4 @@ struct pp_state_table_item pp_state_table[] = { ...@@ -34,3 +35,4 @@ struct pp_state_table_item pp_state_table[] = {
#endif #endif
{ PPS_END_OF_TABLE,} { PPS_END_OF_TABLE,}
}; };
#endif
This diff is collapsed.
...@@ -22,15 +22,17 @@ static int next_pps_ms(struct pp_instance *ppi, struct pp_time *t) ...@@ -22,15 +22,17 @@ static int next_pps_ms(struct pp_instance *ppi, struct pp_time *t)
* This is using a software loop during the last 10ms in order to get * This is using a software loop during the last 10ms in order to get
* right after the pps event * right after the pps event
*/ */
int wr_abscal(struct pp_instance *ppi, void *buf, int plen) #define WR_TMO_NAME "WR_ABSCAL"
int wr_abscal(struct pp_instance *ppi, void *buf, int plen, int new_state)
{ {
struct pp_time t; struct pp_time t;
struct wr_dsport *wrp = WR_DSPOR(ppi); struct wr_dsport *wrp = WR_DSPOR(ppi);
int len, i; int len, i;
if (ppi->is_new_state) { if (new_state) {
/* add 1s to be enough in the future, the first time */ /* add 1s to be enough in the future, the first time */
pp_timeout_set_rename(ppi, wrTmoIdx, 990 + next_pps_ms(ppi, &t),"WR_ABSCAL"); pp_timeout_set_rename(ppi, wrTmoIdx, 990 + next_pps_ms(ppi, &t),WR_TMO_NAME);
return 0; return 0;
} }
...@@ -51,10 +53,8 @@ int wr_abscal(struct pp_instance *ppi, void *buf, int plen) ...@@ -51,10 +53,8 @@ int wr_abscal(struct pp_instance *ppi, void *buf, int plen)
/* And again next second */ /* And again next second */
pp_timeout_set(ppi, wrTmoIdx, next_pps_ms(ppi, &t) - 10); pp_timeout_set(ppi, wrTmoIdx, next_pps_ms(ppi, &t) - 10);
ppi->next_delay = next_pps_ms(ppi, &t) - 10; return next_pps_ms(ppi, &t) - 10;
return 0;
} }
/* no timeout: wait according to next_pps_ms calculated earlier */ /* no timeout: wait according to next_pps_ms calculated earlier */
ppi->next_delay = i > 0 ? i : 0; return i > 0 ? i : 0;
return 0;
} }
...@@ -12,47 +12,53 @@ ...@@ -12,47 +12,53 @@
* We enter here from WRS_CALIBRATION. If master we wait for * We enter here from WRS_CALIBRATION. If master we wait for
* a CALIBRATE message, if slave we wait for LINK_ON. * a CALIBRATE message, if slave we wait for LINK_ON.
*/ */
int wr_calibrated(struct pp_instance *ppi, void *buf, int len) #define WR_TMO_NAME "WR_CALIBRATED"
#define WR_TMO_MS WR_CALIBRATED_TIMEOUT_MS
int wr_calibrated(struct pp_instance *ppi, void *buf, int len, int new_state)
{ {
struct wr_dsport *wrp = WR_DSPOR(ppi); struct wr_dsport *wrp = WR_DSPOR(ppi);
MsgSignaling wrsig_msg; MsgSignaling wrsig_msg;
int enable = 0; int sendmsg = 0;
if (ppi->is_new_state) { if (new_state) {
wrp->wrStateRetry = WR_STATE_RETRY; wrp->wrStateRetry = WR_STATE_RETRY;
pp_timeout_set_rename(ppi, wrTmoIdx, WR_CALIBRATED_TIMEOUT_MS*(WR_STATE_RETRY+1),"WR_CLAIBRATED"); pp_timeout_set_rename(ppi, wrTmoIdx, WR_TMO_MS*(WR_STATE_RETRY+1),WR_TMO_NAME);
enable = 1; sendmsg = 1;
} else { } else {
int rms=pp_next_delay_1(ppi, wrTmoIdx);
if ( rms==0 || rms<(wrp->wrStateRetry*WR_CALIBRATED_TIMEOUT_MS)) { if (ppi->received_ptp_header.messageType == PPM_SIGNALING) {
/* msg_unpack_wrsig(ppi, buf, &wrsig_msg,
* FIXME: We should implement a retry by re-sending &(wrp->msgTmpWrMessageID));
* the "calibrated" message, moving it here from the
* previous state (sub-state 8 of "state-wr-calibration" if ((wrp->msgTmpWrMessageID == CALIBRATE) &&
*/ (wrp->wrMode == WR_MASTER)) {
if (wr_handshake_retry(ppi)) wrp->next_state = WRS_RESP_CALIB_REQ;
enable = 1; return 0;
else }
return 0; /* non-wr already */ else if ((wrp->msgTmpWrMessageID == WR_MODE_ON) &&
(wrp->wrMode == WR_SLAVE)) {
wrp->next_state = WRS_WR_LINK_ON;
return 0;
}
}
{
/* Check if tmo expired */
int rms=pp_next_delay_1(ppi, wrTmoIdx);
if ( rms==0 || rms<(wrp->wrStateRetry*WR_TMO_MS)) {
if (wr_handshake_retry(ppi))
sendmsg = 1;
else {
pp_diag(ppi, time, 1, "timeout expired: "WR_TMO_NAME"\n");
return 0; /* non-wr already */
}
}
} }
} }
if (enable){ if (sendmsg){
msg_issue_wrsig(ppi, CALIBRATED); msg_issue_wrsig(ppi, CALIBRATED);
} }
if (ppi->received_ptp_header.messageType == PPM_SIGNALING) { return pp_next_delay_1(ppi,wrTmoIdx)-wrp->wrStateRetry*WR_TMO_MS;
msg_unpack_wrsig(ppi, buf, &wrsig_msg,
&(wrp->msgTmpWrMessageID));
if ((wrp->msgTmpWrMessageID == CALIBRATE) &&
(wrp->wrMode == WR_MASTER))
ppi->next_state = WRS_RESP_CALIB_REQ;
else if ((wrp->msgTmpWrMessageID == WR_MODE_ON) &&
(wrp->wrMode == WR_SLAVE))
ppi->next_state = WRS_WR_LINK_ON;
}
ppi->next_delay = pp_next_delay_1(ppi,wrTmoIdx)-wrp->wrStateRetry*WR_CALIBRATED_TIMEOUT_MS;
return 0;
} }
...@@ -12,132 +12,39 @@ ...@@ -12,132 +12,39 @@
* We enter this state from WRS_M_LOCK or WRS_RESP_CALIB_REQ. * We enter this state from WRS_M_LOCK or WRS_RESP_CALIB_REQ.
* We send CALIBRATE and do the hardware steps; finally we send CALIBRATED. * We send CALIBRATE and do the hardware steps; finally we send CALIBRATED.
*/ */
int wr_calibration(struct pp_instance *ppi, void *buf, int len) #define WR_TMO_NAME "WR_CALIBRATION"
#define WR_TMO_MS wrp->calPeriod
int wr_calibration(struct pp_instance *ppi, void *buf, int len, int new_state)
{ {
struct wr_dsport *wrp = WR_DSPOR(ppi); struct wr_dsport *wrp = WR_DSPOR(ppi);
int sendmsg = 0; wr_servo_ext_t *se =WRE_SRV(ppi);
uint32_t delta; UInteger64 *delta;
if (ppi->is_new_state) { /* Calculate deltaTx and update servo*/
wrp->wrStateRetry = WR_STATE_RETRY; delta=(UInteger64 *)&wrp->deltaTx;
pp_timeout_set_rename(ppi, wrTmoIdx, wrp->calPeriod*(WR_STATE_RETRY+1),"WR_CALIBRATED"); *delta= (UInteger64)(ppi->timestampCorrectionPortDS.egressLatency*1000);
sendmsg = 1; pp_diag(ppi, ext, 1, "deltaTx: msb=0x%x lsb=0x%x\n",
} else { wrp->deltaTx.scaledPicoseconds.msb,
int rms=pp_next_delay_1(ppi, wrTmoIdx); wrp->deltaTx.scaledPicoseconds.lsb);
if ( rms==0 || rms<(wrp->wrStateRetry*wrp->calPeriod)) { fixedDelta_to_pp_time(*(struct FixedDelta *)delta,&se->delta_txs);/* Update servo specific data */
if (wr_handshake_retry(ppi))
sendmsg = 1; /* Calculate deltaRx and update servo*/
else delta=(UInteger64 *)&wrp->deltaRx;
return 0; /* non-wr already */ *delta=(UInteger64)((ppi->timestampCorrectionPortDS.ingressLatency +
} ppi->timestampCorrectionPortDS.semistaticLatency) * 1000);
} pp_diag(ppi, ext, 1, "deltaRx: msb=0x%x lsb=0x%x\n",
wrp->deltaRx.scaledPicoseconds.msb,
if (sendmsg) { wrp->deltaRx.scaledPicoseconds.lsb);
msg_issue_wrsig(ppi, CALIBRATE); fixedDelta_to_pp_time(*(struct FixedDelta *)delta, &se->delta_rxs);/* Update servo specific data */
wrp->wrPortState = WR_PORT_CALIBRATION_0;
if (wrp->calibrated) /* Go to the next state */
wrp->wrPortState = WR_PORT_CALIBRATION_2; wrp->next_state = WRS_CALIBRATED;
} wrp->calibrated = TRUE;
pp_diag(ppi, ext, 1, "%s: substate %i\n", __func__, /* Send CLALIBRATE message */
wrp->wrPortState - WR_PORT_CALIBRATION_0); msg_issue_wrsig(ppi, CALIBRATE);
wrp->wrPortState = 0; /* No longer used */
switch (wrp->wrPortState) {
case WR_PORT_CALIBRATION_0: return 0;
/* enable pattern sending */
if (WRH_OPER()->calib_pattern_enable(ppi, 0, 0, 0) ==
WRH_HW_CALIB_OK)
wrp->wrPortState = WR_PORT_CALIBRATION_1;
else
break;
case WR_PORT_CALIBRATION_1:
/* enable Tx calibration */
if (WRH_OPER()->calib_enable(ppi, WRH_HW_CALIB_TX)
== WRH_HW_CALIB_OK)
wrp->wrPortState = WR_PORT_CALIBRATION_2;
else
break;
case WR_PORT_CALIBRATION_2:
/* wait until Tx calibration is finished */
if (WRH_OPER()->calib_poll(ppi, WRH_HW_CALIB_TX, &delta) ==
WRH_HW_CALIB_READY) {
wrp->deltaTx.scaledPicoseconds.msb =
0xFFFFFFFF & (((uint64_t)delta) >> 16);
wrp->deltaTx.scaledPicoseconds.lsb =
0xFFFFFFFF & (((uint64_t)delta) << 16);
pp_diag(ppi, ext, 1, "Tx=>>scaledPicoseconds.msb = 0x%x\n",
wrp->deltaTx.scaledPicoseconds.msb);
pp_diag(ppi, ext, 1, "Tx=>>scaledPicoseconds.lsb = 0x%x\n",
wrp->deltaTx.scaledPicoseconds.lsb);
wrp->wrPortState = WR_PORT_CALIBRATION_3;
} else {
break; /* again */
}
case WR_PORT_CALIBRATION_3:
/* disable Tx calibration */
if (WRH_OPER()->calib_disable(ppi, WRH_HW_CALIB_TX)
== WRH_HW_CALIB_OK)
wrp->wrPortState = WR_PORT_CALIBRATION_4;
else
break;
case WR_PORT_CALIBRATION_4:
/* disable pattern sending */
if (WRH_OPER()->calib_pattern_disable(ppi) == WRH_HW_CALIB_OK)
wrp->wrPortState = WR_PORT_CALIBRATION_5;
else
break;
case WR_PORT_CALIBRATION_5:
/* enable Rx calibration using the pattern sent by other port */
if (WRH_OPER()->calib_enable(ppi, WRH_HW_CALIB_RX) ==
WRH_HW_CALIB_OK)
wrp->wrPortState = WR_PORT_CALIBRATION_6;
else
break;
case WR_PORT_CALIBRATION_6:
/* wait until Rx calibration is finished */
if (WRH_OPER()->calib_poll(ppi, WRH_HW_CALIB_RX, &delta) ==
WRH_HW_CALIB_READY) {
pp_diag(ppi, ext, 1, "Rx fixed delay = %d\n", (int)delta);
wrp->deltaRx.scaledPicoseconds.msb =
0xFFFFFFFF & (delta >> 16);
wrp->deltaRx.scaledPicoseconds.lsb =
0xFFFFFFFF & (delta << 16);
pp_diag(ppi, ext, 1, "Rx=>>scaledPicoseconds.msb = 0x%x\n",
wrp->deltaRx.scaledPicoseconds.msb);
pp_diag(ppi, ext, 1, "Rx=>>scaledPicoseconds.lsb = 0x%x\n",
wrp->deltaRx.scaledPicoseconds.lsb);
wrp->wrPortState = WR_PORT_CALIBRATION_7;
} else {
break; /* again */
}
case WR_PORT_CALIBRATION_7:
/* disable Rx calibration */
if (WRH_OPER()->calib_disable(ppi, WRH_HW_CALIB_RX)
== WRH_HW_CALIB_OK)
wrp->wrPortState = WR_PORT_CALIBRATION_8;
else
break;
case WR_PORT_CALIBRATION_8:
/* send deltas to the other port and go to the next state */
// msg_issue_wrsig(ppi, CALIBRATED);
ppi->next_state = WRS_CALIBRATED;
wrp->calibrated = TRUE;
default:
break;
}
ppi->next_delay = pp_next_delay_1(ppi,wrTmoIdx)-wrp->wrStateRetry*wrp->calPeriod;
return 0; /* ignore error */
} }
...@@ -12,26 +12,19 @@ ...@@ -12,26 +12,19 @@
* This is the last WR state: ack the other party and go master or slave. * This is the last WR state: ack the other party and go master or slave.
* There is no timeout nor a check for is_new_state: we just do things once * There is no timeout nor a check for is_new_state: we just do things once
*/ */
int wr_link_on(struct pp_instance *ppi, void *buf, int len) int wr_link_on(struct pp_instance *ppi, void *buf, int len, int new_state)
{ {
struct wr_dsport *wrp = WR_DSPOR(ppi); struct wr_dsport *wrp = WR_DSPOR(ppi);
int e = 0;
wrp->wrModeOn = TRUE;
WRH_OPER()->enable_ptracker(ppi);
if (wrp->wrMode == WR_MASTER) if (wrp->wrMode == WR_MASTER)
e = msg_issue_wrsig(ppi, WR_MODE_ON); if ( msg_issue_wrsig(ppi, WR_MODE_ON) )
return 0; /* Retry next time */
wrp->parentWrModeOn = TRUE;
if (e != 0) // Success
return -1; WRH_OPER()->enable_ptracker(ppi);
wrp->wrModeOn =
if (wrp->wrMode == WR_SLAVE) wrp->parentWrModeOn = TRUE;
ppi->next_state = PPS_SLAVE; wrp->next_state=WRS_IDLE;
else
ppi->next_state = PPS_MASTER;
#ifdef CONFIG_ABSCAL #ifdef CONFIG_ABSCAL
/* /*
...@@ -42,7 +35,7 @@ int wr_link_on(struct pp_instance *ppi, void *buf, int len) ...@@ -42,7 +35,7 @@ int wr_link_on(struct pp_instance *ppi, void *buf, int len)
extern int ep_get_bitslide(void); extern int ep_get_bitslide(void);
if (ptp_mode == 4 /* WRC_MODE_ABSCAL */) { if (ptp_mode == 4 /* WRC_MODE_ABSCAL */) {
ppi->next_state = WRS_ABSCAL; wrp->next_state = WRS_ABSCAL;
/* print header for the serial port stream of stamps */ /* print header for the serial port stream of stamps */
pp_printf("### t4.phase is already corrected for bitslide\n"); pp_printf("### t4.phase is already corrected for bitslide\n");
pp_printf("t1: t4: " pp_printf("t1: t4: "
......
...@@ -12,40 +12,48 @@ ...@@ -12,40 +12,48 @@
* WR slave: got here from WRS_S_LOCK: send LOCKED, wait for CALIBRATE. * WR slave: got here from WRS_S_LOCK: send LOCKED, wait for CALIBRATE.
* On timeout resend. * On timeout resend.
*/ */
int wr_locked(struct pp_instance *ppi, void *buf, int len) #define WR_TMO_NAME "WR_LOCKED"
#define WR_TMO_MS WR_LOCKED_TIMEOUT_MS
int wr_locked(struct pp_instance *ppi, void *buf, int len, int new_state)
{ {
int e=0, sendmsg = 0; int sendmsg = 0;
MsgSignaling wrsig_msg; MsgSignaling wrsig_msg;
struct wr_dsport *wrp = WR_DSPOR(ppi); struct wr_dsport *wrp = WR_DSPOR(ppi);
if (ppi->is_new_state) { if (new_state) {
wrp->wrStateRetry = WR_STATE_RETRY; wrp->wrStateRetry = WR_STATE_RETRY;
pp_timeout_set_rename(ppi, wrTmoIdx, WR_LOCKED_TIMEOUT_MS*(WR_STATE_RETRY+1),"WR_LOCKED"); WRH_SRV(ppi)->readyForSync=TRUE; /* We can start synchronization in the servo */
pp_timeout_set_rename(ppi, wrTmoIdx, WR_TMO_MS*(WR_STATE_RETRY+1),WR_TMO_NAME);
sendmsg = 1; sendmsg = 1;
} else { } else {
int rms=pp_next_delay_1(ppi, wrTmoIdx); if (ppi->received_ptp_header.messageType == PPM_SIGNALING) {
if ( rms==0 || rms<(wrp->wrStateRetry*WR_LOCKED_TIMEOUT_MS)) {
if (wr_handshake_retry(ppi))
sendmsg = 1;
else
return 0; /* non-wr already */
}
}
if (sendmsg) {
e=msg_issue_wrsig(ppi, LOCKED);
}
if (ppi->received_ptp_header.messageType == PPM_SIGNALING) { msg_unpack_wrsig(ppi, buf, &wrsig_msg,
&(wrp->msgTmpWrMessageID));
msg_unpack_wrsig(ppi, buf, &wrsig_msg, if (wrp->msgTmpWrMessageID == CALIBRATE) {
&(wrp->msgTmpWrMessageID)); wrp->next_state = WRS_RESP_CALIB_REQ;
return 0;
}
}
if (wrp->msgTmpWrMessageID == CALIBRATE) { /* Check remaining time */
ppi->next_state = WRS_RESP_CALIB_REQ; int rms=pp_next_delay_1(ppi, wrTmoIdx);
if ( rms==0 || rms<(wrp->wrStateRetry*WR_TMO_MS)) {
if (wr_handshake_retry(ppi))
sendmsg = 1;
else {
pp_diag(ppi, time, 1, "timeout expired: "WR_TMO_NAME"\n");
return 0; /* non-wr already */
}
}
}
} }
ppi->next_delay = pp_next_delay_1(ppi,wrTmoIdx)-wrp->wrStateRetry*WR_LOCKED_TIMEOUT_MS; if (sendmsg) {
msg_issue_wrsig(ppi, LOCKED);
}
return e; return pp_next_delay_1(ppi,wrTmoIdx)-wrp->wrStateRetry*WR_TMO_MS;
} }
...@@ -12,40 +12,47 @@ ...@@ -12,40 +12,47 @@
* This the entry point for a WR master: send "LOCK" and wait * This the entry point for a WR master: send "LOCK" and wait
* for "LOCKED". On timeout retry sending, for WR_STATE_RETRY times. * for "LOCKED". On timeout retry sending, for WR_STATE_RETRY times.
*/ */
int wr_m_lock(struct pp_instance *ppi, void *buf, int len) #define WR_TMO_NAME "WR_MLOCK"
#define WR_TMO_MS WR_M_LOCK_TIMEOUT_MS
int wr_m_lock(struct pp_instance *ppi, void *buf, int len, int new_state)
{ {
int e = 0, sendmsg = 0; int sendmsg = 0;
MsgSignaling wrsig_msg; MsgSignaling wrsig_msg;
struct wr_dsport *wrp = WR_DSPOR(ppi); struct wr_dsport *wrp = WR_DSPOR(ppi);
if (ppi->is_new_state) { if (new_state) {
wr_reset_process(ppi,WR_MASTER);
wrp->wrStateRetry = WR_STATE_RETRY; wrp->wrStateRetry = WR_STATE_RETRY;
pp_timeout_set_rename(ppi, wrTmoIdx, WR_M_LOCK_TIMEOUT_MS*(WR_STATE_RETRY+1),"WR_MLOCK"); pp_timeout_set_rename(ppi, wrTmoIdx, WR_TMO_MS*(WR_STATE_RETRY+1),WR_TMO_NAME);
sendmsg = 1; sendmsg = 1;
} else { } else {
int rms=pp_next_delay_1(ppi, wrTmoIdx); if (ppi->received_ptp_header.messageType == PPM_SIGNALING) {
if ( rms==0 || rms<(wrp->wrStateRetry*WR_M_LOCK_TIMEOUT_MS)) { msg_unpack_wrsig(ppi, buf, &wrsig_msg,
if (wr_handshake_retry(ppi)) &(wrp->msgTmpWrMessageID));
sendmsg = 1;
else if (wrp->msgTmpWrMessageID == LOCKED) {
return 0; /* non-wr already */ wrp->next_state = WRS_CALIBRATION;
return 0;
}
} }
}
if (sendmsg) { { /* Check remaining time */
e = msg_issue_wrsig(ppi, LOCK); int rms=pp_next_delay_1(ppi, wrTmoIdx);
if ( rms==0 || rms<(wrp->wrStateRetry*WR_TMO_MS)) {
if (wr_handshake_retry(ppi))
sendmsg = 1;
else {
pp_diag(ppi, time, 1, "timeout expired: "WR_TMO_NAME"\n");
return 0; /* non-wr already */
}
}
}
} }
if (ppi->received_ptp_header.messageType == PPM_SIGNALING) { if (sendmsg) {
msg_unpack_wrsig(ppi, buf, &wrsig_msg, msg_issue_wrsig(ppi, LOCK);
&(wrp->msgTmpWrMessageID));
if (wrp->msgTmpWrMessageID == LOCKED)
ppi->next_state = WRS_CALIBRATION;
} }
return pp_next_delay_1(ppi,wrTmoIdx)-wrp->wrStateRetry*WR_TMO_MS;
ppi->next_delay = pp_next_delay_1(ppi,wrTmoIdx)-wrp->wrStateRetry*WR_M_LOCK_TIMEOUT_MS;
return e;
} }
...@@ -14,46 +14,50 @@ ...@@ -14,46 +14,50 @@
* Here we send SLAVE_PRESENT and wait for LOCK. If timeout, * Here we send SLAVE_PRESENT and wait for LOCK. If timeout,
* resent SLAVE_PRESENT from WR_STATE_RETRY times * resent SLAVE_PRESENT from WR_STATE_RETRY times
*/ */
int wr_present(struct pp_instance *ppi, void *buf, int len) #define WR_TMO_NAME "WR_PRESENT"
#define WR_TMO_MS WR_PRESENT_TIMEOUT_MS
int wr_present(struct pp_instance *ppi, void *buf, int len, int new_state)
{ {
int e = 0, sendmsg = 0; int sendmsg = 0;
struct wr_dsport *wrp = WR_DSPOR(ppi); struct wr_dsport *wrp = WR_DSPOR(ppi);
MsgSignaling wrsig_msg; MsgSignaling wrsig_msg;
if (ppi->is_new_state) { if (new_state) {
wr_servo_init(ppi);
wrp->wrStateRetry = WR_STATE_RETRY; wrp->wrStateRetry = WR_STATE_RETRY;
pp_timeout_set_rename(ppi, wrTmoIdx, WR_PRESENT_TIMEOUT_MS*(WR_STATE_RETRY+1),"WR_PRESENT"); pp_timeout_set_rename(ppi, wrTmoIdx, WR_TMO_MS*(WR_STATE_RETRY+1),WR_TMO_NAME);
sendmsg = 1; sendmsg = 1;
} else { } else {
int rms=pp_next_delay_1(ppi, wrTmoIdx); if (ppi->received_ptp_header.messageType == PPM_SIGNALING) {
if ( rms==0 || rms<(wrp->wrStateRetry*WR_PRESENT_TIMEOUT_MS)) { msg_unpack_wrsig(ppi, buf, &wrsig_msg,
if (wr_handshake_retry(ppi)) &(wrp->msgTmpWrMessageID));
sendmsg = 1;
else if (wrp->msgTmpWrMessageID == LOCK) {
return 0; /* non-wr already */ wrp->next_state = WRS_S_LOCK;
lstate_set_link_in_progress(ppi);
return 0;
}
} }
}
if (sendmsg) {
e = msg_issue_wrsig(ppi, SLAVE_PRESENT);
}
if (ppi->received_ptp_header.messageType == PPM_SIGNALING) {
msg_unpack_wrsig(ppi, buf, &wrsig_msg,
&(wrp->msgTmpWrMessageID));
if (wrp->msgTmpWrMessageID == LOCK) { /* Check remaining time */
ppi->next_state = WRS_S_LOCK; int rms=pp_next_delay_1(ppi, wrTmoIdx);
if ( rms==0 || rms<(wrp->wrStateRetry*WR_TMO_MS)) {
if (wr_handshake_retry(ppi))
sendmsg = 1;
else {
pp_diag(ppi, time, 1, "timeout expired: "WR_TMO_NAME"\n");
return 0; /* non-wr already */
}
}
}
} }
if (e == 0) if (sendmsg) {
wr_execute_slave(ppi); msg_issue_wrsig(ppi, SLAVE_PRESENT);
else {
/* nothing, just stay here again */
} }
ppi->next_delay = pp_next_delay_1(ppi,wrTmoIdx)-wrp->wrStateRetry*WR_PRESENT_TIMEOUT_MS;
return e; return pp_next_delay_1(ppi,wrTmoIdx)-wrp->wrStateRetry*WR_TMO_MS;
} }
...@@ -8,49 +8,52 @@ ...@@ -8,49 +8,52 @@
#include <ppsi/ppsi.h> #include <ppsi/ppsi.h>
int wr_resp_calib_req(struct pp_instance *ppi, void *buf, int len) #define WR_TMO_NAME "WR_CALIBREQ"
#define WR_TMO_MS WR_RESP_CALIB_REQ_TIMEOUT_MS
int wr_resp_calib_req(struct pp_instance *ppi, void *buf, int len, int new_state)
{ {
struct wr_dsport *wrp = WR_DSPOR(ppi); struct wr_dsport *wrp = WR_DSPOR(ppi);
MsgSignaling wrsig_msg; MsgSignaling wrsig_msg;
int e = 0, enable = 0;
int send_pattern = (wrp->otherNodeCalSendPattern != 0);
if (ppi->is_new_state) { static unsigned long startTime;
if (new_state) {
wrp->wrStateRetry = WR_STATE_RETRY; wrp->wrStateRetry = WR_STATE_RETRY;
pp_timeout_set_rename(ppi, wrTmoIdx,WR_RESP_CALIB_REQ_TIMEOUT_MS*(WR_STATE_RETRY+1),"WR_CALIBREQ"); pp_timeout_set_rename(ppi, wrTmoIdx,WR_TMO_MS*(WR_STATE_RETRY+1),WR_TMO_NAME);
enable = 1; startTime = ppi->t_ops->calc_timeout(ppi, 0);
} else { } else {
int rms=pp_next_delay_1(ppi, wrTmoIdx);
if ( rms==0 || rms<(wrp->wrStateRetry*WR_RESP_CALIB_REQ_TIMEOUT_MS)) {
if (send_pattern)
WRH_OPER()->calib_pattern_disable(ppi);
if (wr_handshake_retry(ppi))
enable = 1;
else
return 0; /* non-wr already */
}
}
if (enable) { /* first or retry */ if (ppi->received_ptp_header.messageType == PPM_SIGNALING) {
if (send_pattern)
WRH_OPER()->calib_pattern_enable(ppi, 0, 0, 0); msg_unpack_wrsig(ppi, buf, &wrsig_msg,
} &(wrp->msgTmpWrMessageID));
if (ppi->received_ptp_header.messageType == PPM_SIGNALING) { if (wrp->msgTmpWrMessageID == CALIBRATED) {
/* Update servo */
wr_servo_ext_t *se =WRE_SRV(ppi);
msg_unpack_wrsig(ppi, buf, &wrsig_msg, fixedDelta_to_pp_time(wrp->otherNodeDeltaTx,&se->delta_txm);
&(wrp->msgTmpWrMessageID)); fixedDelta_to_pp_time(wrp->otherNodeDeltaRx,&se->delta_rxm);
wrp->next_state = (wrp->wrMode == WR_MASTER) ?
WRS_WR_LINK_ON :
WRS_CALIBRATION;
pp_printf("JCB: CALIBRATED RECEIVED. Started= %ld ms, Now=%ld\n",startTime,ppi->t_ops->calc_timeout(ppi, 0));
return 0;
}
}
if (wrp->msgTmpWrMessageID == CALIBRATED) { { /* Check remaining time */
if (send_pattern) int rms=pp_next_delay_1(ppi, wrTmoIdx);
WRH_OPER()->calib_pattern_disable(ppi); if ( rms==0 || rms<(wrp->wrStateRetry*WR_TMO_MS)) {
if (wrp->wrMode == WR_MASTER) if (!wr_handshake_retry(ppi)) {
ppi->next_state = WRS_WR_LINK_ON; pp_diag(ppi, time, 1, "timeout expired: "WR_TMO_NAME"\n");
else return 0; /* non-wr already */
ppi->next_state = WRS_CALIBRATION; }
}
} }
} }
ppi->next_delay = pp_next_delay_1(ppi,wrTmoIdx)-wrp->wrStateRetry*WR_RESP_CALIB_REQ_TIMEOUT_MS; return pp_next_delay_1(ppi,wrTmoIdx)-wrp->wrStateRetry*WR_TMO_MS;
return e;
} }
...@@ -8,45 +8,43 @@ ...@@ -8,45 +8,43 @@
#include <ppsi/ppsi.h> #include <ppsi/ppsi.h>
int wr_s_lock(struct pp_instance *ppi, void *buf, int len) #define WR_TMO_NAME "WR_SLOCK"
#define WR_TMO_MS WR_S_LOCK_TIMEOUT_MS
int wr_s_lock(struct pp_instance *ppi, void *buf, int len, int new_state)
{ {
struct wr_dsport *wrp = WR_DSPOR(ppi); struct wr_dsport *wrp = WR_DSPOR(ppi);
int enable = 0; int enable = 0;
int poll_ret;
if (ppi->is_new_state) { if (new_state) {
wrp->wrStateRetry = WR_STATE_RETRY; wrp->wrStateRetry = WR_STATE_RETRY;
pp_timeout_set_rename(ppi, wrTmoIdx, WR_S_LOCK_TIMEOUT_MS*(WR_STATE_RETRY+1),"WR_SLOCK"); pp_timeout_set_rename(ppi, wrTmoIdx, WR_TMO_MS*(WR_STATE_RETRY+1),WR_TMO_NAME);
enable = 1; enable = 1;
} else { } else {
int rms=pp_next_delay_1(ppi, wrTmoIdx);
if ( rms==0 || rms<(wrp->wrStateRetry*WR_S_LOCK_TIMEOUT_MS)) { int poll_ret = WRH_OPER()->locking_poll(ppi);
WRH_OPER()->locking_disable(ppi); if (poll_ret == WRH_SPLL_READY) {
if (wr_handshake_retry(ppi)) wrp->next_state = WRS_LOCKED;
enable = 1; return 0;
else }
return 0; /* non-wr already */
{ /* Check remaining time */
int rms=pp_next_delay_1(ppi, wrTmoIdx);
if ( rms==0 || rms<(wrp->wrStateRetry*WR_TMO_MS)) {
WRH_OPER()->locking_disable(ppi);
if (wr_handshake_retry(ppi))
enable = 1;
else {
pp_diag(ppi, time, 1, "timeout expired: "WR_TMO_NAME"\n");
return 0; /* non-wr already */
}
} }
}
} }
if (enable) { if (enable) {
WRH_OPER()->locking_enable(ppi); WRH_OPER()->locking_enable(ppi);
} }
ppi->next_delay = pp_next_delay_1(ppi,wrTmoIdx)-wrp->wrStateRetry*WR_S_LOCK_TIMEOUT_MS; return 100 ;/* 100ms : We check every 100ms if the PLL is locked */
poll_ret = WRH_OPER()->locking_poll(ppi);
if (poll_ret == WRH_SPLL_READY) {
ppi->next_state = WRS_LOCKED;
WRH_OPER()->locking_disable(ppi);
} else if (poll_ret == WRH_SPLL_CALIB_NOT_READY) {
/* rxts_calibration not ready, enter the same state without
* a delay */
ppi->next_delay = 0;
}
/* Calibration can take time so we restart the BMC timer to avoid aged foreign master removed. */
pp_gtimeout_reset(GLBS(ppi), PP_TO_BMC);
return 0;
} }
...@@ -22,6 +22,7 @@ ...@@ -22,6 +22,7 @@
* (see wrspec.v2-06-07-2011, page 17) * (see wrspec.v2-06-07-2011, page 17)
*/ */
struct wr_dsport { struct wr_dsport {
wr_state_t state, next_state; /* WR state */
Boolean wrModeOn; /* True when extension is running */ Boolean wrModeOn; /* True when extension is running */
Boolean parentWrModeOn; Boolean parentWrModeOn;
FixedDelta deltaTx; FixedDelta deltaTx;
...@@ -49,6 +50,9 @@ struct wr_dsport { ...@@ -49,6 +50,9 @@ struct wr_dsport {
UInteger16 otherNodeCalSendPattern; UInteger16 otherNodeCalSendPattern;
UInteger32 otherNodeCalPeriod;/* microseconsds, never changed */ UInteger32 otherNodeCalPeriod;/* microseconsds, never changed */
UInteger8 otherNodeCalRetry; UInteger8 otherNodeCalRetry;
struct PortIdentity parentAnnPortIdentity; /* Last received announce message port identity */
UInteger16 parentAnnSequenceId; /* Last received sequence did in the parent announce message */
}; };
/* This uppercase name matches "DSPOR(ppi)" used by standard protocol */ /* This uppercase name matches "DSPOR(ppi)" used by standard protocol */
...@@ -73,7 +77,7 @@ static inline Integer32 phase_to_cf_units(Integer32 phase) ...@@ -73,7 +77,7 @@ static inline Integer32 phase_to_cf_units(Integer32 phase)
/* Pack/Unkpack White rabbit message in the suffix of PTP announce message */ /* Pack/Unkpack White rabbit message in the suffix of PTP announce message */
void msg_pack_announce_wr_tlv(struct pp_instance *ppi); void msg_pack_announce_wr_tlv(struct pp_instance *ppi);
void msg_unpack_announce_wr_tlv(void *buf, MsgAnnounce *ann); void msg_unpack_announce_wr_tlv(void *buf, MsgAnnounce *ann, UInteger16 *wrFlags);
/* Pack/Unkpack/Issue White rabbit message signaling msg */ /* Pack/Unkpack/Issue White rabbit message signaling msg */
int msg_pack_wrsig(struct pp_instance *ppi, Enumeration16 wr_msg_id); int msg_pack_wrsig(struct pp_instance *ppi, Enumeration16 wr_msg_id);
...@@ -82,70 +86,96 @@ void msg_unpack_wrsig(struct pp_instance *ppi, void *buf, ...@@ -82,70 +86,96 @@ void msg_unpack_wrsig(struct pp_instance *ppi, void *buf,
int msg_issue_wrsig(struct pp_instance *ppi, Enumeration16 wr_msg_id); int msg_issue_wrsig(struct pp_instance *ppi, Enumeration16 wr_msg_id);
/* White rabbit state functions */ /* White rabbit state functions */
int wr_present(struct pp_instance *ppi, void *buf, int len); int wr_present(struct pp_instance *ppi, void *buf, int len,int new_state);
int wr_m_lock(struct pp_instance *ppi, void *buf, int len); int wr_m_lock(struct pp_instance *ppi, void *buf, int len,int new_state);
int wr_s_lock(struct pp_instance *ppi, void *buf, int len); int wr_s_lock(struct pp_instance *ppi, void *buf, int len,int new_state);
int wr_locked(struct pp_instance *ppi, void *buf, int len); int wr_locked(struct pp_instance *ppi, void *buf, int len,int new_state);
int wr_calibration(struct pp_instance *ppi, void *buf, int len); int wr_calibration(struct pp_instance *ppi, void *buf, int len,int new_state);
int wr_calibrated(struct pp_instance *ppi, void *buf, int len); int wr_calibrated(struct pp_instance *ppi, void *buf, int len,int new_state);
int wr_resp_calib_req(struct pp_instance *ppi, void *buf, int len); int wr_resp_calib_req(struct pp_instance *ppi, void *buf, int len,int new_state);
int wr_link_on(struct pp_instance *ppi, void *buf, int len); int wr_link_on(struct pp_instance *ppi, void *buf, int len,int new_state);
int wr_abscal(struct pp_instance *ppi, void *buf, int plen); int wr_abscal(struct pp_instance *ppi, void *buf, int len,int new_state);
int wr_idle(struct pp_instance *ppi, void *buf, int len, int new_state);
int wr_run_state_machine(struct pp_instance *ppi, void *buf, int len);
/* Common functions, used by various states and hooks */ /* Common functions, used by various states and hooks */
void wr_handshake_init(struct pp_instance *ppi, int mode); void wr_handshake_init(struct pp_instance *ppi, int mode);
void wr_handshake_fail(struct pp_instance *ppi); /* goto non-wr */ void wr_handshake_fail(struct pp_instance *ppi); /* goto non-wr */
int wr_handshake_retry(struct pp_instance *ppi); /* 1 == retry; 0 == failed */ int wr_handshake_retry(struct pp_instance *ppi); /* 1 == retry; 0 == failed */
int wr_execute_slave(struct pp_instance *ppi); int wr_execute_slave(struct pp_instance *ppi);
int wr_ready_for_slave(struct pp_instance *ppi);
void wr_reset_process(struct pp_instance *ppi, wr_role_t role);
/* wr_servo interface */ /* wr_servo interface */
int wr_servo_init(struct pp_instance *ppi); int wr_servo_init(struct pp_instance *ppi);
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);
int wr_servo_got_delay(struct pp_instance *ppi);
int wr_servo_update(struct pp_instance *ppi);
struct wr_servo_state {
/* These fields are used by servo code, after asetting at init time */
int32_t delta_txm_ps;
int32_t delta_rxm_ps;
int32_t delta_txs_ps;
int32_t delta_rxs_ps;
int32_t fiber_fix_alpha;
int32_t clock_period_ps;
/* Following fields are for monitoring/diagnostics (use w/ shmem) */ #define WR_SERVO_RESET_DATA_SIZE (sizeof(struct wr_servo_state)-offsetof(struct wr_servo_state,reset_address))
struct pp_time delayMM; #define WR_SERVO_RESET_DATA(servo) memset(&servo->reset_address,0,WR_SERVO_RESET_DATA_SIZE);
int64_t delayMM_ps;
int32_t cur_setpoint;
int64_t delayMS_ps;
int tracking_enabled;
int64_t skew;
struct wr_servo_state {
/* Values used by snmp. Values are increased at servo update when /* Values used by snmp. Values are increased at servo update when
* erroneous condition occurs. */ * erroneous condition occurs. */
uint32_t n_err_state; uint32_t n_err_state;
uint32_t n_err_offset; uint32_t n_err_offset;
uint32_t n_err_delta_rtt; uint32_t n_err_delta_rtt;
struct pp_time update_time;
/* ----- All data after this line will cleared during a servo reset */
int reset_address;
int64_t delayMM_ps;
int32_t cur_setpoint_ps;
int64_t delayMS_ps;
int tracking_enabled;
int64_t skew_ps;
int64_t offsetMS_ps;
/* These fields are used by servo code, across iterations */ /* These fields are used by servo code, across iterations */
struct pp_time t1, t2, t3, t4, t5, t6; int64_t prev_delayMS_ps;
int64_t prev_delayMS_ps;
int missed_iters; int missed_iters;
/* These fields are used by servo code, after asetting at init time */
int32_t delta_txm_ps;
int32_t delta_rxm_ps;
int32_t delta_txs_ps;
int32_t delta_rxs_ps;
int32_t clock_period_ps;
}; };
typedef struct wr_servo_ext {
struct pp_time delta_txm;
struct pp_time delta_rxm;
struct pp_time delta_txs;
struct pp_time delta_rxs;
}wr_servo_ext_t;
/* All data used as extension ppsi-wr must be put here */ /* All data used as extension ppsi-wr must be put here */
struct wr_data { struct wr_data {
struct wr_servo_state servo_state; wrh_servo_t servo; /* As to be in the first place in this structure */
wr_servo_ext_t servo_ext;
}; };
static inline struct wr_servo_ext *WRE_SRV(struct pp_instance *ppi)
{
return &((struct wr_data *)ppi->ext_data)->servo_ext;
}
extern struct pp_ext_hooks wr_ext_hooks; extern struct pp_ext_hooks wr_ext_hooks;
extern int wrTmoIdx; extern int wrTmoIdx;
/* Servo routines */
static inline void wr_servo_reset(struct pp_instance *ppi) {
wrh_servo_reset(ppi);
}
extern int wr_servo_got_sync(struct pp_instance *ppi);
extern int wr_servo_got_resp(struct pp_instance *ppi);
extern int wr_servo_got_presp(struct pp_instance *ppi);
#endif /* __ASSEMBLY__ */ #endif /* __ASSEMBLY__ */
#endif /* CONFIG_EXT_WR == 1*/ #endif /* CONFIG_EXT_WR == 1*/
......
...@@ -30,7 +30,7 @@ ...@@ -30,7 +30,7 @@
#define WR_S_LOCK_TIMEOUT_MS 15000 #define WR_S_LOCK_TIMEOUT_MS 15000
#define WR_LOCKED_TIMEOUT_MS 300 #define WR_LOCKED_TIMEOUT_MS 300
#define WR_CALIBRATION_TIMEOUT_MS 3000 #define WR_CALIBRATION_TIMEOUT_MS 3000
#define WR_RESP_CALIB_REQ_TIMEOUT_MS 100 // 3 #define WR_RESP_CALIB_REQ_TIMEOUT_MS 300 // 3
#define WR_CALIBRATED_TIMEOUT_MS 300 #define WR_CALIBRATED_TIMEOUT_MS 300
...@@ -61,29 +61,20 @@ ...@@ -61,29 +61,20 @@
/* Indicates if a port is configured as White Rabbit, and what kind /* Indicates if a port is configured as White Rabbit, and what kind
* (master/slave) */ * (master/slave) */
enum { typedef enum {
NON_WR = 0x0, NON_WR = 0,
WR_S_ONLY = 0x2,
WR_M_ONLY = 0x1, WR_M_ONLY = 0x1,
WR_S_ONLY = 0x2,
WR_M_AND_S = 0x3, WR_M_AND_S = 0x3,
WR_MODE_AUTO = 0x4, /* only for ptpx - not in the spec */ WR_MODE_AUTO= 0x4, /* only for ptpx - not in the spec */
}; }wr_config_t;
/* White Rabbit node */ /* White Rabbit node */
enum { typedef enum {
WR_SLAVE = 2, WR_ROLE_NONE=0,
WR_MASTER = 1, WR_MASTER = 1,
}; WR_SLAVE = 2
}wr_role_t;
/* White Rabbit Servo */
enum {
WR_UNINITIALIZED = 0,
WR_SYNC_NSEC,
WR_SYNC_TAI,
WR_SYNC_PHASE,
WR_TRACK_PHASE,
WR_WAIT_OFFSET_STABLE,
};
/* Values of Management Actions (extended for WR), see table 38 /* Values of Management Actions (extended for WR), see table 38
*/ */
...@@ -96,13 +87,10 @@ enum { ...@@ -96,13 +87,10 @@ enum {
WR_CMD, /* White Rabbit */ WR_CMD, /* White Rabbit */
}; };
/* brief WR PTP states (new, single FSM) */ /* brief WR PTP states */
enum { typedef enum {
/* WRS_IDLE=0,
* Extension-specific states start from 100 according to some docs WRS_PRESENT,
* so not to conflict with normal states
*/
WRS_PRESENT = 100,
WRS_S_LOCK, WRS_S_LOCK,
WRS_M_LOCK, WRS_M_LOCK,
WRS_LOCKED, WRS_LOCKED,
...@@ -110,19 +98,10 @@ enum { ...@@ -110,19 +98,10 @@ enum {
WRS_CALIBRATED, WRS_CALIBRATED,
WRS_RESP_CALIB_REQ, WRS_RESP_CALIB_REQ,
WRS_WR_LINK_ON, WRS_WR_LINK_ON,
/* substates: used within WRS_CALIBRATED as wrPortState field */
WR_PORT_CALIBRATION_0,
WR_PORT_CALIBRATION_1,
WR_PORT_CALIBRATION_2,
WR_PORT_CALIBRATION_3,
WR_PORT_CALIBRATION_4,
WR_PORT_CALIBRATION_5,
WR_PORT_CALIBRATION_6,
WR_PORT_CALIBRATION_7,
WR_PORT_CALIBRATION_8,
/* A special send-sync-only state for absolute calibration */
WRS_ABSCAL, WRS_ABSCAL,
}; WRS_MAX_STATES,
wr_state_t_ForceToIntSize = INT_MAX
}wr_state_t;
/* White Rabbit commands (for new implementation, single FSM), see table 38 */ /* White Rabbit commands (for new implementation, single FSM), see table 38 */
enum { enum {
......
...@@ -55,7 +55,8 @@ static inline UInteger16 get_be16(void *ptr) ...@@ -55,7 +55,8 @@ static inline UInteger16 get_be16(void *ptr)
void msg_pack_announce_wr_tlv(struct pp_instance *ppi) void msg_pack_announce_wr_tlv(struct pp_instance *ppi)
{ {
void *buf; void *buf;
UInteger16 wr_flags = 0; UInteger16 wr_flags;
struct wr_dsport *wrp = WR_DSPOR(ppi);
buf = ppi->tx_ptp; buf = ppi->tx_ptp;
...@@ -72,17 +73,17 @@ void msg_pack_announce_wr_tlv(struct pp_instance *ppi) ...@@ -72,17 +73,17 @@ void msg_pack_announce_wr_tlv(struct pp_instance *ppi)
| WR_TLV_WR_VERSION_NUMBER))); | WR_TLV_WR_VERSION_NUMBER)));
/* wrMessageId */ /* wrMessageId */
*(UInteger16 *)(buf + 74) = htons(ANN_SUFIX); *(UInteger16 *)(buf + 74) = htons(ANN_SUFIX);
wr_flags = wr_flags | WR_DSPOR(ppi)->wrConfig;
if (WR_DSPOR(ppi)->calibrated) wr_flags = wrp->wrConfig;
wr_flags = WR_IS_CALIBRATED | wr_flags; if (wrp->calibrated)
wr_flags |= WR_IS_CALIBRATED;
if (WR_DSPOR(ppi)->wrModeOn) if (wrp->wrModeOn)
wr_flags = WR_IS_WR_MODE | wr_flags; wr_flags |= WR_IS_WR_MODE;
*(UInteger16 *)(buf + 76) = htons(wr_flags); *(UInteger16 *)(buf + 76) = htons(wr_flags);
} }
void msg_unpack_announce_wr_tlv(void *buf, MsgAnnounce *ann) void msg_unpack_announce_wr_tlv(void *buf, MsgAnnounce *ann, UInteger16 *wrFlags)
{ {
UInteger16 tlv_type; UInteger16 tlv_type;
UInteger32 tlv_organizationID; UInteger32 tlv_organizationID;
...@@ -105,16 +106,9 @@ void msg_unpack_announce_wr_tlv(void *buf, MsgAnnounce *ann) ...@@ -105,16 +106,9 @@ void msg_unpack_announce_wr_tlv(void *buf, MsgAnnounce *ann)
tlv_magicNumber == WR_TLV_MAGIC_NUMBER && tlv_magicNumber == WR_TLV_MAGIC_NUMBER &&
tlv_versionNumber == WR_TLV_WR_VERSION_NUMBER && tlv_versionNumber == WR_TLV_WR_VERSION_NUMBER &&
tlv_wrMessageID == ANN_SUFIX) { tlv_wrMessageID == ANN_SUFIX) {
ann->ext_specific = (UInteger16)get_be16(buf+76); *wrFlags= (UInteger16)get_be16(buf+76);
} else } else
ann->ext_specific = 0; *wrFlags = 0;
}
static inline int32_t delta_to_ps(struct FixedDelta d)
{
_UInteger64 *sps = &d.scaledPicoseconds; /* ieee type :( */
return (sps->lsb >> 16) | (sps->msb << 16);
} }
/* White Rabbit: packing WR Signaling messages*/ /* White Rabbit: packing WR Signaling messages*/
...@@ -123,14 +117,6 @@ int msg_pack_wrsig(struct pp_instance *ppi, Enumeration16 wr_msg_id) ...@@ -123,14 +117,6 @@ int msg_pack_wrsig(struct pp_instance *ppi, Enumeration16 wr_msg_id)
void *buf; void *buf;
UInteger16 len = 0; UInteger16 len = 0;
struct wr_dsport *wrp = WR_DSPOR(ppi); struct wr_dsport *wrp = WR_DSPOR(ppi);
struct wr_servo_state *s =&((struct wr_data *)ppi->ext_data)->servo_state;
if ( (wrp->wrMode == NON_WR) || (wr_msg_id == ANN_SUFIX)) {
pp_diag(ppi, frames, 1,
"BUG: Trying to send invalid wr_msg mode=%x id=%x",
wrp->wrMode, wr_msg_id);
return 0;
}
buf = ppi->tx_ptp; buf = ppi->tx_ptp;
...@@ -171,7 +157,7 @@ int msg_pack_wrsig(struct pp_instance *ppi, Enumeration16 wr_msg_id) ...@@ -171,7 +157,7 @@ int msg_pack_wrsig(struct pp_instance *ppi, Enumeration16 wr_msg_id)
len = 14; len = 14;
break; break;
case CALIBRATED: /* new fsm */ case CALIBRATED:
/* delta TX */ /* delta TX */
put_be32(buf+56, wrp->deltaTx.scaledPicoseconds.msb); put_be32(buf+56, wrp->deltaTx.scaledPicoseconds.msb);
put_be32(buf+60, wrp->deltaTx.scaledPicoseconds.lsb); put_be32(buf+60, wrp->deltaTx.scaledPicoseconds.lsb);
...@@ -180,13 +166,6 @@ int msg_pack_wrsig(struct pp_instance *ppi, Enumeration16 wr_msg_id) ...@@ -180,13 +166,6 @@ int msg_pack_wrsig(struct pp_instance *ppi, Enumeration16 wr_msg_id)
put_be32(buf+64, wrp->deltaRx.scaledPicoseconds.msb); put_be32(buf+64, wrp->deltaRx.scaledPicoseconds.msb);
put_be32(buf+68, wrp->deltaRx.scaledPicoseconds.lsb); put_be32(buf+68, wrp->deltaRx.scaledPicoseconds.lsb);
len = 24; len = 24;
/*JCB: Hack. servo_init() called too early. PTP state machine must be modify. */
/* We should stay in UNCALIBRATED state during WR protocol */
s->delta_txm_ps = delta_to_ps(wrp->otherNodeDeltaTx);
s->delta_rxm_ps = delta_to_ps(wrp->otherNodeDeltaRx);
s->delta_txs_ps = delta_to_ps(wrp->deltaTx);
s->delta_rxs_ps = delta_to_ps(wrp->deltaRx);
break; break;
default: default:
...@@ -213,7 +192,6 @@ void msg_unpack_wrsig(struct pp_instance *ppi, void *buf, ...@@ -213,7 +192,6 @@ void msg_unpack_wrsig(struct pp_instance *ppi, void *buf,
UInteger16 tlv_versionNumber; UInteger16 tlv_versionNumber;
Enumeration16 wr_msg_id; Enumeration16 wr_msg_id;
struct wr_dsport *wrp = WR_DSPOR(ppi); struct wr_dsport *wrp = WR_DSPOR(ppi);
struct wr_servo_state *s =&((struct wr_data *)ppi->ext_data)->servo_state;
memcpy(&wrsig_msg->targetPortIdentity.clockIdentity, (buf + 34), memcpy(&wrsig_msg->targetPortIdentity.clockIdentity, (buf + 34),
PP_CLOCK_IDENTITY_LENGTH); PP_CLOCK_IDENTITY_LENGTH);
...@@ -284,10 +262,6 @@ void msg_unpack_wrsig(struct pp_instance *ppi, void *buf, ...@@ -284,10 +262,6 @@ void msg_unpack_wrsig(struct pp_instance *ppi, void *buf,
get_be32(buf+64); get_be32(buf+64);
wrp->otherNodeDeltaRx.scaledPicoseconds.lsb = wrp->otherNodeDeltaRx.scaledPicoseconds.lsb =
get_be32(buf+68); get_be32(buf+68);
/*JCB: Hack. serrvo_init() called too early. PTP state machine must be modify. */
/* We should stay in UNCALIBRATED state during WR protocol */
s->delta_txm_ps = delta_to_ps(wrp->otherNodeDeltaTx);
s->delta_rxm_ps = delta_to_ps(wrp->otherNodeDeltaRx);
break; break;
default: default:
......
This diff is collapsed.
/*
* Copyright (C) 2018 CERN (www.cern.ch)
* Author: Jean-Claude BAU & Maciej Lipinski
*
* Released according to the GNU LGPL, version 2.1 or any later version.
*/
#include <ppsi/ppsi.h>
#include <common-fun.h>
#include "wr-constants.h"
#include <math.h>
typedef struct {
char *name;
int (*action)(struct pp_instance *ppi, void *buf, int len, int new_state);
}wr_state_machine_t;
#define MAX_STATE_ACTIONS (sizeof(wr_state_actions)/sizeof(wr_state_machine_t))
static wr_state_machine_t wr_state_actions[] ={
[WRS_IDLE]{
.name="wr-idle",
.action=wr_idle,
},
[WRS_PRESENT]{
.name="wr-present",
.action=wr_present,
},
[WRS_M_LOCK]{
.name="wr_m_lock",
.action=wr_m_lock,
},
[WRS_S_LOCK]{
.name="wr-s-lock",
.action=wr_s_lock,
},
[WRS_LOCKED]{
.name="wr-locked",
.action=wr_locked,
},
[WRS_CALIBRATION]{
.name="wr-calibration",
.action=wr_calibration,
},
[WRS_CALIBRATED]{
.name="wr-calibrated",
.action=wr_calibrated,
},
[WRS_RESP_CALIB_REQ]{
.name="wr-resp-calib-req",
.action=wr_resp_calib_req,
},
[WRS_WR_LINK_ON]{
.name="wr-link-on",
.action=wr_link_on,
},
#ifdef CONFIG_ABSCAL
[WRS_ABSCAL]{
.name="absolute-calibration",
.action=wr_abscal,
},
#endif
};
/*
* This hook is called by fsm to run the extension state machine.
* It is used to send signaling messages.
* It returns the ext-specific timeout value
*/
int wr_run_state_machine(struct pp_instance *ppi, void *buf, int len) {
struct wr_dsport * wrp=WR_DSPOR(ppi);
wr_state_t nextState=wrp->next_state;
Boolean newState=nextState!=wrp->state;
int delay;
if ( !ppi->ext_enabled || ppi->state==PPS_INITIALIZING || nextState>=MAX_STATE_ACTIONS) {
if ( wrp->state!=WRS_IDLE ) {
nextState=wrp->next_state=WRS_IDLE;
/* Force to IDLE state when extension is disabled */
} else
return INT_MAX; /* Return a big delay. fsm will then not use it */
}
/*
* Evaluation of events common to all states
*/
if ( newState ) {
pp_diag(ppi, ext, 2, "WR state: LEAVE=%s, ENTER=%s\n",
wr_state_actions[wrp->state].name,
wr_state_actions[nextState].name);
wrp->state=nextState;
}
delay=(*wr_state_actions[wrp->state].action) (ppi, buf,len, newState);
return delay;
}
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