> -----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