From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mga11.intel.com (mga11.intel.com [192.55.52.93]) by dpdk.org (Postfix) with ESMTP id 0E220C340 for ; Thu, 9 Jul 2015 15:30:25 +0200 (CEST) Received: from orsmga001.jf.intel.com ([10.7.209.18]) by fmsmga102.fm.intel.com with ESMTP; 09 Jul 2015 06:30:24 -0700 X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="5.15,440,1432623600"; d="scan'208";a="725720903" Received: from irvmail001.ir.intel.com ([163.33.26.43]) by orsmga001.jf.intel.com with ESMTP; 09 Jul 2015 06:30:23 -0700 Received: from sivswdev02.ir.intel.com (sivswdev02.ir.intel.com [10.237.217.46]) by irvmail001.ir.intel.com (8.14.3/8.13.6/MailSET/Hub) with ESMTP id t69DUM0Q010610; Thu, 9 Jul 2015 14:30:23 +0100 Received: from sivswdev02.ir.intel.com (localhost [127.0.0.1]) by sivswdev02.ir.intel.com with ESMTP id t69DUMBp014049; Thu, 9 Jul 2015 14:30:22 +0100 Received: (from jmcnam2x@localhost) by sivswdev02.ir.intel.com with id t69DUMY6014045; Thu, 9 Jul 2015 14:30:22 +0100 From: John McNamara To: dev@dpdk.org Date: Thu, 9 Jul 2015 14:30:18 +0100 Message-Id: <1436448620-13972-6-git-send-email-john.mcnamara@intel.com> X-Mailer: git-send-email 1.7.4.1 In-Reply-To: <1436448620-13972-1-git-send-email-john.mcnamara@intel.com> References: <1436448620-13972-1-git-send-email-john.mcnamara@intel.com> Subject: [dpdk-dev] [PATCH v4 5/7] i40e: add support for ieee1588 timestamping X-BeenThere: dev@dpdk.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: patches and discussions about DPDK List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Thu, 09 Jul 2015 13:30:27 -0000 Add ixgbe support for new ethdev APIs to enable and read IEEE1588/ 802.1AS PTP timestamps. Signed-off-by: John McNamara --- drivers/net/i40e/i40e_ethdev.c | 143 +++++++++++++++++++++++++++++++++++++++++ drivers/net/i40e/i40e_rxtx.c | 40 +++++++++++- 2 files changed, 182 insertions(+), 1 deletion(-) diff --git a/drivers/net/i40e/i40e_ethdev.c b/drivers/net/i40e/i40e_ethdev.c index 5fb6b4c..db642a5 100644 --- a/drivers/net/i40e/i40e_ethdev.c +++ b/drivers/net/i40e/i40e_ethdev.c @@ -55,6 +55,7 @@ #include "base/i40e_prototype.h" #include "base/i40e_adminq_cmd.h" #include "base/i40e_type.h" +#include "base/i40e_register.h" #include "i40e_ethdev.h" #include "i40e_rxtx.h" #include "i40e_pf.h" @@ -106,6 +107,12 @@ (1UL << RTE_ETH_FLOW_NONFRAG_IPV6_OTHER) | \ (1UL << RTE_ETH_FLOW_L2_PAYLOAD)) +#define I40E_PTP_40GB_INCVAL 0x0199999999ULL +#define I40E_PTP_10GB_INCVAL 0x0333333333ULL +#define I40E_PTP_1GB_INCVAL 0x2000000000ULL +#define I40E_PRTTSYN_TSYNENA 0x80000000 +#define I40E_PRTTSYN_TSYNTYPE 0x0e000000 + static int eth_i40e_dev_init(struct rte_eth_dev *eth_dev); static int i40e_dev_configure(struct rte_eth_dev *dev); static int i40e_dev_start(struct rte_eth_dev *dev); @@ -217,6 +224,14 @@ static int i40e_mirror_rule_set(struct rte_eth_dev *dev, uint8_t sw_id, uint8_t on); static int i40e_mirror_rule_reset(struct rte_eth_dev *dev, uint8_t sw_id); +static int i40e_timesync_enable(struct rte_eth_dev *dev); +static int i40e_timesync_disable(struct rte_eth_dev *dev); +static int i40e_timesync_read_rx_timestamp(struct rte_eth_dev *dev, + struct timespec *timestamp, + uint32_t flags); +static int i40e_timesync_read_tx_timestamp(struct rte_eth_dev *dev, + struct timespec *timestamp); + static const struct rte_pci_id pci_id_i40e_map[] = { #define RTE_PCI_DEV_ID_DECL_I40E(vend, dev) {RTE_PCI_DEVICE(vend, dev)}, #include "rte_pci_dev_ids.h" @@ -269,6 +284,10 @@ static const struct eth_dev_ops i40e_eth_dev_ops = { .filter_ctrl = i40e_dev_filter_ctrl, .mirror_rule_set = i40e_mirror_rule_set, .mirror_rule_reset = i40e_mirror_rule_reset, + .timesync_enable = i40e_timesync_enable, + .timesync_disable = i40e_timesync_disable, + .timesync_read_rx_timestamp = i40e_timesync_read_rx_timestamp, + .timesync_read_tx_timestamp = i40e_timesync_read_tx_timestamp, }; static struct eth_driver rte_i40e_pmd = { @@ -6086,3 +6105,127 @@ i40e_mirror_rule_reset(struct rte_eth_dev *dev, uint8_t sw_id) } return 0; } + +static int +i40e_timesync_enable(struct rte_eth_dev *dev) +{ + struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); + struct rte_eth_link *link = &dev->data->dev_link; + uint32_t tsync_ctl_l; + uint32_t tsync_ctl_h; + uint32_t tsync_inc_l; + uint32_t tsync_inc_h; + + switch (link->link_speed) { + case ETH_LINK_SPEED_40G: + tsync_inc_l = I40E_PTP_40GB_INCVAL & 0xFFFFFFFF; + tsync_inc_h = I40E_PTP_40GB_INCVAL >> 32; + break; + case ETH_LINK_SPEED_10G: + tsync_inc_l = I40E_PTP_10GB_INCVAL & 0xFFFFFFFF; + tsync_inc_h = I40E_PTP_10GB_INCVAL >> 32; + break; + case ETH_LINK_SPEED_1000: + tsync_inc_l = I40E_PTP_1GB_INCVAL & 0xFFFFFFFF; + tsync_inc_h = I40E_PTP_1GB_INCVAL >> 32; + break; + default: + tsync_inc_l = 0x0; + tsync_inc_h = 0x0; + } + + /* Clear timesync registers. */ + I40E_READ_REG(hw, I40E_PRTTSYN_STAT_0); + I40E_READ_REG(hw, I40E_PRTTSYN_TXTIME_H); + I40E_READ_REG(hw, I40E_PRTTSYN_RXTIME_L(0)); + I40E_READ_REG(hw, I40E_PRTTSYN_RXTIME_L(1)); + I40E_READ_REG(hw, I40E_PRTTSYN_RXTIME_L(2)); + I40E_READ_REG(hw, I40E_PRTTSYN_RXTIME_L(3)); + I40E_READ_REG(hw, I40E_PRTTSYN_TXTIME_H); + + /* Set the timesync increment value. */ + I40E_WRITE_REG(hw, I40E_PRTTSYN_INC_L, tsync_inc_l); + I40E_WRITE_REG(hw, I40E_PRTTSYN_INC_H, tsync_inc_h); + + /* Enable timestamping of PTP packets. */ + tsync_ctl_l = I40E_READ_REG(hw, I40E_PRTTSYN_CTL0); + tsync_ctl_l |= I40E_PRTTSYN_TSYNENA; + + tsync_ctl_h = I40E_READ_REG(hw, I40E_PRTTSYN_CTL1); + tsync_ctl_h |= I40E_PRTTSYN_TSYNENA; + tsync_ctl_h |= I40E_PRTTSYN_TSYNTYPE; + + I40E_WRITE_REG(hw, I40E_PRTTSYN_CTL0, tsync_ctl_l); + I40E_WRITE_REG(hw, I40E_PRTTSYN_CTL1, tsync_ctl_h); + + return 0; +} + +static int +i40e_timesync_disable(struct rte_eth_dev *dev) +{ + struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); + uint32_t tsync_ctl_l; + uint32_t tsync_ctl_h; + + /* Disable timestamping of transmitted PTP packets. */ + tsync_ctl_l = I40E_READ_REG(hw, I40E_PRTTSYN_CTL0); + tsync_ctl_l &= ~I40E_PRTTSYN_TSYNENA; + + tsync_ctl_h = I40E_READ_REG(hw, I40E_PRTTSYN_CTL1); + tsync_ctl_h &= ~I40E_PRTTSYN_TSYNENA; + + I40E_WRITE_REG(hw, I40E_PRTTSYN_CTL0, tsync_ctl_l); + I40E_WRITE_REG(hw, I40E_PRTTSYN_CTL1, tsync_ctl_h); + + /* Set the timesync increment value. */ + I40E_WRITE_REG(hw, I40E_PRTTSYN_INC_L, 0x0); + I40E_WRITE_REG(hw, I40E_PRTTSYN_INC_H, 0x0); + + return 0; +} + +static int +i40e_timesync_read_rx_timestamp(struct rte_eth_dev *dev, + struct timespec *timestamp, uint32_t flags) +{ + struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); + uint32_t sync_status; + uint32_t rx_stmpl; + uint32_t rx_stmph; + uint32_t index = flags & 0x03; + + sync_status = I40E_READ_REG(hw, I40E_PRTTSYN_STAT_1); + if ((sync_status & (1 << index)) == 0) + return -EINVAL; + + rx_stmpl = I40E_READ_REG(hw, I40E_PRTTSYN_RXTIME_L(index)); + rx_stmph = I40E_READ_REG(hw, I40E_PRTTSYN_RXTIME_H(index)); + + timestamp->tv_sec = (uint64_t)(((uint64_t)rx_stmph << 32) | rx_stmpl); + timestamp->tv_nsec = 0; + + return 0; +} + +static int +i40e_timesync_read_tx_timestamp(struct rte_eth_dev *dev, + struct timespec *timestamp) +{ + struct i40e_hw *hw = I40E_DEV_PRIVATE_TO_HW(dev->data->dev_private); + uint32_t sync_status; + uint32_t tx_stmpl; + uint32_t tx_stmph; + + sync_status = I40E_READ_REG(hw, I40E_PRTTSYN_STAT_0); + if ((sync_status & I40E_PRTTSYN_STAT_0_TXTIME_MASK) == 0) + return -EINVAL; + + tx_stmpl = I40E_READ_REG(hw, I40E_PRTTSYN_TXTIME_L); + tx_stmph = I40E_READ_REG(hw, I40E_PRTTSYN_TXTIME_H); + + timestamp->tv_sec = (uint64_t)(((uint64_t)tx_stmph << 32) | tx_stmpl); + timestamp->tv_nsec = 0; + + return 0; +} diff --git a/drivers/net/i40e/i40e_rxtx.c b/drivers/net/i40e/i40e_rxtx.c index 88b015d..c79160f 100644 --- a/drivers/net/i40e/i40e_rxtx.c +++ b/drivers/net/i40e/i40e_rxtx.c @@ -185,7 +185,7 @@ i40e_rxd_ptype_to_pkt_flags(uint64_t qword) static const uint64_t ip_ptype_map[I40E_MAX_PKT_TYPE] = { 0, /* PTYPE 0 */ 0, /* PTYPE 1 */ - 0, /* PTYPE 2 */ + PKT_RX_IEEE1588_PTP, /* PTYPE 2 */ 0, /* PTYPE 3 */ 0, /* PTYPE 4 */ 0, /* PTYPE 5 */ @@ -741,7 +741,19 @@ i40e_rx_scan_hw_ring(struct i40e_rx_queue *rxq) if (pkt_flags & PKT_RX_FDIR) pkt_flags |= i40e_rxd_build_fdir(&rxdp[j], mb); +#ifdef RTE_LIBRTE_IEEE1588 + uint16_t tsyn = (qword1 + & (I40E_RXD_QW1_STATUS_TSYNVALID_MASK + | I40E_RXD_QW1_STATUS_TSYNINDX_MASK)) + >> I40E_RX_DESC_STATUS_TSYNINDX_SHIFT; + + if (tsyn & 0x04) + pkt_flags |= PKT_RX_IEEE1588_TMST; + + mb->timesync = tsyn & 0x03; +#endif mb->ol_flags |= pkt_flags; + } for (j = 0; j < I40E_LOOK_AHEAD; j++) @@ -923,6 +935,7 @@ i40e_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) qword1 = rte_le_to_cpu_64(rxdp->wb.qword1.status_error_len); rx_status = (qword1 & I40E_RXD_QW1_STATUS_MASK) >> I40E_RXD_QW1_STATUS_SHIFT; + /* Check the DD bit first */ if (!(rx_status & (1 << I40E_RX_DESC_STATUS_DD_SHIFT))) break; @@ -980,6 +993,16 @@ i40e_recv_pkts(void *rx_queue, struct rte_mbuf **rx_pkts, uint16_t nb_pkts) if (pkt_flags & PKT_RX_FDIR) pkt_flags |= i40e_rxd_build_fdir(&rxd, rxm); +#ifdef RTE_LIBRTE_IEEE1588 + uint16_t tsyn = (qword1 & (I40E_RXD_QW1_STATUS_TSYNVALID_MASK + | I40E_RXD_QW1_STATUS_TSYNINDX_MASK)) + >> I40E_RX_DESC_STATUS_TSYNINDX_SHIFT; + + if (tsyn & 0x04) + pkt_flags |= PKT_RX_IEEE1588_TMST; + + rxm->timesync = tsyn & 0x03; +#endif rxm->ol_flags |= pkt_flags; rx_pkts[nb_rx++] = rxm; @@ -1030,6 +1053,7 @@ i40e_recv_scattered_pkts(void *rx_queue, qword1 = rte_le_to_cpu_64(rxdp->wb.qword1.status_error_len); rx_status = (qword1 & I40E_RXD_QW1_STATUS_MASK) >> I40E_RXD_QW1_STATUS_SHIFT; + /* Check the DD bit */ if (!(rx_status & (1 << I40E_RX_DESC_STATUS_DD_SHIFT))) break; @@ -1139,6 +1163,16 @@ i40e_recv_scattered_pkts(void *rx_queue, if (pkt_flags & PKT_RX_FDIR) pkt_flags |= i40e_rxd_build_fdir(&rxd, rxm); +#ifdef RTE_LIBRTE_IEEE1588 + uint16_t tsyn = (qword1 & (I40E_RXD_QW1_STATUS_TSYNVALID_MASK + | I40E_RXD_QW1_STATUS_TSYNINDX_MASK)) + >> I40E_RX_DESC_STATUS_TSYNINDX_SHIFT; + + if (tsyn & 0x04) + pkt_flags |= PKT_RX_IEEE1588_TMST; + + first_seg->timesync = tsyn & 0x03; +#endif first_seg->ol_flags |= pkt_flags; /* Prefetch data of first segment, if configured to do so. */ @@ -2389,6 +2423,10 @@ i40e_tx_queue_init(struct i40e_tx_queue *txq) tx_ctx.new_context = 1; tx_ctx.base = txq->tx_ring_phys_addr / I40E_QUEUE_BASE_ADDR_UNIT; tx_ctx.qlen = txq->nb_tx_desc; + +#ifdef RTE_LIBRTE_IEEE1588 + tx_ctx.timesync_ena = 1; +#endif tx_ctx.rdylist = rte_le_to_cpu_16(vsi->info.qs_handle[0]); if (vsi->type == I40E_VSI_FDIR) tx_ctx.fd_ena = TRUE; -- 1.8.1.4