Skip to content

Commit 83bb623

Browse files
Pavan Chebbidavem330
authored andcommitted
bnxt_en: Transmit and retrieve packet timestamps
Setup the TXBD to enable TX timestamp if requested. At TX packet DMA completion, if we requested TX timestamp on that packet, we defer to .do_aux_work() to obtain the TX timestamp from the firmware before we free the TX SKB. v2: Use .do_aux_work() to get the TX timestamp from firmware. Reviewed-by: Edwin Peer <[email protected]> Signed-off-by: Pavan Chebbi <[email protected]> Signed-off-by: Michael Chan <[email protected]> Signed-off-by: David S. Miller <[email protected]>
1 parent 7f5515d commit 83bb623

File tree

4 files changed

+131
-5
lines changed

4 files changed

+131
-5
lines changed

drivers/net/ethernet/broadcom/bnxt/bnxt.c

Lines changed: 33 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -421,12 +421,25 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
421421
vlan_tag_flags |= 1 << TX_BD_CFA_META_TPID_SHIFT;
422422
}
423423

424-
if (unlikely(skb->no_fcs)) {
425-
lflags |= cpu_to_le32(TX_BD_FLAGS_NO_CRC);
426-
goto normal_tx;
424+
if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_HW_TSTAMP)) {
425+
struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
426+
427+
if (ptp && ptp->tx_tstamp_en && !skb_is_gso(skb) &&
428+
atomic_dec_if_positive(&ptp->tx_avail) >= 0) {
429+
if (!bnxt_ptp_parse(skb, &ptp->tx_seqid)) {
430+
lflags |= cpu_to_le32(TX_BD_FLAGS_STAMP);
431+
skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
432+
} else {
433+
atomic_inc(&bp->ptp_cfg->tx_avail);
434+
}
435+
}
427436
}
428437

429-
if (free_size == bp->tx_ring_size && length <= bp->tx_push_thresh) {
438+
if (unlikely(skb->no_fcs))
439+
lflags |= cpu_to_le32(TX_BD_FLAGS_NO_CRC);
440+
441+
if (free_size == bp->tx_ring_size && length <= bp->tx_push_thresh &&
442+
!lflags) {
430443
struct tx_push_buffer *tx_push_buf = txr->tx_push;
431444
struct tx_push_bd *tx_push = &tx_push_buf->push_bd;
432445
struct tx_bd_ext *tx_push1 = &tx_push->txbd2;
@@ -593,6 +606,8 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
593606

594607
netdev_tx_sent_queue(txq, skb->len);
595608

609+
skb_tx_timestamp(skb);
610+
596611
/* Sync BD data before updating doorbell */
597612
wmb();
598613

@@ -622,6 +637,9 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
622637
return NETDEV_TX_OK;
623638

624639
tx_dma_error:
640+
if (BNXT_TX_PTP_IS_SET(lflags))
641+
atomic_inc(&bp->ptp_cfg->tx_avail);
642+
625643
last_frag = i;
626644

627645
/* start back at beginning and unmap skb */
@@ -656,6 +674,7 @@ static void bnxt_tx_int(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts)
656674

657675
for (i = 0; i < nr_pkts; i++) {
658676
struct bnxt_sw_tx_bd *tx_buf;
677+
bool compl_deferred = false;
659678
struct sk_buff *skb;
660679
int j, last;
661680

@@ -682,12 +701,21 @@ static void bnxt_tx_int(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts)
682701
skb_frag_size(&skb_shinfo(skb)->frags[j]),
683702
PCI_DMA_TODEVICE);
684703
}
704+
if (unlikely(skb_shinfo(skb)->tx_flags & SKBTX_IN_PROGRESS)) {
705+
if (bp->flags & BNXT_FLAG_CHIP_P5) {
706+
if (!bnxt_get_tx_ts_p5(bp, skb))
707+
compl_deferred = true;
708+
else
709+
atomic_inc(&bp->ptp_cfg->tx_avail);
710+
}
711+
}
685712

686713
next_tx_int:
687714
cons = NEXT_TX(cons);
688715

689716
tx_bytes += skb->len;
690-
dev_kfree_skb_any(skb);
717+
if (!compl_deferred)
718+
dev_kfree_skb_any(skb);
691719
}
692720

693721
netdev_tx_completed_queue(txq, nr_pkts, tx_bytes);

drivers/net/ethernet/broadcom/bnxt/bnxt.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -89,6 +89,8 @@ struct tx_bd_ext {
8989
#define TX_BD_CFA_META_KEY_VLAN (1 << 28)
9090
};
9191

92+
#define BNXT_TX_PTP_IS_SET(lflags) ((lflags) & cpu_to_le32(TX_BD_FLAGS_STAMP))
93+
9294
struct rx_bd {
9395
__le32 rx_bd_len_flags_type;
9496
#define RX_BD_TYPE (0x3f << 0)

drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c

Lines changed: 94 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,10 +15,32 @@
1515
#include <linux/net_tstamp.h>
1616
#include <linux/timecounter.h>
1717
#include <linux/timekeeping.h>
18+
#include <linux/ptp_classify.h>
1819
#include "bnxt_hsi.h"
1920
#include "bnxt.h"
2021
#include "bnxt_ptp.h"
2122

23+
int bnxt_ptp_parse(struct sk_buff *skb, u16 *seq_id)
24+
{
25+
unsigned int ptp_class;
26+
struct ptp_header *hdr;
27+
28+
ptp_class = ptp_classify_raw(skb);
29+
30+
switch (ptp_class & PTP_CLASS_VMASK) {
31+
case PTP_CLASS_V1:
32+
case PTP_CLASS_V2:
33+
hdr = ptp_parse_header(skb, ptp_class);
34+
if (!hdr)
35+
return -EINVAL;
36+
37+
*seq_id = ntohs(hdr->sequence_id);
38+
return 0;
39+
default:
40+
return -ERANGE;
41+
}
42+
}
43+
2244
static int bnxt_ptp_settime(struct ptp_clock_info *ptp_info,
2345
const struct timespec64 *ts)
2446
{
@@ -57,6 +79,28 @@ static void bnxt_ptp_get_current_time(struct bnxt *bp)
5779
spin_unlock_bh(&ptp->ptp_lock);
5880
}
5981

82+
static int bnxt_hwrm_port_ts_query(struct bnxt *bp, u32 flags, u64 *ts)
83+
{
84+
struct hwrm_port_ts_query_output *resp = bp->hwrm_cmd_resp_addr;
85+
struct hwrm_port_ts_query_input req = {0};
86+
int rc;
87+
88+
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_PORT_TS_QUERY, -1, -1);
89+
req.flags = cpu_to_le32(flags);
90+
if ((flags & PORT_TS_QUERY_REQ_FLAGS_PATH) ==
91+
PORT_TS_QUERY_REQ_FLAGS_PATH_TX) {
92+
req.enables = cpu_to_le16(BNXT_PTP_QTS_TX_ENABLES);
93+
req.ptp_seq_id = cpu_to_le32(bp->ptp_cfg->tx_seqid);
94+
req.ts_req_timeout = cpu_to_le16(BNXT_PTP_QTS_TIMEOUT);
95+
}
96+
mutex_lock(&bp->hwrm_cmd_lock);
97+
rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
98+
if (!rc)
99+
*ts = le64_to_cpu(resp->ptp_msg_ts);
100+
mutex_unlock(&bp->hwrm_cmd_lock);
101+
return rc;
102+
}
103+
60104
static int bnxt_ptp_gettimex(struct ptp_clock_info *ptp_info,
61105
struct timespec64 *ts,
62106
struct ptp_system_timestamp *sts)
@@ -269,16 +313,62 @@ static u64 bnxt_cc_read(const struct cyclecounter *cc)
269313
return bnxt_refclk_read(ptp->bp, NULL);
270314
}
271315

316+
static void bnxt_stamp_tx_skb(struct bnxt *bp, struct sk_buff *skb)
317+
{
318+
struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
319+
struct skb_shared_hwtstamps timestamp;
320+
u64 ts = 0, ns = 0;
321+
int rc;
322+
323+
rc = bnxt_hwrm_port_ts_query(bp, PORT_TS_QUERY_REQ_FLAGS_PATH_TX, &ts);
324+
if (!rc) {
325+
memset(&timestamp, 0, sizeof(timestamp));
326+
spin_lock_bh(&ptp->ptp_lock);
327+
ns = timecounter_cyc2time(&ptp->tc, ts);
328+
spin_unlock_bh(&ptp->ptp_lock);
329+
timestamp.hwtstamp = ns_to_ktime(ns);
330+
skb_tstamp_tx(ptp->tx_skb, &timestamp);
331+
} else {
332+
netdev_err(bp->dev, "TS query for TX timer failed rc = %x\n",
333+
rc);
334+
}
335+
336+
dev_kfree_skb_any(ptp->tx_skb);
337+
ptp->tx_skb = NULL;
338+
atomic_inc(&ptp->tx_avail);
339+
}
340+
272341
static long bnxt_ptp_ts_aux_work(struct ptp_clock_info *ptp_info)
273342
{
274343
struct bnxt_ptp_cfg *ptp = container_of(ptp_info, struct bnxt_ptp_cfg,
275344
ptp_info);
345+
unsigned long now = jiffies;
276346
struct bnxt *bp = ptp->bp;
277347

348+
if (ptp->tx_skb)
349+
bnxt_stamp_tx_skb(bp, ptp->tx_skb);
350+
351+
if (!time_after_eq(now, ptp->next_period))
352+
return ptp->next_period - now;
353+
278354
bnxt_ptp_get_current_time(bp);
355+
ptp->next_period = now + HZ;
279356
return HZ;
280357
}
281358

359+
int bnxt_get_tx_ts_p5(struct bnxt *bp, struct sk_buff *skb)
360+
{
361+
struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
362+
363+
if (ptp->tx_skb) {
364+
netdev_err(bp->dev, "deferring skb:one SKB is still outstanding\n");
365+
return -EBUSY;
366+
}
367+
ptp->tx_skb = skb;
368+
ptp_schedule_worker(ptp->ptp_clock, 0);
369+
return 0;
370+
}
371+
282372
int bnxt_get_rx_ts_p5(struct bnxt *bp, u64 *ts, u32 pkt_ts)
283373
{
284374
struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
@@ -375,5 +465,9 @@ void bnxt_ptp_clear(struct bnxt *bp)
375465
ptp_clock_unregister(ptp->ptp_clock);
376466

377467
ptp->ptp_clock = NULL;
468+
if (ptp->tx_skb) {
469+
dev_kfree_skb_any(ptp->tx_skb);
470+
ptp->tx_skb = NULL;
471+
}
378472
bnxt_unmap_ptp_regs(bp);
379473
}

drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,8 +70,10 @@ do { \
7070
((dst) = READ_ONCE(src))
7171
#endif
7272

73+
int bnxt_ptp_parse(struct sk_buff *skb, u16 *seq_id);
7374
int bnxt_hwtstamp_set(struct net_device *dev, struct ifreq *ifr);
7475
int bnxt_hwtstamp_get(struct net_device *dev, struct ifreq *ifr);
76+
int bnxt_get_tx_ts_p5(struct bnxt *bp, struct sk_buff *skb);
7577
int bnxt_get_rx_ts_p5(struct bnxt *bp, u64 *ts, u32 pkt_ts);
7678
void bnxt_ptp_start(struct bnxt *bp);
7779
int bnxt_ptp_init(struct bnxt *bp);

0 commit comments

Comments
 (0)