Commit ff6d7afa authored by Adam Wujek's avatar Adam Wujek 💬

Merge branch absolute_calibration

parents 0cc9d341 8611fb6d
......@@ -51,6 +51,8 @@ void sim_main_loop(struct pp_globals *ppg)
for (j = 0; j < ppg->nlinks; j++) {
ppi = INST(ppg, j);
ppi->is_new_state = 1;
/* just tell that the links are up */
ppi->link_up = TRUE;
}
delay_ns = run_all_state_machines(ppg) * 1000LL * 1000LL;
......
......@@ -12,9 +12,9 @@
static struct pp_runtime_opts sim_master_rt_opts = {
.clock_quality = {
.clockClass = PP_CLASS_WR_GM_LOCKED,
.clockAccuracy = PP_DEFAULT_CLOCK_ACCURACY,
.offsetScaledLogVariance = PP_DEFAULT_CLOCK_VARIANCE,
.clockClass = PP_PTP_CLASS_GM_LOCKED,
.clockAccuracy = PP_ACCURACY_DEFAULT,
.offsetScaledLogVariance = PP_VARIANCE_DEFAULT,
},
.flags = PP_DEFAULT_FLAGS,
.ap = PP_DEFAULT_AP,
......
......@@ -48,6 +48,8 @@ void unix_main_loop(struct pp_globals *ppg)
for (j = 0; j < ppg->nlinks; j++) {
ppi = INST(ppg, j);
/* just tell that the links are up */
ppi->link_up = TRUE;
/*
* The main loop here is based on select. While we are not
......
......@@ -32,6 +32,7 @@ static struct wr_operations wrpc_wr_operations = {
.locking_enable = wrpc_spll_locking_enable,
.locking_poll = wrpc_spll_locking_poll,
.locking_disable = wrpc_spll_locking_disable,
.locking_reset = wrpc_spll_locking_reset,
.enable_ptracker = wrpc_spll_enable_ptracker,
.adjust_in_progress = wrpc_adjust_in_progress,
......@@ -118,12 +119,14 @@ int wrc_ptp_set_mode(int mode)
struct pp_globals *ppg = ppi->glbs;
struct wr_dsport *wrp = WR_DSPOR(ppi);
typeof(ppg->rt_opts->clock_quality.clockClass) *class_ptr;
typeof(ppg->rt_opts->clock_quality.clockAccuracy) *accuracy_ptr;
int error = 0;
/*
* We need to change the class in the default options.
* Unfortunately, ppg->rt_opts may be yet unassigned when this runs
*/
class_ptr = &__pp_default_rt_opts.clock_quality.clockClass;
accuracy_ptr = &__pp_default_rt_opts.clock_quality.clockAccuracy;
ptp_mode = 0;
......@@ -134,31 +137,38 @@ int wrc_ptp_set_mode(int mode)
case WRC_MODE_ABSCAL: /* absolute calibration, gm-lookalike */
wrp->wrConfig = WR_M_ONLY;
ppi->role = PPSI_ROLE_MASTER;
*class_ptr = PP_CLASS_WR_GM_LOCKED;
*class_ptr = PP_PTP_CLASS_GM_LOCKED;
*accuracy_ptr = PP_PTP_ACCURACY_GM_LOCKED;
spll_init(SPLL_MODE_GRAND_MASTER, 0, 1);
shw_pps_gen_unmask_output(1);
lock_timeout = LOCK_TIMEOUT_GM;
DSDEF(ppi)->clockQuality.clockClass = PP_CLASS_WR_GM_LOCKED;
m1(ppi);
DSDEF(ppi)->clockQuality.clockClass = PP_PTP_CLASS_GM_LOCKED;
DSDEF(ppi)->clockQuality.clockAccuracy = PP_PTP_ACCURACY_GM_LOCKED;
bmc_m1(ppi);
break;
case WRC_MODE_MASTER:
wrp->wrConfig = WR_M_ONLY;
ppi->role = PPSI_ROLE_MASTER;
*class_ptr = PP_CLASS_DEFAULT;
*class_ptr = PP_PTP_CLASS_GM_UNLOCKED;
*accuracy_ptr = PP_PTP_ACCURACY_GM_UNLOCKED;
spll_init(SPLL_MODE_FREE_RUNNING_MASTER, 0, 1);
shw_pps_gen_unmask_output(1);
lock_timeout = LOCK_TIMEOUT_FM;
DSDEF(ppi)->clockQuality.clockClass = PP_CLASS_DEFAULT;
m1(ppi);
DSDEF(ppi)->clockQuality.clockClass = PP_PTP_CLASS_GM_UNLOCKED;
DSDEF(ppi)->clockQuality.clockAccuracy = PP_PTP_ACCURACY_GM_UNLOCKED;
bmc_m1(ppi);
break;
case WRC_MODE_SLAVE:
wrp->wrConfig = WR_S_ONLY;
ppi->role = PPSI_ROLE_SLAVE;
*class_ptr = PP_CLASS_SLAVE_ONLY;
*accuracy_ptr = PP_ACCURACY_DEFAULT;
spll_init(SPLL_MODE_SLAVE, 0, 1);
shw_pps_gen_unmask_output(0);
DSDEF(ppi)->clockQuality.clockClass = PP_CLASS_SLAVE_ONLY;
DSDEF(ppi)->clockQuality.clockAccuracy = PP_ACCURACY_DEFAULT;
break;
}
......@@ -180,8 +190,10 @@ int wrc_ptp_set_mode(int mode)
pp_printf("\n");
/* If we can't lock to the atomic/gps, we say it in the class */
if (error && mode == WRC_MODE_GM)
*class_ptr = PP_CLASS_WR_GM_UNLOCKED;
if (error && mode == WRC_MODE_GM) {
*class_ptr = PP_PTP_CLASS_GM_UNLOCKED;
*accuracy_ptr = PP_PTP_ACCURACY_GM_UNLOCKED;
}
ptp_mode = mode;
return error;
......@@ -225,9 +237,10 @@ int wrc_ptp_start()
delay_ms = pp_state_machine(ppi, NULL, 0);
start_tics = timer_get_tics();
WR_DSPOR(ppi)->linkUP = FALSE;
/* just tell that the link is up, if not it will anyhow not receive anything */
ppi->link_up = TRUE;
ppi->state = PPS_INITIALIZING;
wr_servo_reset(ppi);
ptp_enabled = 1;
return 0;
}
......@@ -244,7 +257,11 @@ int wrc_ptp_stop()
memset(ppi->frgn_master, 0, sizeof(ppi->frgn_master));
ppi->frgn_rec_num = 0; /* no known master */
/* just tell that the link is down now */
ppi->link_up = FALSE;
ptp_enabled = 0;
ppi->next_state = PPS_DISABLED;
pp_leave_current_state(ppi);
wr_servo_reset(ppi);
pp_close_globals(&ppg_static);
......
......@@ -47,6 +47,13 @@ int wrpc_spll_locking_poll(struct pp_instance *ppi, int grandmaster)
return locked ? WR_SPLL_READY : WR_SPLL_ERROR;
}
int wrpc_spll_locking_reset(struct pp_instance *ppi)
{
//TODO?
return WR_SPLL_OK;
}
int wrpc_spll_locking_disable(struct pp_instance *ppi)
{
/* softpll_disable(); */
......
......@@ -46,6 +46,7 @@ struct wrpc_ethhdr {
int wrpc_spll_locking_enable(struct pp_instance *ppi);
int wrpc_spll_locking_poll(struct pp_instance *ppi, int grandmaster);
int wrpc_spll_locking_disable(struct pp_instance *ppi);
int wrpc_spll_locking_reset(struct pp_instance *ppi);
int wrpc_spll_enable_ptracker(struct pp_instance *ppi);
int wrpc_adjust_in_progress(void);
int wrpc_adjust_counters(int64_t adjust_sec, int32_t adjust_nsec);
......
......@@ -26,6 +26,7 @@
#define HEXP_LOCK_CMD_START 1
#define HEXP_LOCK_CMD_CHECK 2
#define HEXP_LOCK_CMD_ENABLE_TRACKING 3
#define HEXP_LOCK_CMD_RESET 4
#define HEXP_LOCK_STATUS_LOCKED 0
#define HEXP_LOCK_STATUS_BUSY 1
......
......@@ -11,6 +11,7 @@
#define HAL_PORT_STATE_UP 2
#define HAL_PORT_STATE_CALIBRATION 3
#define HAL_PORT_STATE_LOCKING 4
#define HAL_PORT_STATE_RESET 5
/* Read temperature from SFPs */
#define READ_SFP_DIAG_ENABLE 1
......
......@@ -76,6 +76,7 @@ int wrs_calibration_pattern_disable(struct pp_instance *ppi);
int wrs_locking_enable(struct pp_instance *ppi);
int wrs_locking_poll(struct pp_instance *ppi, int grandmaster);
int wrs_locking_disable(struct pp_instance *ppi);
int wrs_locking_reset(struct pp_instance *ppi);
int wrs_enable_ptracker(struct pp_instance *ppi);
int wrs_adjust_in_progress(void);
int wrs_adjust_counters(int64_t adjust_sec, int32_t adjust_nsec);
......
......@@ -29,7 +29,7 @@ static int run_all_state_machines(struct pp_globals *ppg)
for (j = 0; j < ppg->nlinks; j++) {
struct pp_instance *ppi = INST(ppg, j);
int old_lu = WR_DSPOR(ppi)->linkUP;
int old_lu = ppi->link_up;
struct hal_port_state *p;
/* FIXME: we should save this pointer in the ppi itself */
......@@ -40,29 +40,31 @@ static int run_all_state_machines(struct pp_globals *ppg)
continue;
}
WR_DSPOR(ppi)->linkUP =
ppi->link_up =
(p->state != HAL_PORT_STATE_LINK_DOWN &&
p->state != HAL_PORT_STATE_DISABLED);
if (old_lu != WR_DSPOR(ppi)->linkUP) {
if (old_lu != ppi->link_up) {
pp_diag(ppi, fsm, 1, "iface %s went %s\n",
ppi->iface_name, WR_DSPOR(ppi)->linkUP ? "up":"down");
ppi->iface_name, ppi->link_up ? "up":"down");
if (WR_DSPOR(ppi)->linkUP) {
if (ppi->link_up) {
ppi->state = PPS_INITIALIZING;
}
else {
ppi->next_state = PPS_DISABLED;
pp_leave_current_state(ppi);
ppi->n_ops->exit(ppi);
ppi->frgn_rec_num = 0;
ppi->frgn_rec_best = -1;
ppi->frgn_rec_best = 0;
if (ppg->ebest_idx == ppi->port_idx)
wr_servo_reset(ppi);
}
}
/* Do not call state machine if link is down */
if (WR_DSPOR(ppi)->linkUP)
if (ppi->link_up)
delay_ms_j = pp_state_machine(ppi, NULL, 0);
else
delay_ms_j = PP_DEFAULT_NEXT_DELAY_MS;
......
......@@ -36,6 +36,7 @@ static struct wr_operations wrs_wr_operations = {
.locking_enable = wrs_locking_enable,
.locking_poll = wrs_locking_poll,
.locking_disable = wrs_locking_disable,
.locking_reset = wrs_locking_reset,
.enable_ptracker = wrs_enable_ptracker,
.adjust_in_progress = wrs_adjust_in_progress,
......
......@@ -44,12 +44,12 @@ enum {
};
static void pp_diag_fsm(struct pp_instance *ppi, char *name, int sequence,
int plen)
int len)
{
if (sequence == STATE_ENTER) {
/* enter with or without a packet len */
pp_fsm_printf(ppi, "ENTER %s, packet len %i\n",
name, plen);
name, len);
return;
}
if (sequence == STATE_LOOP) {
......@@ -85,10 +85,17 @@ get_current_state_table_item(struct pp_instance *ppi)
/*
* Returns delay to next state, which is always zero.
*/
static int leave_current_state(struct pp_instance *ppi)
int pp_leave_current_state(struct pp_instance *ppi)
{
/* If something has to be done in an extension */
if (pp_hooks.state_change)
pp_hooks.state_change(ppi);
/* if the next or old state is non standard PTP reset all timeouts */
if ((ppi->state > PPS_SLAVE) || (ppi->next_state > PPS_SLAVE))
pp_timeout_setall(ppi);
ppi->state = ppi->next_state;
pp_timeout_setall(ppi);
ppi->flags &= ~PPI_FLAGS_WAITING;
pp_diag_fsm(ppi, ppi->current_state_item->name, STATE_LEAVE, 0);
/* next_delay unused: go to new state now */
......@@ -138,22 +145,22 @@ static int pp_packet_prefilter(struct pp_instance *ppi)
}
/*
* 9.5.2.3: if an announce message comes from another port of the same
* clock, switch all the ports but the lowest numbered one to
* PASSIVE. Since all involved ports will see each other's announce,
* we just switch __this__ instance's port's status to PASSIVE if we
* need to.
*/
if (hdr->messageType == PPM_ANNOUNCE &&
!memcmp(&hdr->sourcePortIdentity.clockIdentity,
&DSPOR(ppi)->portIdentity.clockIdentity,
sizeof(ClockIdentity))) {
if (hdr->sourcePortIdentity.portNumber <
DSPOR(ppi)->portIdentity.portNumber)
ppi->next_state = PPS_PASSIVE;
return -1;
* 9.5.2.3 & 9.5.2.2: For BCs the BMC (an extention to it)
* handles the Announce (go to Passive), other messages are dropped
*/
if (!memcmp(&hdr->sourcePortIdentity.clockIdentity,
&DSPOR(ppi)->portIdentity.clockIdentity,
sizeof(ClockIdentity))) {
if (DSDEF(ppi)->numberPorts > 1) {
/* Announces are handled by the BMC, since otherwise the state
* also the PASSIVE states in this case is overwritten */
if (hdr->messageType != PPM_ANNOUNCE) {
/* ignore messages, except announce coming from its own clock */
return -1;
}
}
}
return 0;
}
......@@ -165,24 +172,24 @@ static int type_length[__PP_NR_MESSAGES_TYPES] = {
[PPM_PDELAY_RESP] = PP_PDELAY_RESP_LENGTH,
[PPM_FOLLOW_UP] = PP_FOLLOW_UP_LENGTH,
[PPM_DELAY_RESP] = PP_DELAY_RESP_LENGTH,
[PPM_PDELAY_R_FUP] = PP_PDELAY_R_FUP_LENGTH,
[PPM_PDELAY_R_FUP] = PP_PDELAY_RESP_FOLLOW_UP_LENGTH,
[PPM_ANNOUNCE] = PP_ANNOUNCE_LENGTH,
[PPM_SIGNALING] = PP_HEADER_LENGTH,
[PPM_SIGNALING] = PP_HEADER_LENGTH,
[PPM_MANAGEMENT] = PP_MANAGEMENT_LENGTH,
};
static int fsm_unpack_verify_frame(struct pp_instance *ppi,
uint8_t *packet, int plen)
void *buf, int len)
{
int msgtype = 0;
if (plen)
msgtype = packet[0] & 0xf;
if (msgtype >= __PP_NR_MESSAGES_TYPES || plen < type_length[msgtype])
if (len)
msgtype = ((*(UInteger8 *) (buf + 0)) & 0x0F);
if (msgtype >= __PP_NR_MESSAGES_TYPES || len < type_length[msgtype])
return 1; /* too short */
if ((packet[1] & 0xf) != 2)
if (((*(UInteger8 *) (buf + 1)) & 0x0F) != 2)
return 1; /* wrong ptp version */
return msg_unpack_header(ppi, packet, plen);
return msg_unpack_header(ppi, buf, len);
}
/*
......@@ -194,18 +201,18 @@ static int fsm_unpack_verify_frame(struct pp_instance *ppi,
* is that of the extension, otherwise the one in state-table-default.c
*/
int pp_state_machine(struct pp_instance *ppi, uint8_t *packet, int plen)
int pp_state_machine(struct pp_instance *ppi, void *buf, int len)
{
struct pp_state_table_item *ip;
struct pp_time *t = &ppi->last_rcv_time;
int state, err = 0;
int msgtype;
if (plen > 0) {
msgtype = packet[0] & 0xf;
if (len > 0) {
msgtype = ((*(UInteger8 *) (buf + 0)) & 0x0F);
pp_diag(ppi, frames, 1,
"RECV %02d bytes at %9d.%09d.%03d (type %x, %s)\n",
plen, (int)t->secs, (int)(t->scaled_nsecs >> 16),
len, (int)t->secs, (int)(t->scaled_nsecs >> 16),
((int)(t->scaled_nsecs & 0xffff) * 1000) >> 16,
msgtype, pp_msgtype_info[msgtype].name);
}
......@@ -213,9 +220,9 @@ int pp_state_machine(struct pp_instance *ppi, uint8_t *packet, int plen)
/*
* Discard too short packets
*/
if (plen < PP_HEADER_LENGTH) {
plen = 0;
packet = NULL;
if (len < PP_HEADER_LENGTH) {
len = 0;
buf = NULL;
}
/*
......@@ -224,10 +231,10 @@ int pp_state_machine(struct pp_instance *ppi, uint8_t *packet, int plen)
* In case of error continue without a frame, so the current
* ptp state can update ppi->next_delay and return a proper value
*/
err = fsm_unpack_verify_frame(ppi, packet, plen);
err = fsm_unpack_verify_frame(ppi, buf, len);
if (err) {
plen = 0;
packet = NULL;
len = 0;
buf = NULL;
}
state = ppi->state;
......@@ -242,31 +249,49 @@ int pp_state_machine(struct pp_instance *ppi, uint8_t *packet, int plen)
ppi->next_state = state;
ppi->next_delay = 0;
if (ppi->is_new_state)
pp_diag_fsm(ppi, ip->name, STATE_ENTER, plen);
pp_diag_fsm(ppi, ip->name, STATE_ENTER, len);
/*
* Possibly filter out packet and maybe update port state
* Possibly filter out buf and maybe update port state
*/
if (packet) {
if (buf) {
err = pp_packet_prefilter(ppi);
if (err < 0) {
packet = NULL;
plen = 0;
buf = NULL;
len = 0;
}
}
if (ppi->state != ppi->next_state)
return leave_current_state(ppi);
return pp_leave_current_state(ppi);
if (!plen)
if (!len)
ppi->received_ptp_header.messageType = PPM_NO_MESSAGE;
err = ip->f1(ppi, packet, plen);
err = ip->f1(ppi, buf, len);
if (err)
pp_printf("fsm for %s: Error %i in %s\n",
ppi->port_name, err, ip->name);
/* done: if new state mark it, and enter it now (0 ms) */
if (ppi->state != ppi->next_state)
return leave_current_state(ppi);
return pp_leave_current_state(ppi);
/* run bmc independent of state, and since not message driven do this
* here 9.2.6.8 */
if (pp_timeout(ppi, PP_TO_BMC)) {
ppi->next_state = bmc(ppi);
/* done: if new state mark it, and enter it now (0 ms) */
if (ppi->state != ppi->next_state)
return pp_leave_current_state(ppi);
}
pp_diag_fsm(ppi, ip->name, STATE_LOOP, 0);
/* check if the BMC timeout is the next to run */
if (pp_next_delay_1(ppi, PP_TO_BMC) < ppi->next_delay)
ppi->next_delay = pp_next_delay_1(ppi, PP_TO_BMC);
return ppi->next_delay;
}
......@@ -23,32 +23,56 @@
#define PP_DEFAULT_AP 10
#define PP_DEFAULT_AI 1000
#define PP_DEFAULT_DELAY_S 6
#define PP_DEFAULT_ANNOUNCE_INTERVAL 1 /* 0 in 802.1AS */
#define PP_DEFAULT_ANNOUNCE_INTERVAL 1 /* 0 in 802.1AS */
#define PP_DEFAULT_DELAYREQ_INTERVAL 0
#define PP_DEFAULT_SYNC_INTERVAL 0 /* -7 in 802.1AS */
#define PP_DEFAULT_SYNC_INTERVAL 0 /* -7 in 802.1AS */
#define PP_DEFAULT_SYNC_RECEIPT_TIMEOUT 3
#define PP_DEFAULT_ANNOUNCE_RECEIPT_TIMEOUT 20 /* 3 by default */
#define PP_DEFAULT_ANNOUNCE_RECEIPT_TIMEOUT 3 /* 3 by default */
#define PP_DEFAULT_UTC_OFFSET 37
#define PP_DEFAULT_PRIORITY1 128
#define PP_DEFAULT_PRIORITY2 128
/* Clock classes (pag 55, PTP-2008). See ppsi-manual for an explanation */
#define PP_CLASS_SLAVE_ONLY 255
#define PP_CLASS_DEFAULT 187
#define PP_CLASS_WR_GM_LOCKED 6
#define PP_CLASS_WR_GM_UNLOCKED 52
#define PP_CLASS_DEFAULT 248
#define PP_PTP_CLASS_GM_LOCKED 6
#define PP_PTP_CLASS_GM_HOLDOVER 7
#define PP_PTP_CLASS_GM_UNLOCKED 52
#define PP_ARB_CLASS_GM_LOCKED 13
#define PP_ARB_CLASS_GM_HOLDOVER 14
#define PP_ARB_CLASS_GM_UNLOCKED 58
#define PP_ACCURACY_DEFAULT 0xFE
#define PP_PTP_ACCURACY_GM_LOCKED 0x21
#define PP_PTP_ACCURACY_GM_HOLDOVER 0x21
#define PP_PTP_ACCURACY_GM_UNLOCKED 0xFE
#define PP_ARB_ACCURACY_GM_LOCKED 0x21
#define PP_ARB_ACCURACY_GM_HOLDOVER 0x21
#define PP_ARB_ACCURACY_GM_UNLOCKED 0xFE
#define PP_VARIANCE_DEFAULT 0xC71D
#define PP_PTP_VARIANCE_GM_LOCKED 0xB900
#define PP_PTP_VARIANCE_GM_HOLDOVER 0xC71D
#define PP_PTP_VARIANCE_GM_UNLOCKED 0xC71D
#define PP_ARB_VARIANCE_GM_LOCKED 0xB900
#define PP_ARB_VARIANCE_GM_HOLDOVER 0xC71D
#define PP_ARB_VARIANCE_GM_UNLOCKED 0xC71D
#define PP_SERVO_UNKNOWN 0
#define PP_SERVO_LOCKED 1
#define PP_SERVO_HOLDOVER 2
#define PP_SERVO_UNLOCKED 3
#define PP_DEFAULT_CLOCK_ACCURACY 0xFE
#define PP_DEFAULT_PRIORITY1 128
#define PP_DEFAULT_PRIORITY2 128
#define PP_DEFAULT_CLOCK_VARIANCE -4000 /* To be determined in
* 802.1AS. We use the
* same value as in ptpdv1
*/
#define PP_NR_FOREIGN_RECORDS 5
#define PP_FOREIGN_MASTER_TIME_WINDOW 4
#define PP_FOREIGN_MASTER_THRESHOLD 2
#define PP_DEFAULT_TTL 1
/* We use an array of timeouts, with these indexes */
enum pp_timeouts {
PP_TO_REQUEST = 0,
PP_TO_SYNC_SEND,
PP_TO_BMC,
PP_TO_ANN_RECEIPT,
PP_TO_ANN_SEND,
PP_TO_FAULT,
......@@ -71,7 +95,7 @@ enum pp_timeouts {
#define PP_DELAY_REQ_LENGTH 44
#define PP_DELAY_RESP_LENGTH 54
#define PP_PDELAY_RESP_LENGTH 54
#define PP_PDELAY_R_FUP_LENGTH 54
#define PP_PDELAY_RESP_FOLLOW_UP_LENGTH 54
#define PP_MANAGEMENT_LENGTH 48
#define PP_MINIMUM_LENGTH 44
......
......@@ -45,7 +45,7 @@ typedef struct Integer64 {
typedef struct UInteger64 {
uint32_t lsb;
uint32_t msb;
uint32_t msb;
} UInteger64;
struct TimeInterval { /* page 12 (32) -- never used */
......@@ -54,7 +54,7 @@ struct TimeInterval { /* page 12 (32) -- never used */
/* White Rabbit extension */
typedef struct FixedDelta {
UInteger64 scaledPicoseconds;
UInteger64 scaledPicoseconds;
} FixedDelta;
typedef struct Timestamp { /* page 13 (33) -- no typedef expected */
......@@ -217,7 +217,7 @@ typedef struct DSCurrent { /* page 67 */
typedef struct DSParent { /* page 68 */
/* Dynamic */
PortIdentity parentPortIdentity;
/* Boolean parentStats; -- not used */
/* Boolean parentStats; -- not used */
UInteger16 observedParentOffsetScaledLogVariance;
Integer32 observedParentClockPhaseChangeRate;
ClockIdentity grandmasterIdentity;
......
......@@ -64,11 +64,23 @@ struct pp_channel {
* it is called foreignMasterDS, see 9.3.2.4
*/
struct pp_frgn_master {
PortIdentity port_id; /* used to identify old/new masters */
/* We don't need all fields of the following ones */
MsgAnnounce ann;
MsgHeader hdr;
/* how many announce messages from this port where received in the
* interval */
UInteger16 foreignMasterAnnounceMessages[PP_FOREIGN_MASTER_TIME_WINDOW];
/* on which port we received the frame */
PortIdentity receivePortIdentity;
/* BMC related information */
UInteger16 sequenceId;
PortIdentity sourcePortIdentity;
Octet flagField[2];
Integer16 currentUtcOffset;
UInteger8 grandmasterPriority1;
ClockQuality grandmasterClockQuality;
UInteger8 grandmasterPriority2;
ClockIdentity grandmasterIdentity;
UInteger16 stepsRemoved;
Enumeration8 timeSource;
unsigned long ext_specific; /* used by extension */
};
/*
......@@ -168,6 +180,7 @@ struct pp_instance {
UInteger16 sent_seq[__PP_NR_MESSAGES_TYPES]; /* last sent this type */
MsgHeader received_ptp_header;
Boolean link_up;
char *iface_name; /* for direct actions on hardware */
char *port_name; /* for diagnostics, mainly */
int port_idx;
......@@ -180,7 +193,6 @@ struct pp_instance {
unsigned long ptp_rx_count;
};
/* The following things used to be bit fields. Other flags are now enums */
#define PPI_FLAG_FROM_CURRENT_PARENT 0x01
#define PPI_FLAG_WAITING_FOR_F_UP 0x02
#define PPI_FLAG_WAITING_FOR_RF_UP 0x04
#define PPI_FLAGS_WAITING 0x06 /* both of the above */
......
......@@ -70,8 +70,6 @@ extern struct pp_msgtype_info pp_msgtype_info[16];
extern int pp_lib_may_issue_sync(struct pp_instance *ppi);
extern int pp_lib_may_issue_announce(struct pp_instance *ppi);
extern int pp_lib_may_issue_request(struct pp_instance *ppi);
extern int pp_lib_handle_announce(struct pp_instance *ppi,
unsigned char *buf, int len);
/* We use data sets a lot, so have these helpers */
static inline struct pp_globals *GLBS(struct pp_instance *ppi)
......@@ -150,15 +148,15 @@ extern void pp_prepare_pointers(struct pp_instance *ppi);
* allow NULL pointers.
*/
struct pp_ext_hooks {
int (*init)(struct pp_instance *ppg, unsigned char *pkt, int plen);
int (*init)(struct pp_instance *ppg, void *buf, int len);
int (*open)(struct pp_globals *ppi, struct pp_runtime_opts *rt_opts);
int (*close)(struct pp_globals *ppg);
int (*listening)(struct pp_instance *ppi, unsigned char *pkt, int plen);
int (*master_msg)(struct pp_instance *ppi, unsigned char *pkt,
int plen, int msgtype);
int (*new_slave)(struct pp_instance *ppi, unsigned char *pkt, int plen);
int (*listening)(struct pp_instance *ppi, void *buf, int len);
int (*master_msg)(struct pp_instance *ppi, void *buf,
int len, int msgtype);
int (*new_slave)(struct pp_instance *ppi, void *buf, int len);
int (*handle_resp)(struct pp_instance *ppi);
void (*s1)(struct pp_instance *ppi, MsgHeader *hdr, MsgAnnounce *ann);
void (*s1)(struct pp_instance *ppi, struct pp_frgn_master *frgn_master);
int (*execute_slave)(struct pp_instance *ppi);
int (*handle_announce)(struct pp_instance *ppi);
int (*handle_followup)(struct pp_instance *ppi, struct pp_time *orig);
......@@ -166,6 +164,8 @@ struct pp_ext_hooks {
int (*handle_presp) (struct pp_instance * ppi);
int (*pack_announce)(struct pp_instance *ppi);
void (*unpack_announce)(void *buf, MsgAnnounce *ann);
int (*state_decision)(struct pp_instance *ppi, int next_state);
void (*state_change)(struct pp_instance *ppi);
};
extern struct pp_ext_hooks pp_hooks; /* The one for the extension we build */
......@@ -198,6 +198,9 @@ extern struct pp_network_operations unix_net_ops;
* If "set" receives a NULL time value, it should update the TAI offset.
*/
struct pp_time_operations {
int (*get_utc_time)(struct pp_instance *ppi, int *hours, int *minutes, int *seconds);
int (*get_utc_offset)(struct pp_instance *ppi, int *offset, int *leap59, int *leap61);
int (*set_utc_offset)(struct pp_instance *ppi, int offset, int leap59, int leap61);
int (*get)(struct pp_instance *ppi, struct pp_time *t);
int (*set)(struct pp_instance *ppi, const struct pp_time *t);
/* freq_ppb is parts per billion */
......@@ -205,6 +208,7 @@ struct pp_time_operations {
int (*adjust_offset)(struct pp_instance *ppi, long offset_ns);
int (*adjust_freq)(struct pp_instance *ppi, long freq_ppb);
int (*init_servo)(struct pp_instance *ppi);
int (*get_servo_state)(struct pp_instance *ppi, int *state);
unsigned long (*calc_timeout)(struct pp_instance *ppi, int millisec);
};
......@@ -231,6 +235,7 @@ extern struct pp_time_operations unix_time_ops;
*/
extern void pp_timeout_init(struct pp_instance *ppi);
extern void __pp_timeout_set(struct pp_instance *ppi, int index, int millisec);
extern void pp_timeout_clear(struct pp_instance *ppi, int index);
extern void pp_timeout_set(struct pp_instance *ppi, int index);
extern void pp_timeout_setall(struct pp_instance *ppi);
extern int pp_timeout(struct pp_instance *ppi, int index)
......@@ -358,13 +363,38 @@ extern void pp_servo_got_psync(struct pp_instance *ppi); /* got t1 and t2 */
extern void pp_servo_got_presp(struct pp_instance *ppi); /* got all t3..t6 */
/* bmc.c */
extern void m1(struct pp_instance *ppi);
extern void bmc_m1(struct pp_instance *ppi);
extern void bmc_m2(struct pp_instance *ppi);
extern void bmc_m3(struct pp_instance *ppi);
extern void bmc_s1(struct pp_instance *ppi,
struct pp_frgn_master *frgn_master);
extern void bmc_p1(struct pp_instance *ppi);
extern void bmc_p2(struct pp_instance *ppi);
extern void bmc_setup_local_frgn_master(struct pp_instance *ppi,
struct pp_frgn_master *frgn_master);
extern int bmc_idcmp(struct ClockIdentity *a, struct ClockIdentity *b);
extern int bmc_pidcmp(struct PortIdentity *a, struct PortIdentity *b);
extern int bmc(struct pp_instance *ppi);
extern int bmc_gm_cmp(struct pp_instance *ppi,
struct pp_frgn_master *a,
struct pp_frgn_master *b);
extern int bmc_topology_cmp(struct pp_instance *ppi,
struct pp_frgn_master *a,
struct pp_frgn_master *b);
extern int bmc_dataset_cmp(struct pp_instance *ppi,
struct pp_frgn_master *a,
struct pp_frgn_master *b);
extern void bmc_store_frgn_master(struct pp_instance *ppi,
struct pp_frgn_master *frgn_master, void *buf, int len);
extern void bmc_add_frgn_master(struct pp_instance *ppi, void *buf,
int len);
extern int bmc_check_frgn_master(struct pp_instance *ppi);
/* msg.c */
extern void msg_init_header(struct pp_instance *ppi, void *buf);
extern int msg_from_current_master(struct pp_instance *ppi);
extern int __attribute__((warn_unused_result))
msg_unpack_header(struct pp_instance *ppi, void *buf, int plen);
msg_unpack_header(struct pp_instance *ppi, void *buf, int len);
extern void msg_unpack_sync(void *buf, MsgSync *sync);
extern int msg_pack_sync(struct pp_instance *ppi, struct pp_time *orig_tstamp);
extern void msg_unpack_announce(void *buf, MsgAnnounce *ann);
......@@ -383,7 +413,7 @@ extern void msg_unpack_pdelay_req(void *buf, MsgPDelayReq * pdelay_req);
#define PP_SEND_ERROR -1
#define PP_SEND_NO_STAMP 1
#define PP_SEND_DROP -2
#define PP_RECV_DROP PP_SEND_DROP
#define PP_RECV_DROP PP_SEND_DROP
extern void *msg_copy_header(MsgHeader *dest, MsgHeader *src); /* REMOVE ME!! */
extern int msg_issue_announce(struct pp_instance *ppi);
......@@ -406,7 +436,7 @@ extern void pp_time_div2(struct pp_time *t);
*/
/* Use a typedef, to avoid long prototypes */
typedef int pp_action(struct pp_instance *ppi, uint8_t *packet, int plen);
typedef int pp_action(struct pp_instance *ppi, void *buf, int len);
struct pp_state_table_item {
int state;
......@@ -421,8 +451,11 @@ extern pp_action pp_initializing, pp_faulty, pp_disabled, pp_listening,
pp_master, pp_passive, pp_uncalibrated,
pp_slave, pp_pclock;;
/* Enforce a state change */
extern int pp_leave_current_state(struct pp_instance *ppi);
/* The engine */
extern int pp_state_machine(struct pp_instance *ppi, uint8_t *packet, int plen);
extern int pp_state_machine(struct pp_instance *ppi, void *buf, int len);
/* Frame-drop support -- rx before tx, alphabetically */
extern void ppsi_drop_init(struct pp_globals *ppg, unsigned long seed);
......
......@@ -24,6 +24,8 @@ void bare_main_loop(struct pp_instance *ppi)
{
int delay_ms;
/* just tell that the links are up */
ppi->link_up = TRUE;
/*
* The main loop here is based on select. While we are not
* doing anything else but the protocol, this allows extra stuff
......
......@@ -27,7 +27,7 @@ struct pp_msgtype_info pp_msgtype_info[16] = {
"delay_resp", PP_DELAY_RESP_LENGTH,
PP_NP_GEN, PP_E2E_MECH, 3, PP_LOG_REQUEST },
[PPM_PDELAY_R_FUP] = {
"pdelay_resp_follow_up", PP_PDELAY_R_FUP_LENGTH,
"pdelay_resp_follow_up", PP_PDELAY_RESP_FOLLOW_UP_LENGTH,
PP_NP_GEN, PP_P2P_MECH, 5, 0x7f },
[PPM_ANNOUNCE] = {
"announce", PP_ANNOUNCE_LENGTH,
......
......@@ -10,7 +10,7 @@
/* We are entering WR handshake, as either master or slave */
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) {
......
......@@ -20,7 +20,7 @@ struct pp_state_table_item pp_state_table[] = {
{ PPS_PRE_MASTER, "pre-master", pp_master,},
{ PPS_MASTER, "master", pp_master,},
{ PPS_PASSIVE, "passive", pp_passive,},
{ PPS_UNCALIBRATED, "uncalibrated", pp_uncalibrated,},
{ PPS_UNCALIBRATED, "uncalibrated", pp_slave,},
{ PPS_SLAVE, "slave", pp_slave,},
{ WRS_PRESENT, "uncalibrated/wr-present", wr_present,},
{ WRS_M_LOCK, "master/wr-m-lock", wr_m_lock,},
......
#include <ppsi/ppsi.h>
#include "wr-api.h"
#include "../proto-standard/common-fun.h"
/* ext-whiterabbit must offer its own hooks */
static int wr_init(struct pp_instance *ppi, unsigned char *pkt, int plen)
static int wr_init(struct pp_instance *ppi, void *buf, int len)
{
struct wr_dsport *wrp = WR_DSPOR(ppi);
......@@ -52,8 +51,7 @@ static int wr_open(struct pp_globals *ppg, struct pp_runtime_opts *rt_opts)
/* FIXME check if correct: assign to each instance the same
* wr_data. May I move it to pp_globals? */
INST(ppg, i)->ext_data = ppg->global_ext_data;
INST(ppg, i)->ext_data = ppg->global_ext_data;
if (ppi->cfg.ext == PPSI_EXT_WR) {
switch (ppi->role) {
case PPSI_ROLE_MASTER:
......@@ -73,7 +71,7 @@ static int wr_open(struct pp_globals *ppg, struct pp_runtime_opts *rt_opts)
return 0;
}
static int wr_listening(struct pp_instance *ppi, unsigned char *pkt, int plen)
static int wr_listening(struct pp_instance *ppi, void *buf, int len)
{
struct wr_dsport *wrp = WR_DSPOR(ppi);
......@@ -82,7 +80,7 @@ static int wr_listening(struct pp_instance *ppi, unsigned char *pkt, int plen)
return 0;
}
static int wr_master_msg(struct pp_instance *ppi, unsigned char *pkt, int plen,
static int wr_master_msg(struct pp_instance *ppi, void *buf, int len,
int msgtype)
{
MsgSignaling wrsig_msg;
......@@ -105,7 +103,7 @@ static int wr_master_msg(struct pp_instance *ppi, unsigned char *pkt, int plen,
/* This is missing in the standard protocol */
case PPM_SIGNALING:
msg_unpack_wrsig(ppi, pkt, &wrsig_msg,
msg_unpack_wrsig(ppi, buf, &wrsig_msg,
&(WR_DSPOR(ppi)->msgTmpWrMessageID));
if ((WR_DSPOR(ppi)->msgTmpWrMessageID == SLAVE_PRESENT) &&
(WR_DSPOR(ppi)->wrConfig & WR_M_ONLY)) {
......@@ -119,7 +117,7 @@ static int wr_master_msg(struct pp_instance *ppi, unsigned char *pkt, int plen,
return msgtype;
}
static int wr_new_slave(struct pp_instance *ppi, unsigned char *pkt, int plen)
static int wr_new_slave(struct pp_instance *ppi, void *buf, int len)
{
pp_diag(ppi, ext, 2, "hook: %s\n", __func__);
wr_servo_init(ppi);
......@@ -161,27 +159,35 @@ static int wr_handle_resp(struct pp_instance *ppi)
return 0;
}
static void wr_s1(struct pp_instance *ppi, MsgHeader *hdr, MsgAnnounce *ann)
static void wr_s1(struct pp_instance *ppi, struct pp_frgn_master *frgn_master)
{
pp_diag(ppi, ext, 2, "hook: %s\n", __func__);
WR_DSPOR(ppi)->parentIsWRnode =
((ann->ext_specific & WR_NODE_MODE) != NON_WR);
((frgn_master->ext_specific & WR_NODE_MODE) != NON_WR);
WR_DSPOR(ppi)->parentWrModeOn =
(ann->ext_specific & WR_IS_WR_MODE) ? TRUE : FALSE;
(frgn_master->ext_specific & WR_IS_WR_MODE) ? TRUE : FALSE;
WR_DSPOR(ppi)->parentCalibrated =
((ann->ext_specific & WR_IS_CALIBRATED) ? 1 : 0);
WR_DSPOR(ppi)->parentWrConfig = ann->ext_specific & WR_NODE_MODE;
((frgn_master->ext_specific & WR_IS_CALIBRATED) ? 1 : 0);
WR_DSPOR(ppi)->parentWrConfig = frgn_master->ext_specific & WR_NODE_MODE;
DSCUR(ppi)->primarySlavePortNumber =
DSPOR(ppi)->portIdentity.portNumber;
}
static int wr_execute_slave(struct pp_instance *ppi)
int wr_execute_slave(struct pp_instance *ppi)
{
pp_diag(ppi, ext, 2, "hook: %s\n", __func__);
if (pp_timeout(ppi, PP_TO_FAULT))
wr_servo_reset(ppi); /* the caller handles ptp state machine */
if ((ppi->state == PPS_SLAVE) &&
(WR_DSPOR(ppi)->wrConfig & WR_S_ONLY) &&
(WR_DSPOR(ppi)->parentWrConfig & WR_M_ONLY) &&
(!WR_DSPOR(ppi)->wrModeOn || !WR_DSPOR(ppi)->parentWrModeOn)) {
/* We must start the handshake as a WR slave */
wr_handshake_init(ppi, PPS_SLAVE);
}
/* The doRestart thing is not used, it seems */
if (!WR_DSPOR(ppi)->doRestart)
return 0;
......@@ -193,13 +199,19 @@ static int wr_execute_slave(struct pp_instance *ppi)
static int wr_handle_announce(struct pp_instance *ppi)
{
pp_diag(ppi, ext, 2, "hook: %s\n", __func__);
if ((WR_DSPOR(ppi)->wrConfig & WR_S_ONLY) &&
(1 /* FIXME: Recommended State, see page 33*/) &&
(WR_DSPOR(ppi)->parentWrConfig & WR_M_ONLY) &&
(!WR_DSPOR(ppi)->wrModeOn || !WR_DSPOR(ppi)->parentWrModeOn)) {
/* We must start the handshake as a WR slave */
wr_handshake_init(ppi, PPS_SLAVE);
if ((ppi->state == WRS_PRESENT) ||
(ppi->state == WRS_S_LOCK) ||
(ppi->state == WRS_LOCKED) ||
(ppi->state == WRS_CALIBRATION) ||
(ppi->state == WRS_CALIBRATED) ||
(ppi->state == WRS_RESP_CALIB_REQ) ||
(ppi->state == WRS_WR_LINK_ON)) {
/* reset announce timeout when in the WR slave states */
pp_timeout_set(ppi, PP_TO_ANN_RECEIPT);
}
/* handshake is started in slave mode */
return 0;
}
......@@ -268,10 +280,68 @@ static void wr_unpack_announce(void *buf, MsgAnnounce *ann)
int msg_len = htons(*(UInteger16 *) (buf + 2));
pp_diag(NULL, ext, 2, "hook: %s\n", __func__);
if (msg_len > PP_ANNOUNCE_LENGTH)
if (msg_len >= WR_ANNOUNCE_LENGTH)
msg_unpack_announce_wr_tlv(buf, ann);
else
ann->ext_specific = 0;
}
/* State decision algorithm 9.3.3 Fig 26 with extension for wr */
static int wr_state_decision(struct pp_instance *ppi, int next_state)
{
pp_diag(ppi, ext, 2, "hook: %s\n", __func__);
/*
* if in one of the WR states stay in them,
* they will eventually go back to the normal states
*/
if ((ppi->state == WRS_PRESENT) ||
(ppi->state == WRS_M_LOCK) ||
(ppi->state == WRS_S_LOCK) ||
(ppi->state == WRS_LOCKED) ||
(ppi->state == WRS_CALIBRATION) ||
(ppi->state == WRS_CALIBRATED) ||
(ppi->state == WRS_RESP_CALIB_REQ) ||
(ppi->state == WRS_WR_LINK_ON))
return ppi->state;
/* else do the normal statemachine */
return next_state;
}
static void wr_state_change(struct pp_instance *ppi)
{
struct wr_dsport *wrp = WR_DSPOR(ppi);
pp_diag(ppi, ext, 2, "hook: %s\n", __func__);
if ((ppi->next_state == WRS_PRESENT) ||
(ppi->next_state == WRS_M_LOCK) ||
(ppi->next_state == WRS_S_LOCK) ||
(ppi->next_state == WRS_LOCKED) ||
(ppi->next_state == WRS_CALIBRATION) ||
(ppi->next_state == WRS_CALIBRATED) ||
(ppi->next_state == WRS_RESP_CALIB_REQ) ||
(ppi->next_state == WRS_WR_LINK_ON))
return;
/* if we are leaving the WR locked states reset the WR process */
if ((ppi->next_state != ppi->state) &&
(wrp->wrModeOn == TRUE) &&
((ppi->state == PPS_SLAVE) ||
(ppi->state == PPS_MASTER))) {
wrp->wrStateTimeout = WR_DEFAULT_STATE_TIMEOUT_MS;
wrp->calPeriod = WR_DEFAULT_CAL_PERIOD;
wrp->wrModeOn = FALSE;
wrp->parentWrConfig = NON_WR;
wrp->parentWrModeOn = FALSE;
wrp->calibrated = !WR_DEFAULT_PHY_CALIBRATION_REQUIRED;
if (ppi->state == PPS_SLAVE)
wrp->ops->locking_reset(ppi);
}
}
struct pp_ext_hooks pp_hooks = {
.init = wr_init,
......@@ -289,4 +359,6 @@ struct pp_ext_hooks pp_hooks = {
#endif
.pack_announce = wr_pack_announce,
.unpack_announce = wr_unpack_announce,
.state_decision = wr_state_decision,
.state_change = wr_state_change,
};
......@@ -13,7 +13,7 @@
* We enter here from WRS_CALIBRATION. If master we wait for
* a CALIBRATE message, if slave we wait for LINK_ON.
*/
int wr_calibrated(struct pp_instance *ppi, unsigned char *pkt, int plen)
int wr_calibrated(struct pp_instance *ppi, void *buf, int len)
{
struct wr_dsport *wrp = WR_DSPOR(ppi);
MsgSignaling wrsig_msg;
......@@ -32,7 +32,7 @@ int wr_calibrated(struct pp_instance *ppi, unsigned char *pkt, int plen)
}
if (ppi->received_ptp_header.messageType == PPM_SIGNALING) {
msg_unpack_wrsig(ppi, pkt, &wrsig_msg,
msg_unpack_wrsig(ppi, buf, &wrsig_msg,
&(wrp->msgTmpWrMessageID));
if ((wrp->msgTmpWrMessageID == CALIBRATE) &&
......
......@@ -13,7 +13,7 @@
* 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.
*/
int wr_calibration(struct pp_instance *ppi, unsigned char *pkt, int plen)
int wr_calibration(struct pp_instance *ppi, void *buf, int len)
{
struct wr_dsport *wrp = WR_DSPOR(ppi);
int sendmsg = 0;
......
......@@ -13,7 +13,7 @@
* 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
*/
int wr_link_on(struct pp_instance *ppi, unsigned char *pkt, int plen)
int wr_link_on(struct pp_instance *ppi, void *buf, int len)
{
struct wr_dsport *wrp = WR_DSPOR(ppi);
int e = 0;
......
......@@ -13,7 +13,7 @@
* WR slave: got here from WRS_S_LOCK: send LOCKED, wait for CALIBRATE.
* On timeout resend.
*/
int wr_locked(struct pp_instance *ppi, unsigned char *pkt, int plen)
int wr_locked(struct pp_instance *ppi, void *buf, int len)
{
int e = 0, sendmsg = 0;
MsgSignaling wrsig_msg;
......@@ -36,7 +36,7 @@ int wr_locked(struct pp_instance *ppi, unsigned char *pkt, int plen)
if (ppi->received_ptp_header.messageType == PPM_SIGNALING) {
msg_unpack_wrsig(ppi, pkt, &wrsig_msg,
msg_unpack_wrsig(ppi, buf, &wrsig_msg,
&(wrp->msgTmpWrMessageID));
if (wrp->msgTmpWrMessageID == CALIBRATE)
......
......@@ -13,7 +13,7 @@
* This the entry point for a WR master: send "LOCK" and wait
* for "LOCKED". On timeout retry sending, for WR_STATE_RETRY times.
*/
int wr_m_lock(struct pp_instance *ppi, unsigned char *pkt, int plen)
int wr_m_lock(struct pp_instance *ppi, void *buf, int len)
{
int e = 0, sendmsg = 0;
MsgSignaling wrsig_msg;
......@@ -35,14 +35,14 @@ int wr_m_lock(struct pp_instance *ppi, unsigned char *pkt, int plen)
}
if (ppi->received_ptp_header.messageType == PPM_SIGNALING) {
msg_unpack_wrsig(ppi, pkt, &wrsig_msg,
msg_unpack_wrsig(ppi, buf, &wrsig_msg,
&(wrp->msgTmpWrMessageID));
if (wrp->msgTmpWrMessageID == LOCKED)
ppi->next_state = WRS_CALIBRATION;
}
ppi->next_delay = wrp->wrStateTimeout;
return e;
......
......@@ -8,7 +8,6 @@
#include <ppsi/ppsi.h>
#include "wr-api.h"
#include "../proto-standard/common-fun.h"
/*
* WRS_PRESENT is the entry point for a WR slave
......@@ -16,13 +15,13 @@
* Here we send SLAVE_PRESENT and wait for LOCK. If timeout,
* resent SLAVE_PRESENT from WR_STATE_RETRY times
*/
int wr_present(struct pp_instance *ppi, unsigned char *pkt, int plen)
int wr_present(struct pp_instance *ppi, void *buf, int len)
{
int e = 0, sendmsg = 0;
struct wr_dsport *wrp = WR_DSPOR(ppi);
MsgSignaling wrsig_msg;
if (ppi->is_new_state) {
wrp->wrStateRetry = WR_STATE_RETRY;
sendmsg = 1;
......@@ -39,8 +38,7 @@ int wr_present(struct pp_instance *ppi, unsigned char *pkt, int plen)
}
if (ppi->received_ptp_header.messageType == PPM_SIGNALING) {
msg_unpack_wrsig(ppi, pkt, &wrsig_msg,
msg_unpack_wrsig(ppi, buf, &wrsig_msg,
&(wrp->msgTmpWrMessageID));
if (wrp->msgTmpWrMessageID == LOCK)
......@@ -48,7 +46,7 @@ int wr_present(struct pp_instance *ppi, unsigned char *pkt, int plen)
}
if (e == 0)
st_com_execute_slave(ppi);
wr_execute_slave(ppi);
else {
/* nothing, just stay here again */
}
......
......@@ -9,7 +9,7 @@
#include <ppsi/ppsi.h>
#include "wr-api.h"
int wr_resp_calib_req(struct pp_instance *ppi, unsigned char *pkt, int plen)
int wr_resp_calib_req(struct pp_instance *ppi, void *buf, int len)
{
struct wr_dsport *wrp = WR_DSPOR(ppi);
MsgSignaling wrsig_msg;
......@@ -37,7 +37,7 @@ int wr_resp_calib_req(struct pp_instance *ppi, unsigned char *pkt, int plen)
if (ppi->received_ptp_header.messageType == PPM_SIGNALING) {
msg_unpack_wrsig(ppi, pkt, &wrsig_msg,
msg_unpack_wrsig(ppi, buf, &wrsig_msg,
&(wrp->msgTmpWrMessageID));
if (wrp->msgTmpWrMessageID == CALIBRATED) {
......
......@@ -9,14 +9,14 @@
#include <ppsi/ppsi.h>
#include "wr-api.h"
int wr_s_lock(struct pp_instance *ppi, unsigned char *pkt, int plen)
int wr_s_lock(struct pp_instance *ppi, void *buf, int len)
{
struct wr_dsport *wrp = WR_DSPOR(ppi);
int enable = 0;
int poll_ret;
if (ppi->is_new_state) {
wrp->wrStateRetry = WR_STATE_RETRY;
wrp->wrStateRetry = WR_STATE_RETRY;
enable = 1;
} else if (pp_timeout(ppi, PP_TO_EXT_0)) {
wrp->ops->locking_disable(ppi);
......
......@@ -11,8 +11,7 @@
/* Please increment WRS_PPSI_SHMEM_VERSION if you change any exported data
* structure */
#define WRS_PPSI_SHMEM_VERSION 20 /* Replace cField, t4_cf and t6_cf with
syncCF */
#define WRS_PPSI_SHMEM_VERSION 30 /* added HAL_PORT_STATE_RESET to hal */
/* Don't include the Following when this file is included in assembler. */
#ifndef __ASSEMBLY__
......@@ -52,7 +51,6 @@ struct wr_dsport {
FixedDelta otherNodeDeltaTx;
FixedDelta otherNodeDeltaRx;
Boolean doRestart;
Boolean linkUP;
};
/* This uppercase name matches "DSPOR(ppi)" used by standard protocol */
......@@ -86,21 +84,21 @@ void msg_unpack_wrsig(struct pp_instance *ppi, void *buf,
int msg_issue_wrsig(struct pp_instance *ppi, Enumeration16 wr_msg_id);
/* White rabbit state functions */
int wr_present(struct pp_instance *ppi, unsigned char *pkt, int plen);
int wr_m_lock(struct pp_instance *ppi, unsigned char *pkt, int plen);
int wr_s_lock(struct pp_instance *ppi, unsigned char *pkt, int plen);
int wr_locked(struct pp_instance *ppi, unsigned char *pkt, int plen);
int wr_calibration(struct pp_instance *ppi, unsigned char *pkt, int plen);
int wr_calibrated(struct pp_instance *ppi, unsigned char *pkt, int plen);
int wr_resp_calib_req(struct pp_instance *ppi, unsigned char *pkt, int plen);
int wr_link_on(struct pp_instance *ppi, unsigned char *pkt, int plen);
int wr_present(struct pp_instance *ppi, void *buf, int len);
int wr_m_lock(struct pp_instance *ppi, void *buf, int len);
int wr_s_lock(struct pp_instance *ppi, void *buf, int len);
int wr_locked(struct pp_instance *ppi, void *buf, int len);
int wr_calibration(struct pp_instance *ppi, void *buf, int len);
int wr_calibrated(struct pp_instance *ppi, void *buf, int len);
int wr_resp_calib_req(struct pp_instance *ppi, void *buf, int len);
int wr_link_on(struct pp_instance *ppi, void *buf, int len);
int wr_abscal(struct pp_instance *ppi, unsigned char *pkt, int plen);
/* Common functions, used by various states and hooks */
void wr_handshake_init(struct pp_instance *ppi, int mode);
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_execute_slave(struct pp_instance *ppi);
struct wr_servo_state;
/* White Rabbit hw-dependent functions (code in arch-wrpc and arch-wrs) */
......@@ -108,6 +106,7 @@ struct wr_operations {
int (*locking_enable)(struct pp_instance *ppi);
int (*locking_poll)(struct pp_instance *ppi, int grandmaster);
int (*locking_disable)(struct pp_instance *ppi);
int (*locking_reset)(struct pp_instance *ppi);
int (*enable_ptracker)(struct pp_instance *ppi);
int (*adjust_in_progress)(void);
......
......@@ -57,26 +57,9 @@ void msg_pack_announce_wr_tlv(struct pp_instance *ppi)
{
void *buf;
UInteger16 wr_flags = 0;
int locked, class = DSDEF(ppi)->clockQuality.clockClass;
struct wr_dsport *wrp = WR_DSPOR(ppi);
buf = ppi->tx_ptp;
/* GM: update clock Class, according to whether we are locked or not */
if (class < PP_CLASS_DEFAULT) {
locked = wrp->ops->locking_poll(ppi, 1);
if (locked == WR_SPLL_READY)
class = PP_CLASS_WR_GM_LOCKED;
else
class = PP_CLASS_WR_GM_UNLOCKED;
m1(ppi);
if (class != DSDEF(ppi)->clockQuality.clockClass) {
pp_error("New class %i\n", class);
DSDEF(ppi)->clockQuality.clockClass = class;
*(UInteger8 *) (buf + 48) = class;
}
}
/* Change length */
*(UInteger16 *)(buf + 2) = htons(WR_ANNOUNCE_LENGTH);
......@@ -124,7 +107,8 @@ void msg_unpack_announce_wr_tlv(void *buf, MsgAnnounce *ann)
tlv_versionNumber == WR_TLV_WR_VERSION_NUMBER &&
tlv_wrMessageID == ANN_SUFIX) {
ann->ext_specific = (UInteger16)get_be16(buf+76);
}
} else
ann->ext_specific = 0;
}
/* White Rabbit: packing WR Signaling messages*/
......
......@@ -11,7 +11,6 @@ OBJ-y += $D/fsm-table.o \
$D/state-listening.o \
$D/state-master.o \
$D/state-passive.o \
$D/state-uncalibrated.o \
$D/state-slave.o \
$D/common-fun.o \
$D/bmc.o \
......
This diff is collapsed.
......@@ -71,70 +71,6 @@ void pp_prepare_pointers(struct pp_instance *ppi)
}
}
/* Called by listening, passive, slave, uncalibrated */
int st_com_execute_slave(struct pp_instance *ppi)
{
int ret = 0;
if (pp_hooks.execute_slave)
ret = pp_hooks.execute_slave(ppi);
if (ret == 1) /* done: just return */
return 0;
if (ret < 0)
return ret;
if (pp_timeout(ppi, PP_TO_ANN_RECEIPT)
|| pp_timeout(ppi, PP_TO_FAULT)) {
/*
* Note: TO_FAULTY == SYNCHRONIZATION_FAULT
* should move us to UNCALIBRATED (not implemented)
*/
ppi->frgn_rec_num = 0;
if (DSDEF(ppi)->clockQuality.clockClass != PP_CLASS_SLAVE_ONLY
&& (ppi->role != PPSI_ROLE_SLAVE)) {
ppi->next_state = PPS_MASTER;
} else {
ppi->next_state = PPS_LISTENING;
pp_timeout_set(ppi, PP_TO_ANN_RECEIPT);
}
}
return 0;
}
/* Called by slave and uncalibrated */
int st_com_slave_handle_sync(struct pp_instance *ppi, unsigned char *buf,
int len)
{
MsgHeader *hdr = &ppi->received_ptp_header;
MsgSync sync;
if (!(ppi->flags & PPI_FLAG_FROM_CURRENT_PARENT))
return 0;
/* t2 may be overriden by follow-up, save it immediately */
ppi->t2 = ppi->last_rcv_time;
msg_unpack_sync(buf, &sync);
if ((hdr->flagField[0] & PP_TWO_STEP_FLAG) != 0) {
ppi->flags |= PPI_FLAG_WAITING_FOR_F_UP;
ppi->recv_sync_sequence_id = hdr->sequenceId;
/* for two-step, the stamp comes later */
ppi->t1 = hdr->cField; /* most likely 0 */
return 0;
}
/* one-step folllows */
ppi->flags &= ~PPI_FLAG_WAITING_FOR_F_UP;
ppi->t1 = sync.originTimestamp;
pp_time_add(&ppi->t1, &hdr->cField);
ppi->syncCF = 0;
if (CONFIG_HAS_P2P && ppi->mech == PP_P2P_MECH)
pp_servo_got_psync(ppi);
else
pp_servo_got_sync(ppi);
return 0;
}
static int presp_call_servo(struct pp_instance *ppi)
{
int ret = 0;
......@@ -151,23 +87,59 @@ static int presp_call_servo(struct pp_instance *ppi)
return ret;
}
int st_com_peer_handle_pres(struct pp_instance *ppi, unsigned char *buf,
int st_com_check_announce_receive_timeout(struct pp_instance *ppi)
{
struct pp_globals *ppg = GLBS(ppi);
int is_gm = 1;
int i;
if (pp_timeout(ppi, PP_TO_ANN_RECEIPT)) {
/* 9.2.6.11 b) reset timeout when an announce timeout happended */
pp_timeout_set(ppi, PP_TO_ANN_RECEIPT);
if (DSDEF(ppi)->clockQuality.clockClass != PP_CLASS_SLAVE_ONLY
&& (ppi->role != PPSI_ROLE_SLAVE)) {
if (DSDEF(ppi)->numberPorts > 1) {
for (i = 0; i < ppg->defaultDS->numberPorts; i++) {
if ((INST(ppg, i)->state == PPS_UNCALIBRATED) ||
(INST(ppg, i)->state == PPS_SLAVE))
is_gm = 0;
}
if (is_gm)
bmc_m1(ppi);
else
bmc_m3(ppi);
} else
bmc_m1(ppi);
ppi->next_state = PPS_MASTER;
} else {
ppi->next_state = PPS_LISTENING;
}
}
return 0;
}
int st_com_peer_handle_pres(struct pp_instance *ppi, void *buf,
int len)
{
MsgPDelayResp resp;
MsgHeader *hdr = &ppi->received_ptp_header;
int e = 0;
/* if not in P2P mode, just return */
if (!CONFIG_HAS_P2P || ppi->mech != PP_P2P_MECH)
return 0;
msg_unpack_pdelay_resp(buf, &resp);
if ((memcmp(&DSPOR(ppi)->portIdentity.clockIdentity,
&resp.requestingPortIdentity.clockIdentity,
PP_CLOCK_IDENTITY_LENGTH) == 0) &&
if ((bmc_idcmp(&DSPOR(ppi)->portIdentity.clockIdentity,
&resp.requestingPortIdentity.clockIdentity) == 0) &&
((ppi->sent_seq[PPM_PDELAY_REQ]) ==
hdr->sequenceId) &&
(DSPOR(ppi)->portIdentity.portNumber ==
resp.requestingPortIdentity.portNumber) &&
(ppi->flags & PPI_FLAG_FROM_CURRENT_PARENT)) {
(msg_from_current_master(ppi))) {
ppi->t4 = resp.requestReceiptTimestamp;
pp_time_add(&ppi->t4, &hdr->cField);
......@@ -193,24 +165,26 @@ int st_com_peer_handle_pres(struct pp_instance *ppi, unsigned char *buf,
return e;
}
int st_com_peer_handle_pres_followup(struct pp_instance *ppi,
unsigned char *buf, int plen)
void *buf, int len)
{
MsgHeader *hdr = &ppi->received_ptp_header;
MsgPDelayRespFollowUp respFllw;
int e = 0;
/* if not in P2P mode, just return */
if (!CONFIG_HAS_P2P || ppi->mech != PP_P2P_MECH)
return 0;
msg_unpack_pdelay_resp_follow_up(buf, &respFllw);
if ((memcmp(&DSPOR(ppi)->portIdentity.clockIdentity,
&respFllw.requestingPortIdentity.clockIdentity,
PP_CLOCK_IDENTITY_LENGTH) == 0) &&
if ((bmc_idcmp(&DSPOR(ppi)->portIdentity.clockIdentity,
&respFllw.requestingPortIdentity.clockIdentity) == 0) &&
((ppi->sent_seq[PPM_PDELAY_REQ]) ==
hdr->sequenceId) &&
(DSPOR(ppi)->portIdentity.portNumber ==
respFllw.requestingPortIdentity.portNumber) &&
(ppi->flags & PPI_FLAG_FROM_CURRENT_PARENT)) {
(msg_from_current_master(ppi))) {
ppi->t5 = respFllw.responseOriginTimestamp;
pp_time_add(&ppi->t5, &hdr->cField);
......@@ -224,11 +198,15 @@ int st_com_peer_handle_pres_followup(struct pp_instance *ppi,
return e;
}
int st_com_peer_handle_preq(struct pp_instance *ppi, unsigned char *buf,
int st_com_peer_handle_preq(struct pp_instance *ppi, void *buf,
int len)
{
int e = 0;
/* if not in P2P mode, just return */
if (!CONFIG_HAS_P2P || ppi->mech != PP_P2P_MECH)
return 0;
if (pp_hooks.handle_preq)
e = pp_hooks.handle_preq(ppi);
if (e)
......@@ -240,64 +218,12 @@ int st_com_peer_handle_preq(struct pp_instance *ppi, unsigned char *buf,
return 0;
}
/* Called by slave and uncalibrated */
int st_com_slave_handle_followup(struct pp_instance *ppi, unsigned char *buf,
int len)
int st_com_handle_announce(struct pp_instance *ppi, void *buf, int len)
{
MsgFollowUp follow;
int ret = 0;
MsgHeader *hdr = &ppi->received_ptp_header;
if (!(ppi->flags & PPI_FLAG_FROM_CURRENT_PARENT)) {
pp_error("%s: Follow up message is not from current parent\n",
__func__);
return 0;
}
bmc_add_frgn_master(ppi, buf, len);
if (!(ppi->flags & PPI_FLAG_WAITING_FOR_F_UP)) {
pp_error("%s: Slave was not waiting a follow up message\n",
__func__);
return 0;
}
if (ppi->recv_sync_sequence_id != hdr->sequenceId) {
pp_error("%s: SequenceID %d doesn't match last Sync message %d\n",
__func__, hdr->sequenceId, ppi->recv_sync_sequence_id);
return 0;
}
msg_unpack_follow_up(buf, &follow);
ppi->flags &= ~PPI_FLAG_WAITING_FOR_F_UP;
/* t1 for calculations is T1 + Csyn + Cful -- see README-cfield */
pp_time_add(&ppi->t1, &follow.preciseOriginTimestamp);
pp_time_add(&ppi->t1, &hdr->cField);
ppi->syncCF = hdr->cField.scaled_nsecs; /* for diag about TC */
/* Call the extension; it may do it all and ask to return */
if (pp_hooks.handle_followup)
ret = pp_hooks.handle_followup(ppi, &ppi->t1);
if (ret == 1)
return 0;
if (ret < 0)
return ret;
if (CONFIG_HAS_P2P && ppi->mech == PP_P2P_MECH)
pp_servo_got_psync(ppi);
else
pp_servo_got_sync(ppi);
return 0;
}
/*
* Called by master, listenting, passive.
* FIXME: this must be implemented to support one-step masters
*/
int st_com_master_handle_sync(struct pp_instance *ppi, unsigned char *buf,
int len)
{
/* No more used: follow up is sent right after the corresponding sync */
if (pp_hooks.handle_announce)
return pp_hooks.handle_announce(ppi);
return 0;
}
......
......@@ -12,40 +12,30 @@
#include <ppsi/ppsi.h>
/* Contains all functions common to more than one state */
int st_com_check_announce_receive_timeout(struct pp_instance *ppi);
/* returns -1 in case of error, see below */
int st_com_execute_slave(struct pp_instance *ppi);
/* Each of the following "handle" functions" return 0 in case of correct
* message, -1 in case the message contained in buf is not proper (e.g. size
* is not the expected one
*/
int st_com_slave_handle_sync(struct pp_instance *ppi, unsigned char *buf,
int len);
int st_com_master_handle_sync(struct pp_instance *ppi, unsigned char *buf,
int len);
int st_com_slave_handle_followup(struct pp_instance *ppi, unsigned char *buf,
int len);
int st_com_peer_handle_preq(struct pp_instance *ppi, unsigned char *buf,
int st_com_peer_handle_preq(struct pp_instance *ppi, void *buf,
int len);
int st_com_peer_handle_pres(struct pp_instance *ppi, unsigned char *buf,
int st_com_peer_handle_pres(struct pp_instance *ppi, void *buf,
int len);
int st_com_peer_handle_pres_followup(struct pp_instance *ppi,
unsigned char *buf, int len);
void *buf, int len);
int st_com_handle_announce(struct pp_instance *ppi, void *buf,
int len);
int __send_and_log(struct pp_instance *ppi, int msglen, int chtype);
/* Count successfully received PTP packets */
static inline int __recv_and_count(struct pp_instance *ppi, void *pkt, int len,
static inline int __recv_and_count(struct pp_instance *ppi, void *buf, int len,
struct pp_time *t)
{
int ret;
ret = ppi->n_ops->recv(ppi, pkt, len, t);
ret = ppi->n_ops->recv(ppi, buf, len, t);
if (ret > 0)
ppi->ptp_rx_count++;
return ret;
......
......@@ -79,12 +79,44 @@ int pp_lib_may_issue_sync(struct pp_instance *ppi)
int pp_lib_may_issue_announce(struct pp_instance *ppi)
{
struct DSTimeProperties *prop = DSPRO(ppi);
int ret = 0;
int offset, leap59, leap61;
int hours, minutes, seconds;
int e;
if (!pp_timeout(ppi, PP_TO_ANN_SEND))
return 0;
pp_timeout_set(ppi, PP_TO_ANN_SEND);
/* this check has to be done here since the
* update of the properties might have not
* happened before sending
*/
if (prop->ptpTimescale) {
ret = ppi->t_ops->get_utc_time(ppi, &hours, &minutes, &seconds);
if (ret) {
pp_diag(ppi, frames, 1,
"Could not get UTC time from system, taking received flags\n");
} else {
/* for 2 announce intervals after midnight, get the offset from the system */
if ((hours == 00) && (minutes == 00) &&
(seconds <= (0 + (2 * (1 << ppi->portDS->logAnnounceInterval))))) {
pp_diag(ppi, frames, 2,
"short after midnight, taking local offset\n");
ret = ppi->t_ops->get_utc_offset(ppi, &offset, &leap59, &leap61);
if (ret) {
pp_diag(ppi, frames, 1,
"Could not get UTC offset from system\n");
} else {
prop->currentUtcOffset = offset;
}
prop->leap59 = FALSE;
prop->leap61 = FALSE;
}
}
}
e = pp_vlan_issue_announce(ppi);
if (e)
pp_diag(ppi, frames, 1, "could not send announce\n");
......@@ -108,53 +140,4 @@ int pp_lib_may_issue_request(struct pp_instance *ppi)
return 0;
}
/* Called by this file, basically when an announce is got, all states */
static void __lib_add_foreign(struct pp_instance *ppi, unsigned char *buf)
{
int i;
MsgHeader *hdr = &ppi->received_ptp_header;
/* Check if foreign master is already known */
for (i = 0; i < ppi->frgn_rec_num; i++) {
if (!memcmp(&hdr->sourcePortIdentity,
&ppi->frgn_master[i].port_id,
sizeof(hdr->sourcePortIdentity))) {
/* already in Foreign master data set, update info */
msg_copy_header(&ppi->frgn_master[i].hdr, hdr);
msg_unpack_announce(buf, &ppi->frgn_master[i].ann);
return;
}
}
/* New foreign master */
if (ppi->frgn_rec_num < PP_NR_FOREIGN_RECORDS)
ppi->frgn_rec_num++;
/* FIXME: replace the worst */
i = ppi->frgn_rec_num - 1;
/* Copy new foreign master data set from announce message */
memcpy(&ppi->frgn_master[i].port_id,
&hdr->sourcePortIdentity, sizeof(hdr->sourcePortIdentity));
/*
* header and announce field of each Foreign Master are
* useful to run Best Master Clock Algorithm
*/
msg_copy_header(&ppi->frgn_master[i].hdr, hdr);
msg_unpack_announce(buf, &ppi->frgn_master[i].ann);
pp_diag(ppi, bmc, 1, "New foreign Master %i added\n", i);
}
int pp_lib_handle_announce(struct pp_instance *ppi, unsigned char *buf, int len)
{
__lib_add_foreign(ppi, buf);
ppi->next_state = bmc(ppi); /* got a new announce: run bmc */
pp_timeout_set(ppi, PP_TO_ANN_RECEIPT);
if (pp_hooks.handle_announce)
return pp_hooks.handle_announce(ppi);
return 0;
}
......@@ -21,7 +21,7 @@ struct pp_state_table_item pp_state_table[] __attribute__((weak)) = {
{ PPS_PRE_MASTER, "pre-master", pp_master,},
{ PPS_MASTER, "master", pp_master,},
{ PPS_PASSIVE, "passive", pp_passive,},
{ PPS_UNCALIBRATED, "uncalibrated", pp_uncalibrated,},
{ PPS_UNCALIBRATED, "uncalibrated", pp_slave,},
{ PPS_SLAVE, "slave", pp_slave,},
{ PPS_END_OF_TABLE,}
};
......@@ -9,8 +9,20 @@
#include <ppsi/ppsi.h>
#include "common-fun.h"
/* return 1 if the frame is from the current master, else 0 */
int msg_from_current_master(struct pp_instance *ppi)
{
MsgHeader *hdr = &ppi->received_ptp_header;
if (!bmc_pidcmp(&DSPAR(ppi)->parentPortIdentity,
&hdr->sourcePortIdentity))
return 1;
else
return 0;
}
/* Unpack header from in buffer to receieved_ptp_header field */
int msg_unpack_header(struct pp_instance *ppi, void *buf, int plen)
int msg_unpack_header(struct pp_instance *ppi, void *buf, int len)
{
MsgHeader *hdr = &ppi->received_ptp_header;
uint32_t lsb, msb;
......@@ -35,20 +47,6 @@ int msg_unpack_header(struct pp_instance *ppi, void *buf, int plen)
hdr->sequenceId = htons(*(UInteger16 *) (buf + 30));
hdr->logMessageInterval = (*(Integer8 *) (buf + 33));
/*
* This FLAG_FROM_CURRENT_PARENT must be killed. Meanwhile, say it's
* from current parent if we have no current parent, so the rest works
*/
if (!DSPAR(ppi)->parentPortIdentity.portNumber ||
(!memcmp(&DSPAR(ppi)->parentPortIdentity.clockIdentity,
&hdr->sourcePortIdentity.clockIdentity,
PP_CLOCK_IDENTITY_LENGTH) &&
(DSPAR(ppi)->parentPortIdentity.portNumber ==
hdr->sourcePortIdentity.portNumber)))
ppi->flags |= PPI_FLAG_FROM_CURRENT_PARENT;
else
ppi->flags &= ~PPI_FLAG_FROM_CURRENT_PARENT;
return 0;
}
......@@ -111,6 +109,7 @@ int msg_pack_sync(struct pp_instance *ppi, struct pp_time *orig_tstamp)
*(UInteger16 *) (buf + 30) = htons(ppi->sent_seq[PPM_SYNC]);
/* Sync message */
memset((buf + 34), 0, 10);
*(UInteger16 *)(buf + 34) = htons(orig_tstamp->secs >> 32);
*(UInteger32 *)(buf + 36) = htonl(orig_tstamp->secs);
*(UInteger32 *)(buf + 40) = htonl(orig_tstamp->scaled_nsecs >> 16);
......@@ -173,7 +172,7 @@ static int msg_pack_announce(struct pp_instance *ppi)
*(UInteger16 *) (buf + 30) = htons(ppi->sent_seq[PPM_ANNOUNCE]);
/* Announce message */
memset((buf + 34), 0, 10);
memset((buf + 34), 0, 30);
*(Integer16 *) (buf + 44) = htons(DSPRO(ppi)->currentUtcOffset);
*(UInteger8 *) (buf + 47) = DSPAR(ppi)->grandmasterPriority1;
*(UInteger8 *) (buf + 48) = DSPAR(ppi)->grandmasterClockQuality.clockClass;
......@@ -183,7 +182,9 @@ static int msg_pack_announce(struct pp_instance *ppi)
*(UInteger8 *) (buf + 52) = DSPAR(ppi)->grandmasterPriority2;
memcpy((buf + 53), &DSPAR(ppi)->grandmasterIdentity,
PP_CLOCK_IDENTITY_LENGTH);
*(UInteger16 *) (buf + 61) = htons(DSCUR(ppi)->stepsRemoved);
/* WORKAROUND 16bit casting doesn't seem to work on unaligned addresses */
*(UInteger8 *) (buf + 61) = (UInteger8)(DSCUR(ppi)->stepsRemoved >> 8);
*(UInteger8 *) (buf + 62) = (UInteger8)DSCUR(ppi)->stepsRemoved;
*(Enumeration8 *) (buf + 63) = DSPRO(ppi)->timeSource;
if (pp_hooks.pack_announce)
......@@ -211,11 +212,16 @@ void msg_unpack_announce(void *buf, MsgAnnounce *ann)
ann->grandmasterPriority2 = *(UInteger8 *) (buf + 52);
memcpy(&ann->grandmasterIdentity, (buf + 53),
PP_CLOCK_IDENTITY_LENGTH);
ann->stepsRemoved = htons(*(UInteger16 *) (buf + 61));
/* WORKAROUND htons doesn't seem to work on unaligned addresses */
ann->stepsRemoved = *(UInteger8 *)(buf + 61);
ann->stepsRemoved = (ann->stepsRemoved << 8) + *(UInteger8 *)(buf + 62);
ann->timeSource = *(Enumeration8 *) (buf + 63);
/* this can fill in extention specific flags otherwise just zero them*/
if (pp_hooks.unpack_announce)
pp_hooks.unpack_announce(buf, ann);
else
ann->ext_specific = 0;
}
/* Pack Follow Up message into out buffer of ppi*/
......@@ -229,6 +235,7 @@ static int msg_pack_follow_up(struct pp_instance *ppi,
*(UInteger16 *) (buf + 30) = htons(ppi->sent_seq[PPM_SYNC]);
/* Follow Up message */
memset((buf + 34), 0, 10);
*(UInteger16 *)(buf + 34) = htons(prec_orig_tstamp->secs >> 32);
*(UInteger32 *)(buf + 36) = htonl(prec_orig_tstamp->secs);
*(UInteger32 *)(buf + 40) = htonl(prec_orig_tstamp->scaled_nsecs >> 16);
......@@ -258,6 +265,7 @@ static int msg_pack_pdelay_resp_follow_up(struct pp_instance *ppi,
*(UInteger16 *) (buf + 30) = htons(hdr->sequenceId);
/* requestReceiptTimestamp */
memset((buf + 34), 0, 20);
*(UInteger16 *)(buf + 34) = htons(prec_orig_tstamp->secs >> 32);
*(UInteger32 *)(buf + 36) = htonl(prec_orig_tstamp->secs);
*(UInteger32 *)(buf + 40) = htonl(prec_orig_tstamp->scaled_nsecs >> 16);
......@@ -318,6 +326,7 @@ static int msg_pack_delay_req(struct pp_instance *ppi,
*(UInteger16 *) (buf + 30) = htons(ppi->sent_seq[PPM_DELAY_REQ]);
/* Delay_req message - we may send zero instead */
memset((buf + 34), 0, 10);
*(UInteger16 *) (buf + 34) = htons(now->secs >> 32);
*(UInteger32 *) (buf + 36) = htonl(now->secs);
*(UInteger32 *) (buf + 40) = htonl(now->scaled_nsecs >> 16);
......@@ -336,10 +345,10 @@ static int msg_pack_pdelay_req(struct pp_instance *ppi,
*(UInteger16 *) (buf + 30) = htons(ppi->sent_seq[PPM_PDELAY_REQ]);
/* PDelay_req message - we may send zero instead */
memset((buf + 34), 0, 20);
*(UInteger16 *) (buf + 34) = htons(now->secs >> 32);
*(UInteger32 *) (buf + 36) = htonl(now->secs);
*(UInteger32 *) (buf + 40) = htonl(now->scaled_nsecs >> 16);
memset(buf + 44, 0, 10); /* reserved to match pdelay_resp length */
return len;
}
......@@ -360,6 +369,7 @@ static int msg_pack_pdelay_resp(struct pp_instance *ppi,
= htonl(rcv_tstamp->scaled_nsecs & 0xffff);
/* requestReceiptTimestamp */
memset((buf + 34), 0, 20);
*(UInteger16 *) (buf + 34) = htons(rcv_tstamp->secs >> 32);
*(UInteger32 *) (buf + 36) = htonl(rcv_tstamp->secs);
*(UInteger32 *) (buf + 40) = htonl(rcv_tstamp->scaled_nsecs >> 16);
......@@ -388,6 +398,7 @@ static int msg_pack_delay_resp(struct pp_instance *ppi,
*(UInteger16 *) (buf + 30) = htons(hdr->sequenceId);
/* Delay_resp message */
memset((buf + 34), 0, 20);
*(UInteger16 *)(buf + 34) = htons(rcv_tstamp->secs >> 32);
*(UInteger32 *)(buf + 36) = htonl(rcv_tstamp->secs);
*(UInteger32 *)(buf + 40) = htonl(rcv_tstamp->scaled_nsecs >> 16);
......
......@@ -14,8 +14,8 @@
struct pp_runtime_opts __pp_default_rt_opts = {
.clock_quality = {
.clockClass = PP_CLASS_DEFAULT,
.clockAccuracy = PP_DEFAULT_CLOCK_ACCURACY,
.offsetScaledLogVariance = PP_DEFAULT_CLOCK_VARIANCE,
.clockAccuracy = PP_ACCURACY_DEFAULT,
.offsetScaledLogVariance = PP_VARIANCE_DEFAULT,
},
.flags = PP_DEFAULT_FLAGS,
.ap = PP_DEFAULT_AP,
......
......@@ -20,8 +20,6 @@ void pp_servo_init(struct pp_instance *ppi)
int d;
SRV(ppi)->mpd_fltr.s_exp = 0; /* clears meanPathDelay filter */
ppi->frgn_rec_num = 0; /* no known master */
DSPAR(ppi)->parentPortIdentity.portNumber = 0; /* invalid */
if (ppi->t_ops->init_servo) {
/* The system may pre-set us to keep current frequency */
......
......@@ -8,7 +8,7 @@
#include <ppsi/ppsi.h>
int pp_disabled(struct pp_instance *ppi, unsigned char *pkt, int plen)
int pp_disabled(struct pp_instance *ppi, void *buf, int len)
{
/* nothing to do */
ppi->next_delay = PP_DEFAULT_NEXT_DELAY_MS;
......
......@@ -13,7 +13,7 @@
* PTP_INITIALIZING state after a grace period.
*/
int pp_faulty(struct pp_instance *ppi, unsigned char *pkt, int plen)
int pp_faulty(struct pp_instance *ppi, void *buf, int len)
{
if (pp_timeout(ppi, PP_TO_FAULT)) {
ppi->next_state = PPS_INITIALIZING;
......
......@@ -12,11 +12,11 @@
* Initialize parentDS
*/
static void init_parent_ds(struct pp_instance *ppi)
{
{
/* 8.2.3.2 */
DSPAR(ppi)->parentPortIdentity.clockIdentity =
DSDEF(ppi)->clockIdentity;
/* FIXME: portNumber ? */
DSPAR(ppi)->parentPortIdentity.portNumber = 0;
/* 8.2.3.3 skipped (parentStats is not used) */
/* 8.2.3.4 */
DSPAR(ppi)->observedParentOffsetScaledLogVariance = 0xffff;
......@@ -36,35 +36,66 @@ static void init_parent_ds(struct pp_instance *ppi)
* Initializes network and other stuff
*/
int pp_initializing(struct pp_instance *ppi, unsigned char *pkt, int plen)
int pp_initializing(struct pp_instance *ppi, void *buf, int len)
{
unsigned char *id, *mac;
unsigned char *mac;
unsigned char mac_port1[6];
struct DSPort *port = DSPOR(ppi);
struct pp_runtime_opts *opt = OPTS(ppi);
struct pp_globals *ppg = GLBS(ppi);
int ret = 0;
int i;
unsigned int portidx;
unsigned int remainder;
int initds = 1;
if (ppi->n_ops->init(ppi) < 0) /* it must handle being called twice */
goto failure;
init_parent_ds(ppi);
/* Clock identity comes from mac address with 0xff:0xfe intermixed */
id = (unsigned char *)&DSDEF(ppi)->clockIdentity;
mac = ppi->ch[PP_NP_GEN].addr;
id[0] = mac[0];
id[1] = mac[1];
id[2] = mac[2];
id[3] = 0xff;
id[4] = 0xfe;
id[5] = mac[3];
id[6] = mac[4];
id[7] = mac[5];
/* only fill in the data set when initializing */
if (DSDEF(ppi)->numberPorts > 1) {
for (i = 0; i < ppg->defaultDS->numberPorts; i++) {
if ((INST(ppg, i)->state != PPS_INITIALIZING) && (INST(ppg, i)->link_up == TRUE))
initds = 0;
}
}
/*
* Initialize parent data set
* Initialize default and parent data set
*/
init_parent_ds(ppi);
if (initds)
{
if (DSDEF(ppi)->numberPorts > 1) {
/* Clock identity comes from mac address with 0xff:0xfe intermixed */
mac = ppi->ch[PP_NP_GEN].addr;
/* calculate MAC of Port 0 */
portidx = ppi - ppi->glbs->pp_instances;
remainder = portidx;
for (i = 5; i >= 0; i--) {
mac_port1[i] = mac[i] - remainder;
if (mac[i] >= remainder)
remainder = 0;
else
remainder = 1;
}
} else {
/* Clock identity comes from mac address with 0xff:0xfe intermixed */
for (i = 5; i >= 0; i--)
mac_port1[i] = ((unsigned char*)ppi->ch[PP_NP_GEN].addr)[i];
}
DSDEF(ppi)->clockIdentity.id[0] = mac_port1[0];
DSDEF(ppi)->clockIdentity.id[1] = mac_port1[1];
DSDEF(ppi)->clockIdentity.id[2] = mac_port1[2];
DSDEF(ppi)->clockIdentity.id[3] = 0xff;
DSDEF(ppi)->clockIdentity.id[4] = 0xfe;
DSDEF(ppi)->clockIdentity.id[5] = mac_port1[3];
DSDEF(ppi)->clockIdentity.id[6] = mac_port1[4];
DSDEF(ppi)->clockIdentity.id[7] = mac_port1[5];
init_parent_ds(ppi);
}
/*
* Initialize port data set
*/
......@@ -78,9 +109,10 @@ int pp_initializing(struct pp_instance *ppi, unsigned char *pkt, int plen)
port->logSyncInterval = opt->sync_intvl;
port->versionNumber = PP_VERSION_PTP;
pp_timeout_init(ppi);
pp_timeout_setall(ppi);
if (pp_hooks.init)
ret = pp_hooks.init(ppi, pkt, plen);
ret = pp_hooks.init(ppi, buf, len);
if (ret) {
pp_diag(ppi, ext, 1, "%s: can't init extension\n", __func__);
goto failure;
......@@ -92,7 +124,7 @@ int pp_initializing(struct pp_instance *ppi, unsigned char *pkt, int plen)
DSDEF(ppi)->clockQuality.clockAccuracy);
msg_init_header(ppi, ppi->tx_ptp); /* This is used for all tx */
if (ppi->role != PPSI_ROLE_MASTER)
ppi->next_state = PPS_LISTENING;
else
......
......@@ -9,58 +9,62 @@
#include <ppsi/ppsi.h>
#include "common-fun.h"
int pp_listening(struct pp_instance *ppi, unsigned char *pkt, int plen)
static pp_action *actions[] = {
[PPM_SYNC] = 0,
[PPM_DELAY_REQ] = 0,
#if CONFIG_HAS_P2P
[PPM_PDELAY_REQ] = st_com_peer_handle_preq,
[PPM_PDELAY_RESP] = st_com_peer_handle_pres,
[PPM_PDELAY_R_FUP] = st_com_peer_handle_pres_followup,
#endif
[PPM_FOLLOW_UP] = 0,
[PPM_DELAY_RESP] = 0,
[PPM_ANNOUNCE] = st_com_handle_announce,
/* skip signaling and management, for binary size */
};
int pp_listening(struct pp_instance *ppi, void *buf, int len)
{
int e = 0; /* error var, to check errors in msg handling */
MsgHeader *hdr = &ppi->received_ptp_header;
pp_timeout_set(ppi, PP_TO_FAULT); /* no fault as long as we listen */
if (pp_hooks.listening)
e = pp_hooks.listening(ppi, pkt, plen);
e = pp_hooks.listening(ppi, buf, len);
if (e)
goto out;
/* when the clock is using peer-delay, listening must send it too */
if (CONFIG_HAS_P2P && ppi->mech == PP_P2P_MECH)
e = pp_lib_may_issue_request(ppi);
/*
* The management of messages is now table-driven
*/
if (hdr->messageType < ARRAY_SIZE(actions)
&& actions[hdr->messageType]) {
e = actions[hdr->messageType](ppi, buf, len);
} else {
if (len)
pp_diag(ppi, frames, 1, "Ignored frame %i\n",
hdr->messageType);
}
switch (ppi->received_ptp_header.messageType) {
case PPM_ANNOUNCE:
e = pp_lib_handle_announce(ppi, pkt, plen);
break;
case PPM_SYNC:
e = st_com_master_handle_sync(ppi, pkt, plen);
break;
case PPM_PDELAY_REQ:
if (CONFIG_HAS_P2P)
st_com_peer_handle_preq(ppi, pkt, plen);
break;
case PPM_PDELAY_RESP:
if (CONFIG_HAS_P2P)
e = st_com_peer_handle_pres(ppi, pkt, plen);
break;
case PPM_PDELAY_R_FUP:
if (CONFIG_HAS_P2P)
e = st_com_peer_handle_pres_followup(ppi, pkt, plen);
break;
st_com_check_announce_receive_timeout(ppi);
default:
/* disregard, nothing to do */
break;
}
if (pp_timeout(ppi, PP_TO_FAULT))
ppi->next_state = PPS_FAULTY;
out:
if (e == 0)
e = st_com_execute_slave(ppi);
if (e != 0)
ppi->next_state = PPS_FAULTY;
ppi->next_delay = pp_next_delay_1(ppi, PP_TO_ANN_RECEIPT);
return 0;
if (CONFIG_HAS_P2P && ppi->mech == PP_P2P_MECH) {
ppi->next_delay = pp_next_delay_2(ppi,
PP_TO_ANN_RECEIPT, PP_TO_REQUEST);
} else {
ppi->next_delay = pp_next_delay_1(ppi,
PP_TO_ANN_RECEIPT);
}
return e;
}
......@@ -10,10 +10,10 @@
#include "common-fun.h"
static int master_handle_delay_request(struct pp_instance *ppi,
unsigned char *pkt, int plen);
void *buf, int len);
static pp_action *actions[] = {
[PPM_SYNC] = st_com_master_handle_sync,
[PPM_SYNC] = 0,
[PPM_DELAY_REQ] = master_handle_delay_request,
#if CONFIG_HAS_P2P
[PPM_PDELAY_REQ] = st_com_peer_handle_preq,
......@@ -22,12 +22,12 @@ static pp_action *actions[] = {
#endif
[PPM_FOLLOW_UP] = 0,
[PPM_DELAY_RESP] = 0,
[PPM_ANNOUNCE] = pp_lib_handle_announce,
[PPM_ANNOUNCE] = st_com_handle_announce,
/* skip signaling and management, for binary size */
};
static int master_handle_delay_request(struct pp_instance *ppi,
unsigned char *pkt, int plen)
void *buf, int len)
{
if (ppi->state == PPS_MASTER) /* not pre-master */
msg_issue_delay_resp(ppi, &ppi->last_rcv_time);
......@@ -38,15 +38,22 @@ static int master_handle_delay_request(struct pp_instance *ppi,
* MASTER and PRE_MASTER have many things in common. This function implements
* both states. We set "pre" internally to 0 or 1.
*/
int pp_master(struct pp_instance *ppi, uint8_t *pkt, int plen)
int pp_master(struct pp_instance *ppi, void *buf, int len)
{
int msgtype;
int pre = (ppi->state == PPS_PRE_MASTER);
int e = 0; /* error var, to check errors in msg handling */
pp_timeout_set(ppi, PP_TO_FAULT); /* no fault as long as we are
* master */
/* upgrade from pre-master to master */
if (pre && pp_timeout(ppi, PP_TO_QUALIFICATION)) {
ppi->next_state = PPS_MASTER;
/* start sending imediately and reenter */
pp_timeout_clear(ppi, PP_TO_SYNC_SEND);
pp_timeout_clear(ppi, PP_TO_ANN_SEND);
ppi->next_delay = 0;
return 0;
}
......@@ -62,8 +69,6 @@ int pp_master(struct pp_instance *ppi, uint8_t *pkt, int plen)
/* when the clock is using peer-delay, the master must send it too */
if (CONFIG_HAS_P2P && ppi->mech == PP_P2P_MECH)
pp_lib_may_issue_request(ppi);
else /* please check commit '6d7bf7e3' about below, I'm not sure */
pp_timeout_set(ppi, PP_TO_REQUEST);
/*
* An extension can do special treatment of this message type,
......@@ -72,10 +77,10 @@ int pp_master(struct pp_instance *ppi, uint8_t *pkt, int plen)
*/
msgtype = ppi->received_ptp_header.messageType;
if (pp_hooks.master_msg)
msgtype = pp_hooks.master_msg(ppi, pkt, plen, msgtype);
msgtype = pp_hooks.master_msg(ppi, buf, len, msgtype);
if (msgtype < 0) {
e = msgtype;
plen = 0;
len = 0;
e = PP_SEND_ERROR; /* well, "error" in general */
goto out;
}
......@@ -85,13 +90,16 @@ int pp_master(struct pp_instance *ppi, uint8_t *pkt, int plen)
*/
if (msgtype < ARRAY_SIZE(actions)
&& actions[msgtype]) {
e = actions[msgtype](ppi, pkt, plen);
e = actions[msgtype](ppi, buf, len);
} else {
if (plen && msgtype != PPM_NO_MESSAGE)
if (len && msgtype != PPM_NO_MESSAGE)
pp_diag(ppi, frames, 1, "Ignored frame %i\n",
msgtype);
}
if (pp_timeout(ppi, PP_TO_FAULT))
ppi->next_state = PPS_FAULTY;
out:
switch(e) {
case PP_SEND_OK: /* 0 */
......@@ -108,9 +116,24 @@ out:
break;
}
/* we also use TO_QUALIFICATION, but avoid counting it here */
ppi->next_delay = pp_next_delay_3(ppi,
PP_TO_ANN_SEND, PP_TO_SYNC_SEND, PP_TO_REQUEST);
if (pre) {
if (CONFIG_HAS_P2P && ppi->mech == PP_P2P_MECH) {
ppi->next_delay = pp_next_delay_2(ppi,
PP_TO_QUALIFICATION, PP_TO_REQUEST);
} else {
ppi->next_delay = pp_next_delay_1(ppi,
PP_TO_QUALIFICATION);
}
} else {
if (CONFIG_HAS_P2P && ppi->mech == PP_P2P_MECH) {
ppi->next_delay = pp_next_delay_3(ppi,
PP_TO_ANN_SEND, PP_TO_SYNC_SEND, PP_TO_REQUEST);
} else {
ppi->next_delay = pp_next_delay_2(ppi,
PP_TO_ANN_SEND, PP_TO_SYNC_SEND);
}
}
return e;
}
......@@ -9,53 +9,83 @@
#include <ppsi/ppsi.h>
#include "common-fun.h"
int pp_passive(struct pp_instance *ppi, unsigned char *pkt, int plen)
{
int e = 0; /* error var, to check errors in msg handling */
/* when the clock is using peer-delay, listening must send it too */
if (CONFIG_HAS_P2P && ppi->mech == PP_P2P_MECH)
e = pp_lib_may_issue_request(ppi);
static int passive_handle_announce(struct pp_instance *ppi, void *buf, int len);
switch (ppi->received_ptp_header.messageType) {
static pp_action *actions[] = {
[PPM_SYNC] = 0,
[PPM_DELAY_REQ] = 0,
#if CONFIG_HAS_P2P
[PPM_PDELAY_REQ] = st_com_peer_handle_preq,
[PPM_PDELAY_RESP] = st_com_peer_handle_pres,
[PPM_PDELAY_R_FUP] = st_com_peer_handle_pres_followup,
#endif
[PPM_FOLLOW_UP] = 0,
[PPM_DELAY_RESP] = 0,
[PPM_ANNOUNCE] = passive_handle_announce,
/* skip signaling and management, for binary size */
};
case PPM_ANNOUNCE:
e = pp_lib_handle_announce(ppi, pkt, plen);
break;
case PPM_SYNC:
e = st_com_master_handle_sync(ppi, pkt, plen);
break;
case PPM_PDELAY_REQ:
if (CONFIG_HAS_P2P)
st_com_peer_handle_preq(ppi, pkt, plen);
break;
static int passive_handle_announce(struct pp_instance *ppi, void *buf, int len)
{
int ret = 0;
MsgHeader *hdr = &ppi->received_ptp_header;
struct pp_frgn_master *erbest = &ppi->frgn_master[ppi->frgn_rec_best];
ret = st_com_handle_announce(ppi, buf, len);
if (ret)
return ret;
if (!bmc_pidcmp(&hdr->sourcePortIdentity,
&erbest->sourcePortIdentity)) {
/*
* 9.2.6.11 d) reset timeout when an announce
* is received from the clock putting it into passive (erbest)
*/
pp_timeout_set(ppi, PP_TO_ANN_RECEIPT);
}
return 0;
}
case PPM_PDELAY_RESP:
if (CONFIG_HAS_P2P)
e = st_com_peer_handle_pres(ppi, pkt, plen);
break;
int pp_passive(struct pp_instance *ppi, void *buf, int len)
{
int e = 0; /* error var, to check errors in msg handling */
MsgHeader *hdr = &ppi->received_ptp_header;
case PPM_PDELAY_R_FUP:
if (CONFIG_HAS_P2P)
e = st_com_peer_handle_pres_followup(ppi, pkt, plen);
break;
pp_timeout_set(ppi, PP_TO_FAULT); /* no fault as long as we are
* passive */
default:
/* disreguard, nothing to do */
break;
/* when the clock is using peer-delay, passive must send it too */
if (CONFIG_HAS_P2P && ppi->mech == PP_P2P_MECH)
e = pp_lib_may_issue_request(ppi);
/*
* The management of messages is now table-driven
*/
if (hdr->messageType < ARRAY_SIZE(actions)
&& actions[hdr->messageType]) {
e = actions[hdr->messageType](ppi, buf, len);
} else {
if (len)
pp_diag(ppi, frames, 1, "Ignored frame %i\n",
hdr->messageType);
}
if (e == 0)
e = st_com_execute_slave(ppi);
st_com_check_announce_receive_timeout(ppi);
if (e != 0) {
/* ignore: a lost frame is not the end of the world */
}
if (pp_timeout(ppi, PP_TO_FAULT))
ppi->next_state = PPS_FAULTY;
ppi->next_delay = PP_DEFAULT_NEXT_DELAY_MS;
if (e != 0)
ppi->next_state = PPS_FAULTY;
return 0;
if (CONFIG_HAS_P2P && ppi->mech == PP_P2P_MECH) {
ppi->next_delay = pp_next_delay_2(ppi,
PP_TO_ANN_RECEIPT, PP_TO_REQUEST);
} else {
ppi->next_delay = pp_next_delay_1(ppi,
PP_TO_ANN_RECEIPT);
}
return e;
}
......@@ -11,40 +11,125 @@
#include <ppsi/ppsi.h>
#include "common-fun.h"
static int slave_handle_response(struct pp_instance *ppi, unsigned char *pkt,
int plen);
static int slave_handle_sync(struct pp_instance *ppi, void *buf, int len);
static int slave_handle_followup(struct pp_instance *ppi, void *buf,
int len);
static int slave_handle_response(struct pp_instance *ppi, void *buf,
int len);
static int slave_handle_announce(struct pp_instance *ppi, void *buf, int len);
static pp_action *actions[] = {
[PPM_SYNC] = st_com_slave_handle_sync,
[PPM_SYNC] = slave_handle_sync,
[PPM_DELAY_REQ] = 0,
#if CONFIG_HAS_P2P
[PPM_PDELAY_REQ] = st_com_peer_handle_preq,
[PPM_PDELAY_RESP] = st_com_peer_handle_pres,
[PPM_PDELAY_R_FUP] = st_com_peer_handle_pres_followup,
#endif
[PPM_FOLLOW_UP] = st_com_slave_handle_followup,
[PPM_FOLLOW_UP] = slave_handle_followup,
[PPM_DELAY_RESP] = slave_handle_response,
[PPM_ANNOUNCE] = pp_lib_handle_announce,
[PPM_ANNOUNCE] = slave_handle_announce,
/* skip signaling and management, for binary size */
};
static int slave_handle_response(struct pp_instance *ppi, unsigned char *pkt,
int plen)
static int slave_handle_sync(struct pp_instance *ppi, void *buf,
int len)
{
int e = 0;
MsgHeader *hdr = &ppi->received_ptp_header;
MsgDelayResp resp;
MsgSync sync;
if (!msg_from_current_master(ppi))
return 0;
/* t2 may be overriden by follow-up, save it immediately */
ppi->t2 = ppi->last_rcv_time;
msg_unpack_sync(buf, &sync);
if ((hdr->flagField[0] & PP_TWO_STEP_FLAG) != 0) {
ppi->flags |= PPI_FLAG_WAITING_FOR_F_UP;
ppi->recv_sync_sequence_id = hdr->sequenceId;
/* for two-step, the stamp comes later */
ppi->t1 = hdr->cField; /* most likely 0 */
return 0;
}
/* one-step folllows */
ppi->flags &= ~PPI_FLAG_WAITING_FOR_F_UP;
ppi->t1 = sync.originTimestamp;
pp_time_add(&ppi->t1, &hdr->cField);
ppi->syncCF = 0;
if (CONFIG_HAS_P2P && ppi->mech == PP_P2P_MECH)
pp_servo_got_psync(ppi);
else
pp_servo_got_sync(ppi);
return 0;
}
static int slave_handle_followup(struct pp_instance *ppi, void *buf,
int len)
{
MsgFollowUp follow;
int ret = 0;
MsgHeader *hdr = &ppi->received_ptp_header;
if (!msg_from_current_master(ppi)) {
pp_error("%s: Follow up message is not from current parent\n",
__func__);
return 0;
}
if (!(ppi->flags & PPI_FLAG_WAITING_FOR_F_UP)) {
pp_error("%s: Slave was not waiting a follow up message\n",
__func__);
return 0;
}
if (ppi->recv_sync_sequence_id != hdr->sequenceId) {
pp_error("%s: SequenceID %d doesn't match last Sync message "
"%d\n", __func__,
hdr->sequenceId, ppi->recv_sync_sequence_id);
return 0;
}
msg_unpack_follow_up(buf, &follow);
ppi->flags &= ~PPI_FLAG_WAITING_FOR_F_UP;
/* t1 for calculations is T1 + Csyn + Cful -- see README-cfield */
pp_time_add(&ppi->t1, &follow.preciseOriginTimestamp);
pp_time_add(&ppi->t1, &hdr->cField);
ppi->syncCF = hdr->cField.scaled_nsecs; /* for diag about TC */
/* Call the extension; it may do it all and ask to return */
if (pp_hooks.handle_followup)
ret = pp_hooks.handle_followup(ppi, &ppi->t1);
if (ret == 1)
return 0;
if (ret < 0)
return ret;
if (CONFIG_HAS_P2P && ppi->mech == PP_P2P_MECH)
pp_servo_got_psync(ppi);
else
pp_servo_got_sync(ppi);
msg_unpack_delay_resp(pkt, &resp);
return 0;
}
if ((memcmp(&DSPOR(ppi)->portIdentity.clockIdentity,
&resp.requestingPortIdentity.clockIdentity,
PP_CLOCK_IDENTITY_LENGTH) != 0) ||
static int slave_handle_response(struct pp_instance *ppi, void *buf,
int len)
{
int e = 0;
MsgHeader *hdr = &ppi->received_ptp_header;
MsgDelayResp resp;
msg_unpack_delay_resp(buf, &resp);
if ((bmc_idcmp(&DSPOR(ppi)->portIdentity.clockIdentity,
&resp.requestingPortIdentity.clockIdentity) != 0) ||
((ppi->sent_seq[PPM_DELAY_REQ]) !=
hdr->sequenceId) ||
(DSPOR(ppi)->portIdentity.portNumber !=
resp.requestingPortIdentity.portNumber) ||
!(ppi->flags & PPI_FLAG_FROM_CURRENT_PARENT)) {
(!msg_from_current_master(ppi))) {
pp_diag(ppi, frames, 1, "pp_slave : "
"Delay Resp doesn't match Delay Req (f %x)\n",
ppi->flags);
......@@ -73,40 +158,97 @@ static int slave_handle_response(struct pp_instance *ppi, unsigned char *pkt,
return 0;
}
int pp_slave(struct pp_instance *ppi, unsigned char *pkt, int plen)
static int slave_handle_announce(struct pp_instance *ppi, void *buf, int len)
{
int ret = 0;
struct pp_frgn_master frgn_master;
ret = st_com_handle_announce(ppi, buf, len);
if (ret)
return ret;
if (!msg_from_current_master(ppi))
return 0;
/* 9.2.6.11 a) reset timeout */
pp_timeout_set(ppi, PP_TO_ANN_RECEIPT);
/* 9.5.3 Figure 29 update data set if announce from current master */
bmc_store_frgn_master(ppi, &frgn_master, buf, len);
bmc_s1(ppi, &frgn_master);
return 0;
}
static int slave_execute(struct pp_instance *ppi)
{
int ret = 0;
if (pp_hooks.execute_slave)
ret = pp_hooks.execute_slave(ppi);
if (ret == 1) /* done: just return */
return 0;
if (ret < 0)
return ret;
return 0;
}
/*
* SLAVE and UNCALIBRATED have many things in common. This function implements
* both states. We set "uncalibrated" internally to 0 or 1.
*/
int pp_slave(struct pp_instance *ppi, void *buf, int len)
{
int e = 0; /* error var, to check errors in msg handling */
int uncalibrated = (ppi->state == PPS_UNCALIBRATED);
MsgHeader *hdr = &ppi->received_ptp_header;
if (ppi->is_new_state) {
/* upgrade from uncalibrated to slave or back*/
if (uncalibrated) {
/* TODO add implementation specific MASTER_CLOCK_SELECTED event
for now just change directly to new state on next round */
ppi->next_state = PPS_SLAVE;
} else {
/* TODO add implementation specific SYNCHRONIZATION FAULT
* event */
if (pp_timeout(ppi, PP_TO_FAULT))
ppi->next_state = PPS_UNCALIBRATED;
}
/* when entering uncalibrated init servo */
if ((ppi->state == PPS_UNCALIBRATED) && (ppi->is_new_state)) {
memset(&ppi->t1, 0, sizeof(ppi->t1));
pp_diag(ppi, bmc, 2, "Entered to uncalibrated, reset servo\n");
pp_servo_init(ppi);
if (pp_hooks.new_slave)
e = pp_hooks.new_slave(ppi, pkt, plen);
e = pp_hooks.new_slave(ppi, buf, len);
if (e)
goto out;
}
/* do a delay mesurement either in p2p or e2e delay mode */
pp_lib_may_issue_request(ppi);
/*
* The management of messages is now table-driven
*/
if (hdr->messageType < ARRAY_SIZE(actions)
&& actions[hdr->messageType]) {
e = actions[hdr->messageType](ppi, pkt, plen);
e = actions[hdr->messageType](ppi, buf, len);
} else {
if (plen)
if (len)
pp_diag(ppi, frames, 1, "Ignored frame %i\n",
hdr->messageType);
}
/*
* This function, common to passive,listening etc,
* is the core of the slave: timeout ann-receipt, hook
* This function, common to uncalibrated and slave,
* is the core of the slave: hook
*/
e = st_com_execute_slave(ppi);
e = slave_execute(ppi);
st_com_check_announce_receive_timeout(ppi);
out:
switch(e) {
......@@ -121,12 +263,8 @@ out:
break;
}
if (ppi->next_state != ppi->state) {
pp_servo_init(ppi);
return e;
}
ppi->next_delay = pp_next_delay_2(ppi,
PP_TO_ANN_RECEIPT, PP_TO_REQUEST);
PP_TO_ANN_RECEIPT, PP_TO_REQUEST);
return e;
}
/*
* Copyright (C) 2011 CERN (www.cern.ch)
* Author: Aurelio Colosimo
* Based on PTPd project v. 2.1.0 (see AUTHORS for details)
*
* Released according to the GNU LGPL, version 2.1 or any later version.
*/
#include <ppsi/ppsi.h>
#include "common-fun.h"
int pp_uncalibrated(struct pp_instance *ppi, unsigned char *pkt, int plen)
{
int e = 0; /* error var, to check errors in msg handling */
switch (ppi->received_ptp_header.messageType) {
case PPM_ANNOUNCE:
e = pp_lib_handle_announce(ppi, pkt, plen);
break;
case PPM_SYNC:
e = st_com_slave_handle_sync(ppi, pkt, plen);
break;
case PPM_FOLLOW_UP:
e = st_com_slave_handle_followup(ppi, pkt, plen);
break;
default:
/* disreguard, nothing to do */
break;
}
if (e == 0)
e = st_com_execute_slave(ppi);
if (e != 0)
ppi->next_state = PPS_FAULTY;
ppi->next_delay = PP_DEFAULT_NEXT_DELAY_MS;
return 0;
}
......@@ -8,6 +8,54 @@
#include <ppsi/ppsi.h>
#include "bare-linux.h"
static int bare_time_get_utc_time(struct pp_instance *ppi, int *hours, int *minutes, int *seconds)
{
/* TODO */
return -1;
}
static int bare_time_get_utc_offset(struct pp_instance *ppi, int *offset, int *leap59, int *leap61)
{
int ret;
struct bare_timex t;
/*
* Get the UTC/TAI difference
*/
memset(&t, 0, sizeof(t));
ret = adjtimex(&t);
if (ret >= 0) {
if (ret == TIME_INS) {
*leap59 = 0;
*leap61 = 1;
} else if (ret == TIME_DEL) {
*leap59 = 1;
*leap61 = 0;
} else {
*leap59 = 0;
*leap61 = 0;
}
*offset = (int)t.tai;
return 0;
} else {
*leap59 = 0;
*leap61 = 0;
*offset = 0;
return -1;
}
}
static int bare_time_set_utc_offset(struct pp_instance *ppi, int offset, int leap59, int leap61)
{
/* TODO */
return -1;
}
static int bare_time_get_servo_state(struct pp_instance *ppi, int *state)
{
*state = PP_SERVO_UNKNOWN;
return 0;
}
static int bare_time_get(struct pp_instance *ppi, struct pp_time *t)
{
struct bare_timeval tv;
......@@ -100,6 +148,10 @@ static unsigned long bare_calc_timeout(struct pp_instance *ppi, int millisec)
}
struct pp_time_operations bare_time_ops = {
.get_utc_time = bare_time_get_utc_time,
.get_utc_offset = bare_time_get_utc_offset,
.set_utc_offset = bare_time_set_utc_offset,
.get_servo_state = bare_time_get_servo_state,
.get = bare_time_get,
.set = bare_time_set,
.adjust = bare_time_adjust,
......
......@@ -46,6 +46,36 @@ int sim_fast_forward_ns(struct pp_globals *ppg, int64_t ff_ns)
return 0;
}
static int sim_time_get_utc_time(struct pp_instance *ppi, int *hours, int *minutes, int *seconds)
{
/* no UTC time */
*hours = 0;
*minutes = 0;
*seconds = 0;
return -1;
}
static int sim_time_get_utc_offset(struct pp_instance *ppi, int *offset, int *leap59, int *leap61)
{
/* no UTC offset */
*leap59 = 0;
*leap61 = 0;
*offset = 0;
return -1;
}
static int sim_time_set_utc_offset(struct pp_instance *ppi, int offset, int leap59, int leap61)
{
/* no UTC offset */
return -1;
}
static int sim_time_get_servo_state(struct pp_instance *ppi, int *state)
{
*state = PP_SERVO_UNKNOWN;
return 0;
}
static int sim_time_get(struct pp_instance *ppi, struct pp_time *t)
{
t->scaled_nsecs = (SIM_PPI_ARCH(ppi)->time.current_ns %
......@@ -113,6 +143,10 @@ static unsigned long sim_calc_timeout(struct pp_instance *ppi, int millisec)
}
struct pp_time_operations sim_time_ops = {
.get_utc_time = sim_time_get_utc_time,
.get_utc_offset = sim_time_get_utc_offset,
.set_utc_offset = sim_time_set_utc_offset,
.get_servo_state = sim_time_get_servo_state,
.get = sim_time_get,
.set = sim_time_set,
.adjust = sim_time_adjust,
......
......@@ -23,6 +23,157 @@ static void clock_fatal_error(char *context)
exit(1);
}
static void unix_time_clear_utc_flags(void)
{
struct timex t;
/*
* We have to call adjtime twice here, as kernels
* prior to 6b1859dba01c7 (included in 3.5 and
* -stable), had an issue with the state machine
* and wouldn't clear the STA_INS/DEL flag directly.
*/
t.modes = ADJ_STATUS;
t.status = STA_PLL;
adjtimex(&t);
/* Clear maxerror, as it can cause UNSYNC to be set */
t.modes = ADJ_MAXERROR;
t.maxerror = 0;
adjtimex(&t);
/* Clear the status */
t.modes = ADJ_STATUS;
t.status = 0;
adjtimex(&t);
}
static int unix_time_get_utc_time(struct pp_instance *ppi, int *hours, int *minutes, int *seconds)
{
int ret;
struct timex t;
time_t now;
struct tm *date;
/* Get the UTC time */
memset(&t, 0, sizeof(t));
ret = adjtimex(&t);
if (ret >= 0) {
now = t.time.tv_sec;
/* use gmtime for correct leap handling */
date = gmtime(&now);
*hours = date->tm_hour;
*minutes = date->tm_min;
*seconds = date->tm_sec;
return 0;
} else {
*hours = 0;
*minutes = 0;
*seconds = 0;
return -1;
}
return -1;
}
static int unix_time_get_utc_offset(struct pp_instance *ppi, int *offset, int *leap59, int *leap61)
{
int ret;
struct timex t;
int hours, minutes, seconds;
unix_time_get_utc_time(ppi, &hours, &minutes, &seconds);
/*
* Get the UTC/TAI difference
*/
memset(&t, 0, sizeof(t));
ret = adjtimex(&t);
if (ret >= 0) {
if (hours >= 12) {
if ((t.status & STA_INS) == STA_INS) {
*leap59 = 0;
*leap61 = 1;
} else if ((t.status & STA_DEL) == STA_DEL) {
*leap59 = 1;
*leap61 = 0;
} else {
*leap59 = 0;
*leap61 = 0;
}
} else {
unix_time_clear_utc_flags();
*leap59 = 0;
*leap61 = 0;
}
/*
* Our WRS kernel has tai support, but our compiler does not.
* We are 32-bit only, and we know for sure that tai is
* exactly after stbcnt. It's a bad hack, but it works
*/
*offset = *((int *)(&t.stbcnt) + 1);
return 0;
} else {
*leap59 = 0;
*leap61 = 0;
*offset = 0;
return -1;
}
}
static int unix_time_set_utc_offset(struct pp_instance *ppi, int offset, int leap59, int leap61)
{
struct timex t;
int ret;
unix_time_clear_utc_flags();
/* get the current flags first */
memset(&t, 0, sizeof(t));
ret = adjtimex(&t);
if (ret >= 0) {
if (leap59) {
t.modes = MOD_STATUS;
t.status |= STA_DEL;
t.status &= ~STA_INS;
} else if (leap61) {
t.modes = MOD_STATUS;
t.status |= STA_INS;
t.status &= ~STA_DEL;
} else {
t.modes = MOD_STATUS;
t.status &= ~STA_INS;
t.status &= ~STA_DEL;
}
if (adjtimex(&t) < 0) {
pp_diag(ppi, time, 1, "set UTC flags failed\n");
return -1;
}
} else
pp_diag(ppi, time, 1, "get UTC flags failed\n");
t.modes = MOD_TAI;
t.constant = offset;
if (adjtimex(&t) < 0) {
pp_diag(ppi, time, 1, "set UTC offset failed\n");
return -1;
} else
pp_diag(ppi, time, 1, "set UTC offset to: %i\n", offset);
return 0;
}
static int unix_time_get_servo_state(struct pp_instance *ppi, int *state)
{
*state = PP_SERVO_UNKNOWN;
return 0;
}
static int unix_time_get(struct pp_instance *ppi, struct pp_time *t)
{
struct timespec tp;
......@@ -66,10 +217,17 @@ static int unix_time_set(struct pp_instance *ppi, const struct pp_time *t)
static int unix_time_init_servo(struct pp_instance *ppi)
{
struct timex t;
int ret;
/* get the current flags first */
memset(&t, 0, sizeof(t));
ret = adjtimex(&t);
if (ret < 0)
pp_diag(ppi, time, 1, "get current UTC offset and flags failed");
/* We must set MOD_PLL and recover the current frequency value */
t.modes = MOD_STATUS;
t.status = STA_PLL;
t.status |= STA_PLL;
if (adjtimex(&t) < 0)
return -1;
return (t.freq >> 16) * 1000; /* positive or negative, not -1 */
......@@ -124,6 +282,10 @@ static unsigned long unix_calc_timeout(struct pp_instance *ppi, int millisec)
}
struct pp_time_operations unix_time_ops = {
.get_utc_time = unix_time_get_utc_time,
.get_utc_offset = unix_time_get_utc_offset,
.set_utc_offset = unix_time_set_utc_offset,
.get_servo_state = unix_time_get_servo_state,
.get = unix_time_get,
.set = unix_time_set,
.adjust = unix_time_adjust,
......@@ -132,3 +294,4 @@ struct pp_time_operations unix_time_ops = {
.init_servo = unix_time_init_servo,
.calc_timeout = unix_calc_timeout,
};
......@@ -9,6 +9,43 @@
#include "pps_gen.h" /* in wrpc-sw */
#include "syscon.h" /* in wrpc-sw */
static int wrpc_time_get_utc_time(struct pp_instance *ppi, int *hours, int *minutes, int *seconds)
{
/* no UTC time */
*hours = 0;
*minutes = 0;
*seconds = 0;
return -1;
}
static int wrpc_time_get_utc_offset(struct pp_instance *ppi, int *offset, int *leap59, int *leap61)
{
/* no UTC offset */
*leap59 = 0;
*leap61 = 0;
*offset = 0;
return -1;
}
static int wrpc_time_set_utc_offset(struct pp_instance *ppi, int offset, int leap59, int leap61)
{
/* no UTC offset */
return -1;
}
static int wrpc_time_get_servo_state(struct pp_instance *ppi, int *state)
{
struct wr_dsport *wrp = WR_DSPOR(ppi);
int locked;
locked = wrp->ops->locking_poll(ppi, 1);
if (locked == WR_SPLL_READY)
*state = PP_SERVO_LOCKED;
else
*state = PP_SERVO_UNLOCKED;
return 0;
}
static int wrpc_time_get(struct pp_instance *ppi, struct pp_time *t)
{
uint64_t sec;
......@@ -65,6 +102,10 @@ static unsigned long wrpc_calc_timeout(struct pp_instance *ppi, int millisec)
}
struct pp_time_operations wrpc_time_ops = {
.get_utc_time = wrpc_time_get_utc_time,
.get_utc_offset = wrpc_time_get_utc_offset,
.set_utc_offset = wrpc_time_set_utc_offset,
.get_servo_state = wrpc_time_get_servo_state,
.get = wrpc_time_get,
.set = wrpc_time_set,
.adjust = wrpc_time_adjust,
......
......@@ -136,6 +136,21 @@ int wrs_locking_enable(struct pp_instance *ppi)
return WR_SPLL_OK;
}
int wrs_locking_reset(struct pp_instance *ppi)
{
int ret, rval;
pp_diag(ppi, time, 1, "Reset locking\n");
ret = minipc_call(hal_ch, DEFAULT_TO, &__rpcdef_lock_cmd,
&rval, ppi->iface_name, HEXP_LOCK_CMD_RESET, 0);
if ((ret < 0) || (rval < 0))
return WR_SPLL_ERROR;
return WR_SPLL_OK;
}
int wrs_locking_poll(struct pp_instance *ppi, int grandmaster)
{
int ret, rval;
......@@ -187,6 +202,34 @@ static int wrdate_get(struct pp_time *t)
return 0;
}
static int wrs_time_get_utc_time(struct pp_instance *ppi, int *hours, int *minutes, int *seconds)
{
return unix_time_ops.get_utc_time(ppi, hours, minutes, seconds);
}
static int wrs_time_get_utc_offset(struct pp_instance *ppi, int *offset, int *leap59, int *leap61)
{
return unix_time_ops.get_utc_offset(ppi, offset, leap59, leap61);
}
static int wrs_time_set_utc_offset(struct pp_instance *ppi, int offset, int leap59, int leap61)
{
return unix_time_ops.set_utc_offset(ppi, offset, leap59, leap61);
}
static int wrs_time_get_servo_state(struct pp_instance *ppi, int *state)
{
struct wr_dsport *wrp = WR_DSPOR(ppi);
int locked;
locked = wrp->ops->locking_poll(ppi, 1);
if (locked == WR_SPLL_READY)
*state = PP_SERVO_LOCKED;
else
*state = PP_SERVO_UNLOCKED;
return 0;
}
/* This is only used when the wrs is slave to a non-WR master */
static int wrs_time_get(struct pp_instance *ppi, struct pp_time *t)
{
......@@ -222,7 +265,6 @@ static int wrs_time_set(struct pp_instance *ppi, const struct pp_time *t)
{
struct pp_time diff, now;
struct timex tx;
int tai_offset = 0;
int msec;
/*
......@@ -279,25 +321,8 @@ static int wrs_time_set(struct pp_instance *ppi, const struct pp_time *t)
if (t->secs < 1420730822 /* "now" as I write this */)
return 0;
/*
* Finally, set unix time too, but count the UTC/TAI difference
* assuming somebody has set up up for us
*/
memset(&tx, 0, sizeof(tx));
if (adjtimex(&tx) >= 0) {
/*
* Our WRS kernel has tai support, but our compiler does not.
* We are 32-bit only, and we know for sure that tai is
* exactly after stbcnt. It's a bad hack, but it works
*/
tai_offset = *((int *)(&tx.stbcnt) + 1);
}
{
struct pp_time utc = *t; /* t is "const". uff.... */
utc.secs -= tai_offset;
unix_time_ops.set(ppi, &utc);
}
/* Finally, set unix time too */
unix_time_ops.set(ppi, t);
return 0;
}
......@@ -371,6 +396,10 @@ static unsigned long wrs_calc_timeout(struct pp_instance *ppi,
}
struct pp_time_operations wrs_time_ops = {
.get_utc_time = wrs_time_get_utc_time,
.get_utc_offset = wrs_time_get_utc_offset,
.set_utc_offset = wrs_time_set_utc_offset,
.get_servo_state = wrs_time_get_servo_state,
.get = wrs_time_get,
.set = wrs_time_set,
.adjust = wrs_time_adjust,
......
......@@ -22,6 +22,7 @@ struct timeout_config {
static struct timeout_config to_configs[__PP_TO_ARRAY_SIZE] = {
[PP_TO_REQUEST] = {"REQUEST", RAND_0_200,},
[PP_TO_SYNC_SEND] = {"SYNC_SEND", RAND_70_130,},
[PP_TO_BMC] = {"BMC", RAND_NONE,},
[PP_TO_ANN_RECEIPT] = {"ANN_RECEIPT", RAND_NONE,},
[PP_TO_ANN_SEND] = {"ANN_SEND", RAND_70_130,},
[PP_TO_FAULT] = {"FAULT", RAND_NONE, 4000},
......@@ -40,6 +41,7 @@ void pp_timeout_init(struct pp_instance *ppi)
to_configs[PP_TO_FAULT].value =
1 << (port->logMinDelayReqInterval + 12); /* 0 -> 4096ms */
to_configs[PP_TO_SYNC_SEND].value = port->logSyncInterval;
to_configs[PP_TO_BMC].value = 1000 * (1 << port->logAnnounceInterval);
to_configs[PP_TO_ANN_RECEIPT].value = 1000 * (
port->announceReceiptTimeout << port->logAnnounceInterval);
to_configs[PP_TO_ANN_SEND].value = port->logAnnounceInterval;
......@@ -54,6 +56,10 @@ void __pp_timeout_set(struct pp_instance *ppi, int index, int millisec)
to_configs[index].name, millisec);
}
void pp_timeout_clear(struct pp_instance *ppi, int index)
{
__pp_timeout_set(ppi, index, 0);
}
void pp_timeout_set(struct pp_instance *ppi, int index)
{
......@@ -111,8 +117,11 @@ void pp_timeout_set(struct pp_instance *ppi, int index)
void pp_timeout_setall(struct pp_instance *ppi)
{
int i;
for (i = 0; i < __PP_TO_ARRAY_SIZE; i++)
pp_timeout_set(ppi, i);
for (i = 0; i < __PP_TO_ARRAY_SIZE; i++) {
/* keep BMC timeout */
if (i != PP_TO_BMC)
pp_timeout_set(ppi, i);
}
/* but announce_send must be send soon */
__pp_timeout_set(ppi, PP_TO_ANN_SEND, 20);
}
......
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