1 /*
2  * Copyright (c) 2017 Intel Corporation.
3  *
4  * SPDX-License-Identifier: Apache-2.0
5  */
6 
7 #include <zephyr/logging/log.h>
8 LOG_MODULE_DECLARE(net_gptp, CONFIG_NET_GPTP_LOG_LEVEL);
9 
10 #include <zephyr/drivers/ptp_clock.h>
11 
12 #include "gptp_messages.h"
13 #include "gptp_data_set.h"
14 #include "gptp_state.h"
15 #include "gptp_private.h"
16 
17 #if CONFIG_NET_GPTP_LOG_LEVEL >= LOG_LEVEL_DBG
state2str(enum gptp_port_state state)18 static const char * const state2str(enum gptp_port_state state)
19 {
20 	switch (state) {
21 	case GPTP_PORT_INITIALIZING:
22 		return "INITIALIZING";
23 	case GPTP_PORT_FAULTY:
24 		return "FAULTY";
25 	case GPTP_PORT_DISABLED:
26 		return "DISABLED";
27 	case GPTP_PORT_LISTENING:
28 		return "LISTENING";
29 	case GPTP_PORT_PRE_MASTER:
30 		return "PRE_MASTER";
31 	case GPTP_PORT_MASTER:
32 		return "MASTER";
33 	case GPTP_PORT_PASSIVE:
34 		return "PASSIVE";
35 	case GPTP_PORT_UNCALIBRATED:
36 		return "UNCALIBRATED";
37 	case GPTP_PORT_SLAVE:
38 		return "SLAVE";
39 	}
40 
41 	return "<unknown>";
42 }
43 
pa_info_state2str(enum gptp_pa_info_states state)44 static const char * const pa_info_state2str(enum gptp_pa_info_states state)
45 {
46 	switch (state) {
47 	case GPTP_PA_INFO_DISABLED:
48 		return "DISABLED";
49 	case GPTP_PA_INFO_POST_DISABLED:
50 		return "POST_DISABLED";
51 	case GPTP_PA_INFO_AGED:
52 		return "AGED";
53 	case GPTP_PA_INFO_UPDATE:
54 		return "UPDATE";
55 	case GPTP_PA_INFO_CURRENT:
56 		return "CURRENT";
57 	case GPTP_PA_INFO_RECEIVE:
58 		return "RECEIVE";
59 	case GPTP_PA_INFO_SUPERIOR_MASTER_PORT:
60 		return "SUPERIOR_MASTER_PORT";
61 	case GPTP_PA_INFO_REPEATED_MASTER_PORT:
62 		return "REPEATED_MASTER_PORT";
63 	case GPTP_PA_INFO_INFERIOR_MASTER_OR_OTHER_PORT:
64 		return "INFERIOR_MASTER_OR_OTHER_PORT";
65 	}
66 
67 	return "<unknown>";
68 }
69 #endif
70 
71 #if CONFIG_NET_GPTP_LOG_LEVEL >= LOG_LEVEL_DBG
gptp_change_port_state_debug(int port,enum gptp_port_state state,const char * caller,int line)72 void gptp_change_port_state_debug(int port, enum gptp_port_state state,
73 				  const char *caller,
74 				  int line)
75 #else
76 void gptp_change_port_state(int port, enum gptp_port_state state)
77 #endif
78 {
79 	struct gptp_global_ds *global_ds = GPTP_GLOBAL_DS();
80 
81 	if (global_ds->selected_role[port] == state) {
82 		return;
83 	}
84 
85 #if CONFIG_NET_GPTP_LOG_LEVEL >= LOG_LEVEL_DBG
86 	NET_DBG("[%d] state %s -> %s (%s():%d)", port,
87 		state2str(global_ds->selected_role[port]),
88 		state2str(state), caller, line);
89 #endif
90 
91 	global_ds->selected_role[port] = state;
92 };
93 
94 #if CONFIG_NET_GPTP_LOG_LEVEL >= LOG_LEVEL_DBG
gptp_change_pa_info_state_debug(int port,struct gptp_port_announce_information_state * pa_info_state,enum gptp_pa_info_states state,const char * caller,int line)95 void gptp_change_pa_info_state_debug(
96 	int port,
97 	struct gptp_port_announce_information_state *pa_info_state,
98 	enum gptp_pa_info_states state,
99 	const char *caller,
100 	int line)
101 #else
102 void gptp_change_pa_info_state(
103 	int port,
104 	struct gptp_port_announce_information_state *pa_info_state,
105 	enum gptp_pa_info_states state)
106 #endif
107 {
108 	if (pa_info_state->state == state) {
109 		return;
110 	}
111 
112 #if CONFIG_NET_GPTP_LOG_LEVEL >= LOG_LEVEL_DBG
113 	NET_DBG("[%d] PA info state %s -> %s (%s():%d)", port,
114 		pa_info_state2str(pa_info_state->state),
115 		pa_info_state2str(state), caller, line);
116 #endif
117 
118 	pa_info_state->state = state;
119 }
120 
gptp_mi_half_sync_itv_timeout(struct k_timer * timer)121 static void gptp_mi_half_sync_itv_timeout(struct k_timer *timer)
122 {
123 	struct gptp_pss_send_state *state;
124 	int port;
125 
126 	for (port = GPTP_PORT_START; port < GPTP_PORT_END; port++) {
127 		state = &GPTP_PORT_STATE(port)->pss_send;
128 		if (&state->half_sync_itv_timer == timer) {
129 			if (!state->half_sync_itv_timer_expired) {
130 				state->half_sync_itv_timer_expired = true;
131 			} else {
132 				/* We do not need the timer anymore. */
133 				k_timer_stop(timer);
134 
135 				state->sync_itv_timer_expired = true;
136 			}
137 		}
138 	}
139 }
140 
gptp_mi_rcv_sync_receipt_timeout(struct k_timer * timer)141 static void gptp_mi_rcv_sync_receipt_timeout(struct k_timer *timer)
142 {
143 	struct gptp_pss_rcv_state *state;
144 	int port;
145 
146 	for (port = GPTP_PORT_START; port < GPTP_PORT_END; port++) {
147 		state = &GPTP_PORT_STATE(port)->pss_rcv;
148 		if (&state->rcv_sync_receipt_timeout_timer == timer) {
149 			state->rcv_sync_receipt_timeout_timer_expired = true;
150 		}
151 
152 		GPTP_STATS_INC(port, sync_receipt_timeout_count);
153 	}
154 }
155 
gptp_mi_send_sync_receipt_timeout(struct k_timer * timer)156 static void gptp_mi_send_sync_receipt_timeout(struct k_timer *timer)
157 {
158 	struct gptp_pss_send_state *state;
159 	int port;
160 
161 	for (port = GPTP_PORT_START; port < GPTP_PORT_END; port++) {
162 		state = &GPTP_PORT_STATE(port)->pss_send;
163 		if (&state->send_sync_receipt_timeout_timer == timer) {
164 			state->send_sync_receipt_timeout_timer_expired = true;
165 		}
166 
167 		GPTP_STATS_INC(port, sync_receipt_timeout_count);
168 	}
169 }
170 
gptp_mi_init_port_sync_sync_rcv_sm(int port)171 static void gptp_mi_init_port_sync_sync_rcv_sm(int port)
172 {
173 	struct gptp_pss_rcv_state *pss_rcv;
174 
175 	pss_rcv = &GPTP_PORT_STATE(port)->pss_rcv;
176 	(void)memset(pss_rcv, 0, sizeof(struct gptp_pss_rcv_state));
177 
178 	k_timer_init(&pss_rcv->rcv_sync_receipt_timeout_timer,
179 		     gptp_mi_rcv_sync_receipt_timeout, NULL);
180 
181 	pss_rcv->state = GPTP_PSS_RCV_DISCARD;
182 }
183 
gptp_mi_init_port_sync_sync_send_sm(int port)184 static void gptp_mi_init_port_sync_sync_send_sm(int port)
185 {
186 	struct gptp_pss_send_state *pss_send;
187 
188 	pss_send = &GPTP_PORT_STATE(port)->pss_send;
189 	(void)memset(pss_send, 0, sizeof(struct gptp_pss_send_state));
190 
191 	k_timer_init(&pss_send->half_sync_itv_timer,
192 		     gptp_mi_half_sync_itv_timeout, NULL);
193 	k_timer_init(&pss_send->send_sync_receipt_timeout_timer,
194 		     gptp_mi_send_sync_receipt_timeout, NULL);
195 
196 	pss_send->state = GPTP_PSS_SEND_TRANSMIT_INIT;
197 }
198 
gptp_mi_init_site_sync_sync_sm(void)199 static void gptp_mi_init_site_sync_sync_sm(void)
200 {
201 	struct gptp_site_sync_sync_state *site_ss;
202 
203 	site_ss = &GPTP_STATE()->site_ss;
204 	(void)memset(site_ss, 0, sizeof(struct gptp_site_sync_sync_state));
205 	site_ss->state = GPTP_SSS_INITIALIZING;
206 }
207 
gptp_mi_init_clock_slave_sync_sm(void)208 static void gptp_mi_init_clock_slave_sync_sm(void)
209 {
210 	struct gptp_clk_slave_sync_state *clk_ss;
211 
212 	clk_ss = &GPTP_STATE()->clk_slave_sync;
213 	(void)memset(clk_ss, 0, sizeof(struct gptp_clk_slave_sync_state));
214 	clk_ss->state = GPTP_CLK_SLAVE_SYNC_INITIALIZING;
215 }
216 
gptp_mi_init_port_announce_rcv_sm(int port)217 static void gptp_mi_init_port_announce_rcv_sm(int port)
218 {
219 	struct gptp_port_announce_receive_state *pa_rcv;
220 
221 	pa_rcv = &GPTP_PORT_STATE(port)->pa_rcv;
222 	(void)memset(pa_rcv, 0,
223 		     sizeof(struct gptp_port_announce_receive_state));
224 	pa_rcv->state = GPTP_PA_RCV_DISCARD;
225 }
226 
gptp_mi_init_clock_master_sync_rcv_sm(void)227 static void gptp_mi_init_clock_master_sync_rcv_sm(void)
228 {
229 	struct gptp_clk_master_sync_rcv_state *cms_rcv;
230 
231 	cms_rcv = &GPTP_STATE()->clk_master_sync_receive;
232 	(void)memset(cms_rcv, 0, sizeof(struct gptp_clk_master_sync_rcv_state));
233 	cms_rcv->state = GPTP_CMS_RCV_INITIALIZING;
234 }
235 
announce_timer_handler(struct k_timer * timer)236 static void announce_timer_handler(struct k_timer *timer)
237 {
238 	int port;
239 	struct gptp_port_announce_information_state *state;
240 
241 	for (port = GPTP_PORT_START; port < GPTP_PORT_END; port++) {
242 		state = &GPTP_PORT_STATE(port)->pa_info;
243 		if (&state->ann_rcpt_expiry_timer == timer) {
244 			state->ann_expired = true;
245 			GPTP_STATS_INC(port, announce_receipt_timeout_count);
246 			break;
247 		}
248 	}
249 }
250 
gptp_mi_init_port_announce_info_sm(int port)251 static void gptp_mi_init_port_announce_info_sm(int port)
252 {
253 	struct gptp_port_announce_information_state *state;
254 
255 	state = &GPTP_PORT_STATE(port)->pa_info;
256 
257 	k_timer_init(&state->ann_rcpt_expiry_timer,
258 		     announce_timer_handler, NULL);
259 
260 	state->ann_expired = false;
261 	gptp_change_pa_info_state(port, state, GPTP_PA_INFO_DISABLED);
262 }
263 
gptp_mi_init_bmca_data(int port)264 static void gptp_mi_init_bmca_data(int port)
265 {
266 	struct gptp_port_bmca_data *bmca_data;
267 
268 	bmca_data = GPTP_PORT_BMCA_DATA(port);
269 
270 	(void)memset(bmca_data, 0, sizeof(struct gptp_port_bmca_data));
271 
272 	gptp_set_time_itv(&bmca_data->announce_interval, 1,
273 			  CONFIG_NET_GPTP_INIT_LOG_ANNOUNCE_ITV);
274 
275 	(void)memset(&bmca_data->port_priority, 0xFF,
276 		     sizeof(struct gptp_priority_vector));
277 	(void)memset(&bmca_data->master_priority, 0xFF,
278 		     sizeof(struct gptp_priority_vector));
279 }
280 
announce_periodic_timer_handler(struct k_timer * timer)281 static void announce_periodic_timer_handler(struct k_timer *timer)
282 {
283 	int port;
284 	struct gptp_port_announce_transmit_state *state;
285 
286 	for (port = GPTP_PORT_START; port < GPTP_PORT_END; port++) {
287 		state = &GPTP_PORT_STATE(port)->pa_transmit;
288 		if (&state->ann_send_periodic_timer == timer) {
289 			state->ann_trigger = true;
290 			break;
291 		}
292 	}
293 }
294 
gptp_mi_init_port_announce_transmit_sm(int port)295 static void gptp_mi_init_port_announce_transmit_sm(int port)
296 {
297 	struct gptp_port_announce_transmit_state *state;
298 
299 	state = &GPTP_PORT_STATE(port)->pa_transmit;
300 
301 	k_timer_init(&state->ann_send_periodic_timer,
302 		     announce_periodic_timer_handler, NULL);
303 
304 	state->ann_trigger = false;
305 	state->state = GPTP_PA_TRANSMIT_INIT;
306 }
307 
gptp_mi_init_port_role_selection_sm(void)308 static void gptp_mi_init_port_role_selection_sm(void)
309 {
310 	GPTP_STATE()->pr_sel.state = GPTP_PR_SELECTION_INIT_BRIDGE;
311 }
312 
gptp_mi_init_state_machine(void)313 void gptp_mi_init_state_machine(void)
314 {
315 	int port;
316 
317 	for (port = GPTP_PORT_START;
318 	     port < (GPTP_PORT_START + CONFIG_NET_GPTP_NUM_PORTS); port++) {
319 		gptp_mi_init_port_sync_sync_rcv_sm(port);
320 		gptp_mi_init_port_sync_sync_send_sm(port);
321 		gptp_mi_init_port_announce_rcv_sm(port);
322 		gptp_mi_init_port_announce_info_sm(port);
323 		gptp_mi_init_port_announce_transmit_sm(port);
324 		gptp_mi_init_bmca_data(port);
325 	}
326 
327 	gptp_mi_init_site_sync_sync_sm();
328 	gptp_mi_init_clock_slave_sync_sm();
329 	gptp_mi_init_port_role_selection_sm();
330 	gptp_mi_init_clock_master_sync_rcv_sm();
331 }
332 
gptp_get_current_time_nanosecond(int port)333 uint64_t gptp_get_current_time_nanosecond(int port)
334 {
335 	const struct device *clk;
336 
337 	clk = net_eth_get_ptp_clock(GPTP_PORT_IFACE(port));
338 	if (clk) {
339 		struct net_ptp_time tm = {};
340 
341 		ptp_clock_get(clk, &tm);
342 
343 		if (tm.second == 0U && tm.nanosecond == 0U) {
344 			goto use_uptime;
345 		}
346 
347 		return gptp_timestamp_to_nsec(&tm);
348 	}
349 
350 use_uptime:
351 	/* A workaround if clock cannot be found. Note that accuracy is
352 	 * only in milliseconds.
353 	 */
354 	return k_uptime_get() * 1000000;
355 }
356 
gptp_get_current_master_time_nanosecond(void)357 uint64_t gptp_get_current_master_time_nanosecond(void)
358 {
359 	int port;
360 	enum gptp_port_state *port_role;
361 
362 	port_role = GPTP_GLOBAL_DS()->selected_role;
363 
364 	for (port = GPTP_PORT_START; port < GPTP_PORT_END; port++) {
365 		if (port_role[port] == GPTP_PORT_MASTER) {
366 			return gptp_get_current_time_nanosecond(port);
367 		}
368 	}
369 
370 	/* No master */
371 	return 0;
372 }
373 
gptp_mi_pss_rcv_compute(int port)374 static void gptp_mi_pss_rcv_compute(int port)
375 {
376 	struct gptp_pss_rcv_state *state;
377 	struct gptp_mi_port_sync_sync *pss;
378 	struct gptp_md_sync_info *sync_rcv;
379 	struct gptp_port_ds *port_ds;
380 
381 	state = &GPTP_PORT_STATE(port)->pss_rcv;
382 	pss = &state->pss;
383 	sync_rcv = &state->sync_rcv;
384 	port_ds = GPTP_PORT_DS(port);
385 
386 	state->rate_ratio = sync_rcv->rate_ratio;
387 	state->rate_ratio += (port_ds->neighbor_rate_ratio - 1.0);
388 
389 	port_ds->sync_receipt_timeout_time_itv = port_ds->sync_receipt_timeout;
390 	port_ds->sync_receipt_timeout_time_itv *= NSEC_PER_SEC;
391 	port_ds->sync_receipt_timeout_time_itv *=
392 		GPTP_POW2(sync_rcv->log_msg_interval);
393 
394 	pss->local_port_number = port;
395 
396 	memcpy(&pss->sync_info, sync_rcv, sizeof(struct gptp_md_sync_info));
397 
398 	pss->sync_receipt_timeout_time = gptp_get_current_time_nanosecond(port);
399 	pss->sync_receipt_timeout_time +=
400 		port_ds->sync_receipt_timeout_time_itv;
401 
402 	pss->sync_info.rate_ratio = state->rate_ratio;
403 }
404 
start_rcv_sync_timer(struct gptp_port_ds * port_ds,struct gptp_pss_rcv_state * state)405 static void start_rcv_sync_timer(struct gptp_port_ds *port_ds,
406 				 struct gptp_pss_rcv_state *state)
407 {
408 	k_timeout_t duration;
409 
410 	duration = K_MSEC(port_ds->sync_receipt_timeout_time_itv /
411 			  (NSEC_PER_USEC * USEC_PER_MSEC));
412 
413 	k_timer_start(&state->rcv_sync_receipt_timeout_timer, duration,
414 		      K_NO_WAIT);
415 }
416 
gptp_mi_pss_rcv_state_machine(int port)417 static void gptp_mi_pss_rcv_state_machine(int port)
418 {
419 	struct gptp_pss_rcv_state *state;
420 	struct gptp_site_sync_sync_state *site_ss_state;
421 	struct gptp_port_ds *port_ds;
422 
423 	state = &GPTP_PORT_STATE(port)->pss_rcv;
424 	site_ss_state = &GPTP_STATE()->site_ss;
425 	port_ds = GPTP_PORT_DS(port);
426 
427 	if ((!port_ds->ptt_port_enabled) || !port_ds->as_capable) {
428 		state->rcvd_md_sync = false;
429 		state->state = GPTP_PSS_RCV_DISCARD;
430 		return;
431 	}
432 
433 	switch (state->state) {
434 	case GPTP_PSS_RCV_DISCARD:
435 		k_timer_stop(&state->rcv_sync_receipt_timeout_timer);
436 		state->rcv_sync_receipt_timeout_timer_expired = false;
437 
438 		__fallthrough;
439 	case GPTP_PSS_RCV_RECEIVED_SYNC:
440 		if (state->rcvd_md_sync) {
441 			state->rcvd_md_sync = false;
442 			gptp_mi_pss_rcv_compute(port);
443 
444 			state->state = GPTP_PSS_RCV_RECEIVED_SYNC;
445 
446 			site_ss_state->pss_rcv_ptr = &state->pss;
447 			site_ss_state->rcvd_pss = true;
448 
449 			k_timer_stop(&state->rcv_sync_receipt_timeout_timer);
450 			state->rcv_sync_receipt_timeout_timer_expired = false;
451 
452 			if (GPTP_GLOBAL_DS()->gm_present) {
453 				start_rcv_sync_timer(port_ds, state);
454 			}
455 		}
456 
457 		break;
458 	}
459 }
460 
gptp_mi_pss_store_last_pss(int port)461 static void gptp_mi_pss_store_last_pss(int port)
462 {
463 	struct gptp_pss_send_state *state;
464 	struct gptp_mi_port_sync_sync *pss_ptr;
465 	struct gptp_md_sync_info *sync_info;
466 
467 	state = &GPTP_PORT_STATE(port)->pss_send;
468 	pss_ptr = state->pss_sync_ptr;
469 	sync_info = &pss_ptr->sync_info;
470 
471 	state->last_rcvd_port_num = pss_ptr->local_port_number;
472 
473 	memcpy(&state->last_precise_orig_ts, &sync_info->precise_orig_ts,
474 	       sizeof(struct net_ptp_time));
475 	memcpy(&state->last_gm_phase_change, &sync_info->last_gm_phase_change,
476 	       sizeof(struct gptp_scaled_ns));
477 
478 	state->last_follow_up_correction_field =
479 		sync_info->follow_up_correction_field;
480 	state->last_rate_ratio = sync_info->rate_ratio;
481 	state->last_upstream_tx_time = sync_info->upstream_tx_time;
482 	state->last_gm_time_base_indicator = sync_info->gm_time_base_indicator;
483 	state->last_gm_freq_change = sync_info->last_gm_freq_change;
484 }
485 
gptp_mi_pss_send_md_sync_send(int port)486 static void gptp_mi_pss_send_md_sync_send(int port)
487 {
488 	struct gptp_pss_send_state *state;
489 	struct gptp_mi_port_sync_sync *pss_ptr;
490 	struct gptp_sync_send_state *sync_send;
491 
492 	state = &GPTP_PORT_STATE(port)->pss_send;
493 	pss_ptr = state->pss_sync_ptr;
494 	sync_send = &GPTP_PORT_STATE(port)->sync_send;
495 
496 	memcpy(&state->sync_send, &pss_ptr->sync_info,
497 	       sizeof(struct gptp_md_sync_info));
498 
499 	sync_send->sync_send_ptr = &state->sync_send;
500 	sync_send->rcvd_md_sync = true;
501 }
502 
gptp_mi_pss_send_state_machine(int port)503 static void gptp_mi_pss_send_state_machine(int port)
504 {
505 	struct gptp_pss_send_state *state;
506 	struct gptp_port_ds *port_ds;
507 	struct gptp_global_ds *global_ds;
508 	k_timeout_t duration;
509 
510 	global_ds = GPTP_GLOBAL_DS();
511 	state = &GPTP_PORT_STATE(port)->pss_send;
512 	port_ds = GPTP_PORT_DS(port);
513 
514 	/* Reset interval as defined in LinkDelaySyncIntervalSetting state
515 	 * machine.
516 	 */
517 	if (port_ds->ptt_port_enabled && !port_ds->prev_ptt_port_enabled) {
518 		gptp_update_sync_interval(port, GPTP_ITV_SET_TO_INIT);
519 	}
520 
521 	if (state->rcvd_pss_sync && ((!port_ds->ptt_port_enabled) ||
522 				     !port_ds->as_capable)) {
523 		state->rcvd_pss_sync = false;
524 		state->state = GPTP_PSS_SEND_TRANSMIT_INIT;
525 
526 		return;
527 	}
528 
529 	switch (state->state) {
530 	case GPTP_PSS_SEND_TRANSMIT_INIT:
531 	case GPTP_PSS_SEND_SYNC_RECEIPT_TIMEOUT:
532 		if (state->rcvd_pss_sync &&
533 		    (state->pss_sync_ptr->local_port_number != port) &&
534 		    (global_ds->selected_role[port] == GPTP_PORT_MASTER)) {
535 			state->state = GPTP_PSS_SEND_SEND_MD_SYNC;
536 		} else {
537 			break;
538 		}
539 
540 		__fallthrough;
541 	case GPTP_PSS_SEND_SEND_MD_SYNC:
542 		if (state->rcvd_pss_sync) {
543 			gptp_mi_pss_store_last_pss(port);
544 			state->rcvd_pss_sync = false;
545 		}
546 
547 		/* Make sure no previous timer is still running. */
548 		k_timer_stop(&state->half_sync_itv_timer);
549 		k_timer_stop(&state->send_sync_receipt_timeout_timer);
550 
551 		state->half_sync_itv_timer_expired = false;
552 		state->sync_itv_timer_expired = false;
553 		state->send_sync_receipt_timeout_timer_expired = false;
554 
555 		/* Convert ns to ms. */
556 		duration = K_MSEC(gptp_uscaled_ns_to_timer_ms(
557 					  &port_ds->half_sync_itv));
558 
559 		/* Start 0.5 * syncInterval timeout timer. */
560 		k_timer_start(&state->half_sync_itv_timer, duration,
561 			      K_NO_WAIT);
562 
563 		/* sourcePortIdentity is set to the portIdentity of this
564 		 * PTP Port (see ch. 10.2.12.2.1 and ch 8.5.2).
565 		 */
566 		memcpy(&state->pss_sync_ptr->sync_info.src_port_id.clk_id,
567 			GPTP_DEFAULT_DS()->clk_id,
568 			GPTP_CLOCK_ID_LEN);
569 		state->pss_sync_ptr->sync_info.src_port_id.port_number = port;
570 
571 
572 		gptp_mi_pss_send_md_sync_send(port);
573 
574 		__fallthrough;
575 	case GPTP_PSS_SEND_SET_SYNC_RECEIPT_TIMEOUT:
576 		/* Test conditions have been slightly rearranged compared to
577 		 * their definitions in the standard in order not to test
578 		 * AsCapable and pttPortEnabled when not needed (they are
579 		 * already tested with rcvdPSSync for the reset of this state
580 		 * machine).
581 		 */
582 		if ((global_ds->selected_role[port] == GPTP_PORT_MASTER) &&
583 		    ((state->rcvd_pss_sync &&
584 		      state->half_sync_itv_timer_expired &&
585 		      state->pss_sync_ptr->local_port_number != port) ||
586 		     (state->sync_itv_timer_expired &&
587 		      (state->last_rcvd_port_num != port) &&
588 		      port_ds->as_capable && port_ds->ptt_port_enabled))) {
589 
590 			state->state = GPTP_PSS_SEND_SEND_MD_SYNC;
591 
592 		} else if ((state->state == GPTP_PSS_SEND_SEND_MD_SYNC) ||
593 			   (state->rcvd_pss_sync &&
594 			    !state->sync_itv_timer_expired &&
595 			    (global_ds->selected_role[port] ==
596 							GPTP_PORT_MASTER) &&
597 			    state->pss_sync_ptr->local_port_number != port)) {
598 
599 			/* Change state as it may have transitioned from
600 			 * SEND_MD_SYNC.
601 			 */
602 			state->state = GPTP_PSS_SEND_SET_SYNC_RECEIPT_TIMEOUT;
603 
604 			/* Stop and (re)start receipt timeout timer. */
605 			k_timer_stop(&state->send_sync_receipt_timeout_timer);
606 			state->send_sync_receipt_timeout_timer_expired = false;
607 
608 			duration =
609 				K_MSEC(port_ds->sync_receipt_timeout_time_itv /
610 				       (NSEC_PER_USEC * USEC_PER_MSEC));
611 
612 			k_timer_start(&state->send_sync_receipt_timeout_timer,
613 				      duration, K_NO_WAIT);
614 
615 		} else if (state->send_sync_receipt_timeout_timer_expired) {
616 			state->state = GPTP_PSS_SEND_SYNC_RECEIPT_TIMEOUT;
617 		}
618 
619 		break;
620 	}
621 }
622 
gptp_mi_site_ss_prepare_pss_send(void)623 static void gptp_mi_site_ss_prepare_pss_send(void)
624 {
625 	struct gptp_site_sync_sync_state *state;
626 
627 	state = &GPTP_STATE()->site_ss;
628 
629 	memcpy(&state->pss_send, state->pss_rcv_ptr,
630 	       sizeof(struct gptp_mi_port_sync_sync));
631 }
632 
gptp_mi_site_ss_send_to_pss(void)633 static void gptp_mi_site_ss_send_to_pss(void)
634 {
635 	struct gptp_site_sync_sync_state *state;
636 	struct gptp_pss_send_state *pss_send;
637 	int port;
638 
639 	state = &GPTP_STATE()->site_ss;
640 
641 	for (port = GPTP_PORT_START; port < GPTP_PORT_END; port++) {
642 		pss_send = &GPTP_PORT_STATE(port)->pss_send;
643 		pss_send->pss_sync_ptr = &state->pss_send;
644 		pss_send->rcvd_pss_sync = true;
645 	}
646 }
647 
gptp_mi_site_sync_sync_state_machine(void)648 static void gptp_mi_site_sync_sync_state_machine(void)
649 {
650 	bool gm_present;
651 	uint16_t local_port_number;
652 	struct gptp_site_sync_sync_state *state;
653 	struct gptp_clk_slave_sync_state *clk_ss;
654 
655 	state = &GPTP_STATE()->site_ss;
656 	clk_ss = &GPTP_STATE()->clk_slave_sync;
657 	gm_present = GPTP_GLOBAL_DS()->gm_present;
658 
659 	if (!state->pss_rcv_ptr) {
660 		/* We do not have connection to GM yet */
661 		return;
662 	}
663 
664 	local_port_number = state->pss_rcv_ptr->local_port_number;
665 
666 	switch (state->state) {
667 	case GPTP_SSS_INITIALIZING:
668 		state->rcvd_pss = false;
669 		state->state = GPTP_SSS_RECEIVING_SYNC;
670 		break;
671 
672 	case GPTP_SSS_RECEIVING_SYNC:
673 		if (state->rcvd_pss) {
674 			state->rcvd_pss = false;
675 			if (gptp_is_slave_port(local_port_number) &&
676 					gm_present) {
677 				gptp_mi_site_ss_prepare_pss_send();
678 
679 				/*
680 				 * Send Port Sync Sync to all
681 				 * PortSyncSyncSend State Machines.
682 				 */
683 				gptp_mi_site_ss_send_to_pss();
684 
685 				/*
686 				 * Send PortSyncSync to
687 				 * ClockSlaveSync State Machine.
688 				 */
689 				clk_ss->pss_rcv_ptr = &state->pss_send;
690 				clk_ss->rcvd_pss = true;
691 			}
692 		}
693 
694 		break;
695 	}
696 }
697 
gptp_mi_clk_slave_sync_compute(void)698 static void gptp_mi_clk_slave_sync_compute(void)
699 {
700 	struct gptp_clk_slave_sync_state *state;
701 	struct gptp_clk_master_sync_offset_state *offset_state;
702 	struct gptp_global_ds *global_ds;
703 	struct gptp_md_sync_info *pss;
704 	struct gptp_port_ds *port_ds;
705 	uint64_t sync_receipt_time;
706 
707 	state = &GPTP_STATE()->clk_slave_sync;
708 	offset_state = &GPTP_STATE()->clk_master_sync_offset;
709 	global_ds = GPTP_GLOBAL_DS();
710 	port_ds = GPTP_PORT_DS(state->pss_rcv_ptr->local_port_number);
711 
712 	pss = &state->pss_rcv_ptr->sync_info;
713 
714 	sync_receipt_time = port_ds->neighbor_prop_delay;
715 	sync_receipt_time *= pss->rate_ratio;
716 	sync_receipt_time /= port_ds->neighbor_rate_ratio;
717 	sync_receipt_time += pss->follow_up_correction_field;
718 	sync_receipt_time += port_ds->delay_asymmetry;
719 
720 	global_ds->sync_receipt_time.second = sync_receipt_time / NSEC_PER_SEC;
721 	global_ds->sync_receipt_time.fract_nsecond =
722 		(sync_receipt_time % NSEC_PER_SEC) * GPTP_POW2_16;
723 	global_ds->sync_receipt_time.second += pss->precise_orig_ts.second;
724 	global_ds->sync_receipt_time.fract_nsecond +=
725 		pss->precise_orig_ts.nanosecond * GPTP_POW2_16;
726 
727 	global_ds->sync_receipt_local_time = port_ds->delay_asymmetry;
728 	global_ds->sync_receipt_local_time /= pss->rate_ratio;
729 	global_ds->sync_receipt_local_time +=
730 		(port_ds->neighbor_prop_delay / port_ds->neighbor_rate_ratio);
731 	global_ds->sync_receipt_local_time += pss->upstream_tx_time;
732 
733 	global_ds->gm_time_base_indicator = pss->gm_time_base_indicator;
734 	global_ds->last_gm_phase_change.high = pss->last_gm_phase_change.high;
735 	global_ds->last_gm_phase_change.low = pss->last_gm_phase_change.low;
736 	global_ds->last_gm_freq_change = pss->last_gm_freq_change;
737 
738 	offset_state->rcvd_sync_receipt_time = true;
739 }
740 
741 #if defined(CONFIG_NET_GPTP_USE_DEFAULT_CLOCK_UPDATE)
gptp_update_local_port_clock(void)742 static void gptp_update_local_port_clock(void)
743 {
744 	struct gptp_clk_slave_sync_state *state;
745 	struct gptp_global_ds *global_ds;
746 	struct gptp_port_ds *port_ds;
747 	int port;
748 	int64_t nanosecond_diff;
749 	int64_t second_diff;
750 	const struct device *clk;
751 	struct net_ptp_time tm;
752 	unsigned int key;
753 
754 	state = &GPTP_STATE()->clk_slave_sync;
755 	global_ds = GPTP_GLOBAL_DS();
756 	port = state->pss_rcv_ptr->local_port_number;
757 	NET_ASSERT((port >= GPTP_PORT_START) && (port <= GPTP_PORT_END));
758 
759 	port_ds = GPTP_PORT_DS(port);
760 
761 	/* Check if the last neighbor rate ratio can still be used */
762 	if (!port_ds->neighbor_rate_ratio_valid) {
763 		return;
764 	}
765 
766 	port_ds->neighbor_rate_ratio_valid = false;
767 
768 	second_diff = global_ds->sync_receipt_time.second -
769 		(global_ds->sync_receipt_local_time / NSEC_PER_SEC);
770 	nanosecond_diff =
771 		(global_ds->sync_receipt_time.fract_nsecond / GPTP_POW2_16) -
772 		(global_ds->sync_receipt_local_time % NSEC_PER_SEC);
773 
774 	clk = net_eth_get_ptp_clock(GPTP_PORT_IFACE(port));
775 	if (!clk) {
776 		return;
777 	}
778 
779 	if (second_diff > 0 && nanosecond_diff < 0) {
780 		second_diff--;
781 		nanosecond_diff = NSEC_PER_SEC + nanosecond_diff;
782 	}
783 
784 	if (second_diff < 0 && nanosecond_diff > 0) {
785 		second_diff++;
786 		nanosecond_diff = -(int64_t)NSEC_PER_SEC + nanosecond_diff;
787 	}
788 
789 	ptp_clock_rate_adjust(clk, port_ds->neighbor_rate_ratio);
790 
791 	/* If time difference is too high, set the clock value.
792 	 * Otherwise, adjust it.
793 	 */
794 	if (second_diff || (second_diff == 0 &&
795 			    (nanosecond_diff < -5000 ||
796 			     nanosecond_diff > 5000))) {
797 		bool underflow = false;
798 
799 		key = irq_lock();
800 		ptp_clock_get(clk, &tm);
801 
802 		if (second_diff < 0 && tm.second < -second_diff) {
803 			NET_DBG("Do not set local clock because %lu < %ld",
804 				(unsigned long int)tm.second,
805 				(long int)-second_diff);
806 			goto skip_clock_set;
807 		}
808 
809 		tm.second += second_diff;
810 
811 		if (nanosecond_diff < 0 &&
812 		    tm.nanosecond < -nanosecond_diff) {
813 			underflow = true;
814 		}
815 
816 		tm.nanosecond += nanosecond_diff;
817 
818 		if (underflow) {
819 			tm.second--;
820 			tm.nanosecond += NSEC_PER_SEC;
821 		} else if (tm.nanosecond >= NSEC_PER_SEC) {
822 			tm.second++;
823 			tm.nanosecond -= NSEC_PER_SEC;
824 		}
825 
826 		/* This prints too much data normally but can be enabled to see
827 		 * what time we are setting to the local clock.
828 		 */
829 		if (0) {
830 			NET_INFO("Set local clock %lu.%lu",
831 				 (unsigned long int)tm.second,
832 				 (unsigned long int)tm.nanosecond);
833 		}
834 
835 		ptp_clock_set(clk, &tm);
836 
837 	skip_clock_set:
838 		irq_unlock(key);
839 	} else {
840 		if (nanosecond_diff < -200) {
841 			nanosecond_diff = -200;
842 		} else if (nanosecond_diff > 200) {
843 			nanosecond_diff = 200;
844 		}
845 
846 		ptp_clock_adjust(clk, nanosecond_diff);
847 	}
848 }
849 #endif /* CONFIG_NET_GPTP_USE_DEFAULT_CLOCK_UPDATE */
850 
gptp_mi_clk_slave_sync_state_machine(void)851 static void gptp_mi_clk_slave_sync_state_machine(void)
852 {
853 	struct gptp_clk_slave_sync_state *state;
854 
855 	state = &GPTP_STATE()->clk_slave_sync;
856 
857 	switch (state->state) {
858 	case GPTP_CLK_SLAVE_SYNC_INITIALIZING:
859 		state->rcvd_pss = false;
860 		state->state = GPTP_CLK_SLAVE_SYNC_SEND_SYNC_IND;
861 		break;
862 
863 	case GPTP_CLK_SLAVE_SYNC_SEND_SYNC_IND:
864 		if (state->rcvd_pss) {
865 			state->rcvd_pss = false;
866 			gptp_mi_clk_slave_sync_compute();
867 
868 #if defined(CONFIG_NET_GPTP_USE_DEFAULT_CLOCK_UPDATE)
869 			/* Instead of updating SlaveClock, update LocalClock */
870 			gptp_update_local_port_clock();
871 #endif
872 			gptp_call_phase_dis_cb();
873 		}
874 
875 		break;
876 	}
877 }
878 
gptp_mi_clk_master_sync_offset_state_machine(void)879 static void gptp_mi_clk_master_sync_offset_state_machine(void)
880 {
881 	struct gptp_clk_master_sync_offset_state *state;
882 	struct gptp_global_ds *global_ds;
883 
884 	state = &GPTP_STATE()->clk_master_sync_offset;
885 	global_ds = GPTP_GLOBAL_DS();
886 
887 	switch (state->state) {
888 	case GPTP_CMS_OFFSET_INITIALIZING:
889 		state->rcvd_sync_receipt_time = false;
890 		state->state = GPTP_CMS_OFFSET_INDICATION;
891 		break;
892 	case GPTP_CMS_OFFSET_INDICATION:
893 		if (!state->rcvd_sync_receipt_time) {
894 			break;
895 		}
896 
897 		state->rcvd_sync_receipt_time = false;
898 
899 		if (global_ds->selected_role[0] == GPTP_PORT_PASSIVE) {
900 			/* TODO Calculate real values for proper BC support */
901 			memset(&global_ds->clk_src_phase_offset, 0x0,
902 			       sizeof(struct gptp_scaled_ns));
903 			global_ds->clk_src_freq_offset = 0;
904 		} else if (global_ds->clk_src_time_base_indicator_prev
905 			   != global_ds->clk_src_time_base_indicator) {
906 			memcpy(&global_ds->clk_src_phase_offset,
907 			       &global_ds->last_gm_phase_change,
908 			       sizeof(struct gptp_scaled_ns));
909 
910 			global_ds->clk_src_freq_offset =
911 				global_ds->last_gm_freq_change;
912 		}
913 
914 		break;
915 	default:
916 		NET_ERR("Unrecognised state %d", state->state);
917 		break;
918 	}
919 }
920 
921 #if defined(CONFIG_NET_GPTP_GM_CAPABLE)
gptp_mi_setup_sync_send_time(void)922 static inline void gptp_mi_setup_sync_send_time(void)
923 {
924 	struct gptp_clk_master_sync_snd_state *state;
925 	struct gptp_global_ds *global_ds;
926 	uint64_t time_helper;
927 
928 	state = &GPTP_STATE()->clk_master_sync_send;
929 	global_ds = GPTP_GLOBAL_DS();
930 
931 	time_helper = state->sync_send_time.low;
932 
933 	state->sync_send_time.low +=
934 		global_ds->clk_master_sync_itv;
935 
936 	/* Check for overflow */
937 	if (state->sync_send_time.low < time_helper) {
938 		state->sync_send_time.high += 1U;
939 		state->sync_send_time.low =
940 			UINT64_MAX - state->sync_send_time.low;
941 	}
942 }
943 
gptp_mi_set_ps_sync_cmss(void)944 static void gptp_mi_set_ps_sync_cmss(void)
945 {
946 	struct gptp_clk_master_sync_snd_state *state;
947 	struct gptp_global_ds *global_ds;
948 	struct gptp_md_sync_info *sync_info;
949 	uint64_t current_time;
950 
951 	global_ds = GPTP_GLOBAL_DS();
952 	state = &GPTP_STATE()->clk_master_sync_send;
953 
954 	sync_info = &state->pss_snd.sync_info;
955 
956 	state->pss_snd.local_port_number = 0U;
957 
958 	current_time = gptp_get_current_master_time_nanosecond();
959 
960 	sync_info->precise_orig_ts.second = current_time / NSEC_PER_SEC;
961 	sync_info->precise_orig_ts.nanosecond = current_time % NSEC_PER_SEC;
962 
963 	/* TODO calculate correction field properly, rate_ratio is also set to
964 	 * zero instead of being copied from global_ds as it affects the final
965 	 * value of FUP correction field.
966 	 */
967 	sync_info->follow_up_correction_field = 0;
968 	sync_info->rate_ratio = 0;
969 
970 	memcpy(&sync_info->src_port_id.clk_id,
971 	       GPTP_DEFAULT_DS()->clk_id,
972 	       GPTP_CLOCK_ID_LEN);
973 
974 	sync_info->src_port_id.port_number = 0U;
975 	sync_info->log_msg_interval = CONFIG_NET_GPTP_INIT_LOG_SYNC_ITV;
976 	sync_info->upstream_tx_time = global_ds->local_time.low;
977 
978 	state->pss_snd.sync_receipt_timeout_time = UINT64_MAX;
979 
980 	sync_info->gm_time_base_indicator =
981 		global_ds->clk_src_time_base_indicator;
982 
983 	memcpy(&sync_info->last_gm_phase_change,
984 	       &global_ds->clk_src_phase_offset,
985 	       sizeof(struct gptp_scaled_ns));
986 
987 	sync_info->last_gm_freq_change = global_ds->clk_src_freq_offset;
988 }
989 
gptp_mi_tx_ps_sync_cmss(void)990 static inline void gptp_mi_tx_ps_sync_cmss(void)
991 {
992 	struct gptp_clk_master_sync_snd_state *state;
993 	struct gptp_pss_send_state *pss_send;
994 	int port;
995 
996 	state = &GPTP_STATE()->clk_master_sync_send;
997 
998 	for (port = GPTP_PORT_START; port < GPTP_PORT_END; port++) {
999 		pss_send = &GPTP_PORT_STATE(port)->pss_send;
1000 		pss_send->pss_sync_ptr = &state->pss_snd;
1001 
1002 		pss_send->rcvd_pss_sync = true;
1003 	}
1004 }
1005 
gptp_mi_clk_master_sync_snd_state_machine(void)1006 static void gptp_mi_clk_master_sync_snd_state_machine(void)
1007 {
1008 	struct gptp_clk_master_sync_snd_state *state;
1009 	uint64_t current_time;
1010 
1011 	state = &GPTP_STATE()->clk_master_sync_send;
1012 
1013 	switch (state->state) {
1014 	case GPTP_CMS_SND_INITIALIZING:
1015 		gptp_mi_setup_sync_send_time();
1016 
1017 		state->state = GPTP_CMS_SND_INDICATION;
1018 		break;
1019 
1020 	case GPTP_CMS_SND_INDICATION:
1021 		current_time = gptp_get_current_master_time_nanosecond();
1022 
1023 		if (current_time >= state->sync_send_time.low) {
1024 			gptp_mi_set_ps_sync_cmss();
1025 			gptp_mi_tx_ps_sync_cmss();
1026 
1027 			gptp_mi_setup_sync_send_time();
1028 		}
1029 
1030 		break;
1031 
1032 	default:
1033 		NET_ERR("Unrecognised state %d", state->state);
1034 		break;
1035 	}
1036 }
1037 #endif
1038 
gptp_compute_gm_rate_ratio(void)1039 static void gptp_compute_gm_rate_ratio(void)
1040 {
1041 	static struct net_ptp_extended_time src_time_0;
1042 	static struct gptp_uscaled_ns local_time_0;
1043 	struct net_ptp_extended_time src_time_n;
1044 	struct gptp_uscaled_ns local_time_n;
1045 	struct net_ptp_extended_time src_time_t;
1046 	struct gptp_uscaled_ns local_time_t;
1047 	struct gptp_clk_master_sync_rcv_state *state;
1048 	struct gptp_global_ds *global_ds;
1049 	double new_gm_rate;
1050 
1051 	state = &GPTP_STATE()->clk_master_sync_receive;
1052 	global_ds = GPTP_GLOBAL_DS();
1053 
1054 	/* Get current local and source time */
1055 	memcpy(&src_time_n, &state->rcvd_clk_src_req.src_time,
1056 	       sizeof(struct net_ptp_extended_time));
1057 
1058 	memcpy(&local_time_n, &global_ds->local_time,
1059 	       sizeof(struct gptp_uscaled_ns));
1060 
1061 	if ((src_time_0.second == 0U && src_time_0.fract_nsecond == 0U)
1062 	    || (local_time_0.high == 0U && local_time_0.low == 0U)) {
1063 		memcpy(&src_time_0, &src_time_n,
1064 		       sizeof(struct net_ptp_extended_time));
1065 
1066 		memcpy(&local_time_0, &local_time_n,
1067 		       sizeof(struct gptp_uscaled_ns));
1068 
1069 		global_ds->gm_rate_ratio = 1.0;
1070 
1071 		return;
1072 	}
1073 
1074 	/* Take care of the sign of the result */
1075 	new_gm_rate = 1.0;
1076 
1077 	if ((src_time_n.second < src_time_0.second)
1078 	    || (src_time_n.second == src_time_0.second
1079 		&& src_time_n.fract_nsecond < src_time_0.fract_nsecond)) {
1080 		/* Change result sign and swap src_time_n and src_time_0 */
1081 		memcpy(&src_time_t, &src_time_n,
1082 		       sizeof(struct net_ptp_extended_time));
1083 		memcpy(&src_time_n, &src_time_0,
1084 		       sizeof(struct net_ptp_extended_time));
1085 		memcpy(&src_time_0, &src_time_t,
1086 		       sizeof(struct net_ptp_extended_time));
1087 
1088 		new_gm_rate *= -1;
1089 	}
1090 
1091 	if ((local_time_n.high < local_time_0.high)
1092 	    || (local_time_n.high == local_time_0.high
1093 		&& local_time_n.low < local_time_0.low)) {
1094 		/* Change result sign and swap local_time_n and local_time_0 */
1095 		memcpy(&local_time_t, &local_time_n,
1096 		       sizeof(struct gptp_uscaled_ns));
1097 		memcpy(&local_time_n, &local_time_0,
1098 		       sizeof(struct gptp_uscaled_ns));
1099 		memcpy(&local_time_0, &local_time_t,
1100 		       sizeof(struct gptp_uscaled_ns));
1101 
1102 		new_gm_rate *= -1;
1103 	}
1104 
1105 	/* At this point src_time_n >= src_time_0 */
1106 	src_time_n.second -= src_time_0.second;
1107 
1108 	if (src_time_n.fract_nsecond >= src_time_0.fract_nsecond) {
1109 		src_time_n.fract_nsecond -= src_time_0.fract_nsecond;
1110 	} else {
1111 		src_time_n.second -= 1U;
1112 		src_time_n.fract_nsecond = (NSEC_PER_SEC * GPTP_POW2_16)
1113 			- src_time_0.fract_nsecond;
1114 	}
1115 
1116 	/* At this point local_time_n >= local_time_0 */
1117 	local_time_n.high -= local_time_0.high;
1118 
1119 	if (local_time_n.low >= local_time_0.low) {
1120 		local_time_n.low -= local_time_0.low;
1121 	} else {
1122 		local_time_n.high -= 1U;
1123 		local_time_n.low = UINT64_MAX - local_time_0.low;
1124 	}
1125 
1126 	/* Calculate it in nanoseconds, new_gm_rate is either 1 or -1 here */
1127 	new_gm_rate *= ((src_time_n.second * NSEC_PER_SEC)
1128 		+ (src_time_n.fract_nsecond / GPTP_POW2_16));
1129 
1130 	new_gm_rate /= local_time_n.low;
1131 
1132 	global_ds->gm_rate_ratio = new_gm_rate;
1133 }
1134 
gptp_mi_clk_master_sync_rcv_state_machine(void)1135 static void gptp_mi_clk_master_sync_rcv_state_machine(void)
1136 {
1137 	struct gptp_clk_master_sync_rcv_state *s;
1138 	struct gptp_global_ds *global_ds;
1139 
1140 #ifdef CONFIG_NET_GPTP_PROBE_CLOCK_SOURCE_ON_DEMAND
1141 	struct gptp_clk_src_time_invoke_params invoke_args = {};
1142 	uint64_t cur = gptp_get_current_master_time_nanosecond();
1143 
1144 	invoke_args.src_time.second = cur / NSEC_PER_SEC;
1145 	cur -= (invoke_args.src_time.second * NSEC_PER_SEC);
1146 
1147 	invoke_args.src_time.fract_nsecond = cur * GPTP_POW2_16;
1148 
1149 	memset(&invoke_args.last_gm_phase_change, 0x0,
1150 	       sizeof(struct gptp_scaled_ns));
1151 	invoke_args.last_gm_freq_change = 0;
1152 
1153 	gptp_clk_src_time_invoke(&invoke_args);
1154 #endif
1155 
1156 	global_ds = GPTP_GLOBAL_DS();
1157 
1158 	s = &GPTP_STATE()->clk_master_sync_receive;
1159 	switch (s->state) {
1160 	case GPTP_CMS_RCV_INITIALIZING:
1161 		s->state = GPTP_CMS_RCV_WAITING;
1162 		break;
1163 
1164 	case GPTP_CMS_RCV_WAITING:
1165 		if (s->rcvd_clock_source_req || s->rcvd_local_clock_tick) {
1166 			s->state = GPTP_CMS_RCV_SOURCE_TIME;
1167 		}
1168 
1169 		break;
1170 
1171 	case GPTP_CMS_RCV_SOURCE_TIME:
1172 		global_ds->local_time.high = 0U;
1173 		global_ds->local_time.low =
1174 			gptp_get_current_master_time_nanosecond();
1175 
1176 		if (s->rcvd_clock_source_req) {
1177 			gptp_compute_gm_rate_ratio();
1178 
1179 			global_ds->clk_src_time_base_indicator_prev =
1180 				global_ds->clk_src_time_base_indicator;
1181 
1182 			global_ds->clk_src_time_base_indicator =
1183 				s->rcvd_clk_src_req.time_base_indicator;
1184 
1185 			memcpy(&global_ds->clk_src_last_gm_phase_change,
1186 			       &s->rcvd_clk_src_req.last_gm_phase_change,
1187 			       sizeof(struct gptp_scaled_ns));
1188 
1189 			global_ds->clk_src_last_gm_freq_change =
1190 				s->rcvd_clk_src_req.last_gm_freq_change;
1191 		}
1192 
1193 		s->rcvd_clock_source_req = false;
1194 		s->rcvd_local_clock_tick = false;
1195 		s->state = GPTP_CMS_RCV_WAITING;
1196 		break;
1197 
1198 	default:
1199 		NET_ERR("Unrecognised state %d", s->state);
1200 		break;
1201 	}
1202 }
1203 
copy_path_trace(struct gptp_announce * announce)1204 static void copy_path_trace(struct gptp_announce *announce)
1205 {
1206 	int len = ntohs(announce->tlv.len);
1207 	struct gptp_path_trace *sys_path_trace;
1208 
1209 	if (len > GPTP_MAX_PATHTRACE_SIZE) {
1210 		NET_ERR("Too long path trace (%d vs %d)",
1211 			GPTP_MAX_PATHTRACE_SIZE, len);
1212 		return;
1213 	}
1214 
1215 	sys_path_trace = &GPTP_GLOBAL_DS()->path_trace;
1216 
1217 	sys_path_trace->len = htons(len + GPTP_CLOCK_ID_LEN);
1218 
1219 	memcpy(sys_path_trace->path_sequence, announce->tlv.path_sequence,
1220 	       len);
1221 
1222 	/* Append local clockIdentity. */
1223 	memcpy((uint8_t *)sys_path_trace->path_sequence + len,
1224 	       GPTP_DEFAULT_DS()->clk_id, GPTP_CLOCK_ID_LEN);
1225 }
1226 
gptp_mi_qualify_announce(int port,struct net_pkt * announce_msg)1227 static bool gptp_mi_qualify_announce(int port, struct net_pkt *announce_msg)
1228 {
1229 	struct gptp_announce *announce;
1230 	struct gptp_hdr *hdr;
1231 	int i;
1232 	uint16_t len;
1233 
1234 	hdr = GPTP_HDR(announce_msg);
1235 	announce = GPTP_ANNOUNCE(announce_msg);
1236 
1237 	if (memcmp(hdr->port_id.clk_id, GPTP_DEFAULT_DS()->clk_id,
1238 		   GPTP_CLOCK_ID_LEN) == 0) {
1239 		return false;
1240 	}
1241 
1242 	len = ntohs(announce->steps_removed);
1243 	if (len >= 255U) {
1244 		return false;
1245 	}
1246 
1247 	for (i = 0; i < len + 1; i++) {
1248 		if (memcmp(announce->tlv.path_sequence[i],
1249 			   GPTP_DEFAULT_DS()->clk_id,
1250 			   GPTP_CLOCK_ID_LEN) == 0) {
1251 			return false;
1252 		}
1253 	}
1254 
1255 	if (GPTP_GLOBAL_DS()->selected_role[port] == GPTP_PORT_SLAVE) {
1256 		copy_path_trace(announce);
1257 	}
1258 
1259 	return true;
1260 }
1261 
gptp_mi_port_announce_receive_state_machine(int port)1262 static void gptp_mi_port_announce_receive_state_machine(int port)
1263 {
1264 	struct gptp_port_ds *port_ds;
1265 	struct gptp_port_announce_receive_state *state;
1266 	struct gptp_port_bmca_data *bmca_data;
1267 
1268 	state = &GPTP_PORT_STATE(port)->pa_rcv;
1269 	port_ds = GPTP_PORT_DS(port);
1270 	bmca_data = GPTP_PORT_BMCA_DATA(port);
1271 
1272 	if ((!port_ds->ptt_port_enabled) || (!port_ds->as_capable)) {
1273 		state->state = GPTP_PA_RCV_DISCARD;
1274 	}
1275 
1276 	switch (state->state) {
1277 	case GPTP_PA_RCV_DISCARD:
1278 		state->rcvd_announce = false;
1279 		bmca_data->rcvd_msg = false;
1280 		if (bmca_data->rcvd_announce_ptr != NULL) {
1281 			net_pkt_unref(bmca_data->rcvd_announce_ptr);
1282 			bmca_data->rcvd_announce_ptr = NULL;
1283 		}
1284 
1285 		state->state = GPTP_PA_RCV_RECEIVE;
1286 		break;
1287 
1288 	case GPTP_PA_RCV_RECEIVE:
1289 		/* "portEnabled" is not checked: the interface is always up. */
1290 		if (state->rcvd_announce &&
1291 		    port_ds->ptt_port_enabled &&
1292 		    port_ds->as_capable	&&
1293 		    !bmca_data->rcvd_msg) {
1294 			state->rcvd_announce = false;
1295 
1296 			bmca_data->rcvd_msg = gptp_mi_qualify_announce(
1297 				port, bmca_data->rcvd_announce_ptr);
1298 			if (!bmca_data->rcvd_msg) {
1299 				net_pkt_unref(bmca_data->rcvd_announce_ptr);
1300 				bmca_data->rcvd_announce_ptr = NULL;
1301 			}
1302 		}
1303 
1304 		break;
1305 	}
1306 }
1307 
1308 /*
1309  * Compare a vector to an announce message vector.
1310  * All must be in big endian (network) order.
1311  */
compare_priority_vectors(struct gptp_priority_vector * vector,struct net_pkt * pkt,int port)1312 static enum gptp_received_info compare_priority_vectors(
1313 		struct gptp_priority_vector *vector,
1314 		struct net_pkt *pkt, int port)
1315 {
1316 	struct gptp_hdr *hdr;
1317 	struct gptp_announce *announce;
1318 	int rsi_cmp, spi_cmp, port_cmp;
1319 
1320 	hdr = GPTP_HDR(pkt);
1321 	announce = GPTP_ANNOUNCE(pkt);
1322 
1323 	/* Compare rootSystemIdentity and stepsRemoved. */
1324 	rsi_cmp = memcmp(&announce->root_system_id,
1325 			 &vector->root_system_id,
1326 			 sizeof(struct gptp_root_system_identity) +
1327 			 sizeof(uint16_t));
1328 	if (rsi_cmp < 0) {
1329 		/* Better rootSystemIdentity. */
1330 		return GPTP_RCVD_INFO_SUPERIOR_MASTER_INFO;
1331 	}
1332 
1333 	/* Compare sourcePortIdentity. */
1334 	spi_cmp = memcmp(&hdr->port_id, &vector->src_port_id,
1335 			 sizeof(struct gptp_port_identity));
1336 
1337 	port_cmp = (int)port - ntohs(vector->port_number);
1338 
1339 	if (spi_cmp == 0) {
1340 		if (rsi_cmp == 0) {
1341 			if (port_cmp == 0) {
1342 				/* Same priority vector. */
1343 				return GPTP_RCVD_INFO_REPEATED_MASTER_INFO;
1344 			} else if (port_cmp < 0) {
1345 				/* Priority vector with better reception port
1346 				 * number.
1347 				 */
1348 				return GPTP_RCVD_INFO_SUPERIOR_MASTER_INFO;
1349 			}
1350 		} else {
1351 			/* Same master port but different Grand Master. */
1352 			return GPTP_RCVD_INFO_SUPERIOR_MASTER_INFO;
1353 		}
1354 	} else if ((spi_cmp < 0) && (rsi_cmp == 0)) {
1355 		/* Same Grand Master but better masterPort. */
1356 		return GPTP_RCVD_INFO_SUPERIOR_MASTER_INFO;
1357 	}
1358 
1359 	return GPTP_RCVD_INFO_INFERIOR_MASTER_INFO;
1360 }
1361 
rcv_info(int port)1362 static enum gptp_received_info rcv_info(int port)
1363 {
1364 	/* TODO
1365 	 * How can we define that a message does not convey the port
1366 	 * role Master port ?
1367 	 * It is needed to define that to be able to send
1368 	 * GPTP_RCVD_INFO_OTHER_INFO.
1369 	 */
1370 	struct gptp_port_bmca_data *bmca_data;
1371 	struct gptp_announce *announce;
1372 
1373 	bmca_data = GPTP_PORT_BMCA_DATA(port);
1374 	announce = GPTP_ANNOUNCE(bmca_data->rcvd_announce_ptr);
1375 
1376 	bmca_data->message_steps_removed = announce->steps_removed;
1377 
1378 	return compare_priority_vectors(&bmca_data->port_priority,
1379 					bmca_data->rcvd_announce_ptr,
1380 					port);
1381 }
1382 
record_other_announce_info(int port)1383 static void record_other_announce_info(int port)
1384 {
1385 	struct gptp_hdr *hdr;
1386 	struct gptp_announce *announce;
1387 	struct gptp_port_bmca_data *bmca_data;
1388 
1389 	bmca_data = GPTP_PORT_BMCA_DATA(port);
1390 	hdr = GPTP_HDR(bmca_data->rcvd_announce_ptr);
1391 	announce = GPTP_ANNOUNCE(bmca_data->rcvd_announce_ptr);
1392 
1393 	/* Copy leap61, leap59, current UTC offset valid, time traceable and
1394 	 * frequency traceable flags.
1395 	 */
1396 	bmca_data->ann_flags.octets[1] = hdr->flags.octets[1];
1397 
1398 	bmca_data->ann_current_utc_offset = ntohs(announce->cur_utc_offset);
1399 	bmca_data->ann_time_source = announce->time_source;
1400 }
1401 
copy_priority_vector(struct gptp_priority_vector * vector,struct net_pkt * pkt,int port)1402 static void copy_priority_vector(struct gptp_priority_vector *vector,
1403 				 struct net_pkt *pkt, int port)
1404 {
1405 	struct gptp_hdr *hdr;
1406 	struct gptp_announce *announce;
1407 
1408 	hdr = GPTP_HDR(pkt);
1409 	announce = GPTP_ANNOUNCE(pkt);
1410 
1411 	memcpy(&vector->root_system_id, &announce->root_system_id,
1412 	       sizeof(struct gptp_root_system_identity) + sizeof(uint16_t));
1413 
1414 	memcpy(&vector->src_port_id, &hdr->port_id,
1415 	       sizeof(struct gptp_port_identity));
1416 
1417 	vector->port_number = htons(port);
1418 }
1419 
gptp_mi_port_announce_information_state_machine(int port)1420 static void gptp_mi_port_announce_information_state_machine(int port)
1421 {
1422 	struct gptp_port_ds *port_ds;
1423 	struct gptp_global_ds *global_ds;
1424 	struct gptp_port_announce_information_state *state;
1425 	struct gptp_announce *announce;
1426 	struct gptp_hdr *hdr;
1427 	struct gptp_port_bmca_data *bmca_data;
1428 	struct gptp_pss_rcv_state *pss_rcv;
1429 
1430 	bmca_data = GPTP_PORT_BMCA_DATA(port);
1431 	state = &GPTP_PORT_STATE(port)->pa_info;
1432 	port_ds = GPTP_PORT_DS(port);
1433 	global_ds = GPTP_GLOBAL_DS();
1434 
1435 	if ((!port_ds->ptt_port_enabled || !port_ds->as_capable) &&
1436 	    (bmca_data->info_is != GPTP_INFO_IS_DISABLED)) {
1437 		gptp_change_pa_info_state(port, state, GPTP_PA_INFO_DISABLED);
1438 	}
1439 
1440 	switch (state->state) {
1441 	case GPTP_PA_INFO_DISABLED:
1442 		bmca_data->rcvd_msg = false;
1443 		bmca_data->info_is = GPTP_INFO_IS_DISABLED;
1444 		SET_RESELECT(global_ds, port);
1445 		CLEAR_SELECTED(global_ds, port);
1446 		gptp_change_pa_info_state(port, state,
1447 					  GPTP_PA_INFO_POST_DISABLED);
1448 		k_timer_stop(&state->ann_rcpt_expiry_timer);
1449 		state->ann_expired = true;
1450 		__fallthrough;
1451 
1452 	case GPTP_PA_INFO_POST_DISABLED:
1453 		if (port_ds->ptt_port_enabled && port_ds->as_capable) {
1454 			gptp_change_pa_info_state(port, state,
1455 						  GPTP_PA_INFO_AGED);
1456 		} else if (bmca_data->rcvd_msg) {
1457 			gptp_change_pa_info_state(port, state,
1458 						  GPTP_PA_INFO_DISABLED);
1459 		}
1460 
1461 		break;
1462 
1463 	case GPTP_PA_INFO_AGED:
1464 		bmca_data->info_is = GPTP_INFO_IS_AGED;
1465 		CLEAR_SELECTED(global_ds, port);
1466 		SET_RESELECT(global_ds, port);
1467 		/* Transition will be actually tested in UPDATE state. */
1468 		gptp_change_pa_info_state(port, state, GPTP_PA_INFO_UPDATE);
1469 		break;
1470 
1471 	case GPTP_PA_INFO_UPDATE:
1472 		if (IS_SELECTED(global_ds, port) && bmca_data->updt_info) {
1473 			memcpy(&bmca_data->port_priority,
1474 			       &bmca_data->master_priority,
1475 			       sizeof(struct gptp_priority_vector));
1476 
1477 			bmca_data->port_steps_removed =
1478 				global_ds->master_steps_removed;
1479 			bmca_data->updt_info = false;
1480 			bmca_data->info_is = GPTP_INFO_IS_MINE;
1481 			bmca_data->new_info = true;
1482 			gptp_change_pa_info_state(port, state,
1483 						  GPTP_PA_INFO_CURRENT);
1484 		}
1485 
1486 		break;
1487 
1488 	case GPTP_PA_INFO_CURRENT:
1489 		pss_rcv = &GPTP_PORT_STATE(port)->pss_rcv;
1490 		if (IS_SELECTED(global_ds, port) && bmca_data->updt_info) {
1491 			gptp_change_pa_info_state(port, state,
1492 						  GPTP_PA_INFO_UPDATE);
1493 		} else if (bmca_data->rcvd_msg && !bmca_data->updt_info) {
1494 			gptp_change_pa_info_state(port, state,
1495 						  GPTP_PA_INFO_RECEIVE);
1496 		} else if ((bmca_data->info_is == GPTP_INFO_IS_RECEIVED) &&
1497 			   !bmca_data->updt_info &&
1498 			   !bmca_data->rcvd_msg &&
1499 			   (state->ann_expired ||
1500 			    (global_ds->gm_present &&
1501 			   pss_rcv->rcv_sync_receipt_timeout_timer_expired))) {
1502 			gptp_change_pa_info_state(port, state,
1503 						  GPTP_PA_INFO_AGED);
1504 		}
1505 
1506 		break;
1507 
1508 	case GPTP_PA_INFO_RECEIVE:
1509 		switch (rcv_info(port)) {
1510 		case GPTP_RCVD_INFO_SUPERIOR_MASTER_INFO:
1511 			gptp_change_pa_info_state(port, state,
1512 				GPTP_PA_INFO_SUPERIOR_MASTER_PORT);
1513 			break;
1514 		case GPTP_RCVD_INFO_REPEATED_MASTER_INFO:
1515 			gptp_change_pa_info_state(port, state,
1516 				GPTP_PA_INFO_REPEATED_MASTER_PORT);
1517 			break;
1518 		case GPTP_RCVD_INFO_INFERIOR_MASTER_INFO:
1519 			__fallthrough;
1520 		case GPTP_RCVD_INFO_OTHER_INFO:
1521 			gptp_change_pa_info_state(port, state,
1522 				GPTP_PA_INFO_INFERIOR_MASTER_OR_OTHER_PORT);
1523 			break;
1524 		}
1525 
1526 		break;
1527 
1528 	case GPTP_PA_INFO_SUPERIOR_MASTER_PORT:
1529 		/* We copy directly the content of the message to the port
1530 		 * priority vector without using an intermediate
1531 		 * messagePriority structure.
1532 		 */
1533 
1534 		if (!bmca_data->rcvd_announce_ptr) {
1535 			/* Shouldn't be reached. Checked for safety reason. */
1536 			bmca_data->rcvd_msg = false;
1537 			gptp_change_pa_info_state(port, state,
1538 						  GPTP_PA_INFO_CURRENT);
1539 			break;
1540 		}
1541 
1542 		copy_priority_vector(&bmca_data->port_priority,
1543 				     bmca_data->rcvd_announce_ptr, port);
1544 
1545 		announce = GPTP_ANNOUNCE(bmca_data->rcvd_announce_ptr);
1546 		bmca_data->port_steps_removed = ntohs(announce->steps_removed);
1547 		record_other_announce_info(port);
1548 		hdr = GPTP_HDR(bmca_data->rcvd_announce_ptr);
1549 		gptp_set_time_itv(&bmca_data->ann_rcpt_timeout_time_interval,
1550 				  port_ds->announce_receipt_timeout,
1551 				  hdr->log_msg_interval);
1552 		bmca_data->info_is = GPTP_INFO_IS_RECEIVED;
1553 		CLEAR_SELECTED(global_ds, port);
1554 		SET_RESELECT(global_ds, port);
1555 		__fallthrough;
1556 
1557 	case GPTP_PA_INFO_REPEATED_MASTER_PORT:
1558 		k_timer_stop(&state->ann_rcpt_expiry_timer);
1559 		state->ann_expired = false;
1560 		k_timer_start(&state->ann_rcpt_expiry_timer,
1561 			      K_MSEC(gptp_uscaled_ns_to_timer_ms(
1562 				  &bmca_data->ann_rcpt_timeout_time_interval)),
1563 			      K_NO_WAIT);
1564 		__fallthrough;
1565 
1566 	case GPTP_PA_INFO_INFERIOR_MASTER_OR_OTHER_PORT:
1567 		if (bmca_data->rcvd_announce_ptr != NULL) {
1568 			net_pkt_unref(bmca_data->rcvd_announce_ptr);
1569 			bmca_data->rcvd_announce_ptr = NULL;
1570 		}
1571 
1572 		bmca_data->rcvd_msg = false;
1573 		gptp_change_pa_info_state(port, state, GPTP_PA_INFO_CURRENT);
1574 		break;
1575 	}
1576 }
1577 
gptp_updt_role_disabled_tree(void)1578 static void gptp_updt_role_disabled_tree(void)
1579 {
1580 	struct gptp_global_ds *global_ds;
1581 	int port;
1582 
1583 	global_ds = GPTP_GLOBAL_DS();
1584 
1585 	/* Set all elements of the selectedRole array to DisabledPort. */
1586 	for (port = GPTP_PORT_START; port < GPTP_PORT_END; port++) {
1587 		gptp_change_port_state(port, GPTP_PORT_DISABLED);
1588 	}
1589 
1590 	/* Set lastGmPriority to all ones. */
1591 	(void)memset(&global_ds->last_gm_priority, 0xFF,
1592 		     sizeof(struct gptp_priority_vector));
1593 
1594 	/* Set pathTrace array to contain the single element thisClock. */
1595 	global_ds->path_trace.len = htons(GPTP_CLOCK_ID_LEN);
1596 	memcpy(global_ds->path_trace.path_sequence, GPTP_DEFAULT_DS()->clk_id,
1597 	       GPTP_CLOCK_ID_LEN);
1598 }
1599 
gptp_clear_reselect_tree(void)1600 static void gptp_clear_reselect_tree(void)
1601 {
1602 	/* Set all the elements of the reselect array to FALSE. */
1603 	GPTP_GLOBAL_DS()->reselect_array = 0;
1604 }
1605 
compute_best_vector(void)1606 static int compute_best_vector(void)
1607 {
1608 	struct gptp_priority_vector *gm_prio;
1609 	struct gptp_default_ds *default_ds;
1610 	struct gptp_global_ds *global_ds;
1611 	struct gptp_priority_vector *best_vector, *challenger;
1612 	int best_port, port, tmp;
1613 	struct gptp_pss_rcv_state *pss_rcv;
1614 	struct gptp_port_announce_information_state *pa_info_state;
1615 
1616 	default_ds = GPTP_DEFAULT_DS();
1617 	global_ds = GPTP_GLOBAL_DS();
1618 	best_port = 0;
1619 	gm_prio = &global_ds->gm_priority;
1620 
1621 	/* Write systemPriority into grandmaster. */
1622 	(void)memset(gm_prio, 0, sizeof(struct gptp_priority_vector));
1623 	gm_prio->root_system_id.grand_master_prio1 = default_ds->priority1;
1624 	gm_prio->root_system_id.grand_master_prio2 = default_ds->priority2;
1625 	gm_prio->root_system_id.clk_quality.clock_class =
1626 		default_ds->clk_quality.clock_class;
1627 	gm_prio->root_system_id.clk_quality.clock_accuracy =
1628 		default_ds->clk_quality.clock_accuracy;
1629 	gm_prio->root_system_id.clk_quality.offset_scaled_log_var =
1630 		htons(default_ds->clk_quality.offset_scaled_log_var);
1631 
1632 	memcpy(gm_prio->src_port_id.clk_id, default_ds->clk_id,
1633 	       GPTP_CLOCK_ID_LEN);
1634 	memcpy(gm_prio->root_system_id.grand_master_id, default_ds->clk_id,
1635 	       GPTP_CLOCK_ID_LEN);
1636 
1637 	best_vector = gm_prio;
1638 
1639 	for (port = GPTP_PORT_START; port < GPTP_PORT_END; port++) {
1640 		challenger = &GPTP_PORT_BMCA_DATA(port)->port_priority;
1641 		pa_info_state = &GPTP_PORT_STATE(port)->pa_info;
1642 		pss_rcv = &GPTP_PORT_STATE(port)->pss_rcv;
1643 
1644 		if (pa_info_state->ann_expired ||
1645 		    (global_ds->gm_present &&
1646 		     pss_rcv->rcv_sync_receipt_timeout_timer_expired)) {
1647 			continue;
1648 		}
1649 
1650 		if (memcmp(challenger->src_port_id.clk_id, default_ds->clk_id,
1651 			   GPTP_CLOCK_ID_LEN) == 0) {
1652 			/* Discard this challenger. */
1653 			continue;
1654 		}
1655 
1656 		if (best_port == 0) {
1657 			tmp = memcmp(&challenger->root_system_id,
1658 				     &best_vector->root_system_id,
1659 				     sizeof(struct gptp_root_system_identity));
1660 			if (tmp < 0) {
1661 				best_vector = challenger;
1662 				best_port = port;
1663 			} else if (tmp > 0) {
1664 				continue;
1665 			}
1666 
1667 			tmp = (int)challenger->steps_removed -
1668 				((int)ntohs(best_vector->steps_removed) + 1);
1669 			if (tmp < 0) {
1670 				best_vector = challenger;
1671 				best_port = port;
1672 			} else if (tmp > 0) {
1673 				continue;
1674 			}
1675 
1676 			tmp = memcmp(&challenger->src_port_id,
1677 				     &best_vector->src_port_id,
1678 				     sizeof(struct gptp_port_identity));
1679 			if (tmp < 0) {
1680 				best_vector = challenger;
1681 				best_port = port;
1682 			} else if (tmp > 0) {
1683 				continue;
1684 			}
1685 
1686 			if (ntohs(challenger->port_number) <
1687 			    ntohs(best_vector->port_number)) {
1688 				best_vector = challenger;
1689 				best_port = port;
1690 			}
1691 
1692 		} else {
1693 			/* We can compare portPriority vectors without
1694 			 * calculating pathPriority vectors.
1695 			 */
1696 			if (memcmp(challenger, best_vector,
1697 				   sizeof(struct gptp_priority_vector)) < 0) {
1698 				best_vector = challenger;
1699 				best_port = port;
1700 			}
1701 		}
1702 	}
1703 
1704 	if (best_port != 0) {
1705 		if (&global_ds->gm_priority.root_system_id !=
1706 		    &best_vector->root_system_id) {
1707 			memcpy(&global_ds->gm_priority.root_system_id,
1708 			       &best_vector->root_system_id,
1709 			       sizeof(struct gptp_root_system_identity));
1710 		}
1711 
1712 		global_ds->gm_priority.steps_removed =
1713 			ntohs(best_vector->steps_removed) + 1;
1714 
1715 		if (&global_ds->gm_priority.src_port_id !=
1716 		    &best_vector->src_port_id) {
1717 			memcpy(&global_ds->gm_priority.src_port_id,
1718 			       &best_vector->src_port_id,
1719 			       sizeof(struct gptp_port_identity));
1720 		}
1721 
1722 		global_ds->gm_priority.port_number = best_vector->port_number;
1723 	}
1724 
1725 	return best_port;
1726 }
1727 
update_bmca(int port,int best_port,struct gptp_global_ds * global_ds,struct gptp_default_ds * default_ds,struct gptp_priority_vector * gm_prio)1728 static void update_bmca(int port,
1729 			int best_port,
1730 			struct gptp_global_ds *global_ds,
1731 			struct gptp_default_ds *default_ds,
1732 			struct gptp_priority_vector *gm_prio)
1733 {
1734 	struct gptp_port_bmca_data *bmca_data = GPTP_PORT_BMCA_DATA(port);
1735 
1736 	/* Update masterPriorityVector for the port. */
1737 	if (best_port == 0) {
1738 		memcpy(&bmca_data->master_priority, gm_prio,
1739 		       sizeof(struct gptp_priority_vector));
1740 
1741 		bmca_data->master_priority.port_number = htons(port);
1742 		bmca_data->master_priority.src_port_id.port_number =
1743 			htons(port);
1744 	} else {
1745 		memcpy(&bmca_data->master_priority.root_system_id,
1746 		       &gm_prio->root_system_id,
1747 		       sizeof(struct gptp_root_system_identity));
1748 		memcpy(bmca_data->master_priority.src_port_id.clk_id,
1749 		       default_ds->clk_id, GPTP_CLOCK_ID_LEN);
1750 		bmca_data->master_priority.port_number = htons(port);
1751 		bmca_data->master_priority.src_port_id.port_number =
1752 			htons(port);
1753 	}
1754 
1755 	switch (bmca_data->info_is) {
1756 	case GPTP_INFO_IS_DISABLED:
1757 		gptp_change_port_state(port, GPTP_PORT_DISABLED);
1758 		break;
1759 
1760 	case GPTP_INFO_IS_AGED:
1761 		bmca_data->updt_info = true;
1762 		gptp_change_port_state(port, GPTP_PORT_MASTER);
1763 		break;
1764 
1765 	case GPTP_INFO_IS_MINE:
1766 		gptp_change_port_state(port, GPTP_PORT_MASTER);
1767 
1768 		if ((memcmp(&bmca_data->port_priority,
1769 			    &bmca_data->master_priority,
1770 			    sizeof(struct gptp_priority_vector)) != 0) ||
1771 		    (bmca_data->port_steps_removed !=
1772 		     global_ds->master_steps_removed)) {
1773 			bmca_data->updt_info = true;
1774 		}
1775 
1776 		break;
1777 
1778 	case GPTP_INFO_IS_RECEIVED:
1779 		if (best_port == port) {
1780 			/* gmPriorityVector is now derived from
1781 			 * portPriorityVector.
1782 			 */
1783 			gptp_change_port_state(port, GPTP_PORT_SLAVE);
1784 			bmca_data->updt_info = false;
1785 		} else if (memcmp(&bmca_data->port_priority,
1786 				  &bmca_data->master_priority,
1787 				  sizeof(struct gptp_priority_vector)) <= 0) {
1788 			/* The masterPriorityVector is not better than
1789 			 * the portPriorityVector.
1790 			 */
1791 			gptp_change_port_state(port, GPTP_PORT_PASSIVE);
1792 
1793 			if (memcmp(bmca_data->port_priority.src_port_id.clk_id,
1794 				   default_ds->clk_id,
1795 				   GPTP_CLOCK_ID_LEN)) {
1796 				/* The sourcePortIdentity component of
1797 				 * the portPriorityVector does not
1798 				 * reflect another port on the
1799 				 * time-aware system.
1800 				 */
1801 				bmca_data->updt_info = true;
1802 			} else {
1803 				bmca_data->updt_info = false;
1804 			}
1805 		} else {
1806 			gptp_change_port_state(port, GPTP_PORT_MASTER);
1807 			bmca_data->updt_info = true;
1808 		}
1809 
1810 		break;
1811 	}
1812 }
1813 
gptp_updt_roles_tree(void)1814 static void gptp_updt_roles_tree(void)
1815 {
1816 	struct gptp_global_ds *global_ds;
1817 	struct gptp_default_ds *default_ds;
1818 	struct gptp_priority_vector *gm_prio, *last_gm_prio;
1819 	struct gptp_port_bmca_data *bmca_data;
1820 	int port, best_port;
1821 
1822 	global_ds = GPTP_GLOBAL_DS();
1823 	default_ds = GPTP_DEFAULT_DS();
1824 
1825 	gm_prio = &global_ds->gm_priority;
1826 	last_gm_prio = &global_ds->last_gm_priority;
1827 
1828 	/* Save gmPriority. */
1829 	memcpy(last_gm_prio, gm_prio, sizeof(struct gptp_priority_vector));
1830 
1831 	best_port = compute_best_vector();
1832 
1833 	/* If the best vector was the systemPriorityVector. */
1834 	if (best_port == 0) {
1835 		/* Copy leap61, leap59, current UTC offset valid,
1836 		 * time traceable and frequency traceable flags.
1837 		 */
1838 		global_ds->global_flags.octets[1] =
1839 			global_ds->sys_flags.octets[1];
1840 		global_ds->current_utc_offset =
1841 			global_ds->sys_current_utc_offset;
1842 		global_ds->time_source = global_ds->sys_time_source;
1843 		global_ds->master_steps_removed = 0U;
1844 	} else {
1845 		bmca_data = GPTP_PORT_BMCA_DATA(best_port);
1846 
1847 		/* Copy leap61, leap59, current UTC offset valid,
1848 		 * time traceable and frequency traceable flags.
1849 		 */
1850 		global_ds->global_flags.octets[1] =
1851 			bmca_data->ann_flags.octets[1];
1852 		global_ds->current_utc_offset =
1853 			global_ds->sys_current_utc_offset;
1854 		global_ds->time_source = bmca_data->ann_time_source;
1855 		global_ds->master_steps_removed =
1856 			htons(ntohs(bmca_data->message_steps_removed) + 1);
1857 	}
1858 
1859 	for (port = GPTP_PORT_START; port < GPTP_PORT_END; port++) {
1860 		update_bmca(port, best_port, global_ds, default_ds, gm_prio);
1861 	}
1862 
1863 	/* Update gmPresent. */
1864 	global_ds->gm_present =
1865 		(gm_prio->root_system_id.grand_master_prio1 == 255U) ?
1866 		false : true;
1867 
1868 	/* Assign the port role for port 0. */
1869 	for (port = GPTP_PORT_START; port < GPTP_PORT_END; port++) {
1870 		if (global_ds->selected_role[port] == GPTP_PORT_SLAVE) {
1871 			gptp_change_port_state(0, GPTP_PORT_PASSIVE);
1872 			break;
1873 		}
1874 	}
1875 
1876 	if (port == GPTP_PORT_END) {
1877 		gptp_change_port_state(0, GPTP_PORT_SLAVE);
1878 	}
1879 
1880 	/* If current system is the Grand Master, set pathTrace array. */
1881 	if (memcmp(default_ds->clk_id, gm_prio->root_system_id.grand_master_id,
1882 		   GPTP_CLOCK_ID_LEN) == 0) {
1883 		global_ds->path_trace.len = htons(GPTP_CLOCK_ID_LEN);
1884 		memcpy(global_ds->path_trace.path_sequence,
1885 		       default_ds->clk_id, GPTP_CLOCK_ID_LEN);
1886 	}
1887 }
1888 
gptp_set_selected_tree(void)1889 static void gptp_set_selected_tree(void)
1890 {
1891 	/* Set all the elements of the selected array to TRUE. */
1892 	GPTP_GLOBAL_DS()->selected_array = ~0;
1893 }
1894 
gptp_mi_port_role_selection_state_machine(void)1895 static void gptp_mi_port_role_selection_state_machine(void)
1896 {
1897 	struct gptp_port_role_selection_state *state;
1898 
1899 	state = &GPTP_STATE()->pr_sel;
1900 
1901 	switch (state->state) {
1902 	case GPTP_PR_SELECTION_INIT_BRIDGE:
1903 		gptp_updt_role_disabled_tree();
1904 		state->state = GPTP_PR_SELECTION_ROLE_SELECTION;
1905 
1906 		/* Be sure to enter the "if" statement immediately after. */
1907 		GPTP_GLOBAL_DS()->reselect_array = ~0;
1908 		__fallthrough;
1909 
1910 	case GPTP_PR_SELECTION_ROLE_SELECTION:
1911 		if (GPTP_GLOBAL_DS()->reselect_array != 0) {
1912 			gptp_clear_reselect_tree();
1913 			gptp_updt_roles_tree();
1914 			gptp_set_selected_tree();
1915 		}
1916 
1917 		break;
1918 	}
1919 }
1920 
tx_announce(int port)1921 static void tx_announce(int port)
1922 {
1923 	struct net_pkt *pkt;
1924 
1925 	pkt = gptp_prepare_announce(port);
1926 	if (pkt) {
1927 		gptp_send_announce(port, pkt);
1928 	}
1929 }
1930 
gptp_mi_port_announce_transmit_state_machine(int port)1931 static void gptp_mi_port_announce_transmit_state_machine(int port)
1932 {
1933 	struct gptp_port_ds *port_ds;
1934 	struct gptp_global_ds *global_ds;
1935 	struct gptp_port_announce_transmit_state *state;
1936 	struct gptp_port_bmca_data *bmca_data;
1937 
1938 	port_ds = GPTP_PORT_DS(port);
1939 	global_ds = GPTP_GLOBAL_DS();
1940 	bmca_data = GPTP_PORT_BMCA_DATA(port);
1941 	state = &GPTP_PORT_STATE(port)->pa_transmit;
1942 
1943 	/* Reset interval as defined in AnnounceIntervalSetting
1944 	 * state machine.
1945 	 */
1946 	if (port_ds->ptt_port_enabled && !port_ds->prev_ptt_port_enabled) {
1947 		gptp_update_announce_interval(port, GPTP_ITV_SET_TO_INIT);
1948 	}
1949 
1950 	switch (state->state) {
1951 	case GPTP_PA_TRANSMIT_INIT:
1952 		bmca_data->new_info = true;
1953 		__fallthrough;
1954 
1955 	case GPTP_PA_TRANSMIT_IDLE:
1956 		k_timer_stop(&state->ann_send_periodic_timer);
1957 		state->ann_trigger = false;
1958 		k_timer_start(&state->ann_send_periodic_timer,
1959 			      K_MSEC(gptp_uscaled_ns_to_timer_ms(
1960 					     &bmca_data->announce_interval)),
1961 			      K_NO_WAIT);
1962 
1963 		state->state = GPTP_PA_TRANSMIT_POST_IDLE;
1964 		__fallthrough;
1965 
1966 	case GPTP_PA_TRANSMIT_POST_IDLE:
1967 		if (IS_SELECTED(global_ds, port) &&
1968 		    !bmca_data->updt_info &&
1969 		    state->ann_trigger) {
1970 
1971 			state->state = GPTP_PA_TRANSMIT_PERIODIC;
1972 
1973 		} else if (IS_SELECTED(global_ds, port) &&
1974 			   !bmca_data->updt_info &&
1975 			   !state->ann_trigger &&
1976 			   (global_ds->selected_role[port] ==
1977 			    GPTP_PORT_MASTER) &&
1978 			   bmca_data->new_info) {
1979 
1980 			bmca_data->new_info = false;
1981 			tx_announce(port);
1982 			state->state = GPTP_PA_TRANSMIT_IDLE;
1983 		}
1984 
1985 		break;
1986 
1987 	case GPTP_PA_TRANSMIT_PERIODIC:
1988 		if (global_ds->selected_role[port] == GPTP_PORT_MASTER) {
1989 			bmca_data->new_info = true;
1990 		}
1991 		state->state = GPTP_PA_TRANSMIT_IDLE;
1992 		break;
1993 	}
1994 }
1995 
1996 
gptp_mi_port_sync_state_machines(int port)1997 void gptp_mi_port_sync_state_machines(int port)
1998 {
1999 	gptp_mi_pss_rcv_state_machine(port);
2000 	gptp_mi_pss_send_state_machine(port);
2001 }
2002 
gptp_mi_port_bmca_state_machines(int port)2003 void gptp_mi_port_bmca_state_machines(int port)
2004 {
2005 	gptp_mi_port_announce_receive_state_machine(port);
2006 	gptp_mi_port_announce_information_state_machine(port);
2007 	gptp_mi_port_announce_transmit_state_machine(port);
2008 }
2009 
gptp_mi_state_machines(void)2010 void gptp_mi_state_machines(void)
2011 {
2012 	gptp_mi_site_sync_sync_state_machine();
2013 	gptp_mi_clk_slave_sync_state_machine();
2014 	gptp_mi_port_role_selection_state_machine();
2015 	gptp_mi_clk_master_sync_offset_state_machine();
2016 #if defined(CONFIG_NET_GPTP_GM_CAPABLE)
2017 	gptp_mi_clk_master_sync_snd_state_machine();
2018 #endif
2019 	gptp_mi_clk_master_sync_rcv_state_machine();
2020 }
2021