@@ -189,6 +189,10 @@ struct rte_flow {
struct bnxt_vnic_info *vnic;
};
+#define BNXT_PTP_FLAGS_PATH_TX 0x0
+#define BNXT_PTP_FLAGS_PATH_RX 0x1
+#define BNXT_PTP_FLAGS_CURRENT_TIME 0x2
+
struct bnxt_ptp_cfg {
#define BNXT_GRCPF_REG_WINDOW_BASE_OUT 0x400
#define BNXT_GRCPF_REG_SYNC_TIME 0x480
@@ -234,6 +238,9 @@ struct bnxt_ptp_cfg {
uint32_t rx_mapped_regs[BNXT_PTP_RX_REGS];
uint32_t tx_regs[BNXT_PTP_TX_REGS];
uint32_t tx_mapped_regs[BNXT_PTP_TX_REGS];
+
+ /* On Thor, the Rx timestamp is present in the Rx completion record */
+ uint64_t rx_timestamp;
};
struct bnxt_coal {
@@ -428,6 +435,7 @@ struct bnxt {
#define BNXT_FLAG_EXT_STATS_SUPPORTED BIT(22)
#define BNXT_FLAG_NEW_RM BIT(23)
#define BNXT_FLAG_INIT_DONE BIT(24)
+#define BNXT_FLAG_FW_CAP_ONE_STEP_TX_TS BIT(25)
#define BNXT_PF(bp) (!((bp)->flags & BNXT_FLAG_VF))
#define BNXT_VF(bp) ((bp)->flags & BNXT_FLAG_VF)
#define BNXT_NPAR(bp) ((bp)->port_partition_type)
@@ -740,6 +740,7 @@ static eth_rx_burst_t
bnxt_receive_function(__rte_unused struct rte_eth_dev *eth_dev)
{
#ifdef RTE_ARCH_X86
+#ifndef RTE_LIBRTE_IEEE1588
/*
* Vector mode receive can be enabled only if scatter rx is not
* in use and rx offloads are limited to VLAN stripping and
@@ -766,6 +767,7 @@ bnxt_receive_function(__rte_unused struct rte_eth_dev *eth_dev)
eth_dev->data->port_id,
eth_dev->data->scattered_rx,
eth_dev->data->dev_conf.rxmode.offloads);
+#endif
#endif
return bnxt_recv_pkts;
}
@@ -774,6 +776,7 @@ static eth_tx_burst_t
bnxt_transmit_function(__rte_unused struct rte_eth_dev *eth_dev)
{
#ifdef RTE_ARCH_X86
+#ifndef RTE_LIBRTE_IEEE1588
/*
* Vector mode transmit can be enabled only if not using scatter rx
* or tx offloads.
@@ -791,6 +794,7 @@ bnxt_transmit_function(__rte_unused struct rte_eth_dev *eth_dev)
eth_dev->data->port_id,
eth_dev->data->scattered_rx,
eth_dev->data->dev_conf.txmode.offloads);
+#endif
#endif
return bnxt_xmit_pkts;
}
@@ -3223,18 +3227,24 @@ bnxt_timesync_write_time(struct rte_eth_dev *dev, const struct timespec *ts)
static int
bnxt_timesync_read_time(struct rte_eth_dev *dev, struct timespec *ts)
{
- uint64_t ns, systime_cycles;
struct bnxt *bp = dev->data->dev_private;
struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
+ uint64_t ns, systime_cycles = 0;
+ int rc = 0;
if (!ptp)
return 0;
- systime_cycles = bnxt_cc_read(bp);
+ if (BNXT_CHIP_THOR(bp))
+ rc = bnxt_hwrm_port_ts_query(bp, BNXT_PTP_FLAGS_CURRENT_TIME,
+ &systime_cycles);
+ else
+ systime_cycles = bnxt_cc_read(bp);
+
ns = rte_timecounter_update(&ptp->tc, systime_cycles);
*ts = rte_ns_to_timespec(ns);
- return 0;
+ return rc;
}
static int
bnxt_timesync_enable(struct rte_eth_dev *dev)
@@ -3242,6 +3252,7 @@ bnxt_timesync_enable(struct rte_eth_dev *dev)
struct bnxt *bp = dev->data->dev_private;
struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
uint32_t shift = 0;
+ int rc;
if (!ptp)
return 0;
@@ -3250,8 +3261,9 @@ bnxt_timesync_enable(struct rte_eth_dev *dev)
ptp->tx_tstamp_en = 1;
ptp->rxctl = BNXT_PTP_MSG_EVENTS;
- if (!bnxt_hwrm_ptp_cfg(bp))
- bnxt_map_ptp_regs(bp);
+ rc = bnxt_hwrm_ptp_cfg(bp);
+ if (rc)
+ return rc;
memset(&ptp->tc, 0, sizeof(struct rte_timecounter));
memset(&ptp->rx_tstamp_tc, 0, sizeof(struct rte_timecounter));
@@ -3269,6 +3281,9 @@ bnxt_timesync_enable(struct rte_eth_dev *dev)
ptp->tx_tstamp_tc.cc_shift = shift;
ptp->tx_tstamp_tc.nsec_mask = (1ULL << shift) - 1;
+ if (!BNXT_CHIP_THOR(bp))
+ bnxt_map_ptp_regs(bp);
+
return 0;
}
@@ -3287,7 +3302,8 @@ bnxt_timesync_disable(struct rte_eth_dev *dev)
bnxt_hwrm_ptp_cfg(bp);
- bnxt_unmap_ptp_regs(bp);
+ if (!BNXT_CHIP_THOR(bp))
+ bnxt_unmap_ptp_regs(bp);
return 0;
}
@@ -3305,7 +3321,11 @@ bnxt_timesync_read_rx_timestamp(struct rte_eth_dev *dev,
if (!ptp)
return 0;
- bnxt_get_rx_ts(bp, &rx_tstamp_cycles);
+ if (BNXT_CHIP_THOR(bp))
+ rx_tstamp_cycles = ptp->rx_timestamp;
+ else
+ bnxt_get_rx_ts(bp, &rx_tstamp_cycles);
+
ns = rte_timecounter_update(&ptp->rx_tstamp_tc, rx_tstamp_cycles);
*timestamp = rte_ns_to_timespec(ns);
return 0;
@@ -3319,15 +3339,21 @@ bnxt_timesync_read_tx_timestamp(struct rte_eth_dev *dev,
struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
uint64_t tx_tstamp_cycles = 0;
uint64_t ns;
+ int rc = 0;
if (!ptp)
return 0;
- bnxt_get_tx_ts(bp, &tx_tstamp_cycles);
+ if (BNXT_CHIP_THOR(bp))
+ rc = bnxt_hwrm_port_ts_query(bp, BNXT_PTP_FLAGS_PATH_TX,
+ &tx_tstamp_cycles);
+ else
+ rc = bnxt_get_tx_ts(bp, &tx_tstamp_cycles);
+
ns = rte_timecounter_update(&ptp->tx_tstamp_tc, tx_tstamp_cycles);
*timestamp = rte_ns_to_timespec(ns);
- return 0;
+ return rc;
}
static int
@@ -4574,6 +4600,8 @@ bnxt_uninit_resources(struct bnxt *bp, bool reconfig_dev)
}
}
+ rte_free(bp->ptp_cfg);
+ bp->ptp_cfg = NULL;
return rc;
}
@@ -506,31 +506,37 @@ static int bnxt_hwrm_ptp_qcfg(struct bnxt *bp)
HWRM_CHECK_RESULT();
- if (!(resp->flags & HWRM_PORT_MAC_PTP_QCFG_OUTPUT_FLAGS_DIRECT_ACCESS))
+ if (!BNXT_CHIP_THOR(bp) &&
+ !(resp->flags & HWRM_PORT_MAC_PTP_QCFG_OUTPUT_FLAGS_DIRECT_ACCESS))
return 0;
+ if (resp->flags & HWRM_PORT_MAC_PTP_QCFG_OUTPUT_FLAGS_ONE_STEP_TX_TS)
+ bp->flags |= BNXT_FLAG_FW_CAP_ONE_STEP_TX_TS;
+
ptp = rte_zmalloc("ptp_cfg", sizeof(*ptp), 0);
if (!ptp)
return -ENOMEM;
- ptp->rx_regs[BNXT_PTP_RX_TS_L] =
- rte_le_to_cpu_32(resp->rx_ts_reg_off_lower);
- ptp->rx_regs[BNXT_PTP_RX_TS_H] =
- rte_le_to_cpu_32(resp->rx_ts_reg_off_upper);
- ptp->rx_regs[BNXT_PTP_RX_SEQ] =
- rte_le_to_cpu_32(resp->rx_ts_reg_off_seq_id);
- ptp->rx_regs[BNXT_PTP_RX_FIFO] =
- rte_le_to_cpu_32(resp->rx_ts_reg_off_fifo);
- ptp->rx_regs[BNXT_PTP_RX_FIFO_ADV] =
- rte_le_to_cpu_32(resp->rx_ts_reg_off_fifo_adv);
- ptp->tx_regs[BNXT_PTP_TX_TS_L] =
- rte_le_to_cpu_32(resp->tx_ts_reg_off_lower);
- ptp->tx_regs[BNXT_PTP_TX_TS_H] =
- rte_le_to_cpu_32(resp->tx_ts_reg_off_upper);
- ptp->tx_regs[BNXT_PTP_TX_SEQ] =
- rte_le_to_cpu_32(resp->tx_ts_reg_off_seq_id);
- ptp->tx_regs[BNXT_PTP_TX_FIFO] =
- rte_le_to_cpu_32(resp->tx_ts_reg_off_fifo);
+ if (!BNXT_CHIP_THOR(bp)) {
+ ptp->rx_regs[BNXT_PTP_RX_TS_L] =
+ rte_le_to_cpu_32(resp->rx_ts_reg_off_lower);
+ ptp->rx_regs[BNXT_PTP_RX_TS_H] =
+ rte_le_to_cpu_32(resp->rx_ts_reg_off_upper);
+ ptp->rx_regs[BNXT_PTP_RX_SEQ] =
+ rte_le_to_cpu_32(resp->rx_ts_reg_off_seq_id);
+ ptp->rx_regs[BNXT_PTP_RX_FIFO] =
+ rte_le_to_cpu_32(resp->rx_ts_reg_off_fifo);
+ ptp->rx_regs[BNXT_PTP_RX_FIFO_ADV] =
+ rte_le_to_cpu_32(resp->rx_ts_reg_off_fifo_adv);
+ ptp->tx_regs[BNXT_PTP_TX_TS_L] =
+ rte_le_to_cpu_32(resp->tx_ts_reg_off_lower);
+ ptp->tx_regs[BNXT_PTP_TX_TS_H] =
+ rte_le_to_cpu_32(resp->tx_ts_reg_off_upper);
+ ptp->tx_regs[BNXT_PTP_TX_SEQ] =
+ rte_le_to_cpu_32(resp->tx_ts_reg_off_seq_id);
+ ptp->tx_regs[BNXT_PTP_TX_FIFO] =
+ rte_le_to_cpu_32(resp->tx_ts_reg_off_fifo);
+ }
ptp->bp = bp;
bp->ptp_cfg = ptp;
@@ -4834,3 +4840,45 @@ int bnxt_hwrm_fw_reset(struct bnxt *bp)
return rc;
}
+
+int bnxt_hwrm_port_ts_query(struct bnxt *bp, uint8_t path, uint64_t *timestamp)
+{
+ struct hwrm_port_ts_query_output *resp = bp->hwrm_cmd_resp_addr;
+ struct hwrm_port_ts_query_input req = {0};
+ struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
+ uint32_t flags = 0;
+ int rc;
+
+ if (!ptp)
+ return 0;
+
+ HWRM_PREP(req, PORT_TS_QUERY, BNXT_USE_CHIMP_MB);
+
+ switch (path) {
+ case BNXT_PTP_FLAGS_PATH_TX:
+ flags |= HWRM_PORT_TS_QUERY_INPUT_FLAGS_PATH_TX;
+ break;
+ case BNXT_PTP_FLAGS_PATH_RX:
+ flags |= HWRM_PORT_TS_QUERY_INPUT_FLAGS_PATH_RX;
+ break;
+ case BNXT_PTP_FLAGS_CURRENT_TIME:
+ flags |= HWRM_PORT_TS_QUERY_INPUT_FLAGS_CURRENT_TIME;
+ break;
+ }
+
+ req.flags = rte_cpu_to_le_32(flags);
+ req.port_id = rte_cpu_to_le_16(bp->pf.port_id);
+
+ rc = bnxt_hwrm_send_message(bp, &req, sizeof(req), BNXT_USE_CHIMP_MB);
+
+ HWRM_CHECK_RESULT();
+
+ if (timestamp) {
+ *timestamp = rte_le_to_cpu_32(resp->ptp_msg_ts[0]);
+ *timestamp |=
+ (uint64_t)(rte_le_to_cpu_32(resp->ptp_msg_ts[1])) << 32;
+ }
+ HWRM_UNLOCK();
+
+ return rc;
+}
@@ -206,4 +206,6 @@ int bnxt_hwrm_set_mac(struct bnxt *bp);
int bnxt_hwrm_if_change(struct bnxt *bp, bool state);
int bnxt_hwrm_error_recovery_qcfg(struct bnxt *bp);
int bnxt_hwrm_fw_reset(struct bnxt *bp);
+int bnxt_hwrm_port_ts_query(struct bnxt *bp, uint8_t path,
+ uint64_t *timestamp);
#endif
@@ -17,6 +17,9 @@
#include "bnxt_rxr.h"
#include "bnxt_rxq.h"
#include "hsi_struct_def_dpdk.h"
+#ifdef RTE_LIBRTE_IEEE1588
+#include "bnxt_hwrm.h"
+#endif
/*
* RX Ring handling
@@ -348,6 +351,30 @@ bnxt_parse_pkt_type(struct rx_pkt_cmpl *rxcmp, struct rx_pkt_cmpl_hi *rxcmp1)
return pkt_type;
}
+#ifdef RTE_LIBRTE_IEEE1588
+static void
+bnxt_get_rx_ts_thor(struct bnxt *bp, uint32_t rx_ts_cmpl)
+{
+ uint64_t systime_cycles = 0;
+
+ if (!BNXT_CHIP_THOR(bp))
+ return;
+
+ /* On Thor, Rx timestamps are provided directly in the
+ * Rx completion records to the driver. Only 32 bits of
+ * the timestamp is present in the completion. Driver needs
+ * to read the current 48 bit free running timer using the
+ * HWRM_PORT_TS_QUERY command and combine the upper 16 bits
+ * from the HWRM response with the lower 32 bits in the
+ * Rx completion to produce the 48 bit timestamp for the Rx packet
+ */
+ bnxt_hwrm_port_ts_query(bp, BNXT_PTP_FLAGS_CURRENT_TIME,
+ &systime_cycles);
+ bp->ptp_cfg->rx_timestamp = (systime_cycles & 0xFFFF00000000);
+ bp->ptp_cfg->rx_timestamp |= rx_ts_cmpl;
+}
+#endif
+
static int bnxt_rx_pkt(struct rte_mbuf **rx_pkt,
struct bnxt_rx_queue *rxq, uint32_t *raw_cons)
{
@@ -363,6 +390,7 @@ static int bnxt_rx_pkt(struct rte_mbuf **rx_pkt,
uint8_t agg_buf = 0;
uint16_t cmp_type;
uint32_t flags2_f = 0;
+ uint16_t flags_type;
rxcmp = (struct rx_pkt_cmpl *)
&cpr->cp_desc_ring[cp_cons];
@@ -418,18 +446,22 @@ static int bnxt_rx_pkt(struct rte_mbuf **rx_pkt,
mbuf->data_len = mbuf->pkt_len;
mbuf->port = rxq->port_id;
mbuf->ol_flags = 0;
- if (rxcmp->flags_type & RX_PKT_CMPL_FLAGS_RSS_VALID) {
+
+ flags_type = rte_le_to_cpu_16(rxcmp->flags_type);
+ if (flags_type & RX_PKT_CMPL_FLAGS_RSS_VALID) {
mbuf->hash.rss = rxcmp->rss_hash;
mbuf->ol_flags |= PKT_RX_RSS_HASH;
} else {
mbuf->hash.fdir.id = rxcmp1->cfa_code;
mbuf->ol_flags |= PKT_RX_FDIR | PKT_RX_FDIR_ID;
}
-
- if ((rxcmp->flags_type & rte_cpu_to_le_16(RX_PKT_CMPL_FLAGS_MASK)) ==
- RX_PKT_CMPL_FLAGS_ITYPE_PTP_W_TIMESTAMP)
+#ifdef RTE_LIBRTE_IEEE1588
+ if (unlikely((flags_type & RX_PKT_CMPL_FLAGS_MASK) ==
+ RX_PKT_CMPL_FLAGS_ITYPE_PTP_W_TIMESTAMP)) {
mbuf->ol_flags |= PKT_RX_IEEE1588_PTP | PKT_RX_IEEE1588_TMST;
-
+ bnxt_get_rx_ts_thor(rxq->bp, rxcmp1->reorder);
+ }
+#endif
if (agg_buf)
bnxt_rx_pages(rxq, mbuf, &tmp_raw_cons, agg_buf);
@@ -155,7 +155,7 @@ static uint16_t bnxt_start_xmit(struct rte_mbuf *tx_pkt,
PKT_TX_UDP_CKSUM | PKT_TX_IP_CKSUM |
PKT_TX_VLAN_PKT | PKT_TX_OUTER_IP_CKSUM |
PKT_TX_TUNNEL_GRE | PKT_TX_TUNNEL_VXLAN |
- PKT_TX_TUNNEL_GENEVE))
+ PKT_TX_TUNNEL_GENEVE | PKT_TX_IEEE1588_TMST))
long_bd = true;
nr_bds = long_bd + tx_pkt->nb_segs;
@@ -324,6 +324,11 @@ static uint16_t bnxt_start_xmit(struct rte_mbuf *tx_pkt,
/* IP CSO */
txbd1->lflags |= TX_BD_LONG_LFLAGS_T_IP_CHKSUM;
txbd1->mss = 0;
+ } else if ((tx_pkt->ol_flags & PKT_TX_IEEE1588_TMST) ==
+ PKT_TX_IEEE1588_TMST) {
+ /* PTP */
+ txbd1->lflags |= TX_BD_LONG_LFLAGS_STAMP;
+ txbd1->mss = 0;
}
} else {
txbd->flags_type |= TX_BD_SHORT_TYPE_TX_BD_SHORT;
@@ -33777,4 +33777,90 @@ struct hwrm_fw_reset_output {
uint8_t valid;
} __attribute__((packed));
+/**********************
+ * hwrm_port_ts_query *
+ ***********************/
+
+
+/* hwrm_port_ts_query_input (size:192b/24B) */
+struct hwrm_port_ts_query_input {
+ /* The HWRM command request type. */
+ uint16_t req_type;
+ /*
+ * The completion ring to send the completion event on. This should
+ * be the NQ ID returned from the `nq_alloc` HWRM command.
+ */
+ uint16_t cmpl_ring;
+ /*
+ * The sequence ID is used by the driver for tracking multiple
+ * commands. This ID is treated as opaque data by the firmware and
+ * the value is returned in the `hwrm_resp_hdr` upon completion.
+ */
+ uint16_t seq_id;
+ /*
+ * The target ID of the command:
+ * * 0x0-0xFFF8 - The function ID
+ * * 0xFFF8-0xFFFC, 0xFFFE - Reserved for internal processors
+ * * 0xFFFD - Reserved for user-space HWRM interface
+ * * 0xFFFF - HWRM
+ */
+ uint16_t target_id;
+ /*
+ * A physical address pointer pointing to a host buffer that the
+ * command's response data will be written. This can be either a host
+ * physical address (HPA) or a guest physical address (GPA) and must
+ * point to a physically contiguous block of memory.
+ */
+ uint64_t resp_addr;
+ uint32_t flags;
+ /*
+ * Enumeration denoting the RX, TX type of the resource.
+ * This enumeration is used for resources that are similar for both
+ * TX and RX paths of the chip.
+ */
+ #define HWRM_PORT_TS_QUERY_INPUT_FLAGS_PATH 0x1UL
+ /* tx path */
+ #define HWRM_PORT_TS_QUERY_INPUT_FLAGS_PATH_TX 0x0UL
+ /* rx path */
+ #define HWRM_PORT_TS_QUERY_INPUT_FLAGS_PATH_RX 0x1UL
+ #define HWRM_PORT_TS_QUERY_INPUT_FLAGS_PATH_LAST \
+ HWRM_PORT_TS_QUERY_INPUT_FLAGS_PATH_RX
+ /*
+ * If set, the response includes the current value of the free
+ * running timer.
+ */
+ #define HWRM_PORT_TS_QUERY_INPUT_FLAGS_CURRENT_TIME 0x2UL
+ /* Port ID of port that is being queried. */
+ uint16_t port_id;
+ uint8_t unused_0[2];
+} __attribute__((packed));
+
+/* hwrm_port_ts_query_output (size:192b/24B) */
+struct hwrm_port_ts_query_output {
+ /* The specific error status for the command. */
+ uint16_t error_code;
+ /* The HWRM command request type. */
+ uint16_t req_type;
+ /* The sequence ID from the original command. */
+ uint16_t seq_id;
+ /* The length of the response data in number of bytes. */
+ uint16_t resp_len;
+ /*
+ * Timestamp value of PTP message captured, or current value of
+ * free running timer.
+ */
+ uint32_t ptp_msg_ts[2];
+ /* Sequence ID of the PTP message captured. */
+ uint16_t ptp_msg_seqid;
+ uint8_t unused_0[5];
+ /*
+ * This field is used in Output records to indicate that the output
+ * is completely written to RAM. This field should be read as '1'
+ * to indicate that the output has been completely written.
+ * When writing a command completion or response to an internal processor,
+ * the order of writes has to be such that this field is written last.
+ */
+ uint8_t valid;
+} __attribute__((packed));
+
#endif /* _HSI_STRUCT_DEF_DPDK_H_ */