dpdk/drivers/net/hns3/hns3_ptp.c
<<
>>
Prefs
   1/* SPDX-License-Identifier: BSD-3-Clause
   2 * Copyright(c) 2021-2021 Hisilicon Limited.
   3 */
   4
   5#include <ethdev_pci.h>
   6#include <rte_io.h>
   7#include <rte_time.h>
   8
   9#include "hns3_ethdev.h"
  10#include "hns3_regs.h"
  11#include "hns3_logs.h"
  12
  13uint64_t hns3_timestamp_rx_dynflag;
  14int hns3_timestamp_dynfield_offset = -1;
  15
  16int
  17hns3_mbuf_dyn_rx_timestamp_register(struct rte_eth_dev *dev,
  18                                    struct rte_eth_conf *conf)
  19{
  20        struct hns3_adapter *hns = dev->data->dev_private;
  21        struct hns3_hw *hw = &hns->hw;
  22        int ret;
  23
  24        if (!(conf->rxmode.offloads & DEV_RX_OFFLOAD_TIMESTAMP))
  25                return 0;
  26
  27        ret = rte_mbuf_dyn_rx_timestamp_register
  28                        (&hns3_timestamp_dynfield_offset,
  29                         &hns3_timestamp_rx_dynflag);
  30        if (ret) {
  31                hns3_err(hw,
  32                        "failed to register Rx timestamp field/flag");
  33                return ret;
  34        }
  35
  36        return 0;
  37}
  38
  39static int
  40hns3_ptp_int_en(struct hns3_hw *hw, bool en)
  41{
  42        struct hns3_ptp_int_cmd *req;
  43        struct hns3_cmd_desc desc;
  44        int ret;
  45
  46        req = (struct hns3_ptp_int_cmd *)desc.data;
  47        hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_PTP_INT_EN, false);
  48        req->int_en = en ? 1 : 0;
  49
  50        ret = hns3_cmd_send(hw, &desc, 1);
  51        if (ret)
  52                hns3_err(hw,
  53                        "failed to %s ptp interrupt, ret = %d\n",
  54                        en ? "enable" : "disable", ret);
  55
  56        return ret;
  57}
  58
  59int
  60hns3_ptp_init(struct hns3_hw *hw)
  61{
  62        int ret;
  63
  64        if (!hns3_dev_ptp_supported(hw))
  65                return 0;
  66
  67        ret = hns3_ptp_int_en(hw, true);
  68        if (ret)
  69                return ret;
  70
  71        /* Start PTP timer */
  72        hns3_write_dev(hw, HNS3_CFG_TIME_CYC_EN, 1);
  73
  74        return 0;
  75}
  76
  77static int
  78hns3_timesync_configure(struct hns3_adapter *hns, bool en)
  79{
  80        struct hns3_ptp_mode_cfg_cmd *req;
  81        struct hns3_hw *hw = &hns->hw;
  82        struct hns3_pf *pf = &hns->pf;
  83        struct hns3_cmd_desc desc;
  84        int val;
  85        int ret;
  86
  87        hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_CFG_PTP_MODE, false);
  88
  89        req = (struct hns3_ptp_mode_cfg_cmd *)desc.data;
  90
  91        val = en ? 1 : 0;
  92        hns3_set_bit(req->enable, HNS3_PTP_ENABLE_B, val);
  93        hns3_set_bit(req->enable, HNS3_PTP_TX_ENABLE_B, val);
  94        hns3_set_bit(req->enable, HNS3_PTP_RX_ENABLE_B, val);
  95
  96        if (en) {
  97                hns3_set_field(req->ptp_type, HNS3_PTP_TYPE_M, HNS3_PTP_TYPE_S,
  98                               PTP_TYPE_L2_V2_TYPE);
  99                hns3_set_field(req->v2_message_type_1, HNS3_PTP_MESSAGE_TYPE_M,
 100                               HNS3_PTP_MESSAGE_TYPE_S, ALL_PTP_V2_TYPE);
 101        }
 102
 103        ret = hns3_cmd_send(hw, &desc, 1);
 104        if (ret) {
 105                hns3_err(hw, "configure PTP time failed, en = %d, ret = %d",
 106                         en, ret);
 107                return ret;
 108        }
 109
 110        pf->ptp_enable = en;
 111
 112        return 0;
 113}
 114
 115int
 116hns3_timesync_enable(struct rte_eth_dev *dev)
 117{
 118        struct hns3_adapter *hns = dev->data->dev_private;
 119        struct hns3_hw *hw = &hns->hw;
 120        struct hns3_pf *pf = &hns->pf;
 121        int ret;
 122
 123        if (!hns3_dev_ptp_supported(hw))
 124                return -ENOTSUP;
 125
 126        if (pf->ptp_enable)
 127                return 0;
 128
 129        rte_spinlock_lock(&hw->lock);
 130        ret = hns3_timesync_configure(hns, true);
 131        rte_spinlock_unlock(&hw->lock);
 132        return ret;
 133}
 134
 135int
 136hns3_timesync_disable(struct rte_eth_dev *dev)
 137{
 138        struct hns3_adapter *hns = dev->data->dev_private;
 139        struct hns3_hw *hw = &hns->hw;
 140        struct hns3_pf *pf = &hns->pf;
 141        int ret;
 142
 143        if (!hns3_dev_ptp_supported(hw))
 144                return -ENOTSUP;
 145
 146        if (!pf->ptp_enable)
 147                return 0;
 148
 149        rte_spinlock_lock(&hw->lock);
 150        ret = hns3_timesync_configure(hns, false);
 151        rte_spinlock_unlock(&hw->lock);
 152
 153        return ret;
 154}
 155
 156int
 157hns3_timesync_read_rx_timestamp(struct rte_eth_dev *dev,
 158                                struct timespec *timestamp,
 159                                uint32_t flags __rte_unused)
 160{
 161#define TIME_RX_STAMP_NS_MASK 0x3FFFFFFF
 162        struct hns3_adapter *hns = dev->data->dev_private;
 163        struct hns3_hw *hw = &hns->hw;
 164        struct hns3_pf *pf = &hns->pf;
 165        uint64_t ns, sec;
 166
 167        if (!hns3_dev_ptp_supported(hw))
 168                return -ENOTSUP;
 169
 170        ns = pf->rx_timestamp & TIME_RX_STAMP_NS_MASK;
 171        sec = upper_32_bits(pf->rx_timestamp);
 172
 173        ns += sec * NSEC_PER_SEC;
 174        *timestamp = rte_ns_to_timespec(ns);
 175
 176        return 0;
 177}
 178
 179int
 180hns3_timesync_read_tx_timestamp(struct rte_eth_dev *dev,
 181                                struct timespec *timestamp)
 182{
 183#define TIME_TX_STAMP_NS_MASK 0x3FFFFFFF
 184#define TIME_TX_STAMP_VALID   24
 185#define TIME_TX_STAMP_CNT_MASK 0x7
 186        struct hns3_adapter *hns = dev->data->dev_private;
 187        struct hns3_hw *hw = &hns->hw;
 188        uint64_t sec;
 189        uint64_t tmp;
 190        uint64_t ns;
 191        int ts_cnt;
 192
 193        if (!hns3_dev_ptp_supported(hw))
 194                return -ENOTSUP;
 195
 196        ts_cnt = hns3_read_dev(hw, HNS3_TX_1588_BACK_TSP_CNT) &
 197                        TIME_TX_STAMP_CNT_MASK;
 198        if (ts_cnt == 0)
 199                return -EINVAL;
 200
 201        ns = hns3_read_dev(hw, HNS3_TX_1588_TSP_BACK_0) & TIME_TX_STAMP_NS_MASK;
 202        sec = hns3_read_dev(hw, HNS3_TX_1588_TSP_BACK_1);
 203        tmp = hns3_read_dev(hw, HNS3_TX_1588_TSP_BACK_2) & 0xFFFF;
 204        sec = (tmp << 32) | sec;
 205
 206        ns += sec * NSEC_PER_SEC;
 207
 208        *timestamp = rte_ns_to_timespec(ns);
 209
 210        /* Clear current timestamp hardware stores */
 211        hns3_read_dev(hw, HNS3_TX_1588_SEQID_BACK);
 212
 213        return 0;
 214}
 215
 216int
 217hns3_timesync_read_time(struct rte_eth_dev *dev, struct timespec *ts)
 218{
 219        struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 220        uint64_t ns, sec;
 221
 222        if (!hns3_dev_ptp_supported(hw))
 223                return -ENOTSUP;
 224
 225        sec = hns3_read_dev(hw, HNS3_CURR_TIME_OUT_L);
 226        sec |= (uint64_t)(hns3_read_dev(hw, HNS3_CURR_TIME_OUT_H) & 0xFFFF)
 227                << 32;
 228
 229        ns = hns3_read_dev(hw, HNS3_CURR_TIME_OUT_NS);
 230        ns += sec * NSEC_PER_SEC;
 231        *ts = rte_ns_to_timespec(ns);
 232
 233        return 0;
 234}
 235
 236int
 237hns3_timesync_write_time(struct rte_eth_dev *dev, const struct timespec *ts)
 238{
 239        struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 240        uint64_t sec = ts->tv_sec;
 241        uint64_t ns = ts->tv_nsec;
 242
 243        if (!hns3_dev_ptp_supported(hw))
 244                return -ENOTSUP;
 245
 246        /* Set the timecounters to a new value. */
 247        hns3_write_dev(hw, HNS3_CFG_TIME_SYNC_H, upper_32_bits(sec));
 248        hns3_write_dev(hw, HNS3_CFG_TIME_SYNC_M, lower_32_bits(sec));
 249        hns3_write_dev(hw, HNS3_CFG_TIME_SYNC_L, lower_32_bits(ns));
 250        hns3_write_dev(hw, HNS3_CFG_TIME_SYNC_RDY, 1);
 251
 252        return 0;
 253}
 254
 255int
 256hns3_timesync_adjust_time(struct rte_eth_dev *dev, int64_t delta)
 257{
 258#define TIME_SYNC_L_MASK 0x7FFFFFFF
 259#define SYMBOL_BIT_OFFSET 31
 260        struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private);
 261        struct timespec cur_time;
 262        uint64_t ns;
 263
 264        if (!hns3_dev_ptp_supported(hw))
 265                return -ENOTSUP;
 266
 267        (void)hns3_timesync_read_time(dev, &cur_time);
 268        ns = rte_timespec_to_ns((const struct timespec *)&cur_time);
 269        cur_time = rte_ns_to_timespec(ns + delta);
 270        (void)hns3_timesync_write_time(dev, (const struct timespec *)&cur_time);
 271
 272        return 0;
 273}
 274
 275int
 276hns3_restore_ptp(struct hns3_adapter *hns)
 277{
 278        struct hns3_pf *pf = &hns->pf;
 279        struct hns3_hw *hw = &hns->hw;
 280        bool en = pf->ptp_enable;
 281        int ret;
 282
 283        if (!hns3_dev_ptp_supported(hw))
 284                return 0;
 285
 286        ret = hns3_timesync_configure(hns, en);
 287        if (ret)
 288                hns3_err(hw, "restore PTP enable state(%d) failed, ret = %d",
 289                         en, ret);
 290
 291        return ret;
 292}
 293