[dpdk-dev,v3] bnxt: Support time_sync related APIs

Message ID 20171205072656.2335-1-somnath.kotur@broadcom.com (mailing list archive)
State Accepted, archived
Delegated to: Ferruh Yigit
Headers

Checks

Context Check Description
ci/checkpatch success coding style OK
ci/Intel-compilation success Compilation OK

Commit Message

Somnath Kotur Dec. 5, 2017, 7:26 a.m. UTC
  Implemented the 'time_sync' related APIs for supporting the PTP protocol.

Signed-off-by: Somnath Kotur <somnath.kotur@broadcom.com>
---
v3 Changes
- Initialize the time counters correctly during timesync_enable
- Use correct flag to check for PTP in Rx completion
v2 Changes
- Updated bnxt.ini to announce 'timesync' feature
- Added code to correctly detect PTP in the pkt and set corresponding ol_flags
  for PTP in Rx path

 doc/guides/nics/features/bnxt.ini      |   1 +
 drivers/net/bnxt/bnxt.h                |  50 +++++++
 drivers/net/bnxt/bnxt_ethdev.c         | 262 ++++++++++++++++++++++++++++++++-
 drivers/net/bnxt/bnxt_hwrm.c           |  94 +++++++++++-
 drivers/net/bnxt/bnxt_hwrm.h           |   1 +
 drivers/net/bnxt/bnxt_rxr.c            |   4 +
 drivers/net/bnxt/hsi_struct_def_dpdk.h | 222 ++++++++++++++++++++++++++++
 7 files changed, 632 insertions(+), 2 deletions(-)
  

Comments

Ajit Khaparde Dec. 7, 2017, 10:04 p.m. UTC | #1
On Mon, Dec 4, 2017 at 11:26 PM, Somnath Kotur <somnath.kotur@broadcom.com>
wrote:

> Implemented the 'time_sync' related APIs for supporting the PTP protocol.
>
> Signed-off-by: Somnath Kotur <somnath.kotur@broadcom.com>
>
Acked-by:
​ Ajit Khaparde <ajit.khaparde@broadcom.com>
​


> ---
> v3 Changes
> - Initialize the time counters correctly during timesync_enable
> - Use correct flag to check for PTP in Rx completion
> v2 Changes
> - Updated bnxt.ini to announce 'timesync' feature
> - Added code to correctly detect PTP in the pkt and set corresponding
> ol_flags
>   for PTP in Rx path
>
  
Ferruh Yigit Dec. 7, 2017, 11:18 p.m. UTC | #2
On 12/7/2017 2:04 PM, Ajit Khaparde wrote:
> On Mon, Dec 4, 2017 at 11:26 PM, Somnath Kotur <somnath.kotur@broadcom.com>
> wrote:
> 
>> Implemented the 'time_sync' related APIs for supporting the PTP protocol.
>>
>> Signed-off-by: Somnath Kotur <somnath.kotur@broadcom.com>
>>
> Acked-by:
> ​ Ajit Khaparde <ajit.khaparde@broadcom.com>

"net/bnxt: support timesync"

Applied to dpdk-next-net/master, thanks.
  

Patch

diff --git a/doc/guides/nics/features/bnxt.ini b/doc/guides/nics/features/bnxt.ini
index ef45dd7..9ddce0d 100644
--- a/doc/guides/nics/features/bnxt.ini
+++ b/doc/guides/nics/features/bnxt.ini
@@ -30,6 +30,7 @@  L4 checksum offload  = Y
 Inner L3 checksum    = Y
 Inner L4 checksum    = Y
 Packet type parsing  = Y
+Timesync             = Y
 VLAN offload         = Y
 Rx descriptor status = Y
 Tx descriptor status = Y
diff --git a/drivers/net/bnxt/bnxt.h b/drivers/net/bnxt/bnxt.h
index 8ab1c7f..e46759f 100644
--- a/drivers/net/bnxt/bnxt.h
+++ b/drivers/net/bnxt/bnxt.h
@@ -44,6 +44,7 @@ 
 #include <rte_memory.h>
 #include <rte_lcore.h>
 #include <rte_spinlock.h>
+#include <rte_time.h>
 
 #include "bnxt_cpr.h"
 
@@ -180,6 +181,53 @@  struct rte_flow {
 	struct bnxt_vnic_info	*vnic;
 };
 
+struct bnxt_ptp_cfg {
+#define BNXT_GRCPF_REG_WINDOW_BASE_OUT  0x400
+#define BNXT_GRCPF_REG_SYNC_TIME        0x480
+#define BNXT_CYCLECOUNTER_MASK   0xffffffffffffffffULL
+	struct rte_timecounter      tc;
+	struct rte_timecounter      tx_tstamp_tc;
+	struct rte_timecounter      rx_tstamp_tc;
+	struct bnxt		*bp;
+#define BNXT_MAX_TX_TS	1
+	uint16_t			rxctl;
+#define BNXT_PTP_MSG_SYNC			(1 << 0)
+#define BNXT_PTP_MSG_DELAY_REQ			(1 << 1)
+#define BNXT_PTP_MSG_PDELAY_REQ			(1 << 2)
+#define BNXT_PTP_MSG_PDELAY_RESP		(1 << 3)
+#define BNXT_PTP_MSG_FOLLOW_UP			(1 << 8)
+#define BNXT_PTP_MSG_DELAY_RESP			(1 << 9)
+#define BNXT_PTP_MSG_PDELAY_RESP_FOLLOW_UP	(1 << 10)
+#define BNXT_PTP_MSG_ANNOUNCE			(1 << 11)
+#define BNXT_PTP_MSG_SIGNALING			(1 << 12)
+#define BNXT_PTP_MSG_MANAGEMENT			(1 << 13)
+#define BNXT_PTP_MSG_EVENTS		(BNXT_PTP_MSG_SYNC |		\
+					 BNXT_PTP_MSG_DELAY_REQ |	\
+					 BNXT_PTP_MSG_PDELAY_REQ |	\
+					 BNXT_PTP_MSG_PDELAY_RESP)
+	uint8_t			tx_tstamp_en:1;
+	int			rx_filter;
+
+#define BNXT_PTP_RX_TS_L	0
+#define BNXT_PTP_RX_TS_H	1
+#define BNXT_PTP_RX_SEQ		2
+#define BNXT_PTP_RX_FIFO	3
+#define BNXT_PTP_RX_FIFO_PENDING 0x1
+#define BNXT_PTP_RX_FIFO_ADV	4
+#define BNXT_PTP_RX_REGS	5
+
+#define BNXT_PTP_TX_TS_L	0
+#define BNXT_PTP_TX_TS_H	1
+#define BNXT_PTP_TX_SEQ		2
+#define BNXT_PTP_TX_FIFO	3
+#define BNXT_PTP_TX_FIFO_EMPTY	 0x2
+#define BNXT_PTP_TX_REGS	4
+	uint32_t			rx_regs[BNXT_PTP_RX_REGS];
+	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];
+};
+
 #define BNXT_HWRM_SHORT_REQ_LEN		sizeof(struct hwrm_short_input)
 struct bnxt {
 	void				*bar0;
@@ -195,6 +243,7 @@  struct bnxt {
 #define BNXT_FLAG_JUMBO		(1 << 3)
 #define BNXT_FLAG_SHORT_CMD	(1 << 4)
 #define BNXT_FLAG_UPDATE_HASH	(1 << 5)
+#define BNXT_FLAG_PTP_SUPPORTED	(1 << 6)
 #define BNXT_PF(bp)		(!((bp)->flags & BNXT_FLAG_VF))
 #define BNXT_VF(bp)		((bp)->flags & BNXT_FLAG_VF)
 #define BNXT_NPAR_ENABLED(bp)	((bp)->port_partition_type)
@@ -272,6 +321,7 @@  struct bnxt {
 
 	struct bnxt_led_info	leds[BNXT_MAX_LED];
 	uint8_t			num_leds;
+	struct bnxt_ptp_cfg     *ptp_cfg;
 };
 
 int bnxt_link_update_op(struct rte_eth_dev *eth_dev, int wait_to_complete);
diff --git a/drivers/net/bnxt/bnxt_ethdev.c b/drivers/net/bnxt/bnxt_ethdev.c
index 3b6813c..6f8a633 100644
--- a/drivers/net/bnxt/bnxt_ethdev.c
+++ b/drivers/net/bnxt/bnxt_ethdev.c
@@ -869,7 +869,7 @@  static int bnxt_reta_query_op(struct rte_eth_dev *eth_dev,
 			"(%d)\n", reta_size, HW_HASH_INDEX_SIZE);
 		return -EINVAL;
 	}
-	/* EW - need to revisit here copying from u64 to u16 */
+	/* EW - need to revisit here copying from uint64_t to uint16_t */
 	memcpy(reta_conf, vnic->rss_table, reta_size);
 
 	if (rte_intr_allow_others(intr_handle)) {
@@ -2536,7 +2536,260 @@  static int bnxt_mtu_set_op(struct rte_eth_dev *eth_dev, uint16_t new_mtu)
 	return NULL;
 }
 
+static int bnxt_map_regs(struct bnxt *bp, uint32_t *reg_arr, int count,
+			 int reg_win)
+{
+	uint32_t reg_base = *reg_arr & 0xfffff000;
+	uint32_t win_off;
+	int i;
+
+	for (i = 0; i < count; i++) {
+		if ((reg_arr[i] & 0xfffff000) != reg_base)
+			return -ERANGE;
+	}
+	win_off = BNXT_GRCPF_REG_WINDOW_BASE_OUT + (reg_win - 1) * 4;
+	rte_cpu_to_le_32(rte_write32(reg_base, (uint8_t *)bp->bar0 + win_off));
+	return 0;
+}
+
+static int bnxt_map_ptp_regs(struct bnxt *bp)
+{
+	struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
+	uint32_t *reg_arr;
+	int rc, i;
+
+	reg_arr = ptp->rx_regs;
+	rc = bnxt_map_regs(bp, reg_arr, BNXT_PTP_RX_REGS, 5);
+	if (rc)
+		return rc;
+
+	reg_arr = ptp->tx_regs;
+	rc = bnxt_map_regs(bp, reg_arr, BNXT_PTP_TX_REGS, 6);
+	if (rc)
+		return rc;
+
+	for (i = 0; i < BNXT_PTP_RX_REGS; i++)
+		ptp->rx_mapped_regs[i] = 0x5000 + (ptp->rx_regs[i] & 0xfff);
+
+	for (i = 0; i < BNXT_PTP_TX_REGS; i++)
+		ptp->tx_mapped_regs[i] = 0x6000 + (ptp->tx_regs[i] & 0xfff);
+
+	return 0;
+}
+
+static void bnxt_unmap_ptp_regs(struct bnxt *bp)
+{
+	rte_cpu_to_le_32(rte_write32(0, (uint8_t *)bp->bar0 +
+			 BNXT_GRCPF_REG_WINDOW_BASE_OUT + 16));
+	rte_cpu_to_le_32(rte_write32(0, (uint8_t *)bp->bar0 +
+			 BNXT_GRCPF_REG_WINDOW_BASE_OUT + 20));
+}
+
+static uint64_t bnxt_cc_read(struct bnxt *bp)
+{
+	uint64_t ns;
+
+	ns = rte_le_to_cpu_32(rte_read32((uint8_t *)bp->bar0 +
+			      BNXT_GRCPF_REG_SYNC_TIME));
+	ns |= (uint64_t)(rte_le_to_cpu_32(rte_read32((uint8_t *)bp->bar0 +
+					  BNXT_GRCPF_REG_SYNC_TIME + 4))) << 32;
+	return ns;
+}
+
+static int bnxt_get_tx_ts(struct bnxt *bp, uint64_t *ts)
+{
+	struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
+	uint32_t fifo;
+
+	fifo = rte_le_to_cpu_32(rte_read32((uint8_t *)bp->bar0 +
+				ptp->tx_mapped_regs[BNXT_PTP_TX_FIFO]));
+	if (fifo & BNXT_PTP_TX_FIFO_EMPTY)
+		return -EAGAIN;
+
+	fifo = rte_le_to_cpu_32(rte_read32((uint8_t *)bp->bar0 +
+				ptp->tx_mapped_regs[BNXT_PTP_TX_FIFO]));
+	*ts = rte_le_to_cpu_32(rte_read32((uint8_t *)bp->bar0 +
+				ptp->tx_mapped_regs[BNXT_PTP_TX_TS_L]));
+	*ts |= (uint64_t)rte_le_to_cpu_32(rte_read32((uint8_t *)bp->bar0 +
+				ptp->tx_mapped_regs[BNXT_PTP_TX_TS_H])) << 32;
+
+	return 0;
+}
+
+static int bnxt_get_rx_ts(struct bnxt *bp, uint64_t *ts)
+{
+	struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
+	struct bnxt_pf_info *pf = &bp->pf;
+	uint16_t port_id;
+	uint32_t fifo;
+
+	if (!ptp)
+		return -ENODEV;
+
+	fifo = rte_le_to_cpu_32(rte_read32((uint8_t *)bp->bar0 +
+				ptp->rx_mapped_regs[BNXT_PTP_RX_FIFO]));
+	if (!(fifo & BNXT_PTP_RX_FIFO_PENDING))
+		return -EAGAIN;
+
+	port_id = pf->port_id;
+	rte_cpu_to_le_32(rte_write32(1 << port_id, (uint8_t *)bp->bar0 +
+	       ptp->rx_mapped_regs[BNXT_PTP_RX_FIFO_ADV]));
+
+	fifo = rte_le_to_cpu_32(rte_read32((uint8_t *)bp->bar0 +
+				   ptp->rx_mapped_regs[BNXT_PTP_RX_FIFO]));
+	if (fifo & BNXT_PTP_RX_FIFO_PENDING) {
+/*		bnxt_clr_rx_ts(bp);	  TBD  */
+		return -EBUSY;
+	}
+
+	*ts = rte_le_to_cpu_32(rte_read32((uint8_t *)bp->bar0 +
+				ptp->rx_mapped_regs[BNXT_PTP_RX_TS_L]));
+	*ts |= (uint64_t)rte_le_to_cpu_32(rte_read32((uint8_t *)bp->bar0 +
+				ptp->rx_mapped_regs[BNXT_PTP_RX_TS_H])) << 32;
+
+	return 0;
+}
+
+static int
+bnxt_timesync_write_time(struct rte_eth_dev *dev, const struct timespec *ts)
+{
+	uint64_t ns;
+	struct bnxt *bp = (struct bnxt *)dev->data->dev_private;
+	struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
+
+	if (!ptp)
+		return 0;
+
+	ns = rte_timespec_to_ns(ts);
+	/* Set the timecounters to a new value. */
+	ptp->tc.nsec = ns;
+
+	return 0;
+}
+
+static int
+bnxt_timesync_read_time(struct rte_eth_dev *dev, struct timespec *ts)
+{
+	uint64_t ns, systime_cycles;
+	struct bnxt *bp = (struct bnxt *)dev->data->dev_private;
+	struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
 
+	if (!ptp)
+		return 0;
+
+	systime_cycles = bnxt_cc_read(bp);
+	ns = rte_timecounter_update(&ptp->tc, systime_cycles);
+	*ts = rte_ns_to_timespec(ns);
+
+	return 0;
+}
+static int
+bnxt_timesync_enable(struct rte_eth_dev *dev)
+{
+	struct bnxt *bp = (struct bnxt *)dev->data->dev_private;
+	struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
+	uint32_t shift = 0;
+
+	if (!ptp)
+		return 0;
+
+	ptp->rx_filter = 1;
+	ptp->tx_tstamp_en = 1;
+	ptp->rxctl = BNXT_PTP_MSG_EVENTS;
+
+	if (!bnxt_hwrm_ptp_cfg(bp))
+		bnxt_map_ptp_regs(bp);
+
+	memset(&ptp->tc, 0, sizeof(struct rte_timecounter));
+	memset(&ptp->rx_tstamp_tc, 0, sizeof(struct rte_timecounter));
+	memset(&ptp->tx_tstamp_tc, 0, sizeof(struct rte_timecounter));
+
+	ptp->tc.cc_mask = BNXT_CYCLECOUNTER_MASK;
+	ptp->tc.cc_shift = shift;
+	ptp->tc.nsec_mask = (1ULL << shift) - 1;
+
+	ptp->rx_tstamp_tc.cc_mask = BNXT_CYCLECOUNTER_MASK;
+	ptp->rx_tstamp_tc.cc_shift = shift;
+	ptp->rx_tstamp_tc.nsec_mask = (1ULL << shift) - 1;
+
+	ptp->tx_tstamp_tc.cc_mask = BNXT_CYCLECOUNTER_MASK;
+	ptp->tx_tstamp_tc.cc_shift = shift;
+	ptp->tx_tstamp_tc.nsec_mask = (1ULL << shift) - 1;
+
+	return 0;
+}
+
+static int
+bnxt_timesync_disable(struct rte_eth_dev *dev)
+{
+	struct bnxt *bp = (struct bnxt *)dev->data->dev_private;
+	struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
+
+	if (!ptp)
+		return 0;
+
+	ptp->rx_filter = 0;
+	ptp->tx_tstamp_en = 0;
+	ptp->rxctl = 0;
+
+	bnxt_hwrm_ptp_cfg(bp);
+
+	bnxt_unmap_ptp_regs(bp);
+
+	return 0;
+}
+
+static int
+bnxt_timesync_read_rx_timestamp(struct rte_eth_dev *dev,
+				 struct timespec *timestamp,
+				 uint32_t flags __rte_unused)
+{
+	struct bnxt *bp = (struct bnxt *)dev->data->dev_private;
+	struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
+	uint64_t rx_tstamp_cycles = 0;
+	uint64_t ns;
+
+	if (!ptp)
+		return 0;
+
+	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;
+}
+
+static int
+bnxt_timesync_read_tx_timestamp(struct rte_eth_dev *dev,
+				 struct timespec *timestamp)
+{
+	struct bnxt *bp = (struct bnxt *)dev->data->dev_private;
+	struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
+	uint64_t tx_tstamp_cycles = 0;
+	uint64_t ns;
+
+	if (!ptp)
+		return 0;
+
+	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;
+}
+
+static int
+bnxt_timesync_adjust_time(struct rte_eth_dev *dev, int64_t delta)
+{
+	struct bnxt *bp = (struct bnxt *)dev->data->dev_private;
+	struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
+
+	if (!ptp)
+		return 0;
+
+	ptp->tc.nsec += delta;
+
+	return 0;
+}
 
 static int
 bnxt_get_eeprom_length_op(struct rte_eth_dev *dev)
@@ -2732,6 +2985,13 @@  static bool bnxt_dir_type_is_executable(uint16_t dir_type)
 	.get_eeprom_length    = bnxt_get_eeprom_length_op,
 	.get_eeprom           = bnxt_get_eeprom_op,
 	.set_eeprom           = bnxt_set_eeprom_op,
+	.timesync_enable      = bnxt_timesync_enable,
+	.timesync_disable     = bnxt_timesync_disable,
+	.timesync_read_time   = bnxt_timesync_read_time,
+	.timesync_write_time   = bnxt_timesync_write_time,
+	.timesync_adjust_time = bnxt_timesync_adjust_time,
+	.timesync_read_rx_timestamp = bnxt_timesync_read_rx_timestamp,
+	.timesync_read_tx_timestamp = bnxt_timesync_read_tx_timestamp,
 };
 
 static bool bnxt_vf_pciid(uint16_t id)
diff --git a/drivers/net/bnxt/bnxt_hwrm.c b/drivers/net/bnxt/bnxt_hwrm.c
index d2c800d..2f1d88f 100644
--- a/drivers/net/bnxt/bnxt_hwrm.c
+++ b/drivers/net/bnxt/bnxt_hwrm.c
@@ -427,12 +427,95 @@  int bnxt_hwrm_set_l2_filter(struct bnxt *bp,
 	return rc;
 }
 
+int bnxt_hwrm_ptp_cfg(struct bnxt *bp)
+{
+	struct hwrm_port_mac_cfg_input req = {.req_type = 0};
+	struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
+	uint32_t flags = 0;
+	int rc;
+
+	if (!ptp)
+		return 0;
+
+	HWRM_PREP(req, PORT_MAC_CFG);
+
+	if (ptp->rx_filter)
+		flags |= PORT_MAC_CFG_REQ_FLAGS_PTP_RX_TS_CAPTURE_ENABLE;
+	else
+		flags |= PORT_MAC_CFG_REQ_FLAGS_PTP_RX_TS_CAPTURE_DISABLE;
+	if (ptp->tx_tstamp_en)
+		flags |= PORT_MAC_CFG_REQ_FLAGS_PTP_TX_TS_CAPTURE_ENABLE;
+	else
+		flags |= PORT_MAC_CFG_REQ_FLAGS_PTP_TX_TS_CAPTURE_DISABLE;
+	req.flags = rte_cpu_to_le_32(flags);
+	req.enables =
+	rte_cpu_to_le_32(PORT_MAC_CFG_REQ_ENABLES_RX_TS_CAPTURE_PTP_MSG_TYPE);
+	req.rx_ts_capture_ptp_msg_type = rte_cpu_to_le_16(ptp->rxctl);
+
+	rc = bnxt_hwrm_send_message(bp, &req, sizeof(req));
+	HWRM_UNLOCK();
+
+	return rc;
+}
+
+static int bnxt_hwrm_ptp_qcfg(struct bnxt *bp)
+{
+	int rc = 0;
+	struct hwrm_port_mac_ptp_qcfg_input req = {.req_type = 0};
+	struct hwrm_port_mac_ptp_qcfg_output *resp = bp->hwrm_cmd_resp_addr;
+	struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
+
+/*	if (bp->hwrm_spec_code < 0x10801 || ptp)  TBD  */
+	if (ptp)
+		return 0;
+
+	HWRM_PREP(req, PORT_MAC_PTP_QCFG);
+
+	req.port_id = rte_cpu_to_le_16(bp->pf.port_id);
+
+	rc = bnxt_hwrm_send_message(bp, &req, sizeof(req));
+
+	HWRM_CHECK_RESULT();
+
+	if (!(resp->flags & PORT_MAC_PTP_QCFG_RESP_FLAGS_DIRECT_ACCESS))
+		return 0;
+
+	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);
+
+	ptp->bp = bp;
+	bp->ptp_cfg = ptp;
+
+	return 0;
+}
+
 int bnxt_hwrm_func_qcaps(struct bnxt *bp)
 {
 	int rc = 0;
 	struct hwrm_func_qcaps_input req = {.req_type = 0 };
 	struct hwrm_func_qcaps_output *resp = bp->hwrm_cmd_resp_addr;
 	uint16_t new_max_vfs;
+	uint32_t flags;
 	int i;
 
 	HWRM_PREP(req, FUNC_QCAPS);
@@ -444,6 +527,7 @@  int bnxt_hwrm_func_qcaps(struct bnxt *bp)
 	HWRM_CHECK_RESULT();
 
 	bp->max_ring_grps = rte_le_to_cpu_32(resp->max_hw_ring_grps);
+	flags = rte_le_to_cpu_32(resp->flags);
 	if (BNXT_PF(bp)) {
 		bp->pf.port_id = resp->port_id;
 		bp->pf.first_vf_id = rte_le_to_cpu_16(resp->first_vf_id);
@@ -500,8 +584,16 @@  int bnxt_hwrm_func_qcaps(struct bnxt *bp)
 		bp->max_vnics = 1;
 	}
 	bp->max_stat_ctx = rte_le_to_cpu_16(resp->max_stat_ctx);
-	if (BNXT_PF(bp))
+	if (BNXT_PF(bp)) {
 		bp->pf.total_vnics = rte_le_to_cpu_16(resp->max_vnics);
+		if (flags & HWRM_FUNC_QCAPS_OUTPUT_FLAGS_PTP_SUPPORTED) {
+			bp->flags |= BNXT_FLAG_PTP_SUPPORTED;
+			RTE_LOG(INFO, PMD, "PTP SUPPORTED");
+			HWRM_UNLOCK();
+			bnxt_hwrm_ptp_qcfg(bp);
+		}
+	}
+
 	HWRM_UNLOCK();
 
 	return rc;
diff --git a/drivers/net/bnxt/bnxt_hwrm.h b/drivers/net/bnxt/bnxt_hwrm.h
index 85083e6..46f6f32 100644
--- a/drivers/net/bnxt/bnxt_hwrm.h
+++ b/drivers/net/bnxt/bnxt_hwrm.h
@@ -175,4 +175,5 @@  int bnxt_hwrm_flash_nvram(struct bnxt *bp, uint16_t dir_type,
 			  uint16_t dir_ordinal, uint16_t dir_ext,
 			  uint16_t dir_attr, const uint8_t *data,
 			  size_t data_len);
+int bnxt_hwrm_ptp_cfg(struct bnxt *bp);
 #endif
diff --git a/drivers/net/bnxt/bnxt_rxr.c b/drivers/net/bnxt/bnxt_rxr.c
index 30891b7..188df36 100644
--- a/drivers/net/bnxt/bnxt_rxr.c
+++ b/drivers/net/bnxt/bnxt_rxr.c
@@ -456,6 +456,10 @@  static int bnxt_rx_pkt(struct rte_mbuf **rx_pkt,
 		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)
+		mbuf->ol_flags |= PKT_RX_IEEE1588_PTP;
+
 	if (agg_buf)
 		bnxt_rx_pages(rxq, mbuf, &tmp_raw_cons, agg_buf);
 
diff --git a/drivers/net/bnxt/hsi_struct_def_dpdk.h b/drivers/net/bnxt/hsi_struct_def_dpdk.h
index c16edba..93a44d3 100644
--- a/drivers/net/bnxt/hsi_struct_def_dpdk.h
+++ b/drivers/net/bnxt/hsi_struct_def_dpdk.h
@@ -85,6 +85,7 @@ 
 #define HWRM_PORT_CLR_STATS		(UINT32_C(0x25))
 #define HWRM_PORT_PHY_QCFG		(UINT32_C(0x27))
 #define HWRM_PORT_MAC_QCFG		(UINT32_C(0x28))
+#define HWRM_PORT_MAC_PTP_QCFG          (UINT32_C(0x29))
 #define HWRM_PORT_PHY_QCAPS		(UINT32_C(0x2a))
 #define HWRM_PORT_LED_CFG		(UINT32_C(0x2d))
 #define HWRM_PORT_LED_QCFG		(UINT32_C(0x2e))
@@ -7121,6 +7122,227 @@  struct hwrm_queue_qportcfg_output {
 	 */
 } __attribute__((packed));
 
+/*********************
+ * hwrm_port_mac_cfg *
+ *********************/
+
+
+/* hwrm_port_mac_cfg_input (size:320b/40B) */
+struct hwrm_port_mac_cfg_input {
+	uint16_t	req_type;
+	uint16_t	cmpl_ring;
+	uint16_t	seq_id;
+	uint16_t	target_id;
+	uint64_t	resp_addr;
+	uint32_t	flags;
+	#define PORT_MAC_CFG_REQ_FLAGS_MATCH_LINK                    0x1UL
+	#define PORT_MAC_CFG_REQ_FLAGS_VLAN_PRI2COS_ENABLE           0x2UL
+	#define PORT_MAC_CFG_REQ_FLAGS_TUNNEL_PRI2COS_ENABLE         0x4UL
+	#define PORT_MAC_CFG_REQ_FLAGS_IP_DSCP2COS_ENABLE            0x8UL
+	#define PORT_MAC_CFG_REQ_FLAGS_PTP_RX_TS_CAPTURE_ENABLE      0x10UL
+	#define PORT_MAC_CFG_REQ_FLAGS_PTP_RX_TS_CAPTURE_DISABLE     0x20UL
+	#define PORT_MAC_CFG_REQ_FLAGS_PTP_TX_TS_CAPTURE_ENABLE      0x40UL
+	#define PORT_MAC_CFG_REQ_FLAGS_PTP_TX_TS_CAPTURE_DISABLE     0x80UL
+	#define PORT_MAC_CFG_REQ_FLAGS_OOB_WOL_ENABLE                0x100UL
+	#define PORT_MAC_CFG_REQ_FLAGS_OOB_WOL_DISABLE               0x200UL
+	#define PORT_MAC_CFG_REQ_FLAGS_VLAN_PRI2COS_DISABLE          0x400UL
+	#define PORT_MAC_CFG_REQ_FLAGS_TUNNEL_PRI2COS_DISABLE        0x800UL
+	#define PORT_MAC_CFG_REQ_FLAGS_IP_DSCP2COS_DISABLE           0x1000UL
+	uint32_t	enables;
+	#define PORT_MAC_CFG_REQ_ENABLES_IPG                            0x1UL
+	#define PORT_MAC_CFG_REQ_ENABLES_LPBK                           0x2UL
+	#define PORT_MAC_CFG_REQ_ENABLES_VLAN_PRI2COS_MAP_PRI           0x4UL
+	#define PORT_MAC_CFG_REQ_ENABLES_TUNNEL_PRI2COS_MAP_PRI         0x10UL
+	#define PORT_MAC_CFG_REQ_ENABLES_DSCP2COS_MAP_PRI               0x20UL
+	#define PORT_MAC_CFG_REQ_ENABLES_RX_TS_CAPTURE_PTP_MSG_TYPE     0x40UL
+	#define PORT_MAC_CFG_REQ_ENABLES_TX_TS_CAPTURE_PTP_MSG_TYPE     0x80UL
+	#define PORT_MAC_CFG_REQ_ENABLES_COS_FIELD_CFG                  0x100UL
+	uint16_t	port_id;
+	uint8_t		ipg;
+	uint8_t		lpbk;
+	#define PORT_MAC_CFG_REQ_LPBK_NONE   0x0UL
+	#define PORT_MAC_CFG_REQ_LPBK_LOCAL  0x1UL
+	#define PORT_MAC_CFG_REQ_LPBK_REMOTE 0x2UL
+	#define PORT_MAC_CFG_REQ_LPBK_LAST  PORT_MAC_CFG_REQ_LPBK_REMOTE
+	uint8_t		vlan_pri2cos_map_pri;
+	uint8_t		reserved1;
+	uint8_t		tunnel_pri2cos_map_pri;
+	uint8_t		dscp2pri_map_pri;
+	uint16_t	rx_ts_capture_ptp_msg_type;
+	uint16_t	tx_ts_capture_ptp_msg_type;
+	uint8_t		cos_field_cfg;
+	#define PORT_MAC_CFG_REQ_COS_FIELD_CFG_RSVD1                     0x1UL
+	#define PORT_MAC_CFG_REQ_COS_FIELD_CFG_VLAN_PRI_SEL_MASK         0x6UL
+	#define PORT_MAC_CFG_REQ_COS_FIELD_CFG_VLAN_PRI_SEL_SFT          1
+	#define PORT_MAC_CFG_REQ_COS_FIELD_CFG_VLAN_PRI_SEL_INNERMOST \
+		(0x0UL << 1)
+	#define PORT_MAC_CFG_REQ_COS_FIELD_CFG_VLAN_PRI_SEL_OUTER \
+		(0x1UL << 1)
+	#define PORT_MAC_CFG_REQ_COS_FIELD_CFG_VLAN_PRI_SEL_OUTERMOST \
+		(0x2UL << 1)
+	#define PORT_MAC_CFG_REQ_COS_FIELD_CFG_VLAN_PRI_SEL_UNSPECIFIED \
+		(0x3UL << 1)
+	#define PORT_MAC_CFG_REQ_COS_FIELD_CFG_VLAN_PRI_SEL_LAST \
+		PORT_MAC_CFG_REQ_COS_FIELD_CFG_VLAN_PRI_SEL_UNSPECIFIED
+	#define PORT_MAC_CFG_REQ_COS_FIELD_CFG_T_VLAN_PRI_SEL_MASK       0x18UL
+	#define PORT_MAC_CFG_REQ_COS_FIELD_CFG_T_VLAN_PRI_SEL_SFT        3
+	#define PORT_MAC_CFG_REQ_COS_FIELD_CFG_T_VLAN_PRI_SEL_INNERMOST \
+		(0x0UL << 3)
+	#define PORT_MAC_CFG_REQ_COS_FIELD_CFG_T_VLAN_PRI_SEL_OUTER \
+		(0x1UL << 3)
+	#define PORT_MAC_CFG_REQ_COS_FIELD_CFG_T_VLAN_PRI_SEL_OUTERMOST \
+		(0x2UL << 3)
+	#define PORT_MAC_CFG_REQ_COS_FIELD_CFG_T_VLAN_PRI_SEL_UNSPECIFIED \
+		(0x3UL << 3)
+	#define PORT_MAC_CFG_REQ_COS_FIELD_CFG_T_VLAN_PRI_SEL_LAST \
+		PORT_MAC_CFG_REQ_COS_FIELD_CFG_T_VLAN_PRI_SEL_UNSPECIFIED
+	#define PORT_MAC_CFG_REQ_COS_FIELD_CFG_DEFAULT_COS_MASK          0xe0UL
+	#define PORT_MAC_CFG_REQ_COS_FIELD_CFG_DEFAULT_COS_SFT           5
+	uint8_t		unused_0[3];
+};
+
+
+/* hwrm_port_mac_cfg_output (size:128b/16B) */
+struct hwrm_port_mac_cfg_output {
+	uint16_t	error_code;
+	uint16_t	req_type;
+	uint16_t	seq_id;
+	uint16_t	resp_len;
+	uint16_t	mru;
+	uint16_t	mtu;
+	uint8_t		ipg;
+	uint8_t		lpbk;
+	#define PORT_MAC_CFG_RESP_LPBK_NONE   0x0UL
+	#define PORT_MAC_CFG_RESP_LPBK_LOCAL  0x1UL
+	#define PORT_MAC_CFG_RESP_LPBK_REMOTE 0x2UL
+	#define PORT_MAC_CFG_RESP_LPBK_LAST  PORT_MAC_CFG_RESP_LPBK_REMOTE
+	uint8_t		unused_0;
+	uint8_t		valid;
+};
+
+
+/**********************
+ * hwrm_port_mac_qcfg *
+ **********************/
+
+
+/* hwrm_port_mac_qcfg_input (size:192b/24B) */
+struct hwrm_port_mac_qcfg_input {
+	uint16_t	req_type;
+	uint16_t	cmpl_ring;
+	uint16_t	seq_id;
+	uint16_t	target_id;
+	uint64_t	resp_addr;
+	uint16_t	port_id;
+	uint8_t		unused_0[6];
+};
+
+
+/* hwrm_port_mac_qcfg_output (size:192b/24B) */
+struct hwrm_port_mac_qcfg_output {
+	uint16_t	error_code;
+	uint16_t	req_type;
+	uint16_t	seq_id;
+	uint16_t	resp_len;
+	uint16_t	mru;
+	uint16_t	mtu;
+	uint8_t		ipg;
+	uint8_t		lpbk;
+	#define PORT_MAC_QCFG_RESP_LPBK_NONE   0x0UL
+	#define PORT_MAC_QCFG_RESP_LPBK_LOCAL  0x1UL
+	#define PORT_MAC_QCFG_RESP_LPBK_REMOTE 0x2UL
+	#define PORT_MAC_QCFG_RESP_LPBK_LAST  PORT_MAC_QCFG_RESP_LPBK_REMOTE
+	uint8_t		vlan_pri2cos_map_pri;
+	uint8_t		flags;
+	#define PORT_MAC_QCFG_RESP_FLAGS_VLAN_PRI2COS_ENABLE          0x1UL
+	#define PORT_MAC_QCFG_RESP_FLAGS_TUNNEL_PRI2COS_ENABLE        0x2UL
+	#define PORT_MAC_QCFG_RESP_FLAGS_IP_DSCP2COS_ENABLE           0x4UL
+	#define PORT_MAC_QCFG_RESP_FLAGS_OOB_WOL_ENABLE               0x8UL
+	#define PORT_MAC_QCFG_RESP_FLAGS_PTP_RX_TS_CAPTURE_ENABLE     0x10UL
+	#define PORT_MAC_QCFG_RESP_FLAGS_PTP_TX_TS_CAPTURE_ENABLE     0x20UL
+	uint8_t		tunnel_pri2cos_map_pri;
+	uint8_t		dscp2pri_map_pri;
+	uint16_t	rx_ts_capture_ptp_msg_type;
+	uint16_t	tx_ts_capture_ptp_msg_type;
+	uint8_t		cos_field_cfg;
+	#define PORT_MAC_QCFG_RESP_COS_FIELD_CFG_RSVD                      0x1UL
+	#define PORT_MAC_QCFG_RESP_COS_FIELD_CFG_VLAN_PRI_SEL_MASK         0x6UL
+	#define PORT_MAC_QCFG_RESP_COS_FIELD_CFG_VLAN_PRI_SEL_SFT          1
+	#define PORT_MAC_QCFG_RESP_COS_FIELD_CFG_VLAN_PRI_SEL_INNERMOST \
+		(0x0UL << 1)
+	#define PORT_MAC_QCFG_RESP_COS_FIELD_CFG_VLAN_PRI_SEL_OUTER \
+		(0x1UL << 1)
+	#define PORT_MAC_QCFG_RESP_COS_FIELD_CFG_VLAN_PRI_SEL_OUTERMOST \
+		(0x2UL << 1)
+	#define PORT_MAC_QCFG_RESP_COS_FIELD_CFG_VLAN_PRI_SEL_UNSPECIFIED \
+		(0x3UL << 1)
+	#define PORT_MAC_QCFG_RESP_COS_FIELD_CFG_VLAN_PRI_SEL_LAST \
+		PORT_MAC_QCFG_RESP_COS_FIELD_CFG_VLAN_PRI_SEL_UNSPECIFIED
+	#define PORT_MAC_QCFG_RESP_COS_FIELD_CFG_T_VLAN_PRI_SEL_MASK	0x18UL
+	#define PORT_MAC_QCFG_RESP_COS_FIELD_CFG_T_VLAN_PRI_SEL_SFT        3
+	#define PORT_MAC_QCFG_RESP_COS_FIELD_CFG_T_VLAN_PRI_SEL_INNERMOST \
+		(0x0UL << 3)
+	#define PORT_MAC_QCFG_RESP_COS_FIELD_CFG_T_VLAN_PRI_SEL_OUTER \
+		(0x1UL << 3)
+	#define PORT_MAC_QCFG_RESP_COS_FIELD_CFG_T_VLAN_PRI_SEL_OUTERMOST \
+		(0x2UL << 3)
+	#define PORT_MAC_QCFG_RESP_COS_FIELD_CFG_T_VLAN_PRI_SEL_UNSPECIFIED \
+		(0x3UL << 3)
+	#define PORT_MAC_QCFG_RESP_COS_FIELD_CFG_T_VLAN_PRI_SEL_LAST \
+		PORT_MAC_QCFG_RESP_COS_FIELD_CFG_T_VLAN_PRI_SEL_UNSPECIFIED
+	#define PORT_MAC_QCFG_RESP_COS_FIELD_CFG_DEFAULT_COS_MASK	0xe0UL
+	#define PORT_MAC_QCFG_RESP_COS_FIELD_CFG_DEFAULT_COS_SFT           5
+	uint8_t		valid;
+};
+
+
+/**************************
+ * hwrm_port_mac_ptp_qcfg *
+ **************************/
+
+
+/* hwrm_port_mac_ptp_qcfg_input (size:192b/24B) */
+struct hwrm_port_mac_ptp_qcfg_input {
+	uint16_t	req_type;
+	uint16_t	cmpl_ring;
+	uint16_t	seq_id;
+	uint16_t	target_id;
+	uint64_t	resp_addr;
+	uint16_t	port_id;
+	uint8_t		unused_0[6];
+};
+
+
+/* hwrm_port_mac_ptp_qcfg_output (size:640b/80B) */
+struct hwrm_port_mac_ptp_qcfg_output {
+	uint16_t	error_code;
+	uint16_t	req_type;
+	uint16_t	seq_id;
+	uint16_t	resp_len;
+	uint8_t		flags;
+	#define PORT_MAC_PTP_QCFG_RESP_FLAGS_DIRECT_ACCESS     0x1UL
+	#define PORT_MAC_PTP_QCFG_RESP_FLAGS_HWRM_ACCESS       0x2UL
+	uint8_t		unused_0[3];
+	uint32_t	rx_ts_reg_off_lower;
+	uint32_t	rx_ts_reg_off_upper;
+	uint32_t	rx_ts_reg_off_seq_id;
+	uint32_t	rx_ts_reg_off_src_id_0;
+	uint32_t	rx_ts_reg_off_src_id_1;
+	uint32_t	rx_ts_reg_off_src_id_2;
+	uint32_t	rx_ts_reg_off_domain_id;
+	uint32_t	rx_ts_reg_off_fifo;
+	uint32_t	rx_ts_reg_off_fifo_adv;
+	uint32_t	rx_ts_reg_off_granularity;
+	uint32_t	tx_ts_reg_off_lower;
+	uint32_t	tx_ts_reg_off_upper;
+	uint32_t	tx_ts_reg_off_seq_id;
+	uint32_t	tx_ts_reg_off_fifo;
+	uint32_t	tx_ts_reg_off_granularity;
+	uint8_t		unused_1[7];
+	uint8_t		valid;
+};
+
+
 /* hwrm_vnic_alloc */
 /*
  * Description: This VNIC is a resource in the RX side of the chip that is used