From 39f3a83dcd333a507c26c6bd2054dd9c1c53177e Mon Sep 17 00:00:00 2001
From: Adam Wujek <adam.wujek@cern.ch>
Date: Fri, 9 Jan 2015 16:20:12 +0100
Subject: [PATCH] userspace/tools: make wr_phytool to use ports info via shm

Signed-off-by: Adam Wujek <adam.wujek@cern.ch>
---
 userspace/libwr/include/libwr/ptpd_netif.h | 10 ++-
 userspace/libwr/ptpd_netif.c               | 45 ++++++++------
 userspace/tools/wr_phytool.c               | 71 +++++++++++++++-------
 3 files changed, 82 insertions(+), 44 deletions(-)

diff --git a/userspace/libwr/include/libwr/ptpd_netif.h b/userspace/libwr/include/libwr/ptpd_netif.h
index e3da1b0f0..14618fe42 100644
--- a/userspace/libwr/include/libwr/ptpd_netif.h
+++ b/userspace/libwr/include/libwr/ptpd_netif.h
@@ -5,6 +5,8 @@
 
 #include <stdio.h>
 #include <net/ethernet.h>
+#include <libwr/hal_shmem.h>
+#include <libwr/hal_client.h>
 
 #define PTPD_SOCK_RAW_ETHERNET 	1
 #define PTPD_SOCK_UDP 		2
@@ -80,7 +82,8 @@ int ptpd_netif_init();
 // Creates UDP or Ethernet RAW socket (determined by sock_type) bound to bind_addr. If PTPD_FLAG_MULTICAST is set, the socket is
 // automatically added to multicast group. User can specify physical_port field to bind the socket to specific switch port only.
 struct wr_socket *ptpd_netif_create_socket(int sock_type, int flags,
-				      struct wr_sockaddr *bind_addr);
+				      struct wr_sockaddr *bind_addr,
+				      struct hal_port_state *port);
 
 // Sends a UDP/RAW packet (data, data_length) to address provided in wr_sockaddr
 // For raw frames, mac/ethertype needs to be provided, for UDP - ip/port.
@@ -94,7 +97,8 @@ int ptpd_netif_sendto(struct wr_socket *sock, struct wr_sockaddr *to, void *data
 // by data_length parameter. Sender information is stored in structure specified in 'from'. All RXed packets are timestamped and the timestamp
 // is stored in rx_timestamp (unless it's NULL).
 int ptpd_netif_recvfrom(struct wr_socket *sock, struct wr_sockaddr *from, void *data,
-			size_t data_length, struct wr_tstamp *rx_timestamp);
+			size_t data_length, struct wr_tstamp *rx_timestamp,
+			struct hal_port_state *port);
 
 // Closes the socket.
 int ptpd_netif_close_socket(struct wr_socket *sock);
@@ -112,7 +116,7 @@ int ptpd_netif_poll(struct wr_sockaddr *);
 
 /* Timebase adjustment functions - the servo should not call the HAL directly */
 int ptpd_netif_adjust_counters(int64_t adjust_sec, int32_t adjust_nsec);
-int ptpd_netif_get_dmtd_phase(struct wr_socket *sock, int32_t *phase);
+int ptpd_netif_get_dmtd_phase(int32_t *phase, struct hal_port_state *p);
 void ptpd_netif_linearize_rx_timestamp(struct wr_tstamp *ts, int32_t dmtd_phase,
 				       int cntr_ahead, int transition_point,
 				       int clock_period);
diff --git a/userspace/libwr/ptpd_netif.c b/userspace/libwr/ptpd_netif.c
index ea50a2f25..d28727725 100644
--- a/userspace/libwr/ptpd_netif.c
+++ b/userspace/libwr/ptpd_netif.c
@@ -23,7 +23,10 @@
 #include <asm/socket.h>
 
 #include <libwr/ptpd_netif.h>
+#include <libwr/shmem.h>
+#include <libwr/hal_shmem.h>
 #include <libwr/hal_client.h>
+#include <libwr/switch_hw.h>
 #include <net/ethernet.h>
 
 #ifdef NETIF_VERBOSE
@@ -83,27 +86,29 @@ static inline int inside_range(int min, int max, int x)
 }
 
 /* For debugging/testing purposes */
-int ptpd_netif_get_dmtd_phase(struct wr_socket *s, int32_t *phase)
+int ptpd_netif_get_dmtd_phase(int32_t *phase, struct hal_port_state *p)
 {
-	hexp_port_state_t pstate;
+	int phase_val_valid_local;
 
-	halexp_get_port_state(&pstate, s->bind_addr.if_name);
+	if (!p)
+		return -1;
 
+	phase_val_valid_local = p->phase_val_valid;
 	if (phase)
-		*phase = pstate.phase_val;
-	return pstate.phase_val_valid;
+		*phase = phase_val_valid_local;
+	return phase_val_valid_local;
 }
 
-static void update_dmtd(struct wr_socket *s)
+static void update_dmtd(struct wr_socket *s, struct hal_port_state *p)
 {
-	hexp_port_state_t pstate;
 
-	if (tmo_expired(&s->dmtd_update_tmo)) {
-		halexp_get_port_state(&pstate, s->bind_addr.if_name);
+	if (!p)
+		return;
 
+	if (tmo_expired(&s->dmtd_update_tmo)) {
 		// FIXME: ccheck if phase value is ready
-		s->dmtd_phase = pstate.phase_val;
-		s->dmtd_phase_valid = pstate.phase_val_valid;
+		s->dmtd_phase = p->phase_val;
+		s->dmtd_phase_valid = p->phase_val_valid;
 
 		tmo_restart(&s->dmtd_update_tmo);
 	}
@@ -169,14 +174,13 @@ int ptpd_netif_init()
 }
 
 struct wr_socket *ptpd_netif_create_socket(int sock_type, int flags,
-				      struct wr_sockaddr *bind_addr)
+				      struct wr_sockaddr *bind_addr,
+				      struct hal_port_state *port)
 {
 	struct wr_socket *s;
 	struct sockaddr_ll sll;
 	struct ifreq f;
 
-	hexp_port_state_t pstate;
-
 	int fd;
 
 	//    fprintf(stderr,"CreateSocket!\n");
@@ -184,7 +188,7 @@ struct wr_socket *ptpd_netif_create_socket(int sock_type, int flags,
 	if (sock_type != PTPD_SOCK_RAW_ETHERNET)
 		return NULL;
 
-	if (halexp_get_port_state(&pstate, bind_addr->if_name) < 0)
+	if (!port)
 		return NULL;
 
 	fd = socket(PF_PACKET, SOCK_RAW, htons(ETH_P_ALL));
@@ -267,10 +271,10 @@ struct wr_socket *ptpd_netif_create_socket(int sock_type, int flags,
 	s->fd = fd;
 
 	// store the linearization parameters
-	s->clock_period = pstate.clock_period;
-	s->phase_transition = pstate.t2_phase_transition;
+	s->clock_period = REF_CLOCK_PERIOD_PS;
+	s->phase_transition = DEFAULT_T2_PHASE_TRANS;
 	s->dmtd_phase_valid = 0;
-	s->dmtd_phase = pstate.phase_val;
+	s->dmtd_phase = port->phase_val;
 
 	tmo_init(&s->dmtd_update_tmo, DMTD_UPDATE_INTERVAL);
 
@@ -406,7 +410,8 @@ static void poll_tx_timestamp(struct wr_socket *s, struct wr_tstamp *tx_timestam
 }
 
 int ptpd_netif_recvfrom(struct wr_socket *s, struct wr_sockaddr *from, void *data,
-			size_t data_length, struct wr_tstamp *rx_timestamp)
+			size_t data_length, struct wr_tstamp *rx_timestamp,
+			struct hal_port_state *port)
 {
 	struct etherpacket pkt;
 	struct msghdr msg;
@@ -468,7 +473,7 @@ int ptpd_netif_recvfrom(struct wr_socket *s, struct wr_sockaddr *from, void *dat
 		rx_timestamp->raw_nsec = sts->hwtimeraw.tv_nsec;
 		rx_timestamp->raw_ahead = cntr_ahead;
 
-		update_dmtd(s);
+		update_dmtd(s, port);
 		if (s->dmtd_phase_valid) {
 			ptpd_netif_linearize_rx_timestamp(rx_timestamp,
 							  s->dmtd_phase,
diff --git a/userspace/tools/wr_phytool.c b/userspace/tools/wr_phytool.c
index ab46cbc3c..7349dcb27 100644
--- a/userspace/tools/wr_phytool.c
+++ b/userspace/tools/wr_phytool.c
@@ -50,27 +50,46 @@ static struct EP_WB _ep_wb;
 
 extern int rts_connect();
 
-int get_nports_from_hal(void)
+static int hal_nports_local;
+static struct wrs_shm_head *hal_head;
+static struct hal_port_state *hal_ports;
+
+int hal_shm_init(void)
 {
+	int ii;
 	struct hal_shmem_header *h;
-	struct wrs_shm_head *hal_head;
-	int hal_nports_local; /* local copy of number of ports */
 
-	hal_head = wrs_shm_get(wrs_shm_hal, "", WRS_SHM_READ);
+	/* open shmem to HAL */
+	hal_head = wrs_shm_get(wrs_shm_hal, "", WRS_SHM_READ | WRS_SHM_LOCKED);
 	if (!hal_head) {
-		fprintf(stderr, "unable to open shm for HAL!\n");
-		exit(-1);
+		fprintf(stderr,
+			"FATAL: wr_phytool unable to open shm to HAL.\n");
+		return -1;
 	}
+
 	h = (void *)hal_head + hal_head->data_off;
-	/* Assume number of ports does not change in runtime */
-	hal_nports_local = h->nports;
+
+	while (1) { /* wait forever for HAL to produce consistent nports */
+		ii = wrs_shm_seqbegin(hal_head);
+		/* Assume number of ports does not change in runtime */
+		hal_nports_local = h->nports;
+		if (!wrs_shm_seqretry(hal_head, ii))
+			break;
+		fprintf(stderr, "INFO: wr_phytool Wait for HAL.\n");
+		sleep(1);
+	}
+
+	/* Even after HAL restart, HAL will place structures at the same
+	 * addresses. No need to re-dereference pointer at each read. */
+	hal_ports = wrs_shm_follow(hal_head, h->ports);
 	if (hal_nports_local > HAL_MAX_PORTS) {
-		fprintf(stderr, "Too many ports reported by HAL. "
+		fprintf(stderr,
+			"FATAL: wr_phytool Too many ports reported by HAL."
 			"%d vs %d supported\n",
 			hal_nports_local, HAL_MAX_PORTS);
-		exit(-1);
+		return -1;
 	}
-	return hal_nports_local;
+	return 0;
 }
 
 int fpga_map(char *prgname)
@@ -247,6 +266,7 @@ void calc_trans(int ep, int argc, char *argv[])
 	FILE *f_log = NULL;
 	struct wr_sockaddr sock_addr, from;
 	int bitslide,phase, i;
+	struct hal_port_state *port;
 
 	signal (SIGINT, sighandler);
 	for(i=0;i<MAX_BITSLIDES;i++)
@@ -265,8 +285,12 @@ void calc_trans(int ep, int argc, char *argv[])
 	memset(sock_addr.mac, 0xff, 6);
 
 	assert(ptpd_netif_init() == 0);
+	assert(hal_shm_init() == 0);
+	port = hal_lookup_port(hal_ports, hal_nports_local,
+			       sock_addr.if_name);
+	sock = ptpd_netif_create_socket(PTPD_SOCK_RAW_ETHERNET, 0, &sock_addr,
+					port);
 
-	sock = ptpd_netif_create_socket(PTPD_SOCK_RAW_ETHERNET, 0, &sock_addr);
 //	fpga_writel(EP_DMCR_N_AVG_W(1024) | EP_DMCR_EN, IDX_TO_EP(ep) + EP_REG(DMCR));
 
 	if( rts_connect() < 0)
@@ -312,7 +336,8 @@ void calc_trans(int ep, int argc, char *argv[])
 		to.family = PTPD_SOCK_RAW_ETHERNET; // socket type
 
 		ptpd_netif_sendto(sock, &to, buf, 64, &ts_tx);
-		int n = ptpd_netif_recvfrom(sock, &from, buf, 64, &ts_rx);
+		int n = ptpd_netif_recvfrom(sock, &from, buf, 64, &ts_rx,
+					    port);
 
 
 		if(n>0)
@@ -378,6 +403,7 @@ void pps_adjustment_test(int ep, int argc, char *argv[])
 	struct wr_socket *sock;
 	struct wr_sockaddr sock_addr, from;
 	int adjust_count = 0;
+	struct hal_port_state *port;
 
 	signal (SIGINT, sighandler);
 
@@ -387,9 +413,11 @@ void pps_adjustment_test(int ep, int argc, char *argv[])
 	memset(sock_addr.mac, 0xff, 6);
 
 	assert(ptpd_netif_init() == 0);
-
-	sock = ptpd_netif_create_socket(PTPD_SOCK_RAW_ETHERNET, 0, &sock_addr);
-
+	assert(hal_shm_init() == 0);
+	port = hal_lookup_port(hal_ports, hal_nports_local,
+			       sock_addr.if_name);
+	sock = ptpd_netif_create_socket(PTPD_SOCK_RAW_ETHERNET, 0, &sock_addr,
+					port);
 
 	while(!quit)
 	{
@@ -409,7 +437,8 @@ void pps_adjustment_test(int ep, int argc, char *argv[])
 //		if(!ptpd_netif_adjust_in_progress())
 		{
 			ptpd_netif_sendto(sock, &to, buf, 64, &ts_tx);
-			ptpd_netif_recvfrom(sock, &from, buf, 64, &ts_rx);
+			ptpd_netif_recvfrom(sock, &from, buf, 64, &ts_rx,
+					    port);
 			printf("TX timestamp: correct %d %12lld:%12d\n", ts_tx.correct, ts_tx.sec, ts_tx.nsec);
 			printf("RX timestamp: correct %d %12lld:%12d\n", ts_rx.correct, ts_rx.sec, ts_rx.nsec);
 			adjust_count --;
@@ -423,9 +452,8 @@ void rt_command(int ep, int argc, char *argv[])
 {
 	struct rts_pll_state pstate;
 	int i;
-	int nports;
 
-	nports = get_nports_from_hal();
+	assert(hal_shm_init() == 0); /* to get hal_nports_local */
 
 	if(	rts_connect() < 0)
 	{
@@ -437,9 +465,10 @@ void rt_command(int ep, int argc, char *argv[])
 
 	if(!strcmp(argv[3], "show"))
 	{
-		printf("RTS State Dump [%d physical ports]:\n", nports);
+		printf("RTS State Dump [%d physical ports]:\n",
+		       hal_nports_local);
 		printf("CurrentRef: %d Mode: %d Flags: %x\n", pstate.current_ref, pstate.mode, pstate.flags);
-		for (i = 0; i < nports; i++)
+		for (i = 0; i < hal_nports_local; i++)
 			printf("wr%-2d: setpoint: %-8dps current: %-8dps loopback: %-8dps flags: %x\n", i,
 			       pstate.channels[i].phase_setpoint,
 			       pstate.channels[i].phase_current,
-- 
GitLab