> -----Original Message-----
> From: Aya Levin <a...@nvidia.com> 
> Sent: Wednesday, June 8, 2022 11:10 AM
> 
> On 5/2/2022 12:05 PM, Arkadiusz Kubalewski wrote:
> > synce_clock interface allows creation, polling and destruction of
> > SyncE clock, designed to step and drive SyncE logic on all configured
> > SyncE devices.
> > 
> > SyncE clock is created with a SyncE-type configuration, where
> > SyncE-type configuration is prepared by parsing SyncE config file.
> > 
> > Poll of a SyncE clock, will step each configured SyncE device.
> > 
> > Destruction of SyncE clock releases all resources obtained by SyncE
> > clock and devices.
> > 
> > Co-developed-by: Piotr Kwapulinski <piotr.kwapulin...@intel.com>
> > Signed-off-by: Piotr Kwapulinski <piotr.kwapulin...@intel.com>
> > Co-developed-by: Michal Michalik <michal.micha...@intel.com>
> > Signed-off-by: Michal Michalik <michal.micha...@intel.com>
> > Signed-off-by: Arkadiusz Kubalewski <arkadiusz.kubalew...@intel.com>
> > ---
> >   synce_clock.c | 296 ++++++++++++++++++++++++++++++++++++++++++++++++++
> >   synce_clock.h |  52 +++++++++
> >   2 files changed, 348 insertions(+)
> >   create mode 100644 synce_clock.c
> >   create mode 100644 synce_clock.h
> > 
> > diff --git a/synce_clock.c b/synce_clock.c
> > new file mode 100644
> > index 000000000000..8007fa390bbd
> > --- /dev/null
> > +++ b/synce_clock.c
> > @@ -0,0 +1,296 @@
> > +/* SPDX-License-Identifier: GPL-2.0-only */
> > +/**
> > + * @file synce_clock.c
> > + * @brief Implements a SYNCE clock interface.
> > + * @note Copyright (C) 2022 Intel Corporation
> > + *
> > + * This program is free software; you can redistribute it and/or modify it
> > + * under the terms of the GNU General Public License version 2, as 
> > published
> > + * by the Free Software Foundation.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > + * GNU General Public License for more details.
> > + *
> > + * You should have received a copy of the GNU General Public License
> > + * along with this program; if not, see <http://www.gnu.org/licenses/>.
> > + */
> > +#include <stdlib.h>
> > +#include <errno.h>
> > +#include <unistd.h>
> > +#include <sys/queue.h>
> > +
> > +#include "synce_clock.h"
> > +#include "interface.h"
> > +#include "synce_dev.h"
> > +#include "print.h"
> > +#include "config.h"
> > +#include "missing.h"
> > +
> > +#define SYNCE_CLOCK_DELAY_USEC     20000
> > +#define SYNCE_CLOCK_INIT_DELAY_USEC        200000
> > +#define SYNCE_CLOCK_INIT_N_TRIES   10
> > +
> > +struct interface {
> > +   STAILQ_ENTRY(interface) list;
> > +};
> > +
> > +struct synce_dev {
> > +   LIST_ENTRY(synce_dev) list;
> > +};
> > +
> > +enum synce_clock_state {
> > +   SYNCE_CLK_UNKNOWN = 0,
> > +   SYNCE_CLK_INITED,
> > +   SYNCE_CLK_DEV_RDY,
> > +   SYNCE_CLK_DEV_INITED,
> > +   SYNCE_CLK_RUNNING,
> > +   SYNCE_CLK_FAILED,
> > +};
> > +
> > +struct synce_clock {
> > +   int num_devices;
> > +   int state;
> > +   LIST_HEAD(devices_head, synce_dev) devices;
> > +};
> > +
> > +static struct synce_clock *create_clock(void)
> Please rename to create_synce_clock()

Sure, makes sense, I will fix that.

Thank you,
Arkadiusz

> > +{
> > +   static struct synce_clock clk;
> > +
> > +   if (clk.state != SYNCE_CLK_UNKNOWN) {
> > +           synce_clock_destroy(&clk);
> > +           pr_info("old synce_clock destroyed");
> > +   }
> > +   clk.state = SYNCE_CLK_INITED;
> > +
> > +   return &clk;
> > +}
> > +
> > +static void add_device(struct synce_clock *clk, struct synce_dev *dev)
> > +{
> > +   struct synce_dev *dev_iter, *last_dev = NULL;
> > +
> > +   LIST_FOREACH(dev_iter, &clk->devices, list) {
> > +           last_dev = dev_iter;
> > +   }
> > +
> > +   if (last_dev) {
> > +           LIST_INSERT_AFTER(last_dev, dev, list);
> > +   } else {
> > +           LIST_INSERT_HEAD(&clk->devices, dev, list);
> > +   }
> > +}
> > +
> > +static int create_synce_devices(struct synce_clock *clk, struct config 
> > *cfg)
> > +{
> > +   struct interface *iface;
> > +   struct synce_dev *dev;
> > +   const char *dev_name;
> > +   int count = 0;
> > +
> > +   if (clk->state != SYNCE_CLK_INITED) {
> > +           goto err;
> > +   }
> > +
> > +   LIST_INIT(&clk->devices);
> > +   STAILQ_FOREACH(iface, &cfg->interfaces, list) {
> > +           /* only parent devices shall be addresed */
> > +           if (!interface_se_has_parent_dev(iface)) {
> > +                   dev_name = interface_name(iface);
> > +                   dev = synce_dev_create(dev_name);
> > +                   if (!dev) {
> > +                           pr_err("failed to create device %s", dev_name);
> > +                           continue;
> > +                   }
> > +
> > +                   pr_debug("device init %s addr %p", dev_name, dev);
> > +                   add_device(clk, dev);
> > +                   count++;
> > +           }
> > +   }
> > +
> > +   if (!count) {
> > +           pr_err("no devices created");
> > +           goto err;
> > +   }
> > +
> > +   pr_info("created num_devices: %d", count);
> > +   clk->num_devices = count;
> > +   clk->state = SYNCE_CLK_DEV_RDY;
> > +
> > +   return 0;
> > +err:
> > +   clk->state = SYNCE_CLK_FAILED;
> > +   return -EINVAL;
> > +}
> > +
> > +static int init_synce_devices(struct synce_clock *clk, struct config *cfg)
> > +{
> > +   struct synce_dev *dev, *tmp;
> > +   int count = 0;
> > +
> > +   if (clk->state != SYNCE_CLK_DEV_RDY) {
> > +           goto err;
> > +   }
> > +
> > +   LIST_FOREACH_SAFE(dev, &clk->devices, list, tmp) {
> > +           /* Each parent device will init its ports */
> > +           if (synce_dev_init(dev, cfg)) {
> > +                   pr_err("failed to init device %s",
> > +                          synce_dev_name(dev));
> > +                   synce_dev_destroy(dev);
> > +                   LIST_REMOVE(dev, list);
> > +                   free(dev);
> > +                   continue;
> > +           } else {
> > +                   pr_debug("device inited %s", synce_dev_name(dev));
> > +                   count++;
> > +           }
> > +   }
> > +
> > +   if (count == 0) {
> > +           pr_err("no Sync-E devices initialized");
> > +           goto err;
> > +   } else if (count != clk->num_devices) {
> > +           pr_warning("initialized only %d from %d Sync-E devices",
> > +                      count, clk->num_devices);
> > +           clk->num_devices = count;
> > +   }
> > +   clk->state = SYNCE_CLK_DEV_INITED;
> > +
> > +   return 0;
> > +err:
> > +   clk->state = SYNCE_CLK_FAILED;
> > +   return -EINVAL;
> > +}
> > +
> > +static void remove_failed_devices(struct synce_clock *clk)
> > +{
> > +   struct synce_dev *dev, *tmp;
> > +   int failed_cnt = 0;
> > +
> > +   LIST_FOREACH_SAFE(dev, &clk->devices, list, tmp) {
> > +           if (!synce_dev_is_running(dev)) {
> > +                   synce_dev_destroy(dev);
> > +                   LIST_REMOVE(dev, list);
> > +                   free(dev);
> > +                   failed_cnt++;
> > +           }
> > +   }
> > +   clk->num_devices -= failed_cnt;
> > +   pr_warning("Found dead devices: %d", failed_cnt);
> > +   pr_info("devices still running: %d", clk->num_devices);
> > +}
> > +
> > +static int verify_clock_state(struct synce_clock *clk)
> > +{
> > +   int i, running, timeout = SYNCE_CLOCK_INIT_N_TRIES;
> > +   struct synce_dev *dev;
> > +
> > +   if (clk->state < SYNCE_CLK_DEV_INITED) {
> > +           return -ENODEV;
> > +   }
> > +
> > +   /* let threads get running */
> > +   for (i = 0; i < timeout; ++i) {
> > +           running = 0;
> > +           LIST_FOREACH(dev, &clk->devices, list) {
> > +                   if (synce_dev_is_running(dev))
> > +                           running++;
> > +           }
> > +
> > +           if (running == clk->num_devices) {
> > +                   clk->state = SYNCE_CLK_RUNNING;
> > +                   break;
> > +           }
> > +           usleep(SYNCE_CLOCK_INIT_DELAY_USEC);
> > +   }
> > +
> > +   pr_debug("running num_devices %d configured %d",
> > +            running, clk->num_devices);
> > +
> > +   /* If at least one dev is running we leave clock running
> > +    * while removing failed devices.
> > +    * Previous traces shall indicate which ones have failed.
> > +    */
> > +   if (!running) {
> > +           pr_err("no device is running");
> > +           return -ENODEV;
> > +   } else if (running != clk->num_devices) {
> > +           remove_failed_devices(clk);
> > +   }
> > +
> > +   return 0;
> > +}
> > +
> > +struct synce_clock *synce_clock_create(struct config *cfg)
> > +{
> > +   struct synce_clock *clk;
> > +   int err;
> > +
> > +   if (!cfg) {
> > +           pr_err("%s cfg is NULL", __func__);
> > +           return NULL;
> > +   }
> > +
> > +   clk = create_clock();
> > +   if (!clk) {
> > +           return NULL;
> > +   }
> > +   err = create_synce_devices(clk, cfg);
> > +   if (err) {
> > +           goto destroy;
> > +   }
> > +   err = init_synce_devices(clk, cfg);
> > +   if (err) {
> > +           goto destroy;
> > +   }
> > +   err = verify_clock_state(clk);
> > +   if (err) {
> > +           goto destroy;
> > +   }
> > +
> > +   return clk;
> > +
> > +destroy:
> > +   synce_clock_destroy(clk);
> > +
> > +   return NULL;
> > +}
> > +
> > +void synce_clock_destroy(struct synce_clock *clk)
> > +{
> > +   struct synce_dev *dev, *tmp;
> > +
> > +   pr_debug("%s", __func__);
> > +
> > +   LIST_FOREACH_SAFE(dev, &clk->devices, list, tmp) {
> > +           synce_dev_destroy(dev);
> > +           LIST_REMOVE(dev, list);
> > +           free(dev);
> > +   }
> > +   clk->num_devices = 0;
> > +   clk->state = SYNCE_CLK_UNKNOWN;
> > +
> > +   return;
> > +}
> > +
> > +int synce_clock_poll(struct synce_clock *clk)
> > +{
> > +   struct synce_dev *dev;
> > +   int ret = -ENODEV;
> > +
> > +   if (clk->state == SYNCE_CLK_RUNNING) {
> > +           LIST_FOREACH(dev, &clk->devices, list) {
> > +                   ret = synce_dev_step(dev);
> > +                   if (ret) {
> > +                           pr_err("dev_step fail");
> > +                   }
> > +           }
> > +   }
> > +   usleep(SYNCE_CLOCK_DELAY_USEC);
> > +
> > +   return ret;
> > +}
> > diff --git a/synce_clock.h b/synce_clock.h
> > new file mode 100644
> > index 000000000000..e5559a4cc9cc
> > --- /dev/null
> > +++ b/synce_clock.h
> > @@ -0,0 +1,52 @@
> > +/* SPDX-License-Identifier: GPL-2.0-only */
> > +/**
> > + * @file synce_clock.h
> > + * @brief Implements a Sync-E clock behavior.
> > + * @note Copyright (C) 2022 Intel Corporation
> > + *
> > + * This program is free software; you can redistribute it and/or modify it
> > + * under the terms of the GNU General Public License version 2, as 
> > published
> > + * by the Free Software Foundation.
> > + *
> > + * This program is distributed in the hope that it will be useful,
> > + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> > + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> > + * GNU General Public License for more details.
> > + *
> > + * You should have received a copy of the GNU General Public License
> > + * along with this program; if not, see <http://www.gnu.org/licenses/>.
> > + */
> > +#ifndef HAVE_SYNCE_CLOCK_H
> > +#define HAVE_SYNCE_CLOCK_H
> > +
> > +#include "config.h"
> > +
> > +/* Opaque type */
> > +struct synce_clock;
> > +
> > +/**
> > + * Create a Sync-E clock instance. There can only be one synce_clock in a
> > + * system so subsequent calls will destroy the previous clock instance.
> > + *
> > + * @param cfg      Pointer to the SYNCE-type configuration database
> > + * @return Pointer to the single global Sync-E clock instance
> > + */
> > +struct synce_clock *synce_clock_create(struct config *cfg);
> > +
> > +/**
> > + * Destroy resources associated with the synce clock.
> > + *
> > + * @param clk      Pointer to synce_clock instance
> > + */
> > +void synce_clock_destroy(struct synce_clock *clk);
> > +
> > +/**
> > + * Poll for synce events and dispatch them.
> > + *
> > + * @param clk      A pointer to a synce_clock instance obtained with
> > + *         synce_clock_create().
> > + * @return Zero on success, non-zero otherwise
> > + */
> > +int synce_clock_poll(struct synce_clock *clk);
> > +
> > +#endif
>

_______________________________________________
Linuxptp-devel mailing list
Linuxptp-devel@lists.sourceforge.net
https://lists.sourceforge.net/lists/listinfo/linuxptp-devel

Reply via email to