> -----Original Message-----
> From: Aya Levin via Linuxptp-devel <[email protected]>
> Sent: Wednesday, June 8, 2022 12:54 PM
>
> On 6/8/2022 12:55 PM, Erez wrote:
> >
> > אינך מקבל לעתים קרובות דואר אלקטרוני מ- [email protected]. למד מדוע
> > הדבר חשוב <https://aka.ms/LearnAboutSenderIdentification>
> >
> >
> >
> >
> > On Wed, 8 Jun 2022 at 11:11, Aya Levin via Linuxptp-devel
> > <[email protected]
> > <mailto:[email protected]>> 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
> > <[email protected] <mailto:[email protected]>>
> > > Signed-off-by: Anatolii Gerasymenko
> > <[email protected] <mailto:[email protected]>>
> > > Co-developed-by: Piotr Kwapulinski <[email protected]
> > <mailto:[email protected]>>
> > > Signed-off-by: Piotr Kwapulinski <[email protected]
> > <mailto:[email protected]>>
> > > Co-developed-by: Michal Michalik <[email protected]
> > <mailto:[email protected]>>
> > > Signed-off-by: Michal Michalik <[email protected]
> > <mailto:[email protected]>>
> > > Signed-off-by: Arkadiusz Kubalewski
> > <[email protected] <mailto:[email protected]>>
> > > ---
> > > 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
[email protected]
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel