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 		gptp_mi_pss_send_md_sync_send(port);
564 
565 		__fallthrough;
566 	case GPTP_PSS_SEND_SET_SYNC_RECEIPT_TIMEOUT:
567 		/* Test conditions have been slightly rearranged compared to
568 		 * their definitions in the standard in order not to test
569 		 * AsCapable and pttPortEnabled when not needed (they are
570 		 * already tested with rcvdPSSync for the reset of this state
571 		 * machine).
572 		 */
573 		if ((global_ds->selected_role[port] == GPTP_PORT_MASTER) &&
574 		    ((state->rcvd_pss_sync &&
575 		      state->half_sync_itv_timer_expired &&
576 		      state->pss_sync_ptr->local_port_number != port) ||
577 		     (state->sync_itv_timer_expired &&
578 		      (state->last_rcvd_port_num != port) &&
579 		      port_ds->as_capable && port_ds->ptt_port_enabled))) {
580 
581 			state->state = GPTP_PSS_SEND_SEND_MD_SYNC;
582 
583 		} else if ((state->state == GPTP_PSS_SEND_SEND_MD_SYNC) ||
584 			   (state->rcvd_pss_sync &&
585 			    !state->sync_itv_timer_expired &&
586 			    (global_ds->selected_role[port] ==
587 							GPTP_PORT_MASTER) &&
588 			    state->pss_sync_ptr->local_port_number != port)) {
589 
590 			/* Change state as it may have transitioned from
591 			 * SEND_MD_SYNC.
592 			 */
593 			state->state = GPTP_PSS_SEND_SET_SYNC_RECEIPT_TIMEOUT;
594 
595 			/* Stop and (re)start receipt timeout timer. */
596 			k_timer_stop(&state->send_sync_receipt_timeout_timer);
597 			state->send_sync_receipt_timeout_timer_expired = false;
598 
599 			duration =
600 				K_MSEC(port_ds->sync_receipt_timeout_time_itv /
601 				       (NSEC_PER_USEC * USEC_PER_MSEC));
602 
603 			k_timer_start(&state->send_sync_receipt_timeout_timer,
604 				      duration, K_NO_WAIT);
605 
606 		} else if (state->send_sync_receipt_timeout_timer_expired) {
607 			state->state = GPTP_PSS_SEND_SYNC_RECEIPT_TIMEOUT;
608 		}
609 
610 		break;
611 	}
612 }
613 
gptp_mi_site_ss_prepare_pss_send(void)614 static void gptp_mi_site_ss_prepare_pss_send(void)
615 {
616 	struct gptp_site_sync_sync_state *state;
617 
618 	state = &GPTP_STATE()->site_ss;
619 
620 	memcpy(&state->pss_send, state->pss_rcv_ptr,
621 	       sizeof(struct gptp_mi_port_sync_sync));
622 }
623 
gptp_mi_site_ss_send_to_pss(void)624 static void gptp_mi_site_ss_send_to_pss(void)
625 {
626 	struct gptp_site_sync_sync_state *state;
627 	struct gptp_pss_send_state *pss_send;
628 	int port;
629 
630 	state = &GPTP_STATE()->site_ss;
631 
632 	for (port = GPTP_PORT_START; port < GPTP_PORT_END; port++) {
633 		pss_send = &GPTP_PORT_STATE(port)->pss_send;
634 		pss_send->pss_sync_ptr = &state->pss_send;
635 		pss_send->rcvd_pss_sync = true;
636 	}
637 }
638 
gptp_mi_site_sync_sync_state_machine(void)639 static void gptp_mi_site_sync_sync_state_machine(void)
640 {
641 	bool gm_present;
642 	uint16_t local_port_number;
643 	struct gptp_site_sync_sync_state *state;
644 	struct gptp_clk_slave_sync_state *clk_ss;
645 
646 	state = &GPTP_STATE()->site_ss;
647 	clk_ss = &GPTP_STATE()->clk_slave_sync;
648 	gm_present = GPTP_GLOBAL_DS()->gm_present;
649 
650 	if (!state->pss_rcv_ptr) {
651 		/* We do not have connection to GM yet */
652 		return;
653 	}
654 
655 	local_port_number = state->pss_rcv_ptr->local_port_number;
656 
657 	switch (state->state) {
658 	case GPTP_SSS_INITIALIZING:
659 		state->rcvd_pss = false;
660 		state->state = GPTP_SSS_RECEIVING_SYNC;
661 		break;
662 
663 	case GPTP_SSS_RECEIVING_SYNC:
664 		if (state->rcvd_pss) {
665 			state->rcvd_pss = false;
666 			if (gptp_is_slave_port(local_port_number) &&
667 					gm_present) {
668 				gptp_mi_site_ss_prepare_pss_send();
669 
670 				/*
671 				 * Send Port Sync Sync to all
672 				 * PortSyncSyncSend State Machines.
673 				 */
674 				gptp_mi_site_ss_send_to_pss();
675 
676 				/*
677 				 * Send PortSyncSync to
678 				 * ClockSlaveSync State Machine.
679 				 */
680 				clk_ss->pss_rcv_ptr = &state->pss_send;
681 				clk_ss->rcvd_pss = true;
682 			}
683 		}
684 
685 		break;
686 	}
687 }
688 
gptp_mi_clk_slave_sync_compute(void)689 static void gptp_mi_clk_slave_sync_compute(void)
690 {
691 	struct gptp_clk_slave_sync_state *state;
692 	struct gptp_clk_master_sync_offset_state *offset_state;
693 	struct gptp_global_ds *global_ds;
694 	struct gptp_md_sync_info *pss;
695 	struct gptp_port_ds *port_ds;
696 	uint64_t sync_receipt_time;
697 
698 	state = &GPTP_STATE()->clk_slave_sync;
699 	offset_state = &GPTP_STATE()->clk_master_sync_offset;
700 	global_ds = GPTP_GLOBAL_DS();
701 	port_ds = GPTP_PORT_DS(state->pss_rcv_ptr->local_port_number);
702 
703 	pss = &state->pss_rcv_ptr->sync_info;
704 
705 	sync_receipt_time = port_ds->neighbor_prop_delay;
706 	sync_receipt_time *= pss->rate_ratio;
707 	sync_receipt_time /= port_ds->neighbor_rate_ratio;
708 	sync_receipt_time += pss->follow_up_correction_field;
709 	sync_receipt_time += port_ds->delay_asymmetry;
710 
711 	global_ds->sync_receipt_time.second = sync_receipt_time / NSEC_PER_SEC;
712 	global_ds->sync_receipt_time.fract_nsecond =
713 		(sync_receipt_time % NSEC_PER_SEC) * GPTP_POW2_16;
714 	global_ds->sync_receipt_time.second += pss->precise_orig_ts.second;
715 	global_ds->sync_receipt_time.fract_nsecond +=
716 		pss->precise_orig_ts.nanosecond * GPTP_POW2_16;
717 
718 	global_ds->sync_receipt_local_time = port_ds->delay_asymmetry;
719 	global_ds->sync_receipt_local_time /= pss->rate_ratio;
720 	global_ds->sync_receipt_local_time +=
721 		(port_ds->neighbor_prop_delay / port_ds->neighbor_rate_ratio);
722 	global_ds->sync_receipt_local_time += pss->upstream_tx_time;
723 
724 	global_ds->gm_time_base_indicator = pss->gm_time_base_indicator;
725 	global_ds->last_gm_phase_change.high = pss->last_gm_phase_change.high;
726 	global_ds->last_gm_phase_change.low = pss->last_gm_phase_change.low;
727 	global_ds->last_gm_freq_change = pss->last_gm_freq_change;
728 
729 	offset_state->rcvd_sync_receipt_time = true;
730 }
731 
732 #if defined(CONFIG_NET_GPTP_USE_DEFAULT_CLOCK_UPDATE)
gptp_update_local_port_clock(void)733 static void gptp_update_local_port_clock(void)
734 {
735 	struct gptp_clk_slave_sync_state *state;
736 	struct gptp_global_ds *global_ds;
737 	struct gptp_port_ds *port_ds;
738 	int port;
739 	int64_t nanosecond_diff;
740 	int64_t second_diff;
741 	const struct device *clk;
742 	struct net_ptp_time tm;
743 	unsigned int key;
744 
745 	state = &GPTP_STATE()->clk_slave_sync;
746 	global_ds = GPTP_GLOBAL_DS();
747 	port = state->pss_rcv_ptr->local_port_number;
748 	NET_ASSERT((port >= GPTP_PORT_START) && (port <= GPTP_PORT_END));
749 
750 	port_ds = GPTP_PORT_DS(port);
751 
752 	/* Check if the last neighbor rate ratio can still be used */
753 	if (!port_ds->neighbor_rate_ratio_valid) {
754 		return;
755 	}
756 
757 	port_ds->neighbor_rate_ratio_valid = false;
758 
759 	second_diff = global_ds->sync_receipt_time.second -
760 		(global_ds->sync_receipt_local_time / NSEC_PER_SEC);
761 	nanosecond_diff =
762 		(global_ds->sync_receipt_time.fract_nsecond / GPTP_POW2_16) -
763 		(global_ds->sync_receipt_local_time % NSEC_PER_SEC);
764 
765 	clk = net_eth_get_ptp_clock(GPTP_PORT_IFACE(port));
766 	if (!clk) {
767 		return;
768 	}
769 
770 	if (second_diff > 0 && nanosecond_diff < 0) {
771 		second_diff--;
772 		nanosecond_diff = NSEC_PER_SEC + nanosecond_diff;
773 	}
774 
775 	if (second_diff < 0 && nanosecond_diff > 0) {
776 		second_diff++;
777 		nanosecond_diff = -(int64_t)NSEC_PER_SEC + nanosecond_diff;
778 	}
779 
780 	ptp_clock_rate_adjust(clk, port_ds->neighbor_rate_ratio);
781 
782 	/* If time difference is too high, set the clock value.
783 	 * Otherwise, adjust it.
784 	 */
785 	if (second_diff || (second_diff == 0 &&
786 			    (nanosecond_diff < -5000 ||
787 			     nanosecond_diff > 5000))) {
788 		bool underflow = false;
789 
790 		key = irq_lock();
791 		ptp_clock_get(clk, &tm);
792 
793 		if (second_diff < 0 && tm.second < -second_diff) {
794 			NET_DBG("Do not set local clock because %lu < %ld",
795 				(unsigned long int)tm.second,
796 				(long int)-second_diff);
797 			goto skip_clock_set;
798 		}
799 
800 		tm.second += second_diff;
801 
802 		if (nanosecond_diff < 0 &&
803 		    tm.nanosecond < -nanosecond_diff) {
804 			underflow = true;
805 		}
806 
807 		tm.nanosecond += nanosecond_diff;
808 
809 		if (underflow) {
810 			tm.second--;
811 			tm.nanosecond += NSEC_PER_SEC;
812 		} else if (tm.nanosecond >= NSEC_PER_SEC) {
813 			tm.second++;
814 			tm.nanosecond -= NSEC_PER_SEC;
815 		}
816 
817 		/* This prints too much data normally but can be enabled to see
818 		 * what time we are setting to the local clock.
819 		 */
820 		if (0) {
821 			NET_INFO("Set local clock %lu.%lu",
822 				 (unsigned long int)tm.second,
823 				 (unsigned long int)tm.nanosecond);
824 		}
825 
826 		ptp_clock_set(clk, &tm);
827 
828 	skip_clock_set:
829 		irq_unlock(key);
830 	} else {
831 		if (nanosecond_diff < -200) {
832 			nanosecond_diff = -200;
833 		} else if (nanosecond_diff > 200) {
834 			nanosecond_diff = 200;
835 		}
836 
837 		ptp_clock_adjust(clk, nanosecond_diff);
838 	}
839 }
840 #endif /* CONFIG_NET_GPTP_USE_DEFAULT_CLOCK_UPDATE */
841 
gptp_mi_clk_slave_sync_state_machine(void)842 static void gptp_mi_clk_slave_sync_state_machine(void)
843 {
844 	struct gptp_clk_slave_sync_state *state;
845 
846 	state = &GPTP_STATE()->clk_slave_sync;
847 
848 	switch (state->state) {
849 	case GPTP_CLK_SLAVE_SYNC_INITIALIZING:
850 		state->rcvd_pss = false;
851 		state->state = GPTP_CLK_SLAVE_SYNC_SEND_SYNC_IND;
852 		break;
853 
854 	case GPTP_CLK_SLAVE_SYNC_SEND_SYNC_IND:
855 		if (state->rcvd_pss) {
856 			state->rcvd_pss = false;
857 			gptp_mi_clk_slave_sync_compute();
858 
859 #if defined(CONFIG_NET_GPTP_USE_DEFAULT_CLOCK_UPDATE)
860 			/* Instead of updating SlaveClock, update LocalClock */
861 			gptp_update_local_port_clock();
862 #endif
863 			gptp_call_phase_dis_cb();
864 		}
865 
866 		break;
867 	}
868 }
869 
gptp_mi_clk_master_sync_offset_state_machine(void)870 static void gptp_mi_clk_master_sync_offset_state_machine(void)
871 {
872 	struct gptp_clk_master_sync_offset_state *state;
873 	struct gptp_global_ds *global_ds;
874 
875 	state = &GPTP_STATE()->clk_master_sync_offset;
876 	global_ds = GPTP_GLOBAL_DS();
877 
878 	switch (state->state) {
879 	case GPTP_CMS_OFFSET_INITIALIZING:
880 		state->rcvd_sync_receipt_time = false;
881 		state->state = GPTP_CMS_OFFSET_INDICATION;
882 		break;
883 	case GPTP_CMS_OFFSET_INDICATION:
884 		if (!state->rcvd_sync_receipt_time) {
885 			break;
886 		}
887 
888 		state->rcvd_sync_receipt_time = false;
889 
890 		if (global_ds->selected_role[0] == GPTP_PORT_PASSIVE) {
891 			/* TODO Calculate real values for proper BC support */
892 			memset(&global_ds->clk_src_phase_offset, 0x0,
893 			       sizeof(struct gptp_scaled_ns));
894 			global_ds->clk_src_freq_offset = 0;
895 		} else if (global_ds->clk_src_time_base_indicator_prev
896 			   != global_ds->clk_src_time_base_indicator) {
897 			memcpy(&global_ds->clk_src_phase_offset,
898 			       &global_ds->last_gm_phase_change,
899 			       sizeof(struct gptp_scaled_ns));
900 
901 			global_ds->clk_src_freq_offset =
902 				global_ds->last_gm_freq_change;
903 		}
904 
905 		break;
906 	default:
907 		NET_ERR("Unrecognised state %d", state->state);
908 		break;
909 	}
910 }
911 
912 #if defined(CONFIG_NET_GPTP_GM_CAPABLE)
gptp_mi_setup_sync_send_time(void)913 static inline void gptp_mi_setup_sync_send_time(void)
914 {
915 	struct gptp_clk_master_sync_snd_state *state;
916 	struct gptp_global_ds *global_ds;
917 	uint64_t time_helper;
918 
919 	state = &GPTP_STATE()->clk_master_sync_send;
920 	global_ds = GPTP_GLOBAL_DS();
921 
922 	time_helper = state->sync_send_time.low;
923 
924 	state->sync_send_time.low +=
925 		global_ds->clk_master_sync_itv;
926 
927 	/* Check for overflow */
928 	if (state->sync_send_time.low < time_helper) {
929 		state->sync_send_time.high += 1U;
930 		state->sync_send_time.low =
931 			UINT64_MAX - state->sync_send_time.low;
932 	}
933 }
934 
gptp_mi_set_ps_sync_cmss(void)935 static void gptp_mi_set_ps_sync_cmss(void)
936 {
937 	struct gptp_clk_master_sync_snd_state *state;
938 	struct gptp_global_ds *global_ds;
939 	struct gptp_md_sync_info *sync_info;
940 	uint64_t current_time;
941 
942 	global_ds = GPTP_GLOBAL_DS();
943 	state = &GPTP_STATE()->clk_master_sync_send;
944 
945 	sync_info = &state->pss_snd.sync_info;
946 
947 	state->pss_snd.local_port_number = 0U;
948 
949 	current_time = gptp_get_current_master_time_nanosecond();
950 
951 	sync_info->precise_orig_ts.second = current_time / NSEC_PER_SEC;
952 	sync_info->precise_orig_ts.nanosecond = current_time % NSEC_PER_SEC;
953 
954 	/* TODO calculate correction field properly, rate_ratio is also set to
955 	 * zero instead of being copied from global_ds as it affects the final
956 	 * value of FUP correction field.
957 	 */
958 	sync_info->follow_up_correction_field = 0;
959 	sync_info->rate_ratio = 0;
960 
961 	memcpy(&sync_info->src_port_id.clk_id,
962 	       GPTP_DEFAULT_DS()->clk_id,
963 	       GPTP_CLOCK_ID_LEN);
964 
965 	sync_info->src_port_id.port_number = 0U;
966 	sync_info->log_msg_interval = CONFIG_NET_GPTP_INIT_LOG_SYNC_ITV;
967 	sync_info->upstream_tx_time = global_ds->local_time.low;
968 
969 	state->pss_snd.sync_receipt_timeout_time = UINT64_MAX;
970 
971 	sync_info->gm_time_base_indicator =
972 		global_ds->clk_src_time_base_indicator;
973 
974 	memcpy(&sync_info->last_gm_phase_change,
975 	       &global_ds->clk_src_phase_offset,
976 	       sizeof(struct gptp_scaled_ns));
977 
978 	sync_info->last_gm_freq_change = global_ds->clk_src_freq_offset;
979 }
980 
gptp_mi_tx_ps_sync_cmss(void)981 static inline void gptp_mi_tx_ps_sync_cmss(void)
982 {
983 	struct gptp_clk_master_sync_snd_state *state;
984 	struct gptp_pss_send_state *pss_send;
985 	int port;
986 
987 	state = &GPTP_STATE()->clk_master_sync_send;
988 
989 	for (port = GPTP_PORT_START; port < GPTP_PORT_END; port++) {
990 		pss_send = &GPTP_PORT_STATE(port)->pss_send;
991 		pss_send->pss_sync_ptr = &state->pss_snd;
992 
993 		pss_send->rcvd_pss_sync = true;
994 	}
995 }
996 
gptp_mi_clk_master_sync_snd_state_machine(void)997 static void gptp_mi_clk_master_sync_snd_state_machine(void)
998 {
999 	struct gptp_clk_master_sync_snd_state *state;
1000 	uint64_t current_time;
1001 
1002 	state = &GPTP_STATE()->clk_master_sync_send;
1003 
1004 	switch (state->state) {
1005 	case GPTP_CMS_SND_INITIALIZING:
1006 		gptp_mi_setup_sync_send_time();
1007 
1008 		state->state = GPTP_CMS_SND_INDICATION;
1009 		break;
1010 
1011 	case GPTP_CMS_SND_INDICATION:
1012 		current_time = gptp_get_current_master_time_nanosecond();
1013 
1014 		if (current_time >= state->sync_send_time.low) {
1015 			gptp_mi_set_ps_sync_cmss();
1016 			gptp_mi_tx_ps_sync_cmss();
1017 
1018 			gptp_mi_setup_sync_send_time();
1019 		}
1020 
1021 		break;
1022 
1023 	default:
1024 		NET_ERR("Unrecognised state %d", state->state);
1025 		break;
1026 	}
1027 }
1028 #endif
1029 
gptp_compute_gm_rate_ratio(void)1030 static void gptp_compute_gm_rate_ratio(void)
1031 {
1032 	static struct net_ptp_extended_time src_time_0;
1033 	static struct gptp_uscaled_ns local_time_0;
1034 	struct net_ptp_extended_time src_time_n;
1035 	struct gptp_uscaled_ns local_time_n;
1036 	struct net_ptp_extended_time src_time_t;
1037 	struct gptp_uscaled_ns local_time_t;
1038 	struct gptp_clk_master_sync_rcv_state *state;
1039 	struct gptp_global_ds *global_ds;
1040 	double new_gm_rate;
1041 
1042 	state = &GPTP_STATE()->clk_master_sync_receive;
1043 	global_ds = GPTP_GLOBAL_DS();
1044 
1045 	/* Get current local and source time */
1046 	memcpy(&src_time_n, &state->rcvd_clk_src_req.src_time,
1047 	       sizeof(struct net_ptp_extended_time));
1048 
1049 	memcpy(&local_time_n, &global_ds->local_time,
1050 	       sizeof(struct gptp_uscaled_ns));
1051 
1052 	if ((src_time_0.second == 0U && src_time_0.fract_nsecond == 0U)
1053 	    || (local_time_0.high == 0U && local_time_0.low == 0U)) {
1054 		memcpy(&src_time_0, &src_time_n,
1055 		       sizeof(struct net_ptp_extended_time));
1056 
1057 		memcpy(&local_time_0, &local_time_n,
1058 		       sizeof(struct gptp_uscaled_ns));
1059 
1060 		global_ds->gm_rate_ratio = 1.0;
1061 
1062 		return;
1063 	}
1064 
1065 	/* Take care of the sign of the result */
1066 	new_gm_rate = 1.0;
1067 
1068 	if ((src_time_n.second < src_time_0.second)
1069 	    || (src_time_n.second == src_time_0.second
1070 		&& src_time_n.fract_nsecond < src_time_0.fract_nsecond)) {
1071 		/* Change result sign and swap src_time_n and src_time_0 */
1072 		memcpy(&src_time_t, &src_time_n,
1073 		       sizeof(struct net_ptp_extended_time));
1074 		memcpy(&src_time_n, &src_time_0,
1075 		       sizeof(struct net_ptp_extended_time));
1076 		memcpy(&src_time_0, &src_time_t,
1077 		       sizeof(struct net_ptp_extended_time));
1078 
1079 		new_gm_rate *= -1;
1080 	}
1081 
1082 	if ((local_time_n.high < local_time_0.high)
1083 	    || (local_time_n.high == local_time_0.high
1084 		&& local_time_n.low < local_time_0.low)) {
1085 		/* Change result sign and swap local_time_n and local_time_0 */
1086 		memcpy(&local_time_t, &local_time_n,
1087 		       sizeof(struct gptp_uscaled_ns));
1088 		memcpy(&local_time_n, &local_time_0,
1089 		       sizeof(struct gptp_uscaled_ns));
1090 		memcpy(&local_time_0, &local_time_t,
1091 		       sizeof(struct gptp_uscaled_ns));
1092 
1093 		new_gm_rate *= -1;
1094 	}
1095 
1096 	/* At this point src_time_n >= src_time_0 */
1097 	src_time_n.second -= src_time_0.second;
1098 
1099 	if (src_time_n.fract_nsecond >= src_time_0.fract_nsecond) {
1100 		src_time_n.fract_nsecond -= src_time_0.fract_nsecond;
1101 	} else {
1102 		src_time_n.second -= 1U;
1103 		src_time_n.fract_nsecond = (NSEC_PER_SEC * GPTP_POW2_16)
1104 			- src_time_0.fract_nsecond;
1105 	}
1106 
1107 	/* At this point local_time_n >= local_time_0 */
1108 	local_time_n.high -= local_time_0.high;
1109 
1110 	if (local_time_n.low >= local_time_0.low) {
1111 		local_time_n.low -= local_time_0.low;
1112 	} else {
1113 		local_time_n.high -= 1U;
1114 		local_time_n.low = UINT64_MAX - local_time_0.low;
1115 	}
1116 
1117 	/* Calculate it in nanoseconds, new_gm_rate is either 1 or -1 here */
1118 	new_gm_rate *= ((src_time_n.second * NSEC_PER_SEC)
1119 		+ (src_time_n.fract_nsecond / GPTP_POW2_16));
1120 
1121 	new_gm_rate /= local_time_n.low;
1122 
1123 	global_ds->gm_rate_ratio = new_gm_rate;
1124 }
1125 
gptp_mi_clk_master_sync_rcv_state_machine(void)1126 static void gptp_mi_clk_master_sync_rcv_state_machine(void)
1127 {
1128 	struct gptp_clk_master_sync_rcv_state *s;
1129 	struct gptp_global_ds *global_ds;
1130 
1131 #ifdef CONFIG_NET_GPTP_PROBE_CLOCK_SOURCE_ON_DEMAND
1132 	struct gptp_clk_src_time_invoke_params invoke_args = {};
1133 	uint64_t cur = gptp_get_current_master_time_nanosecond();
1134 
1135 	invoke_args.src_time.second = cur / NSEC_PER_SEC;
1136 	cur -= (invoke_args.src_time.second * NSEC_PER_SEC);
1137 
1138 	invoke_args.src_time.fract_nsecond = cur * GPTP_POW2_16;
1139 
1140 	memset(&invoke_args.last_gm_phase_change, 0x0,
1141 	       sizeof(struct gptp_scaled_ns));
1142 	invoke_args.last_gm_freq_change = 0;
1143 
1144 	gptp_clk_src_time_invoke(&invoke_args);
1145 #endif
1146 
1147 	global_ds = GPTP_GLOBAL_DS();
1148 
1149 	s = &GPTP_STATE()->clk_master_sync_receive;
1150 	switch (s->state) {
1151 	case GPTP_CMS_RCV_INITIALIZING:
1152 		s->state = GPTP_CMS_RCV_WAITING;
1153 		break;
1154 
1155 	case GPTP_CMS_RCV_WAITING:
1156 		if (s->rcvd_clock_source_req || s->rcvd_local_clock_tick) {
1157 			s->state = GPTP_CMS_RCV_SOURCE_TIME;
1158 		}
1159 
1160 		break;
1161 
1162 	case GPTP_CMS_RCV_SOURCE_TIME:
1163 		global_ds->local_time.high = 0U;
1164 		global_ds->local_time.low =
1165 			gptp_get_current_master_time_nanosecond();
1166 
1167 		if (s->rcvd_clock_source_req) {
1168 			gptp_compute_gm_rate_ratio();
1169 
1170 			global_ds->clk_src_time_base_indicator_prev =
1171 				global_ds->clk_src_time_base_indicator;
1172 
1173 			global_ds->clk_src_time_base_indicator =
1174 				s->rcvd_clk_src_req.time_base_indicator;
1175 
1176 			memcpy(&global_ds->clk_src_last_gm_phase_change,
1177 			       &s->rcvd_clk_src_req.last_gm_phase_change,
1178 			       sizeof(struct gptp_scaled_ns));
1179 
1180 			global_ds->clk_src_last_gm_freq_change =
1181 				s->rcvd_clk_src_req.last_gm_freq_change;
1182 		}
1183 
1184 		s->rcvd_clock_source_req = false;
1185 		s->rcvd_local_clock_tick = false;
1186 		s->state = GPTP_CMS_RCV_WAITING;
1187 		break;
1188 
1189 	default:
1190 		NET_ERR("Unrecognised state %d", s->state);
1191 		break;
1192 	}
1193 }
1194 
copy_path_trace(struct gptp_announce * announce)1195 static void copy_path_trace(struct gptp_announce *announce)
1196 {
1197 	int len = ntohs(announce->tlv.len);
1198 	struct gptp_path_trace *sys_path_trace;
1199 
1200 	if (len > GPTP_MAX_PATHTRACE_SIZE) {
1201 		NET_ERR("Too long path trace (%d vs %d)",
1202 			GPTP_MAX_PATHTRACE_SIZE, len);
1203 		return;
1204 	}
1205 
1206 	sys_path_trace = &GPTP_GLOBAL_DS()->path_trace;
1207 
1208 	sys_path_trace->len = htons(len + GPTP_CLOCK_ID_LEN);
1209 
1210 	memcpy(sys_path_trace->path_sequence, announce->tlv.path_sequence,
1211 	       len);
1212 
1213 	/* Append local clockIdentity. */
1214 	memcpy((uint8_t *)sys_path_trace->path_sequence + len,
1215 	       GPTP_DEFAULT_DS()->clk_id, GPTP_CLOCK_ID_LEN);
1216 }
1217 
gptp_mi_qualify_announce(int port,struct net_pkt * announce_msg)1218 static bool gptp_mi_qualify_announce(int port, struct net_pkt *announce_msg)
1219 {
1220 	struct gptp_announce *announce;
1221 	struct gptp_hdr *hdr;
1222 	int i;
1223 	uint16_t len;
1224 
1225 	hdr = GPTP_HDR(announce_msg);
1226 	announce = GPTP_ANNOUNCE(announce_msg);
1227 
1228 	if (memcmp(hdr->port_id.clk_id, GPTP_DEFAULT_DS()->clk_id,
1229 		   GPTP_CLOCK_ID_LEN) == 0) {
1230 		return false;
1231 	}
1232 
1233 	len = ntohs(announce->steps_removed);
1234 	if (len >= 255U) {
1235 		return false;
1236 	}
1237 
1238 	for (i = 0; i < len + 1; i++) {
1239 		if (memcmp(announce->tlv.path_sequence[i],
1240 			   GPTP_DEFAULT_DS()->clk_id,
1241 			   GPTP_CLOCK_ID_LEN) == 0) {
1242 			return false;
1243 		}
1244 	}
1245 
1246 	if (GPTP_GLOBAL_DS()->selected_role[port] == GPTP_PORT_SLAVE) {
1247 		copy_path_trace(announce);
1248 	}
1249 
1250 	return true;
1251 }
1252 
gptp_mi_port_announce_receive_state_machine(int port)1253 static void gptp_mi_port_announce_receive_state_machine(int port)
1254 {
1255 	struct gptp_port_ds *port_ds;
1256 	struct gptp_port_announce_receive_state *state;
1257 	struct gptp_port_bmca_data *bmca_data;
1258 
1259 	state = &GPTP_PORT_STATE(port)->pa_rcv;
1260 	port_ds = GPTP_PORT_DS(port);
1261 	bmca_data = GPTP_PORT_BMCA_DATA(port);
1262 
1263 	if ((!port_ds->ptt_port_enabled) || (!port_ds->as_capable)) {
1264 		state->state = GPTP_PA_RCV_DISCARD;
1265 	}
1266 
1267 	switch (state->state) {
1268 	case GPTP_PA_RCV_DISCARD:
1269 		state->rcvd_announce = false;
1270 		bmca_data->rcvd_msg = false;
1271 		if (bmca_data->rcvd_announce_ptr != NULL) {
1272 			net_pkt_unref(bmca_data->rcvd_announce_ptr);
1273 			bmca_data->rcvd_announce_ptr = NULL;
1274 		}
1275 
1276 		state->state = GPTP_PA_RCV_RECEIVE;
1277 		break;
1278 
1279 	case GPTP_PA_RCV_RECEIVE:
1280 		/* "portEnabled" is not checked: the interface is always up. */
1281 		if (state->rcvd_announce &&
1282 		    port_ds->ptt_port_enabled &&
1283 		    port_ds->as_capable	&&
1284 		    !bmca_data->rcvd_msg) {
1285 			state->rcvd_announce = false;
1286 
1287 			bmca_data->rcvd_msg = gptp_mi_qualify_announce(
1288 				port, bmca_data->rcvd_announce_ptr);
1289 			if (!bmca_data->rcvd_msg) {
1290 				net_pkt_unref(bmca_data->rcvd_announce_ptr);
1291 				bmca_data->rcvd_announce_ptr = NULL;
1292 			}
1293 		}
1294 
1295 		break;
1296 	}
1297 }
1298 
1299 /*
1300  * Compare a vector to an announce message vector.
1301  * All must be in big endian (network) order.
1302  */
compare_priority_vectors(struct gptp_priority_vector * vector,struct net_pkt * pkt,int port)1303 static enum gptp_received_info compare_priority_vectors(
1304 		struct gptp_priority_vector *vector,
1305 		struct net_pkt *pkt, int port)
1306 {
1307 	struct gptp_hdr *hdr;
1308 	struct gptp_announce *announce;
1309 	int rsi_cmp, spi_cmp, port_cmp;
1310 
1311 	hdr = GPTP_HDR(pkt);
1312 	announce = GPTP_ANNOUNCE(pkt);
1313 
1314 	/* Compare rootSystemIdentity and stepsRemoved. */
1315 	rsi_cmp = memcmp(&announce->root_system_id,
1316 			 &vector->root_system_id,
1317 			 sizeof(struct gptp_root_system_identity) +
1318 			 sizeof(uint16_t));
1319 	if (rsi_cmp < 0) {
1320 		/* Better rootSystemIdentity. */
1321 		return GPTP_RCVD_INFO_SUPERIOR_MASTER_INFO;
1322 	}
1323 
1324 	/* Compare sourcePortIdentity. */
1325 	spi_cmp = memcmp(&hdr->port_id, &vector->src_port_id,
1326 			 sizeof(struct gptp_port_identity));
1327 
1328 	port_cmp = (int)port - ntohs(vector->port_number);
1329 
1330 	if (spi_cmp == 0) {
1331 		if (rsi_cmp == 0) {
1332 			if (port_cmp == 0) {
1333 				/* Same priority vector. */
1334 				return GPTP_RCVD_INFO_REPEATED_MASTER_INFO;
1335 			} else if (port_cmp < 0) {
1336 				/* Priority vector with better reception port
1337 				 * number.
1338 				 */
1339 				return GPTP_RCVD_INFO_SUPERIOR_MASTER_INFO;
1340 			}
1341 		} else {
1342 			/* Same master port but different Grand Master. */
1343 			return GPTP_RCVD_INFO_SUPERIOR_MASTER_INFO;
1344 		}
1345 	} else if ((spi_cmp < 0) && (rsi_cmp == 0)) {
1346 		/* Same Grand Master but better masterPort. */
1347 		return GPTP_RCVD_INFO_SUPERIOR_MASTER_INFO;
1348 	}
1349 
1350 	return GPTP_RCVD_INFO_INFERIOR_MASTER_INFO;
1351 }
1352 
rcv_info(int port)1353 static enum gptp_received_info rcv_info(int port)
1354 {
1355 	/* TODO
1356 	 * How can we define that a message does not convey the port
1357 	 * role Master port ?
1358 	 * It is needed to define that to be able to send
1359 	 * GPTP_RCVD_INFO_OTHER_INFO.
1360 	 */
1361 	struct gptp_port_bmca_data *bmca_data;
1362 	struct gptp_announce *announce;
1363 
1364 	bmca_data = GPTP_PORT_BMCA_DATA(port);
1365 	announce = GPTP_ANNOUNCE(bmca_data->rcvd_announce_ptr);
1366 
1367 	bmca_data->message_steps_removed = announce->steps_removed;
1368 
1369 	return compare_priority_vectors(&bmca_data->port_priority,
1370 					bmca_data->rcvd_announce_ptr,
1371 					port);
1372 }
1373 
record_other_announce_info(int port)1374 static void record_other_announce_info(int port)
1375 {
1376 	struct gptp_hdr *hdr;
1377 	struct gptp_announce *announce;
1378 	struct gptp_port_bmca_data *bmca_data;
1379 
1380 	bmca_data = GPTP_PORT_BMCA_DATA(port);
1381 	hdr = GPTP_HDR(bmca_data->rcvd_announce_ptr);
1382 	announce = GPTP_ANNOUNCE(bmca_data->rcvd_announce_ptr);
1383 
1384 	/* Copy leap61, leap59, current UTC offset valid, time traceable and
1385 	 * frequency traceable flags.
1386 	 */
1387 	bmca_data->ann_flags.octets[1] = hdr->flags.octets[1];
1388 
1389 	bmca_data->ann_current_utc_offset = ntohs(announce->cur_utc_offset);
1390 	bmca_data->ann_time_source = announce->time_source;
1391 }
1392 
copy_priority_vector(struct gptp_priority_vector * vector,struct net_pkt * pkt,int port)1393 static void copy_priority_vector(struct gptp_priority_vector *vector,
1394 				 struct net_pkt *pkt, int port)
1395 {
1396 	struct gptp_hdr *hdr;
1397 	struct gptp_announce *announce;
1398 
1399 	hdr = GPTP_HDR(pkt);
1400 	announce = GPTP_ANNOUNCE(pkt);
1401 
1402 	memcpy(&vector->root_system_id, &announce->root_system_id,
1403 	       sizeof(struct gptp_root_system_identity) + sizeof(uint16_t));
1404 
1405 	memcpy(&vector->src_port_id, &hdr->port_id,
1406 	       sizeof(struct gptp_port_identity));
1407 
1408 	vector->port_number = htons(port);
1409 }
1410 
gptp_mi_port_announce_information_state_machine(int port)1411 static void gptp_mi_port_announce_information_state_machine(int port)
1412 {
1413 	struct gptp_port_ds *port_ds;
1414 	struct gptp_global_ds *global_ds;
1415 	struct gptp_port_announce_information_state *state;
1416 	struct gptp_announce *announce;
1417 	struct gptp_hdr *hdr;
1418 	struct gptp_port_bmca_data *bmca_data;
1419 	struct gptp_pss_rcv_state *pss_rcv;
1420 
1421 	bmca_data = GPTP_PORT_BMCA_DATA(port);
1422 	state = &GPTP_PORT_STATE(port)->pa_info;
1423 	port_ds = GPTP_PORT_DS(port);
1424 	global_ds = GPTP_GLOBAL_DS();
1425 
1426 	if ((!port_ds->ptt_port_enabled || !port_ds->as_capable) &&
1427 	    (bmca_data->info_is != GPTP_INFO_IS_DISABLED)) {
1428 		gptp_change_pa_info_state(port, state, GPTP_PA_INFO_DISABLED);
1429 	}
1430 
1431 	switch (state->state) {
1432 	case GPTP_PA_INFO_DISABLED:
1433 		bmca_data->rcvd_msg = false;
1434 		bmca_data->info_is = GPTP_INFO_IS_DISABLED;
1435 		SET_RESELECT(global_ds, port);
1436 		CLEAR_SELECTED(global_ds, port);
1437 		gptp_change_pa_info_state(port, state,
1438 					  GPTP_PA_INFO_POST_DISABLED);
1439 		k_timer_stop(&state->ann_rcpt_expiry_timer);
1440 		state->ann_expired = true;
1441 		__fallthrough;
1442 
1443 	case GPTP_PA_INFO_POST_DISABLED:
1444 		if (port_ds->ptt_port_enabled && port_ds->as_capable) {
1445 			gptp_change_pa_info_state(port, state,
1446 						  GPTP_PA_INFO_AGED);
1447 		} else if (bmca_data->rcvd_msg) {
1448 			gptp_change_pa_info_state(port, state,
1449 						  GPTP_PA_INFO_DISABLED);
1450 		}
1451 
1452 		break;
1453 
1454 	case GPTP_PA_INFO_AGED:
1455 		bmca_data->info_is = GPTP_INFO_IS_AGED;
1456 		CLEAR_SELECTED(global_ds, port);
1457 		SET_RESELECT(global_ds, port);
1458 		/* Transition will be actually tested in UPDATE state. */
1459 		gptp_change_pa_info_state(port, state, GPTP_PA_INFO_UPDATE);
1460 		break;
1461 
1462 	case GPTP_PA_INFO_UPDATE:
1463 		if (IS_SELECTED(global_ds, port) && bmca_data->updt_info) {
1464 			memcpy(&bmca_data->port_priority,
1465 			       &bmca_data->master_priority,
1466 			       sizeof(struct gptp_priority_vector));
1467 
1468 			bmca_data->port_steps_removed =
1469 				global_ds->master_steps_removed;
1470 			bmca_data->updt_info = false;
1471 			bmca_data->info_is = GPTP_INFO_IS_MINE;
1472 			bmca_data->new_info = true;
1473 			gptp_change_pa_info_state(port, state,
1474 						  GPTP_PA_INFO_CURRENT);
1475 		}
1476 
1477 		break;
1478 
1479 	case GPTP_PA_INFO_CURRENT:
1480 		pss_rcv = &GPTP_PORT_STATE(port)->pss_rcv;
1481 		if (IS_SELECTED(global_ds, port) && bmca_data->updt_info) {
1482 			gptp_change_pa_info_state(port, state,
1483 						  GPTP_PA_INFO_UPDATE);
1484 		} else if (bmca_data->rcvd_msg && !bmca_data->updt_info) {
1485 			gptp_change_pa_info_state(port, state,
1486 						  GPTP_PA_INFO_RECEIVE);
1487 		} else if ((bmca_data->info_is == GPTP_INFO_IS_RECEIVED) &&
1488 			   !bmca_data->updt_info &&
1489 			   !bmca_data->rcvd_msg &&
1490 			   (state->ann_expired ||
1491 			    (global_ds->gm_present &&
1492 			   pss_rcv->rcv_sync_receipt_timeout_timer_expired))) {
1493 			gptp_change_pa_info_state(port, state,
1494 						  GPTP_PA_INFO_AGED);
1495 		}
1496 
1497 		break;
1498 
1499 	case GPTP_PA_INFO_RECEIVE:
1500 		switch (rcv_info(port)) {
1501 		case GPTP_RCVD_INFO_SUPERIOR_MASTER_INFO:
1502 			gptp_change_pa_info_state(port, state,
1503 				GPTP_PA_INFO_SUPERIOR_MASTER_PORT);
1504 			break;
1505 		case GPTP_RCVD_INFO_REPEATED_MASTER_INFO:
1506 			gptp_change_pa_info_state(port, state,
1507 				GPTP_PA_INFO_REPEATED_MASTER_PORT);
1508 			break;
1509 		case GPTP_RCVD_INFO_INFERIOR_MASTER_INFO:
1510 			__fallthrough;
1511 		case GPTP_RCVD_INFO_OTHER_INFO:
1512 			gptp_change_pa_info_state(port, state,
1513 				GPTP_PA_INFO_INFERIOR_MASTER_OR_OTHER_PORT);
1514 			break;
1515 		}
1516 
1517 		break;
1518 
1519 	case GPTP_PA_INFO_SUPERIOR_MASTER_PORT:
1520 		/* We copy directly the content of the message to the port
1521 		 * priority vector without using an intermediate
1522 		 * messagePriority structure.
1523 		 */
1524 
1525 		if (!bmca_data->rcvd_announce_ptr) {
1526 			/* Shouldn't be reached. Checked for safety reason. */
1527 			bmca_data->rcvd_msg = false;
1528 			gptp_change_pa_info_state(port, state,
1529 						  GPTP_PA_INFO_CURRENT);
1530 			break;
1531 		}
1532 
1533 		copy_priority_vector(&bmca_data->port_priority,
1534 				     bmca_data->rcvd_announce_ptr, port);
1535 
1536 		announce = GPTP_ANNOUNCE(bmca_data->rcvd_announce_ptr);
1537 		bmca_data->port_steps_removed = ntohs(announce->steps_removed);
1538 		record_other_announce_info(port);
1539 		hdr = GPTP_HDR(bmca_data->rcvd_announce_ptr);
1540 		gptp_set_time_itv(&bmca_data->ann_rcpt_timeout_time_interval,
1541 				  port_ds->announce_receipt_timeout,
1542 				  hdr->log_msg_interval);
1543 		bmca_data->info_is = GPTP_INFO_IS_RECEIVED;
1544 		CLEAR_SELECTED(global_ds, port);
1545 		SET_RESELECT(global_ds, port);
1546 		__fallthrough;
1547 
1548 	case GPTP_PA_INFO_REPEATED_MASTER_PORT:
1549 		k_timer_stop(&state->ann_rcpt_expiry_timer);
1550 		state->ann_expired = false;
1551 		k_timer_start(&state->ann_rcpt_expiry_timer,
1552 			      K_MSEC(gptp_uscaled_ns_to_timer_ms(
1553 				  &bmca_data->ann_rcpt_timeout_time_interval)),
1554 			      K_NO_WAIT);
1555 		__fallthrough;
1556 
1557 	case GPTP_PA_INFO_INFERIOR_MASTER_OR_OTHER_PORT:
1558 		if (bmca_data->rcvd_announce_ptr != NULL) {
1559 			net_pkt_unref(bmca_data->rcvd_announce_ptr);
1560 			bmca_data->rcvd_announce_ptr = NULL;
1561 		}
1562 
1563 		bmca_data->rcvd_msg = false;
1564 		gptp_change_pa_info_state(port, state, GPTP_PA_INFO_CURRENT);
1565 		break;
1566 	}
1567 }
1568 
gptp_updt_role_disabled_tree(void)1569 static void gptp_updt_role_disabled_tree(void)
1570 {
1571 	struct gptp_global_ds *global_ds;
1572 	int port;
1573 
1574 	global_ds = GPTP_GLOBAL_DS();
1575 
1576 	/* Set all elements of the selectedRole array to DisabledPort. */
1577 	for (port = GPTP_PORT_START; port < GPTP_PORT_END; port++) {
1578 		gptp_change_port_state(port, GPTP_PORT_DISABLED);
1579 	}
1580 
1581 	/* Set lastGmPriority to all ones. */
1582 	(void)memset(&global_ds->last_gm_priority, 0xFF,
1583 		     sizeof(struct gptp_priority_vector));
1584 
1585 	/* Set pathTrace array to contain the single element thisClock. */
1586 	global_ds->path_trace.len = htons(GPTP_CLOCK_ID_LEN);
1587 	memcpy(global_ds->path_trace.path_sequence, GPTP_DEFAULT_DS()->clk_id,
1588 	       GPTP_CLOCK_ID_LEN);
1589 }
1590 
gptp_clear_reselect_tree(void)1591 static void gptp_clear_reselect_tree(void)
1592 {
1593 	/* Set all the elements of the reselect array to FALSE. */
1594 	GPTP_GLOBAL_DS()->reselect_array = 0;
1595 }
1596 
compute_best_vector(void)1597 static int compute_best_vector(void)
1598 {
1599 	struct gptp_priority_vector *gm_prio;
1600 	struct gptp_default_ds *default_ds;
1601 	struct gptp_global_ds *global_ds;
1602 	struct gptp_priority_vector *best_vector, *challenger;
1603 	int best_port, port, tmp;
1604 	struct gptp_pss_rcv_state *pss_rcv;
1605 	struct gptp_port_announce_information_state *pa_info_state;
1606 
1607 	default_ds = GPTP_DEFAULT_DS();
1608 	global_ds = GPTP_GLOBAL_DS();
1609 	best_port = 0;
1610 	gm_prio = &global_ds->gm_priority;
1611 
1612 	/* Write systemPriority into grandmaster. */
1613 	(void)memset(gm_prio, 0, sizeof(struct gptp_priority_vector));
1614 	gm_prio->root_system_id.grand_master_prio1 = default_ds->priority1;
1615 	gm_prio->root_system_id.grand_master_prio2 = default_ds->priority2;
1616 	gm_prio->root_system_id.clk_quality.clock_class =
1617 		default_ds->clk_quality.clock_class;
1618 	gm_prio->root_system_id.clk_quality.clock_accuracy =
1619 		default_ds->clk_quality.clock_accuracy;
1620 	gm_prio->root_system_id.clk_quality.offset_scaled_log_var =
1621 		htons(default_ds->clk_quality.offset_scaled_log_var);
1622 
1623 	memcpy(gm_prio->src_port_id.clk_id, default_ds->clk_id,
1624 	       GPTP_CLOCK_ID_LEN);
1625 	memcpy(gm_prio->root_system_id.grand_master_id, default_ds->clk_id,
1626 	       GPTP_CLOCK_ID_LEN);
1627 
1628 	best_vector = gm_prio;
1629 
1630 	for (port = GPTP_PORT_START; port < GPTP_PORT_END; port++) {
1631 		challenger = &GPTP_PORT_BMCA_DATA(port)->port_priority;
1632 		pa_info_state = &GPTP_PORT_STATE(port)->pa_info;
1633 		pss_rcv = &GPTP_PORT_STATE(port)->pss_rcv;
1634 
1635 		if (pa_info_state->ann_expired ||
1636 		    (global_ds->gm_present &&
1637 		     pss_rcv->rcv_sync_receipt_timeout_timer_expired)) {
1638 			continue;
1639 		}
1640 
1641 		if (memcmp(challenger->src_port_id.clk_id, default_ds->clk_id,
1642 			   GPTP_CLOCK_ID_LEN) == 0) {
1643 			/* Discard this challenger. */
1644 			continue;
1645 		}
1646 
1647 		if (best_port == 0) {
1648 			tmp = memcmp(&challenger->root_system_id,
1649 				     &best_vector->root_system_id,
1650 				     sizeof(struct gptp_root_system_identity));
1651 			if (tmp < 0) {
1652 				best_vector = challenger;
1653 				best_port = port;
1654 			} else if (tmp > 0) {
1655 				continue;
1656 			}
1657 
1658 			tmp = (int)challenger->steps_removed -
1659 				((int)ntohs(best_vector->steps_removed) + 1);
1660 			if (tmp < 0) {
1661 				best_vector = challenger;
1662 				best_port = port;
1663 			} else if (tmp > 0) {
1664 				continue;
1665 			}
1666 
1667 			tmp = memcmp(&challenger->src_port_id,
1668 				     &best_vector->src_port_id,
1669 				     sizeof(struct gptp_port_identity));
1670 			if (tmp < 0) {
1671 				best_vector = challenger;
1672 				best_port = port;
1673 			} else if (tmp > 0) {
1674 				continue;
1675 			}
1676 
1677 			if (ntohs(challenger->port_number) <
1678 			    ntohs(best_vector->port_number)) {
1679 				best_vector = challenger;
1680 				best_port = port;
1681 			}
1682 
1683 		} else {
1684 			/* We can compare portPriority vectors without
1685 			 * calculating pathPriority vectors.
1686 			 */
1687 			if (memcmp(challenger, best_vector,
1688 				   sizeof(struct gptp_priority_vector)) < 0) {
1689 				best_vector = challenger;
1690 				best_port = port;
1691 			}
1692 		}
1693 	}
1694 
1695 	if (best_port != 0) {
1696 		if (&global_ds->gm_priority.root_system_id !=
1697 		    &best_vector->root_system_id) {
1698 			memcpy(&global_ds->gm_priority.root_system_id,
1699 			       &best_vector->root_system_id,
1700 			       sizeof(struct gptp_root_system_identity));
1701 		}
1702 
1703 		global_ds->gm_priority.steps_removed =
1704 			htons(ntohs(best_vector->steps_removed) + 1);
1705 
1706 		if (&global_ds->gm_priority.src_port_id !=
1707 		    &best_vector->src_port_id) {
1708 			memcpy(&global_ds->gm_priority.src_port_id,
1709 			       &best_vector->src_port_id,
1710 			       sizeof(struct gptp_port_identity));
1711 		}
1712 
1713 		global_ds->gm_priority.port_number = best_vector->port_number;
1714 	}
1715 
1716 	return best_port;
1717 }
1718 
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)1719 static void update_bmca(int port,
1720 			int best_port,
1721 			struct gptp_global_ds *global_ds,
1722 			struct gptp_default_ds *default_ds,
1723 			struct gptp_priority_vector *gm_prio)
1724 {
1725 	struct gptp_port_bmca_data *bmca_data = GPTP_PORT_BMCA_DATA(port);
1726 
1727 	/* Update masterPriorityVector for the port. */
1728 	if (best_port == 0) {
1729 		memcpy(&bmca_data->master_priority, gm_prio,
1730 		       sizeof(struct gptp_priority_vector));
1731 
1732 		bmca_data->master_priority.port_number = htons(port);
1733 		bmca_data->master_priority.src_port_id.port_number =
1734 			htons(port);
1735 	} else {
1736 		memcpy(&bmca_data->master_priority.root_system_id,
1737 		       &gm_prio->root_system_id,
1738 		       sizeof(struct gptp_root_system_identity));
1739 		memcpy(bmca_data->master_priority.src_port_id.clk_id,
1740 		       default_ds->clk_id, GPTP_CLOCK_ID_LEN);
1741 		bmca_data->master_priority.port_number = htons(port);
1742 		bmca_data->master_priority.src_port_id.port_number =
1743 			htons(port);
1744 	}
1745 
1746 	switch (bmca_data->info_is) {
1747 	case GPTP_INFO_IS_DISABLED:
1748 		gptp_change_port_state(port, GPTP_PORT_DISABLED);
1749 		break;
1750 
1751 	case GPTP_INFO_IS_AGED:
1752 		bmca_data->updt_info = true;
1753 		gptp_change_port_state(port, GPTP_PORT_MASTER);
1754 		break;
1755 
1756 	case GPTP_INFO_IS_MINE:
1757 		gptp_change_port_state(port, GPTP_PORT_MASTER);
1758 
1759 		if ((memcmp(&bmca_data->port_priority,
1760 			    &bmca_data->master_priority,
1761 			    sizeof(struct gptp_priority_vector)) != 0) ||
1762 		    (bmca_data->port_steps_removed !=
1763 		     global_ds->master_steps_removed)) {
1764 			bmca_data->updt_info = true;
1765 		}
1766 
1767 		break;
1768 
1769 	case GPTP_INFO_IS_RECEIVED:
1770 		if (best_port == port) {
1771 			/* gmPriorityVector is now derived from
1772 			 * portPriorityVector.
1773 			 */
1774 			gptp_change_port_state(port, GPTP_PORT_SLAVE);
1775 			bmca_data->updt_info = false;
1776 		} else if (memcmp(&bmca_data->port_priority,
1777 				  &bmca_data->master_priority,
1778 				  sizeof(struct gptp_priority_vector)) <= 0) {
1779 			/* The masterPriorityVector is not better than
1780 			 * the portPriorityVector.
1781 			 */
1782 			gptp_change_port_state(port, GPTP_PORT_PASSIVE);
1783 
1784 			if (memcmp(bmca_data->port_priority.src_port_id.clk_id,
1785 				   default_ds->clk_id,
1786 				   GPTP_CLOCK_ID_LEN)) {
1787 				/* The sourcePortIdentity component of
1788 				 * the portPriorityVector does not
1789 				 * reflect another port on the
1790 				 * time-aware system.
1791 				 */
1792 				bmca_data->updt_info = true;
1793 			} else {
1794 				bmca_data->updt_info = false;
1795 			}
1796 		} else {
1797 			gptp_change_port_state(port, GPTP_PORT_MASTER);
1798 			bmca_data->updt_info = true;
1799 		}
1800 
1801 		break;
1802 	}
1803 }
1804 
gptp_updt_roles_tree(void)1805 static void gptp_updt_roles_tree(void)
1806 {
1807 	struct gptp_global_ds *global_ds;
1808 	struct gptp_default_ds *default_ds;
1809 	struct gptp_priority_vector *gm_prio, *last_gm_prio;
1810 	struct gptp_port_bmca_data *bmca_data;
1811 	int port, best_port;
1812 
1813 	global_ds = GPTP_GLOBAL_DS();
1814 	default_ds = GPTP_DEFAULT_DS();
1815 
1816 	gm_prio = &global_ds->gm_priority;
1817 	last_gm_prio = &global_ds->last_gm_priority;
1818 
1819 	/* Save gmPriority. */
1820 	memcpy(last_gm_prio, gm_prio, sizeof(struct gptp_priority_vector));
1821 
1822 	best_port = compute_best_vector();
1823 
1824 	/* If the best vector was the systemPriorityVector. */
1825 	if (best_port == 0) {
1826 		/* Copy leap61, leap59, current UTC offset valid,
1827 		 * time traceable and frequency traceable flags.
1828 		 */
1829 		global_ds->global_flags.octets[1] =
1830 			global_ds->sys_flags.octets[1];
1831 		global_ds->current_utc_offset =
1832 			global_ds->sys_current_utc_offset;
1833 		global_ds->time_source = global_ds->sys_time_source;
1834 		global_ds->master_steps_removed = 0U;
1835 	} else {
1836 		bmca_data = GPTP_PORT_BMCA_DATA(best_port);
1837 
1838 		/* Copy leap61, leap59, current UTC offset valid,
1839 		 * time traceable and frequency traceable flags.
1840 		 */
1841 		global_ds->global_flags.octets[1] =
1842 			bmca_data->ann_flags.octets[1];
1843 		global_ds->current_utc_offset =
1844 			global_ds->sys_current_utc_offset;
1845 		global_ds->time_source = bmca_data->ann_time_source;
1846 		global_ds->master_steps_removed =
1847 			htons(ntohs(bmca_data->message_steps_removed) + 1);
1848 	}
1849 
1850 	for (port = GPTP_PORT_START; port < GPTP_PORT_END; port++) {
1851 		update_bmca(port, best_port, global_ds, default_ds, gm_prio);
1852 	}
1853 
1854 	/* Update gmPresent. */
1855 	global_ds->gm_present =
1856 		(gm_prio->root_system_id.grand_master_prio1 == 255U) ?
1857 		false : true;
1858 
1859 	/* Assign the port role for port 0. */
1860 	for (port = GPTP_PORT_START; port < GPTP_PORT_END; port++) {
1861 		if (global_ds->selected_role[port] == GPTP_PORT_SLAVE) {
1862 			gptp_change_port_state(0, GPTP_PORT_PASSIVE);
1863 			break;
1864 		}
1865 	}
1866 
1867 	if (port == GPTP_PORT_END) {
1868 		gptp_change_port_state(0, GPTP_PORT_SLAVE);
1869 	}
1870 
1871 	/* If current system is the Grand Master, set pathTrace array. */
1872 	if (memcmp(default_ds->clk_id, gm_prio->root_system_id.grand_master_id,
1873 		   GPTP_CLOCK_ID_LEN) == 0) {
1874 		global_ds->path_trace.len = htons(GPTP_CLOCK_ID_LEN);
1875 		memcpy(global_ds->path_trace.path_sequence,
1876 		       default_ds->clk_id, GPTP_CLOCK_ID_LEN);
1877 	}
1878 }
1879 
gptp_set_selected_tree(void)1880 static void gptp_set_selected_tree(void)
1881 {
1882 	/* Set all the elements of the selected array to TRUE. */
1883 	GPTP_GLOBAL_DS()->selected_array = ~0;
1884 }
1885 
gptp_mi_port_role_selection_state_machine(void)1886 static void gptp_mi_port_role_selection_state_machine(void)
1887 {
1888 	struct gptp_port_role_selection_state *state;
1889 
1890 	state = &GPTP_STATE()->pr_sel;
1891 
1892 	switch (state->state) {
1893 	case GPTP_PR_SELECTION_INIT_BRIDGE:
1894 		gptp_updt_role_disabled_tree();
1895 		state->state = GPTP_PR_SELECTION_ROLE_SELECTION;
1896 
1897 		/* Be sure to enter the "if" statement immediately after. */
1898 		GPTP_GLOBAL_DS()->reselect_array = ~0;
1899 		__fallthrough;
1900 
1901 	case GPTP_PR_SELECTION_ROLE_SELECTION:
1902 		if (GPTP_GLOBAL_DS()->reselect_array != 0) {
1903 			gptp_clear_reselect_tree();
1904 			gptp_updt_roles_tree();
1905 			gptp_set_selected_tree();
1906 		}
1907 
1908 		break;
1909 	}
1910 }
1911 
tx_announce(int port)1912 static void tx_announce(int port)
1913 {
1914 	struct net_pkt *pkt;
1915 
1916 	pkt = gptp_prepare_announce(port);
1917 	if (pkt) {
1918 		gptp_send_announce(port, pkt);
1919 	}
1920 }
1921 
gptp_mi_port_announce_transmit_state_machine(int port)1922 static void gptp_mi_port_announce_transmit_state_machine(int port)
1923 {
1924 	struct gptp_port_ds *port_ds;
1925 	struct gptp_global_ds *global_ds;
1926 	struct gptp_port_announce_transmit_state *state;
1927 	struct gptp_port_bmca_data *bmca_data;
1928 
1929 	port_ds = GPTP_PORT_DS(port);
1930 	global_ds = GPTP_GLOBAL_DS();
1931 	bmca_data = GPTP_PORT_BMCA_DATA(port);
1932 	state = &GPTP_PORT_STATE(port)->pa_transmit;
1933 
1934 	/* Reset interval as defined in AnnounceIntervalSetting
1935 	 * state machine.
1936 	 */
1937 	if (port_ds->ptt_port_enabled && !port_ds->prev_ptt_port_enabled) {
1938 		gptp_update_announce_interval(port, GPTP_ITV_SET_TO_INIT);
1939 	}
1940 
1941 	switch (state->state) {
1942 	case GPTP_PA_TRANSMIT_INIT:
1943 		bmca_data->new_info = true;
1944 		__fallthrough;
1945 
1946 	case GPTP_PA_TRANSMIT_IDLE:
1947 		k_timer_stop(&state->ann_send_periodic_timer);
1948 		state->ann_trigger = false;
1949 		k_timer_start(&state->ann_send_periodic_timer,
1950 			      K_MSEC(gptp_uscaled_ns_to_timer_ms(
1951 					     &bmca_data->announce_interval)),
1952 			      K_NO_WAIT);
1953 
1954 		state->state = GPTP_PA_TRANSMIT_POST_IDLE;
1955 		__fallthrough;
1956 
1957 	case GPTP_PA_TRANSMIT_POST_IDLE:
1958 		if (IS_SELECTED(global_ds, port) &&
1959 		    !bmca_data->updt_info &&
1960 		    state->ann_trigger) {
1961 
1962 			state->state = GPTP_PA_TRANSMIT_PERIODIC;
1963 
1964 		} else if (IS_SELECTED(global_ds, port) &&
1965 			   !bmca_data->updt_info &&
1966 			   !state->ann_trigger &&
1967 			   (global_ds->selected_role[port] ==
1968 			    GPTP_PORT_MASTER) &&
1969 			   bmca_data->new_info) {
1970 
1971 			bmca_data->new_info = false;
1972 			tx_announce(port);
1973 			state->state = GPTP_PA_TRANSMIT_IDLE;
1974 		}
1975 
1976 		break;
1977 
1978 	case GPTP_PA_TRANSMIT_PERIODIC:
1979 		if (global_ds->selected_role[port] == GPTP_PORT_MASTER) {
1980 			bmca_data->new_info = true;
1981 		}
1982 		state->state = GPTP_PA_TRANSMIT_IDLE;
1983 		break;
1984 	}
1985 }
1986 
1987 
gptp_mi_port_sync_state_machines(int port)1988 void gptp_mi_port_sync_state_machines(int port)
1989 {
1990 	gptp_mi_pss_rcv_state_machine(port);
1991 	gptp_mi_pss_send_state_machine(port);
1992 }
1993 
gptp_mi_port_bmca_state_machines(int port)1994 void gptp_mi_port_bmca_state_machines(int port)
1995 {
1996 	gptp_mi_port_announce_receive_state_machine(port);
1997 	gptp_mi_port_announce_information_state_machine(port);
1998 	gptp_mi_port_announce_transmit_state_machine(port);
1999 }
2000 
gptp_mi_state_machines(void)2001 void gptp_mi_state_machines(void)
2002 {
2003 	gptp_mi_site_sync_sync_state_machine();
2004 	gptp_mi_clk_slave_sync_state_machine();
2005 	gptp_mi_port_role_selection_state_machine();
2006 	gptp_mi_clk_master_sync_offset_state_machine();
2007 #if defined(CONFIG_NET_GPTP_GM_CAPABLE)
2008 	gptp_mi_clk_master_sync_snd_state_machine();
2009 #endif
2010 	gptp_mi_clk_master_sync_rcv_state_machine();
2011 }
2012