From patchwork Fri Mar 26 08:56:01 2021 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: "humin (Q)" X-Patchwork-Id: 89905 X-Patchwork-Delegate: ferruh.yigit@amd.com Return-Path: X-Original-To: patchwork@inbox.dpdk.org Delivered-To: patchwork@inbox.dpdk.org Received: from mails.dpdk.org (mails.dpdk.org [217.70.189.124]) by inbox.dpdk.org (Postfix) with ESMTP id 82497A0A02; Fri, 26 Mar 2021 09:55:52 +0100 (CET) Received: from [217.70.189.124] (localhost [127.0.0.1]) by mails.dpdk.org (Postfix) with ESMTP id 62DC1140D73; Fri, 26 Mar 2021 09:55:43 +0100 (CET) Received: from szxga04-in.huawei.com (szxga04-in.huawei.com [45.249.212.190]) by mails.dpdk.org (Postfix) with ESMTP id 983AA140D4C for ; Fri, 26 Mar 2021 09:55:41 +0100 (CET) Received: from DGGEMS413-HUB.china.huawei.com (unknown [172.30.72.59]) by szxga04-in.huawei.com (SkyGuard) with ESMTP id 4F6G3P2phZz19JjF for ; Fri, 26 Mar 2021 16:53:37 +0800 (CST) Received: from localhost.localdomain (10.69.192.56) by DGGEMS413-HUB.china.huawei.com (10.3.19.213) with Microsoft SMTP Server id 14.3.498.0; Fri, 26 Mar 2021 16:55:35 +0800 From: "Min Hu (Connor)" To: , Date: Fri, 26 Mar 2021 16:56:01 +0800 Message-ID: <1616748961-11239-3-git-send-email-humin29@huawei.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1616748961-11239-1-git-send-email-humin29@huawei.com> References: <1616748961-11239-1-git-send-email-humin29@huawei.com> MIME-Version: 1.0 X-Originating-IP: [10.69.192.56] X-CFilter-Loop: Reflected Subject: [dpdk-dev] [PATCH 2/2] net/hns3: support IEEE 1588 PTP X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: DPDK patches and discussions List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: dev-bounces@dpdk.org Sender: "dev" Add hns3 support for new ethdev APIs to enable and read IEEE1588/ 802.1AS PTP timestamps. Signed-off-by: Min Hu (Connor) --- doc/guides/nics/features/hns3.ini | 2 + doc/guides/nics/hns3.rst | 1 + drivers/net/hns3/hns3_cmd.h | 33 +++++ drivers/net/hns3/hns3_ethdev.c | 59 +++++++- drivers/net/hns3/hns3_ethdev.h | 25 ++++ drivers/net/hns3/hns3_ptp.c | 294 ++++++++++++++++++++++++++++++++++++++ drivers/net/hns3/hns3_regs.h | 25 ++++ drivers/net/hns3/hns3_rxtx.c | 56 +++++++- drivers/net/hns3/hns3_rxtx.h | 12 ++ drivers/net/hns3/hns3_rxtx_vec.c | 19 ++- drivers/net/hns3/meson.build | 3 +- 11 files changed, 516 insertions(+), 13 deletions(-) create mode 100644 drivers/net/hns3/hns3_ptp.c diff --git a/doc/guides/nics/features/hns3.ini b/doc/guides/nics/features/hns3.ini index 3988be4..502bfe7 100644 --- a/doc/guides/nics/features/hns3.ini +++ b/doc/guides/nics/features/hns3.ini @@ -43,6 +43,8 @@ Stats per queue = Y FW version = Y Registers dump = Y Module EEPROM dump = Y +Timesync = Y +Timestamp offload = Y Multiprocess aware = Y Linux = Y ARMv8 = Y diff --git a/doc/guides/nics/hns3.rst b/doc/guides/nics/hns3.rst index ccd2f6f..3366562 100644 --- a/doc/guides/nics/hns3.rst +++ b/doc/guides/nics/hns3.rst @@ -37,6 +37,7 @@ Features of the HNS3 PMD are: - MTU update - NUMA support - Generic flow API +- IEEE1588/802.1AS timestamping Prerequisites ------------- diff --git a/drivers/net/hns3/hns3_cmd.h b/drivers/net/hns3/hns3_cmd.h index e704d0c..abc853b 100644 --- a/drivers/net/hns3/hns3_cmd.h +++ b/drivers/net/hns3/hns3_cmd.h @@ -123,6 +123,12 @@ enum hns3_opcode_type { HNS3_OPC_CLEAR_MAC_TNL_INT = 0x0312, HNS3_OPC_CONFIG_FEC_MODE = 0x031A, +#ifdef RTE_LIBRTE_IEEE1588 + /* PTP command */ + HNS3_OPC_PTP_INT_EN = 0x0501, + HNS3_OPC_CFG_PTP_MODE = 0x0507, +#endif + /* PFC/Pause commands */ HNS3_OPC_CFG_MAC_PAUSE_EN = 0x0701, HNS3_OPC_CFG_PFC_PAUSE_EN = 0x0702, @@ -969,6 +975,33 @@ struct hns3_query_ssu_cmd { uint32_t oq_drop_cnt; uint32_t rev1[2]; }; +#ifdef RTE_LIBRTE_IEEE1588 +#define HNS3_PTP_ENABLE_B 0 +#define HNS3_PTP_TX_ENABLE_B 1 +#define HNS3_PTP_RX_ENABLE_B 2 + +#define HNS3_PTP_TYPE_S 0 +#define HNS3_PTP_TYPE_M (0x3 << HNS3_PTP_TYPE_S) + +#define ALL_PTP_V2_TYPE 0xF +#define HNS3_PTP_MESSAGE_TYPE_S 0 +#define HNS3_PTP_MESSAGE_TYPE_M (0xF << HNS3_PTP_MESSAGE_TYPE_S) + +#define PTP_TYPE_L2_V2_TYPE 0 + +struct hns3_ptp_mode_cfg_cmd { + uint8_t enable; + uint8_t ptp_type; + uint8_t v2_message_type_1; + uint8_t v2_message_type_0; + uint8_t rsv[20]; +}; + +struct hns3_ptp_int_cmd { + uint8_t int_en; + uint8_t rsvd[23]; +}; +#endif #define HNS3_MAX_TQP_NUM_HIP08_PF 64 #define HNS3_DEFAULT_TX_BUF 0x4000 /* 16k bytes */ diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c index b985447..11b9065 100644 --- a/drivers/net/hns3/hns3_ethdev.c +++ b/drivers/net/hns3/hns3_ethdev.c @@ -58,6 +58,10 @@ enum hns3_evt_cause { HNS3_VECTOR0_EVENT_RST, HNS3_VECTOR0_EVENT_MBX, HNS3_VECTOR0_EVENT_ERR, + +#ifdef RTE_LIBRTE_IEEE1588 + HNS3_VECTOR0_EVENT_PTP, +#endif HNS3_VECTOR0_EVENT_OTHER, }; @@ -202,6 +206,14 @@ hns3_check_event_cause(struct hns3_adapter *hns, uint32_t *clearval) goto out; } +#ifdef RTE_LIBRTE_IEEE1588 + /* Check for vector0 1588 event source */ + if (BIT(HNS3_VECTOR0_1588_INT_B) & vector0_int_stats) { + val = BIT(HNS3_VECTOR0_1588_INT_B); + ret = HNS3_VECTOR0_EVENT_PTP; + goto out; + } +#endif /* check for vector0 msix event source */ if (vector0_int_stats & HNS3_VECTOR0_REG_MSIX_MASK || hw_err_src_reg & HNS3_RAS_REG_NFE_MASK) { @@ -227,10 +239,22 @@ hns3_check_event_cause(struct hns3_adapter *hns, uint32_t *clearval) return ret; } +static bool +hns3_is_1588_event_type(uint32_t event_type) +{ +#ifdef RTE_LIBRTE_IEEE1588 + return (event_type == HNS3_VECTOR0_EVENT_PTP); +#else + RTE_SET_USED(event_type); + return false; +#endif +} + static void hns3_clear_event_cause(struct hns3_hw *hw, uint32_t event_type, uint32_t regclr) { - if (event_type == HNS3_VECTOR0_EVENT_RST) + if (event_type == HNS3_VECTOR0_EVENT_RST || + hns3_is_1588_event_type(event_type)) hns3_write_dev(hw, HNS3_MISC_RESET_STS_REG, regclr); else if (event_type == HNS3_VECTOR0_EVENT_MBX) hns3_write_dev(hw, HNS3_VECTOR0_CMDQ_SRC_REG, regclr); @@ -253,6 +277,11 @@ hns3_clear_all_event_cause(struct hns3_hw *hw) BIT(HNS3_VECTOR0_GLOBALRESET_INT_B) | BIT(HNS3_VECTOR0_CORERESET_INT_B)); hns3_clear_event_cause(hw, HNS3_VECTOR0_EVENT_MBX, 0); + +#ifdef RTE_LIBRTE_IEEE1588 + hns3_clear_event_cause(hw, HNS3_VECTOR0_EVENT_PTP, + BIT(HNS3_VECTOR0_1588_INT_B)); +#endif } static void @@ -2467,6 +2496,11 @@ hns3_dev_configure(struct rte_eth_dev *dev) if (ret) goto cfg_err; +#ifdef RTE_LIBRTE_IEEE1588 + ret = hns3_mbuf_dyn_rx_timestamp_register(dev, conf); + if (ret) + goto cfg_err; +#endif ret = hns3_dev_configure_vlan(dev); if (ret) goto cfg_err; @@ -2640,6 +2674,9 @@ hns3_dev_infos_get(struct rte_eth_dev *eth_dev, struct rte_eth_dev_info *info) info->dev_capa = RTE_ETH_DEV_CAPA_RUNTIME_RX_QUEUE_SETUP | RTE_ETH_DEV_CAPA_RUNTIME_TX_QUEUE_SETUP; + if (hns3_dev_ptp_supported(hw)) + info->rx_offload_capa |= DEV_RX_OFFLOAD_TIMESTAMP; + info->rx_desc_lim = (struct rte_eth_desc_lim) { .nb_max = HNS3_MAX_RING_DESC, .nb_min = HNS3_MIN_RING_DESC, @@ -4933,6 +4970,11 @@ hns3_init_pf(struct rte_eth_dev *eth_dev) goto err_intr_callback_register; } +#ifdef RTE_LIBRTE_IEEE1588 + ret = hns3_ptp_init(hw); + if (ret) + goto err_get_config; +#endif /* Enable interrupt */ rte_intr_enable(&pci_dev->intr_handle); hns3_pf_enable_irq0(hw); @@ -5950,6 +5992,12 @@ hns3_restore_conf(struct hns3_adapter *hns) if (ret) goto err_promisc; +#ifdef RTE_LIBRTE_IEEE1588 + ret = hns3_restore_ptp(hns); + if (ret) + goto err_promisc; +#endif + ret = hns3_restore_rx_interrupt(hw); if (ret) goto err_promisc; @@ -6654,6 +6702,15 @@ static const struct eth_dev_ops hns3_eth_dev_ops = { .fec_set = hns3_fec_set, .tm_ops_get = hns3_tm_ops_get, .tx_done_cleanup = hns3_tx_done_cleanup, +#ifdef RTE_LIBRTE_IEEE1588 + .timesync_enable = hns3_timesync_enable, + .timesync_disable = hns3_timesync_disable, + .timesync_read_rx_timestamp = hns3_timesync_read_rx_timestamp, + .timesync_read_tx_timestamp = hns3_timesync_read_tx_timestamp, + .timesync_adjust_time = hns3_timesync_adjust_time, + .timesync_read_time = hns3_timesync_read_time, + .timesync_write_time = hns3_timesync_write_time, +#endif }; static const struct hns3_reset_ops hns3_reset_ops = { diff --git a/drivers/net/hns3/hns3_ethdev.h b/drivers/net/hns3/hns3_ethdev.h index f69e2d8..4ce192c 100644 --- a/drivers/net/hns3/hns3_ethdev.h +++ b/drivers/net/hns3/hns3_ethdev.h @@ -731,6 +731,13 @@ struct hns3_pf { bool support_sfp_query; uint32_t fec_mode; /* current FEC mode for ethdev */ +#ifdef RTE_LIBRTE_IEEE1588 + bool ptp_enable; + + /* Stores timestamp of last received packet on dev */ + uint64_t rx_timestamp; +#endif + struct hns3_vtag_cfg vtag_config; LIST_HEAD(vlan_tbl, hns3_user_vlan_table) vlan_list; @@ -982,6 +989,24 @@ void hns3vf_update_link_status(struct hns3_hw *hw, uint8_t link_status, uint32_t link_speed, uint8_t link_duplex); void hns3_parse_devargs(struct rte_eth_dev *dev); +#ifdef RTE_LIBRTE_IEEE1588 +int hns3_restore_ptp(struct hns3_adapter *hns); +int hns3_mbuf_dyn_rx_timestamp_register(struct rte_eth_dev *dev, + struct rte_eth_conf *conf); +int hns3_ptp_init(struct hns3_hw *hw); +int hns3_timesync_enable(struct rte_eth_dev *dev); +int hns3_timesync_disable(struct rte_eth_dev *dev); +int hns3_timesync_read_rx_timestamp(struct rte_eth_dev *dev, + struct timespec *timestamp, + uint32_t flags __rte_unused); +int hns3_timesync_read_tx_timestamp(struct rte_eth_dev *dev, + struct timespec *timestamp); +int hns3_timesync_read_time(struct rte_eth_dev *dev, struct timespec *ts); +int hns3_timesync_write_time(struct rte_eth_dev *dev, + const struct timespec *ts); +int hns3_timesync_adjust_time(struct rte_eth_dev *dev, int64_t delta); +#endif + static inline bool is_reset_pending(struct hns3_adapter *hns) { diff --git a/drivers/net/hns3/hns3_ptp.c b/drivers/net/hns3/hns3_ptp.c new file mode 100644 index 0000000..d7e18c1 --- /dev/null +++ b/drivers/net/hns3/hns3_ptp.c @@ -0,0 +1,294 @@ +/* SPDX-License-Identifier: BSD-3-Clause + * Copyright(c) 2021-2021 Hisilicon Limited. + */ + +#include +#include +#include + +#include "hns3_ethdev.h" +#include "hns3_regs.h" +#include "hns3_logs.h" + +#ifdef RTE_LIBRTE_IEEE1588 +uint64_t hns3_timestamp_rx_dynflag; +int hns3_timestamp_dynfield_offset = -1; + +int +hns3_mbuf_dyn_rx_timestamp_register(struct rte_eth_dev *dev, + struct rte_eth_conf *conf) +{ + struct hns3_adapter *hns = dev->data->dev_private; + struct hns3_hw *hw = &hns->hw; + int ret; + + if (!(conf->rxmode.offloads & DEV_RX_OFFLOAD_TIMESTAMP)) + return 0; + + ret = rte_mbuf_dyn_rx_timestamp_register + (&hns3_timestamp_dynfield_offset, + &hns3_timestamp_rx_dynflag); + if (ret) { + hns3_err(hw, + "failed to register Rx timestamp field/flag"); + return ret; + } + + return 0; +} + +static int +hns3_ptp_int_en(struct hns3_hw *hw, bool en) +{ + struct hns3_ptp_int_cmd *req; + struct hns3_cmd_desc desc; + int ret; + + req = (struct hns3_ptp_int_cmd *)desc.data; + hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_PTP_INT_EN, false); + req->int_en = en ? 1 : 0; + + ret = hns3_cmd_send(hw, &desc, 1); + if (ret) + hns3_err(hw, + "failed to %s ptp interrupt, ret = %d\n", + en ? "enable" : "disable", ret); + + return ret; +} + +int +hns3_ptp_init(struct hns3_hw *hw) +{ + int ret; + + if (!hns3_dev_ptp_supported(hw)) + return 0; + + ret = hns3_ptp_int_en(hw, true); + if (ret) + return ret; + + /* Start PTP timer */ + hns3_write_dev(hw, HNS3_CFG_TIME_CYC_EN, 1); + + return 0; +} + +static int +hns3_timesync_configure(struct hns3_adapter *hns, bool en) +{ + struct hns3_ptp_mode_cfg_cmd *req; + struct hns3_hw *hw = &hns->hw; + struct hns3_pf *pf = &hns->pf; + struct hns3_cmd_desc desc; + int val; + int ret; + + hns3_cmd_setup_basic_desc(&desc, HNS3_OPC_CFG_PTP_MODE, false); + + req = (struct hns3_ptp_mode_cfg_cmd *)desc.data; + + val = en ? 1 : 0; + hns3_set_bit(req->enable, HNS3_PTP_ENABLE_B, val); + hns3_set_bit(req->enable, HNS3_PTP_TX_ENABLE_B, val); + hns3_set_bit(req->enable, HNS3_PTP_RX_ENABLE_B, val); + + if (en) { + hns3_set_field(req->ptp_type, HNS3_PTP_TYPE_M, HNS3_PTP_TYPE_S, + PTP_TYPE_L2_V2_TYPE); + hns3_set_field(req->v2_message_type_1, HNS3_PTP_MESSAGE_TYPE_M, + HNS3_PTP_MESSAGE_TYPE_S, ALL_PTP_V2_TYPE); + } + + ret = hns3_cmd_send(hw, &desc, 1); + if (ret) { + hns3_err(hw, "configure PTP time failed, en = %d, ret = %d", + en, ret); + return ret; + } + + pf->ptp_enable = en; + + return 0; +} + +int +hns3_timesync_enable(struct rte_eth_dev *dev) +{ + struct hns3_adapter *hns = dev->data->dev_private; + struct hns3_hw *hw = &hns->hw; + struct hns3_pf *pf = &hns->pf; + int ret; + + if (!hns3_dev_ptp_supported(hw)) + return -ENOTSUP; + + if (pf->ptp_enable) + return 0; + + rte_spinlock_lock(&hw->lock); + ret = hns3_timesync_configure(hns, true); + rte_spinlock_unlock(&hw->lock); + return ret; +} + +int +hns3_timesync_disable(struct rte_eth_dev *dev) +{ + struct hns3_adapter *hns = dev->data->dev_private; + struct hns3_hw *hw = &hns->hw; + struct hns3_pf *pf = &hns->pf; + int ret; + + if (!hns3_dev_ptp_supported(hw)) + return -ENOTSUP; + + if (!pf->ptp_enable) + return 0; + + rte_spinlock_lock(&hw->lock); + ret = hns3_timesync_configure(hns, false); + rte_spinlock_unlock(&hw->lock); + + return ret; +} + +int +hns3_timesync_read_rx_timestamp(struct rte_eth_dev *dev, + struct timespec *timestamp, + uint32_t flags __rte_unused) +{ +#define TIME_RX_STAMP_NS_MASK 0x3FFFFFFF + struct hns3_adapter *hns = dev->data->dev_private; + struct hns3_hw *hw = &hns->hw; + struct hns3_pf *pf = &hns->pf; + uint64_t ns, sec; + + if (!hns3_dev_ptp_supported(hw)) + return -ENOTSUP; + + ns = pf->rx_timestamp & TIME_RX_STAMP_NS_MASK; + sec = upper_32_bits(pf->rx_timestamp); + + ns += sec * NSEC_PER_SEC; + *timestamp = rte_ns_to_timespec(ns); + + return 0; +} + +int +hns3_timesync_read_tx_timestamp(struct rte_eth_dev *dev, + struct timespec *timestamp) +{ +#define TIME_TX_STAMP_NS_MASK 0x3FFFFFFF +#define TIME_TX_STAMP_VALID 24 +#define TIME_TX_STAMP_CNT_MASK 0x7 + struct hns3_adapter *hns = dev->data->dev_private; + struct hns3_hw *hw = &hns->hw; + uint64_t sec; + uint64_t tmp; + uint64_t ns; + int ts_cnt; + + if (!hns3_dev_ptp_supported(hw)) + return -ENOTSUP; + + ts_cnt = hns3_read_dev(hw, HNS3_TX_1588_BACK_TSP_CNT) & + TIME_TX_STAMP_CNT_MASK; + if (ts_cnt == 0) + return -EINVAL; + + ns = hns3_read_dev(hw, HNS3_TX_1588_TSP_BACK_0) & TIME_TX_STAMP_NS_MASK; + sec = hns3_read_dev(hw, HNS3_TX_1588_TSP_BACK_1); + tmp = hns3_read_dev(hw, HNS3_TX_1588_TSP_BACK_2) & 0xFFFF; + sec = (tmp << 32) | sec; + + ns += sec * NSEC_PER_SEC; + + *timestamp = rte_ns_to_timespec(ns); + + /* Clear current timestamp hardware stores */ + hns3_read_dev(hw, HNS3_TX_1588_SEQID_BACK); + + return 0; +} + +int +hns3_timesync_read_time(struct rte_eth_dev *dev, struct timespec *ts) +{ + struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private); + uint64_t ns, sec; + + if (!hns3_dev_ptp_supported(hw)) + return -ENOTSUP; + + sec = hns3_read_dev(hw, HNS3_CURR_TIME_OUT_L); + sec |= (uint64_t)(hns3_read_dev(hw, HNS3_CURR_TIME_OUT_H) & 0xFFFF) + << 32; + + ns = hns3_read_dev(hw, HNS3_CURR_TIME_OUT_NS); + ns += sec * NSEC_PER_SEC; + *ts = rte_ns_to_timespec(ns); + + return 0; +} + +int +hns3_timesync_write_time(struct rte_eth_dev *dev, const struct timespec *ts) +{ + struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private); + uint64_t sec = ts->tv_sec; + uint64_t ns = ts->tv_nsec; + + if (!hns3_dev_ptp_supported(hw)) + return -ENOTSUP; + + /* Set the timecounters to a new value. */ + hns3_write_dev(hw, HNS3_CFG_TIME_SYNC_H, upper_32_bits(sec)); + hns3_write_dev(hw, HNS3_CFG_TIME_SYNC_M, lower_32_bits(sec)); + hns3_write_dev(hw, HNS3_CFG_TIME_SYNC_L, lower_32_bits(ns)); + hns3_write_dev(hw, HNS3_CFG_TIME_SYNC_RDY, 1); + + return 0; +} + +int +hns3_timesync_adjust_time(struct rte_eth_dev *dev, int64_t delta) +{ +#define TIME_SYNC_L_MASK 0x7FFFFFFF +#define SYMBOL_BIT_OFFSET 31 + struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private); + struct timespec cur_time; + uint64_t ns; + + if (!hns3_dev_ptp_supported(hw)) + return -ENOTSUP; + + (void)hns3_timesync_read_time(dev, &cur_time); + ns = rte_timespec_to_ns((const struct timespec *)&cur_time); + cur_time = rte_ns_to_timespec(ns + delta); + (void)hns3_timesync_write_time(dev, (const struct timespec *)&cur_time); + + return 0; +} + +int +hns3_restore_ptp(struct hns3_adapter *hns) +{ + struct hns3_pf *pf = &hns->pf; + struct hns3_hw *hw = &hns->hw; + bool en = pf->ptp_enable; + int ret; + + if (!hns3_dev_ptp_supported(hw)) + return 0; + + ret = hns3_timesync_configure(hns, en); + if (ret) + hns3_err(hw, "restore PTP enable state(%d) failed, ret = %d", + en, ret); + + return ret; +} +#endif diff --git a/drivers/net/hns3/hns3_regs.h b/drivers/net/hns3/hns3_regs.h index e141fe1..58a20ca 100644 --- a/drivers/net/hns3/hns3_regs.h +++ b/drivers/net/hns3/hns3_regs.h @@ -121,6 +121,31 @@ #define HNS3_TQP_INTR_RL_DEFAULT 0 #define HNS3_TQP_INTR_QL_DEFAULT 0 +#ifdef RTE_LIBRTE_IEEE1588 +/* Register bit for 1588 event */ +#define HNS3_VECTOR0_1588_INT_B 0 + +#define HNS3_PTP_BASE_ADDRESS 0x29000 + +#define HNS3_TX_1588_SEQID_BACK (HNS3_PTP_BASE_ADDRESS + 0x0) +#define HNS3_TX_1588_TSP_BACK_0 (HNS3_PTP_BASE_ADDRESS + 0x4) +#define HNS3_TX_1588_TSP_BACK_1 (HNS3_PTP_BASE_ADDRESS + 0x8) +#define HNS3_TX_1588_TSP_BACK_2 (HNS3_PTP_BASE_ADDRESS + 0xc) + +#define HNS3_TX_1588_BACK_TSP_CNT (HNS3_PTP_BASE_ADDRESS + 0x30) + +#define HNS3_CFG_TIME_SYNC_H (HNS3_PTP_BASE_ADDRESS + 0x50) +#define HNS3_CFG_TIME_SYNC_M (HNS3_PTP_BASE_ADDRESS + 0x54) +#define HNS3_CFG_TIME_SYNC_L (HNS3_PTP_BASE_ADDRESS + 0x58) +#define HNS3_CFG_TIME_SYNC_RDY (HNS3_PTP_BASE_ADDRESS + 0x5c) + +#define HNS3_CFG_TIME_CYC_EN (HNS3_PTP_BASE_ADDRESS + 0x70) + +#define HNS3_CURR_TIME_OUT_H (HNS3_PTP_BASE_ADDRESS + 0x74) +#define HNS3_CURR_TIME_OUT_L (HNS3_PTP_BASE_ADDRESS + 0x78) +#define HNS3_CURR_TIME_OUT_NS (HNS3_PTP_BASE_ADDRESS + 0x7c) +#endif + /* gl_usec convert to hardware count, as writing each 1 represents 2us */ #define HNS3_GL_USEC_TO_REG(gl_usec) ((gl_usec) >> 1) /* rl_usec convert to hardware count, as writing each 1 represents 4us */ diff --git a/drivers/net/hns3/hns3_rxtx.c b/drivers/net/hns3/hns3_rxtx.c index feeb702..ceed302 100644 --- a/drivers/net/hns3/hns3_rxtx.c +++ b/drivers/net/hns3/hns3_rxtx.c @@ -2275,6 +2275,25 @@ hns3_rx_alloc_buffer(struct hns3_rx_queue *rxq) return rte_mbuf_raw_alloc(rxq->mb_pool); } +#ifdef RTE_LIBRTE_IEEE1588 +static inline void +hns3_rx_ptp_timestamp_handle(struct hns3_rx_queue *rxq, struct rte_mbuf *mbuf, + volatile struct hns3_desc *rxd) +{ + struct hns3_pf *pf = HNS3_DEV_PRIVATE_TO_PF(rxq->hns); + uint64_t timestamp = rte_le_to_cpu_64(rxd->timestamp); + + mbuf->ol_flags |= PKT_RX_IEEE1588_PTP | PKT_RX_IEEE1588_TMST; + if (hns3_timestamp_rx_dynflag > 0) { + *RTE_MBUF_DYNFIELD(mbuf, hns3_timestamp_dynfield_offset, + rte_mbuf_timestamp_t *) = timestamp; + mbuf->ol_flags |= hns3_timestamp_rx_dynflag; + } + + pf->rx_timestamp = timestamp; +} +#endif + uint16_t hns3_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) { @@ -2334,8 +2353,13 @@ hns3_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) } rxm = rxe->mbuf; + rxm->ol_flags = 0; rxe->mbuf = nmb; +#ifdef RTE_LIBRTE_IEEE1588 + if (unlikely(bd_base_info & BIT(HNS3_RXD_TS_VLD_B))) + hns3_rx_ptp_timestamp_handle(rxq, rxm, rxdp); +#endif dma_addr = rte_mbuf_data_iova_default(nmb); rxdp->addr = rte_cpu_to_le_64(dma_addr); rxdp->rx.bd_base_info = 0; @@ -2346,7 +2370,7 @@ hns3_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) rxm->data_len = rxm->pkt_len; rxm->port = rxq->port_id; rxm->hash.rss = rte_le_to_cpu_32(rxd.rx.rss_hash); - rxm->ol_flags = PKT_RX_RSS_HASH; + rxm->ol_flags |= PKT_RX_RSS_HASH; if (unlikely(bd_base_info & BIT(HNS3_RXD_LUM_B))) { rxm->hash.fdir.hi = rte_le_to_cpu_16(rxd.rx.fd_id); @@ -2365,6 +2389,11 @@ hns3_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) rxm->packet_type = hns3_rx_calc_ptype(rxq, l234_info, ol_info); +#ifdef RTE_LIBRTE_IEEE1588 + if (rxm->packet_type == RTE_PTYPE_L2_ETHER_TIMESYNC) + rxm->ol_flags |= PKT_RX_IEEE1588_PTP; +#endif + if (likely(bd_base_info & BIT(HNS3_RXD_L3L4P_B))) hns3_rx_set_cksum_flag(rxm, rxm->packet_type, cksum_err); @@ -2952,7 +2981,7 @@ hns3_fill_per_desc(struct hns3_desc *desc, struct rte_mbuf *rxm) { desc->addr = rte_mbuf_data_iova(rxm); desc->tx.send_size = rte_cpu_to_le_16(rte_pktmbuf_data_len(rxm)); - desc->tx.tp_fe_sc_vld_ra_ri = rte_cpu_to_le_16(BIT(HNS3_TXD_VLD_B)); + desc->tx.tp_fe_sc_vld_ra_ri |= rte_cpu_to_le_16(BIT(HNS3_TXD_VLD_B)); } static void @@ -3000,6 +3029,12 @@ hns3_fill_first_desc(struct hns3_tx_queue *txq, struct hns3_desc *desc, rte_cpu_to_le_32(BIT(HNS3_TXD_VLAN_B)); desc->tx.vlan_tag = rte_cpu_to_le_16(rxm->vlan_tci); } + +#ifdef RTE_LIBRTE_IEEE1588 + if (ol_flags & PKT_TX_IEEE1588_TMST) + desc->tx.tp_fe_sc_vld_ra_ri |= + rte_cpu_to_le_16(BIT(HNS3_TXD_TSYN_B)); +#endif } static inline int @@ -3991,10 +4026,23 @@ hns3_tx_burst_mode_get(struct rte_eth_dev *dev, __rte_unused uint16_t queue_id, return 0; } +static bool +hns3_tx_check_simple_support(struct rte_eth_dev *dev) +{ + uint64_t offloads = dev->data->dev_conf.txmode.offloads; + +#ifdef RTE_LIBRTE_IEEE1588 + struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private); + if (hns3_dev_ptp_supported(hw)) + return false; +#endif + + return (offloads == (offloads & DEV_TX_OFFLOAD_MBUF_FAST_FREE)); +} + static eth_tx_burst_t hns3_get_tx_function(struct rte_eth_dev *dev, eth_tx_prep_t *prep) { - uint64_t offloads = dev->data->dev_conf.txmode.offloads; struct hns3_adapter *hns = dev->data->dev_private; bool vec_allowed, sve_allowed, simple_allowed; @@ -4002,7 +4050,7 @@ hns3_get_tx_function(struct rte_eth_dev *dev, eth_tx_prep_t *prep) hns3_tx_check_vec_support(dev) == 0; sve_allowed = vec_allowed && hns3_check_sve_support(); simple_allowed = hns->tx_simple_allowed && - offloads == (offloads & DEV_TX_OFFLOAD_MBUF_FAST_FREE); + hns3_tx_check_simple_support(dev); *prep = NULL; diff --git a/drivers/net/hns3/hns3_rxtx.h b/drivers/net/hns3/hns3_rxtx.h index f9b3048..74e5407 100644 --- a/drivers/net/hns3/hns3_rxtx.h +++ b/drivers/net/hns3/hns3_rxtx.h @@ -106,6 +106,8 @@ #define HNS3_RXD_L3L4P_B 11 #define HNS3_RXD_TSIND_S 12 #define HNS3_RXD_TSIND_M (0x7 << HNS3_RXD_TSIND_S) + +#define HNS3_RXD_TS_VLD_B 14 #define HNS3_RXD_LKBK_B 15 #define HNS3_RXD_GRO_SIZE_S 16 #define HNS3_RXD_GRO_SIZE_M (0x3fff << HNS3_RXD_GRO_SIZE_S) @@ -200,6 +202,11 @@ enum hns3_pkt_tun_type { struct hns3_desc { union { uint64_t addr; + +#ifdef RTE_LIBRTE_IEEE1588 + uint64_t timestamp; +#endif + struct { uint32_t addr0; uint32_t addr1; @@ -518,6 +525,11 @@ enum hns3_cksum_status { HNS3_OUTER_L4_CKSUM_ERR = 8 }; +#ifdef RTE_LIBRTE_IEEE1588 +extern uint64_t hns3_timestamp_rx_dynflag; +extern int hns3_timestamp_dynfield_offset; +#endif + static inline int hns3_handle_bdinfo(struct hns3_rx_queue *rxq, struct rte_mbuf *rxm, uint32_t bd_base_info, uint32_t l234_info, diff --git a/drivers/net/hns3/hns3_rxtx_vec.c b/drivers/net/hns3/hns3_rxtx_vec.c index 2bc4372..4584d8a 100644 --- a/drivers/net/hns3/hns3_rxtx_vec.c +++ b/drivers/net/hns3/hns3_rxtx_vec.c @@ -18,6 +18,12 @@ hns3_tx_check_vec_support(struct rte_eth_dev *dev) { struct rte_eth_txmode *txmode = &dev->data->dev_conf.txmode; +#ifdef RTE_LIBRTE_IEEE1588 + struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private); + if (hns3_dev_ptp_supported(hw)) + return -ENOTSUP; +#endif + /* Only support DEV_TX_OFFLOAD_MBUF_FAST_FREE */ if (txmode->offloads != DEV_TX_OFFLOAD_MBUF_FAST_FREE) return -ENOTSUP; @@ -167,7 +173,6 @@ hns3_rxq_vec_setup(struct hns3_rx_queue *rxq) memset(rxq->offset_table, 0, sizeof(rxq->offset_table)); } -#ifndef RTE_LIBRTE_IEEE1588 static int hns3_rxq_vec_check(struct hns3_rx_queue *rxq, void *arg) { @@ -183,17 +188,21 @@ hns3_rxq_vec_check(struct hns3_rx_queue *rxq, void *arg) RTE_SET_USED(arg); return 0; } -#endif int hns3_rx_check_vec_support(struct rte_eth_dev *dev) { -#ifndef RTE_LIBRTE_IEEE1588 struct rte_fdir_conf *fconf = &dev->data->dev_conf.fdir_conf; struct rte_eth_rxmode *rxmode = &dev->data->dev_conf.rxmode; uint64_t offloads_mask = DEV_RX_OFFLOAD_TCP_LRO | DEV_RX_OFFLOAD_VLAN; +#ifdef RTE_LIBRTE_IEEE1588 + struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private); + if (hns3_dev_ptp_supported(hw)) + return -ENOTSUP; +#endif + if (dev->data->scattered_rx) return -ENOTSUP; @@ -207,8 +216,4 @@ hns3_rx_check_vec_support(struct rte_eth_dev *dev) return -ENOTSUP; return 0; -#else - RTE_SET_USED(dev); - return -ENOTSUP; -#endif } diff --git a/drivers/net/hns3/meson.build b/drivers/net/hns3/meson.build index f6aac69..6d78c33 100644 --- a/drivers/net/hns3/meson.build +++ b/drivers/net/hns3/meson.build @@ -26,7 +26,8 @@ sources = files('hns3_cmd.c', 'hns3_rxtx.c', 'hns3_stats.c', 'hns3_mp.c', - 'hns3_tm.c') + 'hns3_tm.c', + 'hns3_ptp.c') deps += ['hash']