> -----Original Message----- > From: Aya Levin via Linuxptp-devel <linuxptp-devel@lists.sourceforge.net> > Sent: Wednesday, June 8, 2022 12:54 PM > > On 6/8/2022 12:55 PM, Erez wrote: > > > > אינך מקבל לעתים קרובות דואר אלקטרוני מ- erezge...@gmail.com. למד מדוע > > הדבר חשוב <https://aka.ms/LearnAboutSenderIdentification> > > > > > > > > > > On Wed, 8 Jun 2022 at 11:11, Aya Levin via Linuxptp-devel > > <linuxptp-devel@lists.sourceforge.net > > <mailto:linuxptp-devel@lists.sourceforge.net>> wrote: > > > > > > > > On 5/30/2022 10:34 PM, Arkadiusz Kubalewski wrote: > > > synce_dev interface allows creation, initialization, stepping and > > > destroying of a single SyncE device. > > > > > > Newly created device must be given a device name (same as in config > > > file). > > > > > > After creation the SyncE device is initialized with config struct, > > > where device-level configuration for this device must exists. > > > All ports belonging to this device are also initialized (at least one > > > port configured is required). > > > > > > Once initialized SyncE device is ready for stepping. > > > Each step will: > > > - verify if device is in running state > > > - acquire current state of the DPLL > > > - performs actual step of a device, either as internal or external > > > powered frequency provider for all the ports confgiured > > > > > > Destroying the SyncE device releases all its resources. > > > > > > Co-developed-by: Anatolii Gerasymenko > > <anatolii.gerasyme...@intel.com <mailto:anatolii.gerasyme...@intel.com>> > > > Signed-off-by: Anatolii Gerasymenko > > <anatolii.gerasyme...@intel.com <mailto:anatolii.gerasyme...@intel.com>> > > > Co-developed-by: Piotr Kwapulinski <piotr.kwapulin...@intel.com > > <mailto:piotr.kwapulin...@intel.com>> > > > Signed-off-by: Piotr Kwapulinski <piotr.kwapulin...@intel.com > > <mailto:piotr.kwapulin...@intel.com>> > > > Co-developed-by: Michal Michalik <michal.micha...@intel.com > > <mailto:michal.micha...@intel.com>> > > > Signed-off-by: Michal Michalik <michal.micha...@intel.com > > <mailto:michal.micha...@intel.com>> > > > Signed-off-by: Arkadiusz Kubalewski > > <arkadiusz.kubalew...@intel.com <mailto:arkadiusz.kubalew...@intel.com>> > > > --- > > > v2: updated license headers > > > v3: rebase patch series > > > > > > synce_dev.c | 622 > > ++++++++++++++++++++++++++++++++++++++++++++++++++++ > > > synce_dev.h | 64 ++++++ > > > 2 files changed, 686 insertions(+) > > > create mode 100644 synce_dev.c > > > create mode 100644 synce_dev.h > > > > > > diff --git a/synce_dev.c b/synce_dev.c > > > new file mode 100644 > > > index 0000000..dfe7ff4 > > > --- /dev/null > > > +++ b/synce_dev.c > > > @@ -0,0 +1,622 @@ > > > +/** > > > + * @file synce_dev.c > > > + * @brief Interface for handling Sync-E capable devices and its > > ports > > > + * @note SPDX-FileCopyrightText: Copyright 2022 Intel Corporation > > > + * @note SPDX-License-Identifier: GPL-2.0+ > > > + */ > > > +#include <stdlib.h> > > > +#include <sys/queue.h> > > > +#include <net/if.h> > > > +#include <errno.h> > > > +#include "synce_dev.h" > > > +#include "print.h" > > > +#include "config.h" > > > +#include "util.h" > > > +#include "synce_port.h" > > > +#include "missing.h" > > > +#include "synce_dev_ctrl.h" > > > +#include "synce_msg.h" > > > + > > > +struct interface { > > > + STAILQ_ENTRY(interface) list; > > > +}; > > > + > > > +struct synce_dev_ops { > > > + int (*update_ql)(struct synce_dev *dev); > > > + int (*step)(struct synce_dev *dev); > > > +}; > > > + > > > +enum synce_dev_state { > > > + DEVICE_UNKNOWN, > > > + DEVICE_CREATED, > > > + DEVICE_INITED, > > > + DEVICE_RUNNING, > > > + DEVICE_FAILED, > > > +}; > > > + > > > +struct synce_dev { > > > + LIST_ENTRY(synce_dev) list; > > > + enum synce_dev_state state; > > > + char name[IF_NAMESIZE]; > > > + LIST_HEAD(synce_ports_head, synce_port) ports; > > > + struct synce_port *best_source; > > > + int num_ports; > > > + int internal_input; > > > + int external_input; > > > + int network_option; > > > + uint8_t ql; > > > + uint8_t ext_ql; > > > + int extended_tlv; > > > + int recover_time; > > > + enum dpll_state d_state; > > > + enum dpll_state last_d_state; > > > + struct synce_dev_ctrl *dc; > > > + struct synce_dev_ops ops; > > > +}; > > > + > > > +static int add_port(struct synce_dev *dev, struct synce_port *port) > > > +{ > > > + struct synce_port *port_iter, *last_port = NULL; > > > + > > > + LIST_FOREACH(port_iter, &dev->ports, list) { > > > + last_port = port_iter; > > > + } > > > + > > > + if (last_port) { > > > + LIST_INSERT_AFTER(last_port, port, list); > > > + } else { > > > + LIST_INSERT_HEAD(&dev->ports, port, list); > > > + } > > > + return 0; > > > +} > > > + > > > +static int rx_enabled(struct synce_dev *dev) > > > +{ > > > + return (dev->external_input == 0 && > > > + dev->internal_input != 0); > > > +} > > > + > > > +static void destroy_ports(struct synce_dev *dev) > > > +{ > > > + struct synce_port *port, *tmp; > > > + > > > + LIST_FOREACH_SAFE(port, &dev->ports, list, tmp) { > > > + synce_port_destroy(port); > > > + LIST_REMOVE(port, list); > > > + free(port); > > > + } > > > + dev->num_ports = 0; > > > +} > > > + > > > +static void destroy_dev_ctrl(struct synce_dev *dev) > > > +{ > > > + free(dev->dc); > > > + dev->dc = NULL; > > > +} > > > + > > > +static int init_ports(int *count, struct synce_dev *dev, struct > > config *cfg) > > > +{ > > > + struct interface *iface; > > > + struct synce_port *port; > > > + const char *port_name; > > > + > > > + *count = 0; > > > + > > > + STAILQ_FOREACH(iface, &cfg->interfaces, list) { > > > + /* given device takes care only of its child ports */ > > > + if (interface_se_has_parent_dev(iface) && > > > + (strncmp(interface_se_get_parent_dev_label(iface), > > > + dev->name, sizeof(dev->name)) == 0)) { > > > + port_name = interface_name(iface); > > > + > > > + /* If no sync mode, no need to maintain the > > port */ > > > + if (!synce_port_in_sync_mode(cfg, port_name)) { > > > + continue; > > > + } > > > + > > > + port = synce_port_create(port_name); > > > + if (!port) { > > > + pr_err("failed to create port %s on > > device %s", > > > + port_name, dev->name); > > > + continue; > > > + } > > > + > > > + if (synce_port_init(port, cfg, > > dev->network_option, > > > + dev->extended_tlv, > > rx_enabled(dev), > > > + dev->recover_time, dev->ql, > > > + dev->ext_ql)) { > > > + pr_err("failed to configure port %s > > on device %s", > > > + port_name, dev->name); > > > + synce_port_destroy(port); > > > + continue; > > > + } > > > + > > > + if (add_port(dev, port)) { > > > + pr_err("failed to add port %s to > > device %s", > > > + port_name, dev->name); > > > + synce_port_destroy(port); > > > + continue; > > > + } else { > > > + (*count)++; > > > + pr_debug("port %s added on device > > %s addr %p", > > > + port_name, dev->name, port); > > > + } > > > + } > > > + } > > > + > > > + if (*count == 0) { > > > + pr_err("device %s has no ports configured", dev->name); > > > + return -ENODEV; > > > + } > > > + > > > + return 0; > > > +} > > > + > > > +static void update_dev_state(struct synce_dev *dev) > > > +{ > > > + struct synce_port *p; > > > + int count = 0; > > > + > > > + LIST_FOREACH(p, &dev->ports, list) { > > > + if (synce_port_thread_running(p)) { > > > + count++; > > > + } > > > + } > > > + > > > + if (dev->num_ports == count) { > > > + dev->state = DEVICE_RUNNING; > > > + } else { > > > + pr_warning("found %d ports running - %d configured > > on %s", > > > + count, dev->num_ports, dev->name); > > > + } > > > +} > > > + > > > +static int port_set_dnu(struct synce_port *p, int extended_tlv) > > > +{ > > > + int ret; > > > + > > > + if (!p) { > > > + pr_err("%s port is NULL", __func__); > > > + ret = -EFAULT; > > > + return ret; > > > + } > > > + > > > + ret = synce_port_set_tx_ql_dnu(p, extended_tlv); > > > + if (ret) { > > > + pr_err("set tx DNU fail on %s", > > synce_port_get_name(p)); > > > + return ret; > > > + } > > > + > > > + return ret; > > > +} > > > + > > > +static int port_set_ql_external_input(struct synce_port *p, int > > extended) > > > +{ > > > + int ret = synce_port_set_tx_ql_forced(p, extended); > > > + > > > + if (ret) { > > > + pr_err("set QL external failed"); > > > + return ret; > > > + } > > > + > > > + return ret; > > > +} > > > + > > > +static int update_ql_external_input(struct synce_dev *dev) > > > +{ > > > + struct synce_port *p; > > > + int ret = 0; > > > + > > > + LIST_FOREACH(p, &dev->ports, list) { > > > + if (dev->d_state == DPLL_HOLDOVER) { > > > + ret = port_set_dnu(p, dev->extended_tlv); > > > + } else if (dev->d_state == DPLL_LOCKED || > > > + dev->d_state == DPLL_LOCKED_HO_ACQ) { > > > + ret = port_set_ql_external_input(p, > > dev->extended_tlv); > > > + } > > > + > > > + if (ret) { > > > + pr_err("update QL failed d_state %d, err:%d > > on %s", > > > + dev->d_state, ret, dev->name); > > > + break; > > > + } > > > + > > > + } > > > + > > > + return ret; > > > +} > > > + > > > +static int port_set_ql_internal_input(struct synce_dev *dev, > > > + struct synce_port *p, > > > + struct synce_port *best_p) > > > +{ > > > + int ret = synce_port_set_tx_ql_from_best_input(p, best_p, > > > + > > dev->extended_tlv); > > > + > > > + if (ret) { > > > + pr_err("set QL failed"); > > > + return ret; > > > + } > > > + > > > + if (!ret) { > > > + pr_debug("%s on %s", __func__, dev->name); > > > + } > > > + > > > + return ret; > > > +} > > > + > > > +static int update_ql_internal_input(struct synce_dev *dev) > > > +{ > > > + struct synce_port *p, *best_p = dev->best_source; > > > + int ret = 0; > > > + > > > + LIST_FOREACH(p, &dev->ports, list) { > > > + if (dev->d_state == DPLL_HOLDOVER) { > > > + pr_debug("act on DPLL_HOLDOVER for %s", > > > + synce_port_get_name(p)); > > > + ret = port_set_dnu(p, dev->extended_tlv); > > > + if (ret) { > > > + pr_err("%s set DNU failed on %s", > > > + __func__, dev->name); > > > + return ret; > > > + } > > > + } else if ((dev->d_state == DPLL_LOCKED || > > > + dev->d_state == DPLL_LOCKED_HO_ACQ) && > > best_p) { > > > + pr_debug("act on > > DPLL_LOCKED/DPLL_LOCKED_HO_ACQ for %s", > > > + synce_port_get_name(p)); > > > + /* on best port send DNU, all the others > > > + * propagate what came from best source > > > + */ > > > + if (p != best_p) { > > > + ret = > > port_set_ql_internal_input(dev, p, > > > + > > best_p); > > > + } else { > > > + ret = port_set_dnu(p, > > dev->extended_tlv); > > > + } > > > + > > > + if (ret) { > > > + pr_err("%s set failed on %s", > > > + __func__, dev->name); > > > + return ret; > > > + } > > > + } else { > > > + pr_debug("nothing to do for %s d_state %d, > > best_p %p", > > > + synce_port_get_name(p), > > dev->d_state, best_p); > > > + } > > > + } > > > + > > > + return ret; > > > +} > > > + > > > +static void detach_port_dpll(struct synce_port *port, struct > > synce_dev *dev) > > > +{ > > > + int ret = synce_port_disable_recover_clock(port); > + > > > + if (ret) { > > > + pr_err("disable recover clock cmd failed on %s", > > dev->name); > > > + return; > > > + } > +} > > This is not abstract enough, too HW spesific > > > > > > > > Sorry for interfering, > > Could you explain what is "too hardware specific"? > > What interface? What would you expect here instead? > I'd expect some in-standard event like: move_to_holdover. Error path > like failing to set quality should be handeled internally by the driver. > If the DPLL needs to be reset, it is up to the driver to perform. > HW should be hidden completely in hidden from SyncE demon.
Sure, I agree G.8264 standard doesn't mention DPLL. As answered on patch 0/11 mail thread, we will try to fix naming scheme, using EEC instead of DPLL. Thank you, Arkadiusz > > > > > > > > + > > > +static void force_all_dplls_detach(struct synce_dev *dev) > > > +{ > > > + enum dpll_state state; > > > + struct synce_port *p; > > > + > > > + LIST_FOREACH(p, &dev->ports, list) { > > > + pr_debug("trying to detach DPLL RCLK for %s", > > > + synce_port_get_name(p)); > > > + detach_port_dpll(p, dev); > > > + } > > > + > > > + if (synce_dev_ctrl_get_state(dev->dc, &state)) { > > > + pr_err("failed getting DPLL state"); > > > + dev->last_d_state = DPLL_UNKNOWN; > > > + dev->d_state = DPLL_UNKNOWN; > > > + } else { > > > + dev->last_d_state = state; > > > + dev->d_state = state; > > > + } > > > +}; > > > + > > > +static void dev_update_ql(struct synce_dev *dev) > > > +{ > > > + if (dev->ops.update_ql(dev)) { > > > + pr_err("update QL fail on %s", dev->name); > > > + } > > > +} > > > + > > > +static int rx_ql_changed(struct synce_dev *dev) > > > +{ > > > + struct synce_port *p; > > > + int ret = 0; > > > + > > > + LIST_FOREACH(p, &dev->ports, list) { > > > + ret = synce_port_rx_ql_changed(p); > > > + if (ret) { > > > + break; > > > + } > > > + } > > > + > > > + return ret; > > > +} > > > + > > > +static struct synce_port *find_dev_best_source(struct synce_dev > > *dev) > > > +{ > > > + struct synce_port *p, *best_p = dev->best_source; > > > + > > > + LIST_FOREACH(p, &dev->ports, list) { > > > + if (best_p != p) { > > > + if (synce_port_compare_ql(best_p, p) == p) { > > > + pr_debug("old best %s replaced by > > %s on %s", > > > + synce_port_get_name(best_p), > > > + synce_port_get_name(p), > > dev->name); > > > + best_p = p; > > > + } > > > + } > > > + } > > > + > > > + if (best_p) { > > > + if (synce_port_is_rx_dnu(best_p)) { > > > + return NULL; > > > + } > > > + } > > > + > > > + return best_p; > > > +} > > > + > > > +static int set_input_source(struct synce_dev *dev, > > > + struct synce_port *new_best_source) > > > +{ > > > + const char *best_name = synce_port_get_name(new_best_source); > > > + int ret; > > > + > > > + if (!best_name) { > > > + pr_err("get best input name failed on %s", dev->name); > > > + return -ENXIO; > > > + } > > > + > > > + ret = synce_port_enable_recover_clock(new_best_source); > > > + if (ret) { > > > + pr_err("enable recover clock cmd failed on %s", > > dev->name); > > > + return ret; > > > + } > > > + > > > + return ret; > > > +} > > > + > > > +static int act_on_d_state(struct synce_dev *dev) > > > +{ > > > + int ret = 0; > > > + > > > + if (dev->d_state != dev->last_d_state) { > > > + ret = dev->ops.update_ql(dev); > > > + if (ret) { > > > + pr_err("update QL fail on %s", dev->name); > > > + } else { > > > + dev->last_d_state = dev->d_state; > > > + pr_debug("%s QL updated on %s", __func__, > > dev->name); > > > + } > > > + } > > > + > > > + return ret; > > > +} > > > + > > > +static int dev_step_external_input(struct synce_dev *dev) > > > +{ > > > + return act_on_d_state(dev); > > > +} > > > + > > > +static void choose_best_source(struct synce_dev *dev) > > > +{ > > > + struct synce_port *new_best; > > > + > > > + new_best = find_dev_best_source(dev); > > > + if (!new_best) { > > > + pr_info("best source not found on %s", dev->name); > > > + force_all_dplls_detach(dev); > > > + dev_update_ql(dev); > > > + dev->best_source = NULL; > > > + } else if (new_best != dev->best_source) { > > > + force_all_dplls_detach(dev); > > > + if (set_input_source(dev, new_best)) { > > > + pr_err("set best source failed on %s", > > > + dev->name); > > > + } else { > > > + /* if input source is changing > > > + * current input is invalid, send DNU and wait > > > + * for DPLL being locked in further dev_step > > > + */ > > > + dev_update_ql(dev); > > > + /* DPLL was invalidated we can now set new > > > + * best_source for further use > > > + */ > > > + dev->best_source = new_best; > > > + } > > > + } else { > > > + pr_info("clock source has not changed on %s", > > dev->name); > > > + /* no port change, just update QL on TX */ > > > + dev_update_ql(dev); > > > + > > > + } > > > +} > > > + > > > +static int dev_step_internal_input(struct synce_dev *dev) > > > +{ > > > + int ret; > > > + > > > + ret = act_on_d_state(dev); > > > + if (ret) { > > > + pr_err("act on d_state fail on %s", dev->name); > > > + return ret; > > > + } > > > + > > > + if (rx_ql_changed(dev)) { > > > + choose_best_source(dev); > > > + } else if (dev->best_source) { > > > + if (synce_port_rx_ql_failed(dev->best_source)) { > > > + synce_port_invalidate_rx_ql(dev->best_source); > > > + force_all_dplls_detach(dev); > > > + dev_update_ql(dev); > > > + dev->best_source = NULL; > > > + choose_best_source(dev); > > > + } > > > + } > > > + > > > + return ret; > > > +} > > > + > > > +static void init_ops(struct synce_dev *dev) > > > +{ > > > + if (rx_enabled(dev)) { > > > + dev->ops.update_ql = &update_ql_internal_input; > > > + dev->ops.step = &dev_step_internal_input; > > > + } else { > > > + dev->ops.update_ql = &update_ql_external_input; > > > + dev->ops.step = &dev_step_external_input; > > > + } > > > +} > > > + > > > +int synce_dev_init(struct synce_dev *dev, struct config *cfg) > > > +{ > > > + const char *dpll_get_state_cmd; > > > + struct dpll_state_str dss; > > > + int count, ret; > > > + > > > + if (dev->state != DEVICE_CREATED) { > > > + goto err; > > > + } > > > + > > > + LIST_INIT(&dev->ports); > > > + dev->internal_input = config_get_int(cfg, dev->name, > > "internal_input"); > > > + dev->external_input = config_get_int(cfg, dev->name, > > "external_input"); > > > + dev->ql = config_get_int(cfg, dev->name, "external_input_QL"); > > > + dev->ext_ql = config_get_int(cfg, dev->name, > > "external_input_ext_QL"); > > > + dev->extended_tlv = config_get_int(cfg, dev->name, > > "extended_tlv"); > > > + dev->network_option = config_get_int(cfg, dev->name, > > "network_option"); > > > + dev->recover_time = config_get_int(cfg, dev->name, > > "recover_time"); > > > + dev->best_source = NULL; > > > + dpll_get_state_cmd = config_get_string(cfg, dev->name, > > "dpll_get_state_cmd"); > > > + dss.holdover = config_get_string(cfg, dev->name, > > "dpll_holdover_value"); > > > + dss.locked_ho = config_get_string(cfg, dev->name, > > "dpll_locked_ho_value"); > > > + dss.locked = config_get_string(cfg, dev->name, > > "dpll_locked_value"); > > > + dss.freerun = config_get_string(cfg, dev->name, > > "dpll_freerun_value"); > > > + dss.invalid = config_get_string(cfg, dev->name, > > "dpll_invalid_value"); > > > + dev->dc = synce_dev_ctrl_create(); > > > + if (!dev->dc) { > > > + pr_err("device_ctrl create fail on %s", dev->name); > > > + goto err; > > > + } > > > + > > > + if (dev->external_input && dev->internal_input) { > > > + pr_warning("external_input and internal_input are > > mutually exclusive - disabling internal_input cfg option"); > > > + dev->internal_input = 0; > > > + } else if (!dev->external_input && !dev->internal_input) { > > > + pr_err("either external_input or internal_input > > need to be set to 1 - aborting initialization"); > > > + goto err; > > > + } > > > + > > > + ret = synce_dev_ctrl_init(dev->dc, dev->name, > > dpll_get_state_cmd, &dss); > > > + if (ret) { > > > + pr_err("synce_dev_ctrl init ret %d on %s", ret, > > dev->name); > > > + goto err; > > > + } > > > + > > > + if (init_ports(&count, dev, cfg)) > > > + goto err; > > > + > > > + init_ops(dev); > > > + dev->num_ports = count; > > > + dev->state = DEVICE_INITED; > > > + > > > + dev->d_state = DPLL_HOLDOVER; > > > + dev->ops.update_ql(dev); > > > + > > > + /* in case somebody manually set recovered clock before */ > > > + if (dev->internal_input) { > > > + force_all_dplls_detach(dev); > > > + } > > > + pr_info("inited num_ports %d for %s", count, dev->name); > > > + > > > + return 0; > > > + > > > +err: > > > + dev->state = DEVICE_FAILED; > > > + pr_err("%s failed for %s", __func__, dev->name); > > > + return -ENODEV; > > > +} > > > + > > > +struct synce_dev *synce_dev_create(const char *dev_name) > > > +{ > > > + struct synce_dev *dev = NULL; > > > + > > > + if (!dev_name) { > > > + return NULL; > > > + } > > > + > > > + dev = malloc(sizeof(struct synce_dev)); > > > + if (!dev) { > > > + return NULL; > > > + } > > > + > > > + memcpy(dev->name, dev_name, sizeof(dev->name)); > > > + dev->state = DEVICE_CREATED; > > > + dev->d_state = DPLL_UNKNOWN; > > > + dev->last_d_state = DPLL_UNKNOWN; > > > + pr_debug("created %s", dev->name); > > > + > > > + return dev; > > > +} > > > + > > > +int synce_dev_step(struct synce_dev *dev) > > > +{ > > > + int ret = -EFAULT; > > > + > > > + if (!dev) { > > > + pr_err("%s dev is NULL", __func__); > > > + return ret; > > > + } > > > + > > > + update_dev_state(dev); > > > + if (dev->state != DEVICE_RUNNING) { > > > + pr_err("dev %s is not running", dev->name); > > > + return ret; > > > + } > > > + > > > + ret = synce_dev_ctrl_get_state(dev->dc, &dev->d_state); > > > + if (ret) { > > > + pr_warning("could not acquire dpll state on %s", > > dev->name); > > > + return ret; > > > + } > > > + > > > + ret = dev->ops.step(dev); > > > + > > > + return ret; > > > +} > > > + > > > +const char *synce_dev_name(struct synce_dev *dev) > > > +{ > > > + return dev->name; > > > +} > > > + > > > +int synce_dev_is_running(struct synce_dev *dev) > > > +{ > > > + update_dev_state(dev); > > > + > > > + return !!(dev->state & DEVICE_RUNNING); > > > +} > > > + > > > +void synce_dev_destroy(struct synce_dev *dev) > > > +{ > > > + if (!dev) { > > > + pr_err("%s dev is NULL", __func__); > > > + return; > > > + } > > > + > > > + if (dev->internal_input && dev->state != DEVICE_FAILED) { > > > + force_all_dplls_detach(dev); > > > + } > > > + > > > + destroy_ports(dev); > > > + destroy_dev_ctrl(dev); > > > +} > > > diff --git a/synce_dev.h b/synce_dev.h > > > new file mode 100644 > > > index 0000000..6807c2b > > > --- /dev/null > > > +++ b/synce_dev.h > > > @@ -0,0 +1,64 @@ > > > +/** > > > + * @file synce_dev.h > > > + * @brief Interface for handling Sync-E capable devices and its > > ports > > > + * @note SPDX-FileCopyrightText: Copyright 2022 Intel Corporation > > > + * @note SPDX-License-Identifier: GPL-2.0+ > > > + */ > > > +#ifndef HAVE_SYNCE_DEV_H > > > +#define HAVE_SYNCE_DEV_H > > > + > > > +#include <stdint.h> > > > + > > > +struct config; > > > +struct synce_dev; > > > + > > > +/** > > > + * Initialize Sync-E device and its ports after device was created. > > > + * > > > + * @param dev Device to be initialized > > > + * @param cfg Configuration struct based on SYNCE type, > > must hold > > > + * properities of configured device ports > > > + * @return 0 on success, failure otherwise > > > + */ > > > +int synce_dev_init(struct synce_dev *dev, struct config *cfg); > > > + > > > +/** > > > + * Alloc memory for a single Sync-E device. > > > + * > > > + * @param dev_name Human readable name of a device > > > + * @return 0 on success, failure otherwise > > > + */ > > > +struct synce_dev *synce_dev_create(const char *dev_name); > > > + > > > +/** > > > + * Step a Sync-E device. Probe for events, changes and act on them. > > > + * > > > + * @param dev Device to be stepped > > > + * @return 0 on success, failure otherwise > > > + */ > > > +int synce_dev_step(struct synce_dev *dev); > > > + > > > +/** > > > + * Acquire Sync-E device name. > > > + * > > > + * @param dev Questioned SyncE device instance > > > + * @return The device name > > > + */ > > > +const char *synce_dev_name(struct synce_dev *dev); > > > + > > > +/** > > > + * Clean-up on memory allocated for device and its ports. > > > + * > > > + * @param dev SyncE device to be cleared > > > + */ > > > +void synce_dev_destroy(struct synce_dev *dev); > > > + > > > +/** > > > + * Check if Sync-E device is running. > > > + * > > > + * @param dev Questioned SyncE device > > > + * @return 0 if false, 1 if true > > > + */ > > > +int synce_dev_is_running(struct synce_dev *dev); > > > + > > > +#endif > > > > _______________________________________________ Linuxptp-devel mailing list Linuxptp-devel@lists.sourceforge.net https://lists.sourceforge.net/lists/listinfo/linuxptp-devel