diff --git a/clock.c b/clock.c index 5b251c1..6ed0305 100644 --- a/clock.c +++ b/clock.c @@ -82,7 +82,6 @@ struct clock { struct ClockIdentity best_id; struct port *port[CLK_N_PORTS]; struct pollfd pollfd[CLK_N_PORTS*N_CLOCK_PFD]; - int fault_fd[CLK_N_PORTS]; int nports; /* does not include the UDS port */ int free_running; int freq_est_interval; @@ -257,10 +256,8 @@ void clock_destroy(struct clock *c) int i; clock_flush_subscriptions(c); - for (i = 0; i < c->nports; i++) { + for (i = 0; i < c->nports; i++) port_close(c->port[i]); - close(c->fault_fd[i]); - } port_close(c->port[i]); /*uds*/ if (c->clkid != CLOCK_REALTIME) { phc_close(c->clkid); @@ -282,7 +279,7 @@ static int clock_fault_timeout(struct clock *c, int index, int set) if (!set) { pr_debug("clearing fault on port %d", index + 1); - return set_tmo_lin(c->fault_fd[index], 0); + return port_set_fault_timer_lin(c->port[index], 0); } fault_interval(c->port[index], last_fault_type(c->port[index]), &i); @@ -290,11 +287,11 @@ static int clock_fault_timeout(struct clock *c, int index, int set) if (i.type == FTMO_LINEAR_SECONDS) { pr_debug("waiting %d seconds to clear fault on port %d", i.val, index + 1); - return set_tmo_lin(c->fault_fd[index], i.val); + return port_set_fault_timer_lin(c->port[index], i.val); } else if (i.type == FTMO_LOG2_SECONDS) { pr_debug("waiting 2^{%d} seconds to clear fault on port %d", i.val, index + 1); - return set_tmo_log(c->fault_fd[index], 1, i.val); + return port_set_fault_timer_log(c->port[index], 1, i.val); } pr_err("Unsupported fault interval type %d", i.type); @@ -863,12 +860,7 @@ struct clock *clock_create(int phc_index, struct interface *iface, int count, pr_err("failed to open port %s", iface[i].name); return NULL; } - c->fault_fd[i] = timerfd_create(CLOCK_MONOTONIC, 0); - if (c->fault_fd[i] < 0) { - pr_err("timerfd_create failed: %m"); - return NULL; - } - c->pollfd[N_CLOCK_PFD * i + N_POLLFD].fd = c->fault_fd[i]; + c->pollfd[N_CLOCK_PFD * i + N_POLLFD].fd = port_fault_fd(c->port[i]); c->pollfd[N_CLOCK_PFD * i + N_POLLFD].events = POLLIN|POLLPRI; } diff --git a/port.c b/port.c index 080bc8e..bd1b178 100644 --- a/port.c +++ b/port.c @@ -65,6 +65,7 @@ struct port { struct transport *trp; enum timestamp_type timestamping; struct fdarray fda; + int fault_fd; struct foreign_clock *best; enum syfu_state syfu; struct ptp_message *last_syncfup; @@ -193,6 +194,11 @@ int fault_interval(struct port *port, enum fault_type ft, return 0; } +int port_fault_fd(struct port *port) +{ + return port->fault_fd; +} + int set_tmo_log(int fd, unsigned int scale, int log_seconds) { struct itimerspec tmo = { @@ -253,6 +259,17 @@ int set_tmo_random(int fd, int min, int span, int log_seconds) return timerfd_settime(fd, 0, &tmo, NULL); } +int port_set_fault_timer_log(struct port *port, + unsigned int scale, int log_seconds) +{ + return set_tmo_log(port->fault_fd, scale, log_seconds); +} + +int port_set_fault_timer_lin(struct port *port, int seconds) +{ + return set_tmo_lin(port->fault_fd, seconds); +} + static void fc_clear(struct foreign_clock *fc) { struct ptp_message *m; @@ -1903,6 +1920,8 @@ void port_close(struct port *p) } transport_destroy(p->trp); filter_destroy(p->delay_filter); + if (p->fault_fd >= 0) + close(p->fault_fd); free(p); } @@ -2408,18 +2427,15 @@ struct port *port_open(int phc_index, pr_err("port %d: PHC device mismatch", number); pr_err("port %d: /dev/ptp%d requested, but /dev/ptp%d attached", number, phc_index, interface->ts_info.phc_index); - free(p); - return NULL; + goto err_port; } p->pod = interface->pod; p->name = interface->name; p->clock = clock; p->trp = transport_create(interface->transport); - if (!p->trp) { - free(p); - return NULL; - } + if (!p->trp) + goto err_port; p->timestamping = timestamping; p->portIdentity.clockIdentity = clock_identity(clock); p->portIdentity.portNumber = number; @@ -2431,12 +2447,27 @@ struct port *port_open(int phc_index, interface->delay_filter_length); if (!p->delay_filter) { pr_err("Failed to create delay filter"); - transport_destroy(p->trp); - free(p); - return NULL; + goto err_transport; } p->nrate.ratio = 1.0; + + p->fault_fd = -1; + if (number) { + p->fault_fd = timerfd_create(CLOCK_MONOTONIC, 0); + if (p->fault_fd < 0) { + pr_err("timerfd_create failed: %m"); + goto err_filter; + } + } return p; + +err_filter: + filter_destroy(p->delay_filter); +err_transport: + transport_destroy(p->trp); +err_port: + free(p); + return NULL; } enum port_state port_state(struct port *port) diff --git a/port.h b/port.h index a1b8ad7..20d0f4c 100644 --- a/port.h +++ b/port.h @@ -200,6 +200,13 @@ struct port *port_open(int phc_index, */ enum port_state port_state(struct port *port); +/** + * Return file descriptor of the port. + * @param port A port instance. + * @return File descriptor or -1 if not applicable. + */ +int port_fault_fd(struct port *port); + /** * Utility function for setting or resetting a file descriptor timer. * @@ -244,6 +251,28 @@ int set_tmo_random(int fd, int min, int span, int log_seconds); */ int set_tmo_lin(int fd, int seconds); +/** + * Sets port's fault file descriptor timer. + * Passing both 'scale' and 'log_seconds' as zero disables the timer. + * + * @param fd A port instance. + * @param scale The multiplicative factor for the timer. + * @param log_seconds The exponential factor for the timer. + * @return Zero on success, non-zero otherwise. + */ +int port_set_fault_timer_log(struct port *port, + unsigned int scale, int log_seconds); + +/** + * Sets port's fault file descriptor timer. + * Passing 'seconds' as zero disables the timer. + * + * @param fd A port instance. + * @param seconds The timeout value for the timer. + * @return Zero on success, non-zero otherwise. + */ +int port_set_fault_timer_lin(struct port *port, int seconds); + /** * Returns a port's last fault type. *