From: Min Hu (Connor) Date: Thu, 1 Apr 2021 13:38:04 +0000 (+0800) Subject: net/hns3: support IEEE 1588 PTP X-Git-Url: http://git.droids-corp.org/?a=commitdiff_plain;h=38b539d96eb60cd8bb50e4b4f7bb8f5d4c01212c;p=dpdk.git net/hns3: support IEEE 1588 PTP Add hns3 support for new ethdev APIs to enable and read IEEE1588/ 802.1AS PTP timestamps. Signed-off-by: Min Hu (Connor) --- diff --git a/doc/guides/nics/features/hns3.ini b/doc/guides/nics/features/hns3.ini index 3988be4fba..502bfe72d6 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 ccd2f6fe5c..3366562968 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/doc/guides/rel_notes/release_21_05.rst b/doc/guides/rel_notes/release_21_05.rst index 78ce29004a..0b741b79ee 100644 --- a/doc/guides/rel_notes/release_21_05.rst +++ b/doc/guides/rel_notes/release_21_05.rst @@ -101,6 +101,7 @@ New Features * Added support for outer UDP checksum in Kunpeng930. * Added support for query Tx descriptor status. * Added support for query Rx descriptor status. + * Added support for IEEE 1588 PTP. * **Updated Intel iavf driver.** diff --git a/drivers/net/hns3/hns3_cmd.h b/drivers/net/hns3/hns3_cmd.h index 30aca82d32..5d1fb67644 100644 --- a/drivers/net/hns3/hns3_cmd.h +++ b/drivers/net/hns3/hns3_cmd.h @@ -123,6 +123,10 @@ enum hns3_opcode_type { HNS3_OPC_CLEAR_MAC_TNL_INT = 0x0312, HNS3_OPC_CONFIG_FEC_MODE = 0x031A, + /* PTP command */ + HNS3_OPC_PTP_INT_EN = 0x0501, + HNS3_OPC_CFG_PTP_MODE = 0x0507, + /* PFC/Pause commands */ HNS3_OPC_CFG_MAC_PAUSE_EN = 0x0701, HNS3_OPC_CFG_PFC_PAUSE_EN = 0x0702, @@ -976,6 +980,32 @@ struct hns3_query_ssu_cmd { uint32_t rev1[2]; }; +#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]; +}; + #define HNS3_MAX_TQP_NUM_HIP08_PF 64 #define HNS3_DEFAULT_TX_BUF 0x4000 /* 16k bytes */ #define HNS3_TOTAL_PKT_BUF 0x108000 /* 1.03125M bytes */ diff --git a/drivers/net/hns3/hns3_ethdev.c b/drivers/net/hns3/hns3_ethdev.c index b07996928b..f695db3784 100644 --- a/drivers/net/hns3/hns3_ethdev.c +++ b/drivers/net/hns3/hns3_ethdev.c @@ -58,6 +58,7 @@ enum hns3_evt_cause { HNS3_VECTOR0_EVENT_RST, HNS3_VECTOR0_EVENT_MBX, HNS3_VECTOR0_EVENT_ERR, + HNS3_VECTOR0_EVENT_PTP, HNS3_VECTOR0_EVENT_OTHER, }; @@ -202,6 +203,13 @@ hns3_check_event_cause(struct hns3_adapter *hns, uint32_t *clearval) goto out; } + /* 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; + } + /* 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 +235,17 @@ out: return ret; } +static bool +hns3_is_1588_event_type(uint32_t event_type) +{ + return (event_type == HNS3_VECTOR0_EVENT_PTP); +} + 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 +268,8 @@ 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); + hns3_clear_event_cause(hw, HNS3_VECTOR0_EVENT_PTP, + BIT(HNS3_VECTOR0_1588_INT_B)); } static void @@ -2468,6 +2485,10 @@ hns3_dev_configure(struct rte_eth_dev *dev) if (ret) goto cfg_err; + ret = hns3_mbuf_dyn_rx_timestamp_register(dev, conf); + if (ret) + goto cfg_err; + ret = hns3_dev_configure_vlan(dev); if (ret) goto cfg_err; @@ -2641,6 +2662,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, @@ -4960,6 +4984,10 @@ hns3_init_pf(struct rte_eth_dev *eth_dev) goto err_intr_callback_register; } + ret = hns3_ptp_init(hw); + if (ret) + goto err_get_config; + /* Enable interrupt */ rte_intr_enable(&pci_dev->intr_handle); hns3_pf_enable_irq0(hw); @@ -5977,6 +6005,10 @@ hns3_restore_conf(struct hns3_adapter *hns) if (ret) goto err_promisc; + ret = hns3_restore_ptp(hns); + if (ret) + goto err_promisc; + ret = hns3_restore_rx_interrupt(hw); if (ret) goto err_promisc; @@ -6681,6 +6713,13 @@ 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, + .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, }; 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 ac255a3ff9..d23239d2e1 100644 --- a/drivers/net/hns3/hns3_ethdev.h +++ b/drivers/net/hns3/hns3_ethdev.h @@ -750,6 +750,11 @@ struct hns3_pf { bool support_sfp_query; uint32_t fec_mode; /* current FEC mode for ethdev */ + bool ptp_enable; + + /* Stores timestamp of last received packet on dev */ + uint64_t rx_timestamp; + struct hns3_vtag_cfg vtag_config; LIST_HEAD(vlan_tbl, hns3_user_vlan_table) vlan_list; @@ -999,6 +1004,21 @@ int hns3_dev_infos_get(struct rte_eth_dev *eth_dev, 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); +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); 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 0000000000..df84859046 --- /dev/null +++ b/drivers/net/hns3/hns3_ptp.c @@ -0,0 +1,292 @@ +/* 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" + +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; +} diff --git a/drivers/net/hns3/hns3_regs.h b/drivers/net/hns3/hns3_regs.h index e141fe10a0..c9e10be6b3 100644 --- a/drivers/net/hns3/hns3_regs.h +++ b/drivers/net/hns3/hns3_regs.h @@ -121,6 +121,29 @@ #define HNS3_TQP_INTR_RL_DEFAULT 0 #define HNS3_TQP_INTR_QL_DEFAULT 0 +/* 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) + /* 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 ce5d852773..70cd2c2306 100644 --- a/drivers/net/hns3/hns3_rxtx.c +++ b/drivers/net/hns3/hns3_rxtx.c @@ -2365,6 +2365,23 @@ hns3_rx_alloc_buffer(struct hns3_rx_queue *rxq) return rte_mbuf_raw_alloc(rxq->mb_pool); } +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; +} + uint16_t hns3_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) { @@ -2424,8 +2441,12 @@ 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; + if (unlikely(bd_base_info & BIT(HNS3_RXD_TS_VLD_B))) + hns3_rx_ptp_timestamp_handle(rxq, rxm, rxdp); + dma_addr = rte_mbuf_data_iova_default(nmb); rxdp->addr = rte_cpu_to_le_64(dma_addr); rxdp->rx.bd_base_info = 0; @@ -2436,7 +2457,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); @@ -2455,6 +2476,9 @@ 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); + if (rxm->packet_type == RTE_PTYPE_L2_ETHER_TIMESYNC) + rxm->ol_flags |= PKT_RX_IEEE1588_PTP; + if (likely(bd_base_info & BIT(HNS3_RXD_L3L4P_B))) hns3_rx_set_cksum_flag(rxm, rxm->packet_type, cksum_err); @@ -3043,7 +3067,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 @@ -3091,6 +3115,10 @@ 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); } + + 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)); } static inline int @@ -4149,10 +4177,21 @@ 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; + + struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private); + if (hns3_dev_ptp_supported(hw)) + return false; + + 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; @@ -4160,7 +4199,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 6689397605..eebbebf8c2 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,8 @@ enum hns3_pkt_tun_type { struct hns3_desc { union { uint64_t addr; + uint64_t timestamp; + struct { uint32_t addr0; uint32_t addr1; @@ -534,6 +538,9 @@ enum hns3_cksum_status { HNS3_OUTER_L4_CKSUM_ERR = 8 }; +extern uint64_t hns3_timestamp_rx_dynflag; +extern int hns3_timestamp_dynfield_offset; + 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 2bc4372449..030bfdb627 100644 --- a/drivers/net/hns3/hns3_rxtx_vec.c +++ b/drivers/net/hns3/hns3_rxtx_vec.c @@ -18,6 +18,10 @@ hns3_tx_check_vec_support(struct rte_eth_dev *dev) { struct rte_eth_txmode *txmode = &dev->data->dev_conf.txmode; + struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private); + if (hns3_dev_ptp_supported(hw)) + return -ENOTSUP; + /* Only support DEV_TX_OFFLOAD_MBUF_FAST_FREE */ if (txmode->offloads != DEV_TX_OFFLOAD_MBUF_FAST_FREE) return -ENOTSUP; @@ -167,7 +171,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 +186,19 @@ 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; + struct hns3_hw *hw = HNS3_DEV_PRIVATE_TO_HW(dev->data->dev_private); + if (hns3_dev_ptp_supported(hw)) + return -ENOTSUP; + if (dev->data->scattered_rx) return -ENOTSUP; @@ -207,8 +212,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 f6aac69a1a..6d78c334a5 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']