dpdk/drivers/net/octeontx2/otx2_ptp.c
<<
>>
Prefs
   1/* SPDX-License-Identifier: BSD-3-Clause
   2 * Copyright(C) 2019 Marvell International Ltd.
   3 */
   4
   5#include <ethdev_driver.h>
   6
   7#include "otx2_ethdev.h"
   8
   9#define PTP_FREQ_ADJUST (1 << 9)
  10
  11/* Function to enable ptp config for VFs */
  12void
  13otx2_nix_ptp_enable_vf(struct rte_eth_dev *eth_dev)
  14{
  15        struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
  16
  17        if (otx2_nix_recalc_mtu(eth_dev))
  18                otx2_err("Failed to set MTU size for ptp");
  19
  20        dev->scalar_ena = true;
  21        dev->rx_offload_flags |= NIX_RX_OFFLOAD_TSTAMP_F;
  22
  23        /* Setting up the function pointers as per new offload flags */
  24        otx2_eth_set_rx_function(eth_dev);
  25        otx2_eth_set_tx_function(eth_dev);
  26}
  27
  28static uint16_t
  29nix_eth_ptp_vf_burst(void *queue, struct rte_mbuf **mbufs, uint16_t pkts)
  30{
  31        struct otx2_eth_rxq *rxq = queue;
  32        struct rte_eth_dev *eth_dev;
  33
  34        RTE_SET_USED(mbufs);
  35        RTE_SET_USED(pkts);
  36
  37        eth_dev = rxq->eth_dev;
  38        otx2_nix_ptp_enable_vf(eth_dev);
  39
  40        return 0;
  41}
  42
  43static int
  44nix_read_raw_clock(struct otx2_eth_dev *dev, uint64_t *clock, uint64_t *tsc,
  45                   uint8_t is_pmu)
  46{
  47        struct otx2_mbox *mbox = dev->mbox;
  48        struct ptp_req *req;
  49        struct ptp_rsp *rsp;
  50        int rc;
  51
  52        req = otx2_mbox_alloc_msg_ptp_op(mbox);
  53        req->op = PTP_OP_GET_CLOCK;
  54        req->is_pmu = is_pmu;
  55        rc = otx2_mbox_process_msg(mbox, (void *)&rsp);
  56        if (rc)
  57                goto fail;
  58
  59        if (clock)
  60                *clock = rsp->clk;
  61        if (tsc)
  62                *tsc = rsp->tsc;
  63
  64fail:
  65        return rc;
  66}
  67
  68/* This function calculates two parameters "clk_freq_mult" and
  69 * "clk_delta" which is useful in deriving PTP HI clock from
  70 * timestamp counter (tsc) value.
  71 */
  72int
  73otx2_nix_raw_clock_tsc_conv(struct otx2_eth_dev *dev)
  74{
  75        uint64_t ticks_base = 0, ticks = 0, tsc = 0, t_freq;
  76        int rc, val;
  77
  78        /* Calculating the frequency at which PTP HI clock is running */
  79        rc = nix_read_raw_clock(dev, &ticks_base, &tsc, false);
  80        if (rc) {
  81                otx2_err("Failed to read the raw clock value: %d", rc);
  82                goto fail;
  83        }
  84
  85        rte_delay_ms(100);
  86
  87        rc = nix_read_raw_clock(dev, &ticks, &tsc, false);
  88        if (rc) {
  89                otx2_err("Failed to read the raw clock value: %d", rc);
  90                goto fail;
  91        }
  92
  93        t_freq = (ticks - ticks_base) * 10;
  94
  95        /* Calculating the freq multiplier viz the ratio between the
  96         * frequency at which PTP HI clock works and tsc clock runs
  97         */
  98        dev->clk_freq_mult =
  99                (double)pow(10, floor(log10(t_freq))) / rte_get_timer_hz();
 100
 101        val = false;
 102#ifdef RTE_ARM_EAL_RDTSC_USE_PMU
 103        val = true;
 104#endif
 105        rc = nix_read_raw_clock(dev, &ticks, &tsc, val);
 106        if (rc) {
 107                otx2_err("Failed to read the raw clock value: %d", rc);
 108                goto fail;
 109        }
 110
 111        /* Calculating delta between PTP HI clock and tsc */
 112        dev->clk_delta = ((uint64_t)(ticks / dev->clk_freq_mult) - tsc);
 113
 114fail:
 115        return rc;
 116}
 117
 118static void
 119nix_start_timecounters(struct rte_eth_dev *eth_dev)
 120{
 121        struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
 122
 123        memset(&dev->systime_tc, 0, sizeof(struct rte_timecounter));
 124        memset(&dev->rx_tstamp_tc, 0, sizeof(struct rte_timecounter));
 125        memset(&dev->tx_tstamp_tc, 0, sizeof(struct rte_timecounter));
 126
 127        dev->systime_tc.cc_mask = OTX2_CYCLECOUNTER_MASK;
 128        dev->rx_tstamp_tc.cc_mask = OTX2_CYCLECOUNTER_MASK;
 129        dev->tx_tstamp_tc.cc_mask = OTX2_CYCLECOUNTER_MASK;
 130}
 131
 132static int
 133nix_ptp_config(struct rte_eth_dev *eth_dev, int en)
 134{
 135        struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
 136        struct otx2_mbox *mbox = dev->mbox;
 137        uint8_t rc = -EINVAL;
 138
 139        if (otx2_dev_is_vf_or_sdp(dev) || otx2_dev_is_lbk(dev))
 140                return rc;
 141
 142        if (en) {
 143                /* Enable time stamping of sent PTP packets. */
 144                otx2_mbox_alloc_msg_nix_lf_ptp_tx_enable(mbox);
 145                rc = otx2_mbox_process(mbox);
 146                if (rc) {
 147                        otx2_err("MBOX ptp tx conf enable failed: err %d", rc);
 148                        return rc;
 149                }
 150                /* Enable time stamping of received PTP packets. */
 151                otx2_mbox_alloc_msg_cgx_ptp_rx_enable(mbox);
 152        } else {
 153                /* Disable time stamping of sent PTP packets. */
 154                otx2_mbox_alloc_msg_nix_lf_ptp_tx_disable(mbox);
 155                rc = otx2_mbox_process(mbox);
 156                if (rc) {
 157                        otx2_err("MBOX ptp tx conf disable failed: err %d", rc);
 158                        return rc;
 159                }
 160                /* Disable time stamping of received PTP packets. */
 161                otx2_mbox_alloc_msg_cgx_ptp_rx_disable(mbox);
 162        }
 163
 164        return otx2_mbox_process(mbox);
 165}
 166
 167int
 168otx2_eth_dev_ptp_info_update(struct otx2_dev *dev, bool ptp_en)
 169{
 170        struct otx2_eth_dev *otx2_dev = (struct otx2_eth_dev *)dev;
 171        struct rte_eth_dev *eth_dev;
 172        int i;
 173
 174        if (!dev)
 175                return -EINVAL;
 176
 177        eth_dev = otx2_dev->eth_dev;
 178        if (!eth_dev)
 179                return -EINVAL;
 180
 181        otx2_dev->ptp_en = ptp_en;
 182        for (i = 0; i < eth_dev->data->nb_rx_queues; i++) {
 183                struct otx2_eth_rxq *rxq = eth_dev->data->rx_queues[i];
 184                rxq->mbuf_initializer =
 185                        otx2_nix_rxq_mbuf_setup(otx2_dev,
 186                                                eth_dev->data->port_id);
 187        }
 188        if (otx2_dev_is_vf(otx2_dev) && !(otx2_dev_is_sdp(otx2_dev)) &&
 189            !(otx2_dev_is_lbk(otx2_dev))) {
 190                /* In case of VF, setting of MTU cant be done directly in this
 191                 * function as this is running as part of MBOX request(PF->VF)
 192                 * and MTU setting also requires MBOX message to be
 193                 * sent(VF->PF)
 194                 */
 195                eth_dev->rx_pkt_burst = nix_eth_ptp_vf_burst;
 196                rte_mb();
 197        }
 198
 199        return 0;
 200}
 201
 202int
 203otx2_nix_timesync_enable(struct rte_eth_dev *eth_dev)
 204{
 205        struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
 206        int i, rc = 0;
 207
 208        /* If we are VF/SDP/LBK, ptp cannot not be enabled */
 209        if (otx2_dev_is_vf_or_sdp(dev) || otx2_dev_is_lbk(dev)) {
 210                otx2_info("PTP cannot be enabled in case of VF/SDP/LBK");
 211                return -EINVAL;
 212        }
 213
 214        if (otx2_ethdev_is_ptp_en(dev)) {
 215                otx2_info("PTP mode is already enabled");
 216                return -EINVAL;
 217        }
 218
 219        if (!(dev->rx_offload_flags & NIX_RX_OFFLOAD_PTYPE_F)) {
 220                otx2_err("Ptype offload is disabled, it should be enabled");
 221                return -EINVAL;
 222        }
 223
 224        if (dev->npc_flow.switch_header_type == OTX2_PRIV_FLAGS_HIGIG) {
 225                otx2_err("Both PTP and switch header enabled");
 226                return -EINVAL;
 227        }
 228
 229        /* Allocating a iova address for tx tstamp */
 230        const struct rte_memzone *ts;
 231        ts = rte_eth_dma_zone_reserve(eth_dev, "otx2_ts",
 232                                      0, OTX2_ALIGN, OTX2_ALIGN,
 233                                      dev->node);
 234        if (ts == NULL) {
 235                otx2_err("Failed to allocate mem for tx tstamp addr");
 236                return -ENOMEM;
 237        }
 238
 239        dev->tstamp.tx_tstamp_iova = ts->iova;
 240        dev->tstamp.tx_tstamp = ts->addr;
 241
 242        rc = rte_mbuf_dyn_rx_timestamp_register(
 243                        &dev->tstamp.tstamp_dynfield_offset,
 244                        &dev->tstamp.rx_tstamp_dynflag);
 245        if (rc != 0) {
 246                otx2_err("Failed to register Rx timestamp field/flag");
 247                return -rte_errno;
 248        }
 249
 250        /* System time should be already on by default */
 251        nix_start_timecounters(eth_dev);
 252
 253        dev->rx_offloads |= DEV_RX_OFFLOAD_TIMESTAMP;
 254        dev->rx_offload_flags |= NIX_RX_OFFLOAD_TSTAMP_F;
 255        dev->tx_offload_flags |= NIX_TX_OFFLOAD_TSTAMP_F;
 256
 257        rc = nix_ptp_config(eth_dev, 1);
 258        if (!rc) {
 259                for (i = 0; i < eth_dev->data->nb_tx_queues; i++) {
 260                        struct otx2_eth_txq *txq = eth_dev->data->tx_queues[i];
 261                        otx2_nix_form_default_desc(txq);
 262                }
 263
 264                /* Setting up the function pointers as per new offload flags */
 265                otx2_eth_set_rx_function(eth_dev);
 266                otx2_eth_set_tx_function(eth_dev);
 267        }
 268
 269        rc = otx2_nix_recalc_mtu(eth_dev);
 270        if (rc)
 271                otx2_err("Failed to set MTU size for ptp");
 272
 273        return rc;
 274}
 275
 276int
 277otx2_nix_timesync_disable(struct rte_eth_dev *eth_dev)
 278{
 279        struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
 280        int i, rc = 0;
 281
 282        if (!otx2_ethdev_is_ptp_en(dev)) {
 283                otx2_nix_dbg("PTP mode is disabled");
 284                return -EINVAL;
 285        }
 286
 287        if (otx2_dev_is_vf_or_sdp(dev) || otx2_dev_is_lbk(dev))
 288                return -EINVAL;
 289
 290        dev->rx_offloads &= ~DEV_RX_OFFLOAD_TIMESTAMP;
 291        dev->rx_offload_flags &= ~NIX_RX_OFFLOAD_TSTAMP_F;
 292        dev->tx_offload_flags &= ~NIX_TX_OFFLOAD_TSTAMP_F;
 293
 294        rc = nix_ptp_config(eth_dev, 0);
 295        if (!rc) {
 296                for (i = 0; i < eth_dev->data->nb_tx_queues; i++) {
 297                        struct otx2_eth_txq *txq = eth_dev->data->tx_queues[i];
 298                        otx2_nix_form_default_desc(txq);
 299                }
 300
 301                /* Setting up the function pointers as per new offload flags */
 302                otx2_eth_set_rx_function(eth_dev);
 303                otx2_eth_set_tx_function(eth_dev);
 304        }
 305
 306        rc = otx2_nix_recalc_mtu(eth_dev);
 307        if (rc)
 308                otx2_err("Failed to set MTU size for ptp");
 309
 310        return rc;
 311}
 312
 313int
 314otx2_nix_timesync_read_rx_timestamp(struct rte_eth_dev *eth_dev,
 315                                    struct timespec *timestamp,
 316                                    uint32_t __rte_unused flags)
 317{
 318        struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
 319        struct otx2_timesync_info *tstamp = &dev->tstamp;
 320        uint64_t ns;
 321
 322        if (!tstamp->rx_ready)
 323                return -EINVAL;
 324
 325        ns = rte_timecounter_update(&dev->rx_tstamp_tc, tstamp->rx_tstamp);
 326        *timestamp = rte_ns_to_timespec(ns);
 327        tstamp->rx_ready = 0;
 328
 329        otx2_nix_dbg("rx timestamp: %"PRIu64" sec: %"PRIu64" nsec %"PRIu64"",
 330                     (uint64_t)tstamp->rx_tstamp, (uint64_t)timestamp->tv_sec,
 331                     (uint64_t)timestamp->tv_nsec);
 332
 333        return 0;
 334}
 335
 336int
 337otx2_nix_timesync_read_tx_timestamp(struct rte_eth_dev *eth_dev,
 338                                    struct timespec *timestamp)
 339{
 340        struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
 341        struct otx2_timesync_info *tstamp = &dev->tstamp;
 342        uint64_t ns;
 343
 344        if (*tstamp->tx_tstamp == 0)
 345                return -EINVAL;
 346
 347        ns = rte_timecounter_update(&dev->tx_tstamp_tc, *tstamp->tx_tstamp);
 348        *timestamp = rte_ns_to_timespec(ns);
 349
 350        otx2_nix_dbg("tx timestamp: %"PRIu64" sec: %"PRIu64" nsec %"PRIu64"",
 351                     *tstamp->tx_tstamp, (uint64_t)timestamp->tv_sec,
 352                     (uint64_t)timestamp->tv_nsec);
 353
 354        *tstamp->tx_tstamp = 0;
 355        rte_wmb();
 356
 357        return 0;
 358}
 359
 360int
 361otx2_nix_timesync_adjust_time(struct rte_eth_dev *eth_dev, int64_t delta)
 362{
 363        struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
 364        struct otx2_mbox *mbox = dev->mbox;
 365        struct ptp_req *req;
 366        struct ptp_rsp *rsp;
 367        int rc;
 368
 369        /* Adjust the frequent to make tics increments in 10^9 tics per sec */
 370        if (delta < PTP_FREQ_ADJUST && delta > -PTP_FREQ_ADJUST) {
 371                req = otx2_mbox_alloc_msg_ptp_op(mbox);
 372                req->op = PTP_OP_ADJFINE;
 373                req->scaled_ppm = delta;
 374
 375                rc = otx2_mbox_process_msg(mbox, (void *)&rsp);
 376                if (rc)
 377                        return rc;
 378                /* Since the frequency of PTP comp register is tuned, delta and
 379                 * freq mult calculation for deriving PTP_HI from timestamp
 380                 * counter should be done again.
 381                 */
 382                rc = otx2_nix_raw_clock_tsc_conv(dev);
 383                if (rc)
 384                        otx2_err("Failed to calculate delta and freq mult");
 385        }
 386        dev->systime_tc.nsec += delta;
 387        dev->rx_tstamp_tc.nsec += delta;
 388        dev->tx_tstamp_tc.nsec += delta;
 389
 390        return 0;
 391}
 392
 393int
 394otx2_nix_timesync_write_time(struct rte_eth_dev *eth_dev,
 395                             const struct timespec *ts)
 396{
 397        struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
 398        uint64_t ns;
 399
 400        ns = rte_timespec_to_ns(ts);
 401        /* Set the time counters to a new value. */
 402        dev->systime_tc.nsec = ns;
 403        dev->rx_tstamp_tc.nsec = ns;
 404        dev->tx_tstamp_tc.nsec = ns;
 405
 406        return 0;
 407}
 408
 409int
 410otx2_nix_timesync_read_time(struct rte_eth_dev *eth_dev, struct timespec *ts)
 411{
 412        struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
 413        struct otx2_mbox *mbox = dev->mbox;
 414        struct ptp_req *req;
 415        struct ptp_rsp *rsp;
 416        uint64_t ns;
 417        int rc;
 418
 419        req = otx2_mbox_alloc_msg_ptp_op(mbox);
 420        req->op = PTP_OP_GET_CLOCK;
 421        rc = otx2_mbox_process_msg(mbox, (void *)&rsp);
 422        if (rc)
 423                return rc;
 424
 425        ns = rte_timecounter_update(&dev->systime_tc, rsp->clk);
 426        *ts = rte_ns_to_timespec(ns);
 427
 428        otx2_nix_dbg("PTP time read: %"PRIu64" .%09"PRIu64"",
 429                     (uint64_t)ts->tv_sec, (uint64_t)ts->tv_nsec);
 430
 431        return 0;
 432}
 433
 434
 435int
 436otx2_nix_read_clock(struct rte_eth_dev *eth_dev, uint64_t *clock)
 437{
 438        struct otx2_eth_dev *dev = otx2_eth_pmd_priv(eth_dev);
 439
 440        /* This API returns the raw PTP HI clock value. Since LFs doesn't
 441         * have direct access to PTP registers and it requires mbox msg
 442         * to AF for this value. In fastpath reading this value for every
 443         * packet (which involes mbox call) becomes very expensive, hence
 444         * we should be able to derive PTP HI clock value from tsc by
 445         * using freq_mult and clk_delta calculated during configure stage.
 446         */
 447        *clock = (rte_get_tsc_cycles() + dev->clk_delta) * dev->clk_freq_mult;
 448
 449        return 0;
 450}
 451