Skip to content

Commit

Permalink
Merge branch 'bnxt_en-ptp' into main
Browse files Browse the repository at this point in the history
Michael Chan says:

====================
bnxt_en: PTP updates for net-next

The first 5 patches implement the PTP feature on the new BCM5760X
chips.  The main new hardware feature is the new TX timestamp
completion which enables the driver to retrieve the TX timestamp
in NAPI without deferring to the PTP worker.

The last 5 patches increase the number of TX PTP packets in-flight
from 1 to 4 on the older BCM5750X chips.  On these older chips, we
need to call firmware in the PTP worker to retrieve the timestamp.
We use an arry to keep track of the in-flight TX PTP packets.

v2: Patch #2: Fix the unwind of txr->is_ts_pkt when bnxt_start_xmit() aborts.
    Patch #4: Set the SKBTX_IN_PROGRESS flag for timestamp packets.
====================

Signed-off-by: David S. Miller <[email protected]>
  • Loading branch information
davem330 committed Jul 1, 2024
2 parents 42c45ac + 0603383 commit 2e7b471
Show file tree
Hide file tree
Showing 4 changed files with 252 additions and 83 deletions.
106 changes: 69 additions & 37 deletions drivers/net/ethernet/broadcom/bnxt/bnxt.c
Original file line number Diff line number Diff line change
Expand Up @@ -456,8 +456,9 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
dma_addr_t mapping;
unsigned int length, pad = 0;
u32 len, free_size, vlan_tag_flags, cfa_action, flags;
u16 prod, last_frag;
struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
struct pci_dev *pdev = bp->pdev;
u16 prod, last_frag, txts_prod;
struct bnxt_tx_ring_info *txr;
struct bnxt_sw_tx_bd *tx_buf;
__le32 lflags = 0;
Expand Down Expand Up @@ -509,27 +510,29 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
vlan_tag_flags |= 1 << TX_BD_CFA_META_TPID_SHIFT;
}

if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP) && ptp &&
ptp->tx_tstamp_en) {
if (bp->fw_cap & BNXT_FW_CAP_TX_TS_CMP) {
lflags |= cpu_to_le32(TX_BD_FLAGS_STAMP);
tx_buf->is_ts_pkt = 1;
skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
} else if (!skb_is_gso(skb)) {
u16 seq_id, hdr_off;

if (ptp && ptp->tx_tstamp_en && !skb_is_gso(skb)) {
if (atomic_dec_if_positive(&ptp->tx_avail) < 0) {
atomic64_inc(&ptp->stats.ts_err);
goto tx_no_ts;
}
if (!bnxt_ptp_parse(skb, &ptp->tx_seqid,
&ptp->tx_hdr_off)) {
if (!bnxt_ptp_parse(skb, &seq_id, &hdr_off) &&
!bnxt_ptp_get_txts_prod(ptp, &txts_prod)) {
if (vlan_tag_flags)
ptp->tx_hdr_off += VLAN_HLEN;
hdr_off += VLAN_HLEN;
lflags |= cpu_to_le32(TX_BD_FLAGS_STAMP);
tx_buf->is_ts_pkt = 1;
skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
} else {
atomic_inc(&bp->ptp_cfg->tx_avail);

ptp->txts_req[txts_prod].tx_seqid = seq_id;
ptp->txts_req[txts_prod].tx_hdr_off = hdr_off;
tx_buf->txts_prod = txts_prod;
}
}
}

tx_no_ts:
if (unlikely(skb->no_fcs))
lflags |= cpu_to_le32(TX_BD_FLAGS_NO_CRC);

Expand Down Expand Up @@ -758,8 +761,11 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
dev_kfree_skb_any(skb);
tx_kick_pending:
if (BNXT_TX_PTP_IS_SET(lflags)) {
txr->tx_buf_ring[txr->tx_prod].is_ts_pkt = 0;
atomic64_inc(&bp->ptp_cfg->stats.ts_err);
atomic_inc(&bp->ptp_cfg->tx_avail);
if (!(bp->fw_cap & BNXT_FW_CAP_TX_TS_CMP))
/* set SKB to err so PTP worker will clean up */
ptp->txts_req[txts_prod].tx_skb = ERR_PTR(-EIO);
}
if (txr->kick_pending)
bnxt_txr_db_kick(bp, txr, txr->tx_prod);
Expand All @@ -768,7 +774,8 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
return NETDEV_TX_OK;
}

static void __bnxt_tx_int(struct bnxt *bp, struct bnxt_tx_ring_info *txr,
/* Returns true if some remaining TX packets not processed. */
static bool __bnxt_tx_int(struct bnxt *bp, struct bnxt_tx_ring_info *txr,
int budget)
{
struct netdev_queue *txq = netdev_get_tx_queue(bp->dev, txr->txq_index);
Expand All @@ -777,24 +784,33 @@ static void __bnxt_tx_int(struct bnxt *bp, struct bnxt_tx_ring_info *txr,
unsigned int tx_bytes = 0;
u16 cons = txr->tx_cons;
int tx_pkts = 0;
bool rc = false;

while (RING_TX(bp, cons) != hw_cons) {
struct bnxt_sw_tx_bd *tx_buf;
struct sk_buff *skb;
bool is_ts_pkt;
int j, last;

tx_buf = &txr->tx_buf_ring[RING_TX(bp, cons)];
cons = NEXT_TX(cons);
skb = tx_buf->skb;
tx_buf->skb = NULL;

if (unlikely(!skb)) {
bnxt_sched_reset_txr(bp, txr, cons);
return;
return rc;
}

is_ts_pkt = tx_buf->is_ts_pkt;
if (is_ts_pkt && (bp->fw_cap & BNXT_FW_CAP_TX_TS_CMP)) {
rc = true;
break;
}

cons = NEXT_TX(cons);
tx_pkts++;
tx_bytes += skb->len;
tx_buf->skb = NULL;
tx_buf->is_ts_pkt = 0;

if (tx_buf->is_push) {
tx_buf->is_push = 0;
Expand All @@ -814,15 +830,11 @@ static void __bnxt_tx_int(struct bnxt *bp, struct bnxt_tx_ring_info *txr,
skb_frag_size(&skb_shinfo(skb)->frags[j]),
DMA_TO_DEVICE);
}
if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)) {
if (unlikely(is_ts_pkt)) {
if (BNXT_CHIP_P5(bp)) {
/* PTP worker takes ownership of the skb */
if (!bnxt_get_tx_ts_p5(bp, skb)) {
skb = NULL;
} else {
atomic64_inc(&bp->ptp_cfg->stats.ts_err);
atomic_inc(&bp->ptp_cfg->tx_avail);
}
bnxt_get_tx_ts_p5(bp, skb, tx_buf->txts_prod);
skb = NULL;
}
}

Expand All @@ -837,18 +849,22 @@ static void __bnxt_tx_int(struct bnxt *bp, struct bnxt_tx_ring_info *txr,
__netif_txq_completed_wake(txq, tx_pkts, tx_bytes,
bnxt_tx_avail(bp, txr), bp->tx_wake_thresh,
READ_ONCE(txr->dev_state) == BNXT_DEV_STATE_CLOSING);

return rc;
}

static void bnxt_tx_int(struct bnxt *bp, struct bnxt_napi *bnapi, int budget)
{
struct bnxt_tx_ring_info *txr;
bool more = false;
int i;

bnxt_for_each_napi_tx(i, bnapi, txr) {
if (txr->tx_hw_cons != RING_TX(bp, txr->tx_cons))
__bnxt_tx_int(bp, txr, budget);
more |= __bnxt_tx_int(bp, txr, budget);
}
bnapi->events &= ~BNXT_TX_CMP_EVENT;
if (!more)
bnapi->events &= ~BNXT_TX_CMP_EVENT;
}

static struct page *__bnxt_alloc_rx_page(struct bnxt *bp, dma_addr_t *mapping,
Expand Down Expand Up @@ -2914,6 +2930,8 @@ static int __bnxt_poll_work(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
cpr->has_more_work = 1;
break;
}
} else if (cmp_type == CMP_TYPE_TX_L2_PKT_TS_CMP) {
bnxt_tx_ts_cmp(bp, bnapi, (struct tx_ts_cmp *)txcmp);
} else if (cmp_type >= CMP_TYPE_RX_L2_CMP &&
cmp_type <= CMP_TYPE_RX_L2_TPA_START_V3_CMP) {
if (likely(budget))
Expand Down Expand Up @@ -2945,8 +2963,10 @@ static int __bnxt_poll_work(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
}
}

if (event & BNXT_REDIRECT_EVENT)
if (event & BNXT_REDIRECT_EVENT) {
xdp_do_flush();
event &= ~BNXT_REDIRECT_EVENT;
}

if (event & BNXT_TX_EVENT) {
struct bnxt_tx_ring_info *txr = bnapi->tx_ring[0];
Expand All @@ -2956,6 +2976,7 @@ static int __bnxt_poll_work(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
wmb();

bnxt_db_write_relaxed(bp, &txr->tx_db, prod);
event &= ~BNXT_TX_EVENT;
}

cpr->cp_raw_cons = raw_cons;
Expand All @@ -2973,13 +2994,14 @@ static void __bnxt_poll_work_done(struct bnxt *bp, struct bnxt_napi *bnapi,
struct bnxt_rx_ring_info *rxr = bnapi->rx_ring;

bnxt_db_write(bp, &rxr->rx_db, rxr->rx_prod);
bnapi->events &= ~BNXT_RX_EVENT;
}
if (bnapi->events & BNXT_AGG_EVENT) {
struct bnxt_rx_ring_info *rxr = bnapi->rx_ring;

bnxt_db_write(bp, &rxr->rx_agg_db, rxr->rx_agg_prod);
bnapi->events &= ~BNXT_AGG_EVENT;
}
bnapi->events &= BNXT_TX_CMP_EVENT;
}

static int bnxt_poll_work(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
Expand Down Expand Up @@ -6788,6 +6810,7 @@ static int hwrm_ring_alloc_send_msg(struct bnxt *bp,
switch (ring_type) {
case HWRM_RING_ALLOC_TX: {
struct bnxt_tx_ring_info *txr;
u16 flags = 0;

txr = container_of(ring, struct bnxt_tx_ring_info,
tx_ring_struct);
Expand All @@ -6801,6 +6824,9 @@ static int hwrm_ring_alloc_send_msg(struct bnxt *bp,
if (bp->flags & BNXT_FLAG_TX_COAL_CMPL)
req->cmpl_coal_cnt =
RING_ALLOC_REQ_CMPL_COAL_CNT_COAL_64;
if ((bp->fw_cap & BNXT_FW_CAP_TX_TS_CMP) && bp->ptp_cfg)
flags |= RING_ALLOC_REQ_FLAGS_TX_PKT_TS_CMPL_ENABLE;
req->flags = cpu_to_le16(flags);
break;
}
case HWRM_RING_ALLOC_RX:
Expand Down Expand Up @@ -8981,7 +9007,7 @@ static int __bnxt_hwrm_ptp_qcfg(struct bnxt *bp)
u8 flags;
int rc;

if (bp->hwrm_spec_code < 0x10801 || !BNXT_CHIP_P5(bp)) {
if (bp->hwrm_spec_code < 0x10801 || !BNXT_CHIP_P5_PLUS(bp)) {
rc = -ENODEV;
goto no_ptp;
}
Expand All @@ -8997,7 +9023,8 @@ static int __bnxt_hwrm_ptp_qcfg(struct bnxt *bp)
goto exit;

flags = resp->flags;
if (!(flags & PORT_MAC_PTP_QCFG_RESP_FLAGS_HWRM_ACCESS)) {
if (BNXT_CHIP_P5_AND_MINUS(bp) &&
!(flags & PORT_MAC_PTP_QCFG_RESP_FLAGS_HWRM_ACCESS)) {
rc = -ENODEV;
goto exit;
}
Expand All @@ -9010,10 +9037,13 @@ static int __bnxt_hwrm_ptp_qcfg(struct bnxt *bp)
ptp->bp = bp;
bp->ptp_cfg = ptp;
}
if (flags & PORT_MAC_PTP_QCFG_RESP_FLAGS_PARTIAL_DIRECT_ACCESS_REF_CLOCK) {

if (flags &
(PORT_MAC_PTP_QCFG_RESP_FLAGS_PARTIAL_DIRECT_ACCESS_REF_CLOCK |
PORT_MAC_PTP_QCFG_RESP_FLAGS_64B_PHC_TIME)) {
ptp->refclk_regs[0] = le32_to_cpu(resp->ts_ref_clock_reg_lower);
ptp->refclk_regs[1] = le32_to_cpu(resp->ts_ref_clock_reg_upper);
} else if (bp->flags & BNXT_FLAG_CHIP_P5_PLUS) {
} else if (BNXT_CHIP_P5(bp)) {
ptp->refclk_regs[0] = BNXT_TS_REG_TIMESYNC_TS0_LOWER;
ptp->refclk_regs[1] = BNXT_TS_REG_TIMESYNC_TS0_UPPER;
} else {
Expand Down Expand Up @@ -9095,6 +9125,8 @@ static int __bnxt_hwrm_func_qcaps(struct bnxt *bp)
bp->fw_cap |= BNXT_FW_CAP_RX_ALL_PKT_TS;
if (flags_ext2 & FUNC_QCAPS_RESP_FLAGS_EXT2_UDP_GSO_SUPPORTED)
bp->flags |= BNXT_FLAG_UDP_GSO_CAP;
if (flags_ext2 & FUNC_QCAPS_RESP_FLAGS_EXT2_TX_PKT_TS_CMPL_SUPPORTED)
bp->fw_cap |= BNXT_FW_CAP_TX_TS_CMP;

bp->tx_push_thresh = 0;
if ((flags & FUNC_QCAPS_RESP_FLAGS_PUSH_MODE_SUPPORTED) &&
Expand Down Expand Up @@ -12136,8 +12168,8 @@ static int __bnxt_open_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init)
/* VF-reps may need to be re-opened after the PF is re-opened */
if (BNXT_PF(bp))
bnxt_vf_reps_open(bp);
if (bp->ptp_cfg)
atomic_set(&bp->ptp_cfg->tx_avail, BNXT_MAX_TX_TS);
if (bp->ptp_cfg && !(bp->fw_cap & BNXT_FW_CAP_TX_TS_CMP))
WRITE_ONCE(bp->ptp_cfg->tx_avail, BNXT_MAX_TX_TS);
bnxt_ptp_init_rtc(bp, true);
bnxt_ptp_cfg_tstamp_filters(bp);
if (BNXT_SUPPORTS_MULTI_RSS_CTX(bp))
Expand Down
42 changes: 40 additions & 2 deletions drivers/net/ethernet/broadcom/bnxt/bnxt.h
Original file line number Diff line number Diff line change
Expand Up @@ -181,6 +181,32 @@ struct tx_cmp {
#define TX_CMP_SQ_CONS_IDX(txcmp) \
(le32_to_cpu((txcmp)->sq_cons_idx) & TX_CMP_SQ_CONS_IDX_MASK)

struct tx_ts_cmp {
__le32 tx_ts_cmp_flags_type;
#define TX_TS_CMP_FLAGS_ERROR (1 << 6)
#define TX_TS_CMP_FLAGS_TS_TYPE (1 << 7)
#define TX_TS_CMP_FLAGS_TS_TYPE_PM (0 << 7)
#define TX_TS_CMP_FLAGS_TS_TYPE_PA (1 << 7)
#define TX_TS_CMP_FLAGS_TS_FALLBACK (1 << 8)
#define TX_TS_CMP_TS_SUB_NS (0xf << 12)
#define TX_TS_CMP_TS_NS_MID (0xffff << 16)
#define TX_TS_CMP_TS_NS_MID_SFT 16
u32 tx_ts_cmp_opaque;
__le32 tx_ts_cmp_errors_v;
#define TX_TS_CMP_V (1 << 0)
#define TX_TS_CMP_TS_INVALID_ERR (1 << 10)
__le32 tx_ts_cmp_ts_ns_lo;
};

#define BNXT_GET_TX_TS_48B_NS(tscmp) \
(le32_to_cpu((tscmp)->tx_ts_cmp_ts_ns_lo) | \
((u64)(le32_to_cpu((tscmp)->tx_ts_cmp_flags_type) & \
TX_TS_CMP_TS_NS_MID) << TX_TS_CMP_TS_NS_MID_SFT))

#define BNXT_TX_TS_ERR(tscmp) \
(((tscmp)->tx_ts_cmp_flags_type & cpu_to_le32(TX_TS_CMP_FLAGS_ERROR)) &&\
((tscmp)->tx_ts_cmp_errors_v & cpu_to_le32(TX_TS_CMP_TS_INVALID_ERR)))

struct rx_cmp {
__le32 rx_cmp_len_flags_type;
#define RX_CMP_CMP_TYPE (0x3f << 0)
Expand Down Expand Up @@ -848,11 +874,14 @@ struct bnxt_sw_tx_bd {
DEFINE_DMA_UNMAP_ADDR(mapping);
DEFINE_DMA_UNMAP_LEN(len);
struct page *page;
u8 is_gso;
u8 is_ts_pkt;
u8 is_push;
u8 action;
unsigned short nr_frags;
u16 rx_prod;
union {
u16 rx_prod;
u16 txts_prod;
};
};

struct bnxt_sw_rx_bd {
Expand Down Expand Up @@ -2237,9 +2266,17 @@ struct bnxt {
(BNXT_CHIP_NUM_58700((bp)->chip_num) && \
!BNXT_CHIP_TYPE_NITRO_A0(bp)))

/* Chip class phase 3.x */
#define BNXT_CHIP_P3(bp) \
(BNXT_CHIP_NUM_57X0X((bp)->chip_num) || \
BNXT_CHIP_TYPE_NITRO_A0(bp))

#define BNXT_CHIP_P4_PLUS(bp) \
(BNXT_CHIP_P4(bp) || BNXT_CHIP_P5_PLUS(bp))

#define BNXT_CHIP_P5_AND_MINUS(bp) \
(BNXT_CHIP_P3(bp) || BNXT_CHIP_P4(bp) || BNXT_CHIP_P5(bp))

struct bnxt_aux_priv *aux_priv;
struct bnxt_en_dev *edev;

Expand Down Expand Up @@ -2384,6 +2421,7 @@ struct bnxt {
#define BNXT_FW_CAP_CFA_RFS_RING_TBL_IDX_V2 BIT_ULL(16)
#define BNXT_FW_CAP_PCIE_STATS_SUPPORTED BIT_ULL(17)
#define BNXT_FW_CAP_EXT_STATS_SUPPORTED BIT_ULL(18)
#define BNXT_FW_CAP_TX_TS_CMP BIT_ULL(19)
#define BNXT_FW_CAP_ERR_RECOVER_RELOAD BIT_ULL(20)
#define BNXT_FW_CAP_HOT_RESET BIT_ULL(21)
#define BNXT_FW_CAP_PTP_RTC BIT_ULL(22)
Expand Down
Loading

0 comments on commit 2e7b471

Please sign in to comment.