l1e-hooks.c 9.25 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/*
 * Copyright (C) 2018 CERN (www.cern.ch)
 * Author: Jean-Claude BAU & Maciej Lipinski
 *
 * Released according to the GNU LGPL, version 2.1 or any later version.
 */

#include <inttypes.h>
#include <ppsi/ppsi.h>
#include <common-fun.h>
#include "l1e-constants.h"
#include <math.h>

char *l1e_state_name[] = {
	[L1SYNC_DISABLED]	= "L1SYNC_DISABLED",
	[L1SYNC_IDLE]		= "L1SYNC_IDLE",
	[L1SYNC_LINK_ALIVE]	= "L1SYNC_LINK_ALIVE",
	[L1SYNC_CONFIG_MATCH]	= "L1SYNC_CONFIG_MATCH",
	[L1SYNC_UP]		= "L1SYNC_UP",
};

baujc's avatar
baujc committed
22 23 24
int l1eTmoTxSync=0;
int l1eTmoRxSync=0;

25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55
void l1e_print_L1Sync_basic_bitmaps(struct pp_instance *ppi, uint8_t configed,
					uint8_t active, char* text)
{

	pp_diag(ppi, ext, 2, "ML: L1Sync %s\n", text);
	pp_diag(ppi, ext, 2, "ML: \tConfig: TxC=%d RxC=%d Cong=%d Param=%d\n",
		  ((configed & L1E_TX_COHERENT) == L1E_TX_COHERENT),
		  ((configed & L1E_RX_COHERENT) == L1E_RX_COHERENT),
		  ((configed & L1E_CONGRUENT)   == L1E_CONGRUENT),
		  ((configed & L1E_OPT_PARAMS)  == L1E_OPT_PARAMS));
	pp_diag(ppi, ext, 2, "ML: \tActive: TxC=%d RxC=%d Cong=%d\n",
		  ((active & L1E_TX_COHERENT)   == L1E_TX_COHERENT),
		  ((active & L1E_RX_COHERENT)   == L1E_RX_COHERENT),
		  ((active & L1E_CONGRUENT)     == L1E_CONGRUENT));
}

/* open is global; called from "pp_init_globals" */
static int l1e_open(struct pp_instance *ppi, struct pp_runtime_opts *rt_opts)
{
	pp_diag(NULL, ext, 2, "hook: %s -- ext %i\n", __func__,
		ppi->protocol_extension);
	return 0;
}

/* initialize one specific port */
static int l1e_init(struct pp_instance *ppi, void *buf, int len)
{
	L1SyncBasicPortDS_t * bds=L1E_DSPOR_BS(ppi);

	pp_diag(ppi, ext, 2, "hook: %s -- ext %i\n", __func__,
		ppi->protocol_extension);
baujc's avatar
baujc committed
56 57 58 59 60 61 62 63 64 65 66

	if ( l1eTmoTxSync==0) {
		l1eTmoTxSync=pp_timeout_get_timer(ppi,"L1E_TX_SYNC",TO_RAND_NONE, TMO_CF_INSTANCE_DEPENDENT);
	}

	if ( l1eTmoRxSync==0)
		l1eTmoRxSync=pp_timeout_get_timer(ppi,"L1E_RX_SYNC",TO_RAND_NONE, TMO_CF_INSTANCE_DEPENDENT);

	pp_timeout_set(ppi, L1E_TIMEOUT_TX_SYNC, 100); /* Will be set later to the appropriate value */
	pp_timeout_set(ppi, L1E_TIMEOUT_RX_SYNC, 100); /* Will be set later to the appropriate value */

67 68 69 70 71 72 73 74 75 76 77 78
	// init dynamic data set members with zeros/defaults
	bds->L1SyncLinkAlive          = FALSE;
	bds->isTxCoherent             = FALSE;
	bds->isRxCoherent             = FALSE;
	bds->isCongruent              = FALSE;
	bds->L1SyncState              = L1SYNC_DISABLED;
	bds->peerTxCoherentIsRequired = FALSE;
	bds->peerRxCoherentIsRequired = FALSE;
	bds->peerCongruentIsRequired  = FALSE;
	bds->peerIsTxCoherent     	  = FALSE;
	bds->peerIsRxCoherent     	  = FALSE;
	bds->peerIsCongruent          = FALSE;
79
	/* Init  configurable parameters */
80 81
	bds->logL1SyncInterval=ppi->cfg.l1syncInterval;
	bds->L1SyncReceiptTimeout=ppi->cfg.l1syncReceiptTimeout;
82 83 84 85 86

	/* Init other specific members */
	bds->next_state=bds->L1SyncState;

	/* Init configuration members of L1SyncOptParamsPortDS */
87
	L1E_DSPOR_OP(ppi)->timestampsCorrectedTx=TRUE;
88

Jean-Claude BAU's avatar
Jean-Claude BAU committed
89
	ppi->pdstate = PP_PDSTATE_WAIT_MSG;
90 91 92 93 94 95 96 97 98 99 100 101 102 103
	return 0;
}

/* This hook is called whenever a signaling message is received */
static int l1e_handle_signaling(struct pp_instance * ppi, void *buf, int len)
{
	L1SyncBasicPortDS_t * bds=L1E_DSPOR_BS(ppi);
	pp_diag(ppi, ext, 2, "hook: %s (%i:%s) -- plen %i\n", __func__,
		ppi->state, l1e_state_name[bds->L1SyncState], len);

	if ( l1e_unpack_signal(ppi, buf, len)==0 ) {
		/* Valid Sync message */

		/* Reset reception timeout */
baujc's avatar
baujc committed
104
		pp_timeout_set(ppi, L1E_TIMEOUT_RX_SYNC, l1e_get_rx_tmo_ms(bds));
105 106

		bds->L1SyncLinkAlive = TRUE;
Jean-Claude BAU's avatar
Jean-Claude BAU committed
107 108 109 110
		if ( ppi->extState==PP_EXSTATE_PTP ) {
			// Extension need to be re-enabled
			pdstate_enable_extension(ppi);
		}
111 112
		if ( ppi->pdstate==PP_PDSTATE_PDETECTION)
			pdstate_set_state_pdetected(ppi);
113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130
	}
	return 0;
}

uint8_t l1e_creat_L1Sync_bitmask(int tx_coh, int rx_coh, int congru)
{
	uint8_t outputMask=0;
	if(tx_coh) outputMask |= L1E_TX_COHERENT;
	if(rx_coh) outputMask |= L1E_RX_COHERENT;
	if(congru) outputMask |= L1E_CONGRUENT;
	return outputMask;
}

static int l1e_handle_resp(struct pp_instance *ppi)
{
	pp_diag(ppi, ext, 2, "hook: %s\n", __func__);

	/* This correction_field we received is already part of t4 */
Jean-Claude BAU's avatar
Jean-Claude BAU committed
131
	if ( ppi->extState==PP_EXSTATE_ACTIVE ) {
132
		l1e_servo_got_resp(ppi);
Jean-Claude BAU's avatar
Jean-Claude BAU committed
133 134
		if ( ppi->pdstate==PP_PDSTATE_PDETECTED)
			pdstate_set_state_pdetected(ppi); // Maintain state Protocol detected on MASTER side
baujc's avatar
baujc committed
135 136
	}
	else {
baujc's avatar
baujc committed
137
		pp_servo_got_resp(ppi,OPTS(ppi)->ptpFallbackPpsGen);
138 139 140 141
	}
	return 0;
}

Jean-Claude BAU's avatar
Jean-Claude BAU committed
142 143 144 145 146 147 148 149 150 151 152 153
static int l1e_handle_dreq(struct pp_instance *ppi)
{
	pp_diag(ppi, ext, 2, "hook: %s\n", __func__);
	if ( ppi->extState==PP_EXSTATE_ACTIVE ) {
		if ( ppi->pdstate==PP_PDSTATE_PDETECTED)
			pdstate_set_state_pdetected(ppi); // Maintain state Protocol detected on MASTER side
	}

	return 0;
}


baujc's avatar
baujc committed
154
static int  l1e_sync_followup(struct pp_instance *ppi) {
Jean-Claude BAU's avatar
Jean-Claude BAU committed
155
	if ( ppi->extState==PP_EXSTATE_ACTIVE ) {
baujc's avatar
baujc committed
156 157 158
		l1e_servo_got_sync(ppi);
	}
	else {
baujc's avatar
baujc committed
159
		pp_servo_got_sync(ppi,OPTS(ppi)->ptpFallbackPpsGen);
baujc's avatar
baujc committed
160
	}
161 162 163
	return 1; /* the caller returns too */
}

164
/* Hmm... "execute_slave" should look for errors; but it's off in WR too */
baujc's avatar
baujc committed
165
static int l1e_handle_followup(struct pp_instance *ppi)
166 167 168
{
	/* This handle is called in case of two step clock */
	pp_diag(ppi, ext, 2, "hook: %s\n", __func__);
baujc's avatar
baujc committed
169
	return l1e_sync_followup(ppi);
170 171
}

baujc's avatar
baujc committed
172
static int l1e_handle_sync(struct pp_instance *ppi)
173 174 175
{
	/* This handle is called in case of one step clock */
	pp_diag(ppi, ext, 2, "hook: %s\n", __func__);
baujc's avatar
baujc committed
176
	return l1e_sync_followup(ppi);
177 178
}

baujc's avatar
baujc committed
179
static int l1e_handle_presp(struct pp_instance *ppi)
180
{
Jean-Claude BAU's avatar
Jean-Claude BAU committed
181
	if ( ppi->extState==PP_EXSTATE_ACTIVE ) {
baujc's avatar
baujc committed
182
		l1e_servo_got_presp(ppi);
Jean-Claude BAU's avatar
Jean-Claude BAU committed
183 184 185
		if ( ppi->pdstate==PP_PDSTATE_PDETECTED)
			pdstate_set_state_pdetected(ppi); // Maintain state Protocol detected on MASTER side
	}
baujc's avatar
baujc committed
186 187
	else
		pp_servo_got_presp(ppi);
188 189 190 191 192 193 194 195 196
	return 0;
}

/* Check if ready to go to SLAVE state */
static int l1e_ready_for_slave(struct pp_instance *ppi)
{
	pp_diag(ppi, ext, 2, "hook: %s\n", __func__);

	/* Current state is UNCALIBRATED. Can we go to SLAVE state ? */
197
	/* We do not wait L1SYNC_UP do go to slave state */
198 199 200
	return 1; /* Ready for slave */
}

201
static 	void l1e_state_change(struct pp_instance *ppi) {
202 203 204

	pp_diag(ppi, ext, 2, "hook: %s\n", __func__);

Jean-Claude BAU's avatar
Jean-Claude BAU committed
205 206 207
	if ( ppi->extState==PP_EXSTATE_PTP &&  ppi->next_state==PPS_UNCALIBRATED ) {
		// Extension need to be re-enabled
		pdstate_enable_extension(ppi);
208
	}
Jean-Claude BAU's avatar
Jean-Claude BAU committed
209 210 211 212 213 214 215 216 217 218 219 220 221

	if ( (ppi->next_state==PPS_DISABLED || ppi->extState!=PP_EXSTATE_ACTIVE) &&
			L1E_DSPOR(ppi)->basic.L1SyncState!=L1SYNC_DISABLED) {
		// Extension not active but the l1sync state is not disable yet.
		L1E_DSPOR(ppi)->basic.next_state=L1SYNC_DISABLED; /* Force L1Sync DISABLE state */
		l1e_run_state_machine(ppi,NULL,0);
	} else {
		if ( ppi->extState==PP_EXSTATE_ACTIVE && ppi->next_state==PPS_INITIALIZING) {
			L1E_DSPOR(ppi)->basic.L1SyncState=L1E_DSPOR(ppi)->basic.next_state=L1SYNC_DISABLED;
		} else {
			if ( ppi->state==PPS_SLAVE && ppi->next_state!=PPS_UNCALIBRATED &&
					L1E_DSPOR(ppi)->basic.L1SyncState!=L1SYNC_DISABLED ) {
				/* Leave SLAVE state : We must stop the PPS generation */
222 223
				if ( !GOPTS(GLBS(ppi))->forcePpsGen )
					TOPS(ppi)->enable_timing_output(GLBS(ppi),0);
Jean-Claude BAU's avatar
Jean-Claude BAU committed
224 225 226 227 228
				WRH_OPER()->locking_disable(ppi);
				WRH_OPER()->locking_reset(ppi);
				l1e_servo_reset(ppi);
			}

Jean-Claude BAU's avatar
Jean-Claude BAU committed
229
		}
baujc's avatar
baujc committed
230
	}
Jean-Claude BAU's avatar
Jean-Claude BAU committed
231

232 233
}

baujc's avatar
baujc committed
234
static int l1e_new_slave (struct pp_instance *ppi, void *buf, int len) {
Jean-Claude BAU's avatar
Jean-Claude BAU committed
235
	if ( ppi->extState==PP_EXSTATE_ACTIVE )
baujc's avatar
baujc committed
236 237 238 239 240
		l1e_servo_init(ppi);
	return 0;
}

static int l1e_require_precise_timestamp(struct pp_instance *ppi) {
Jean-Claude BAU's avatar
Jean-Claude BAU committed
241
	return  ppi->extState==PP_EXSTATE_ACTIVE  ? L1E_DSPOR_BS(ppi)->L1SyncState==L1SYNC_UP : 0;
baujc's avatar
baujc committed
242 243 244
}

static int l1e_get_tmo_lstate_detection(struct pp_instance *ppi) {
245 246 247
	return is_externalPortConfigurationEnabled(DSDEF(ppi)) ?
			10000 : /* 10s: externalPortConfiguration enable means no ANN_RECEIPT timeout */
			l1e_get_rx_tmo_ms(L1E_DSPOR_BS(ppi));
baujc's avatar
baujc committed
248 249
}

Jean-Claude BAU's avatar
Jean-Claude BAU committed
250 251 252 253 254 255 256 257 258 259 260 261 262 263
static TimeInterval l1e_get_ingress_latency (struct pp_instance *ppi) {
	return ppi->timestampCorrectionPortDS.ingressLatency;
}

static TimeInterval l1e_get_egress_latency (struct pp_instance *ppi) {
	return ppi->timestampCorrectionPortDS.egressLatency;
}

/* HA extension is compliant with the standard concerning the contents of the correction fields */
static int l1e_is_correction_field_compliant (struct pp_instance *ppi) {
	return 1;
}

static int l1e_extension_state_changed( struct pp_instance * ppi) {
Jean-Claude BAU's avatar
Jean-Claude BAU committed
264 265 266 267 268
	if ( ppi->extState!=PP_EXSTATE_ACTIVE && L1E_DSPOR(ppi)->basic.L1SyncState!=L1SYNC_DISABLED ) {
		// Extension disabled : Force L1SYNC_DISABLED disable state
		L1E_DSPOR(ppi)->basic.next_state=L1SYNC_DISABLED; /* Force L1Sync DISABLE state */
		l1e_run_state_machine(ppi,NULL,0);
	}
Jean-Claude BAU's avatar
Jean-Claude BAU committed
269 270 271
	return 0;
}

272 273 274 275 276 277 278 279
/* The global structure used by ppsi */
struct pp_ext_hooks l1e_ext_hooks = {
	.open = l1e_open,
	.init = l1e_init,
	.handle_signaling = l1e_handle_signaling,
	.run_ext_state_machine = l1e_run_state_machine,
	.ready_for_slave = l1e_ready_for_slave,
	.handle_resp = l1e_handle_resp,
Jean-Claude BAU's avatar
Jean-Claude BAU committed
280
	.handle_dreq = l1e_handle_dreq,
281
	.handle_sync = l1e_handle_sync,
282
	.handle_followup = l1e_handle_followup,
baujc's avatar
baujc committed
283
	.new_slave = l1e_new_slave,
284 285 286
#if CONFIG_HAS_P2P
	.handle_presp = l1e_handle_presp,
#endif
287
	.state_change = l1e_state_change,
baujc's avatar
baujc committed
288 289
	.servo_reset= l1e_servo_reset,
	.require_precise_timestamp=l1e_require_precise_timestamp,
Jean-Claude BAU's avatar
Jean-Claude BAU committed
290 291 292 293 294 295
	.get_tmo_lstate_detection=l1e_get_tmo_lstate_detection,
	.get_ingress_latency=l1e_get_ingress_latency,
	.get_egress_latency=l1e_get_egress_latency,
	.is_correction_field_compliant=l1e_is_correction_field_compliant,
	.extension_state_changed= l1e_extension_state_changed

296 297
};