Skip to content

Commit a1b0563

Browse files
committed
Merge branch 'bnxt_en-ptp'
Michael Chan says: ==================== bnxt_en: Add hardware PTP timestamping support on 575XX devices Add PTP RX and TX hardware timestamp support on 575XX devices. These devices use the two-step method to implement the IEEE-1588 timestamping support. v2: Add spinlock to serialize access to the timecounter. Use .do_aux_work() for the periodic timer reading and to get the TX timestamp from the firmware. Propagate error code from ptp_clock_register(). Make the 64-bit timer access safe on 32-bit CPUs. Read PHC using direct register access. ==================== Signed-off-by: David S. Miller <[email protected]>
2 parents 2eeae3a + 93cb62d commit a1b0563

File tree

9 files changed

+1355
-51
lines changed

9 files changed

+1355
-51
lines changed

drivers/net/ethernet/broadcom/Kconfig

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -206,6 +206,7 @@ config SYSTEMPORT
206206
config BNXT
207207
tristate "Broadcom NetXtreme-C/E support"
208208
depends on PCI
209+
imply PTP_1588_CLOCK
209210
select FW_LOADER
210211
select LIBCRC32C
211212
select NET_DEVLINK
Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# SPDX-License-Identifier: GPL-2.0-only
22
obj-$(CONFIG_BNXT) += bnxt_en.o
33

4-
bnxt_en-y := bnxt.o bnxt_sriov.o bnxt_ethtool.o bnxt_dcb.o bnxt_ulp.o bnxt_xdp.o bnxt_vfr.o bnxt_devlink.o bnxt_dim.o
4+
bnxt_en-y := bnxt.o bnxt_sriov.o bnxt_ethtool.o bnxt_dcb.o bnxt_ulp.o bnxt_xdp.o bnxt_ptp.o bnxt_vfr.o bnxt_devlink.o bnxt_dim.o
55
bnxt_en-$(CONFIG_BNXT_FLOWER_OFFLOAD) += bnxt_tc.o
66
bnxt_en-$(CONFIG_DEBUG_FS) += bnxt_debugfs.o

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

Lines changed: 127 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,8 @@
4949
#include <linux/log2.h>
5050
#include <linux/aer.h>
5151
#include <linux/bitmap.h>
52+
#include <linux/ptp_clock_kernel.h>
53+
#include <linux/timecounter.h>
5254
#include <linux/cpu_rmap.h>
5355
#include <linux/cpumask.h>
5456
#include <net/pkt_cls.h>
@@ -63,6 +65,7 @@
6365
#include "bnxt_ethtool.h"
6466
#include "bnxt_dcb.h"
6567
#include "bnxt_xdp.h"
68+
#include "bnxt_ptp.h"
6669
#include "bnxt_vfr.h"
6770
#include "bnxt_tc.h"
6871
#include "bnxt_devlink.h"
@@ -418,12 +421,25 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
418421
vlan_tag_flags |= 1 << TX_BD_CFA_META_TPID_SHIFT;
419422
}
420423

421-
if (unlikely(skb->no_fcs)) {
422-
lflags |= cpu_to_le32(TX_BD_FLAGS_NO_CRC);
423-
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+
}
424436
}
425437

426-
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) {
427443
struct tx_push_buffer *tx_push_buf = txr->tx_push;
428444
struct tx_push_bd *tx_push = &tx_push_buf->push_bd;
429445
struct tx_bd_ext *tx_push1 = &tx_push->txbd2;
@@ -590,6 +606,8 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
590606

591607
netdev_tx_sent_queue(txq, skb->len);
592608

609+
skb_tx_timestamp(skb);
610+
593611
/* Sync BD data before updating doorbell */
594612
wmb();
595613

@@ -619,6 +637,9 @@ static netdev_tx_t bnxt_start_xmit(struct sk_buff *skb, struct net_device *dev)
619637
return NETDEV_TX_OK;
620638

621639
tx_dma_error:
640+
if (BNXT_TX_PTP_IS_SET(lflags))
641+
atomic_inc(&bp->ptp_cfg->tx_avail);
642+
622643
last_frag = i;
623644

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

654675
for (i = 0; i < nr_pkts; i++) {
655676
struct bnxt_sw_tx_bd *tx_buf;
677+
bool compl_deferred = false;
656678
struct sk_buff *skb;
657679
int j, last;
658680

@@ -679,12 +701,21 @@ static void bnxt_tx_int(struct bnxt *bp, struct bnxt_napi *bnapi, int nr_pkts)
679701
skb_frag_size(&skb_shinfo(skb)->frags[j]),
680702
PCI_DMA_TODEVICE);
681703
}
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+
}
682712

683713
next_tx_int:
684714
cons = NEXT_TX(cons);
685715

686716
tx_bytes += skb->len;
687-
dev_kfree_skb_any(skb);
717+
if (!compl_deferred)
718+
dev_kfree_skb_any(skb);
688719
}
689720

690721
netdev_tx_completed_queue(txq, nr_pkts, tx_bytes);
@@ -1706,9 +1737,9 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
17061737
u8 *data_ptr, agg_bufs, cmp_type;
17071738
dma_addr_t dma_addr;
17081739
struct sk_buff *skb;
1740+
u32 flags, misc;
17091741
void *data;
17101742
int rc = 0;
1711-
u32 misc;
17121743

17131744
rxcmp = (struct rx_cmp *)
17141745
&cpr->cp_desc_ring[CP_RING(cp_cons)][CP_IDX(cp_cons)];
@@ -1806,7 +1837,8 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
18061837
goto next_rx_no_len;
18071838
}
18081839

1809-
len = le32_to_cpu(rxcmp->rx_cmp_len_flags_type) >> RX_CMP_LEN_SHIFT;
1840+
flags = le32_to_cpu(rxcmp->rx_cmp_len_flags_type);
1841+
len = flags >> RX_CMP_LEN_SHIFT;
18101842
dma_addr = rx_buf->mapping;
18111843

18121844
if (bnxt_rx_xdp(bp, rxr, cons, data, &data_ptr, &len, event)) {
@@ -1883,6 +1915,24 @@ static int bnxt_rx_pkt(struct bnxt *bp, struct bnxt_cp_ring_info *cpr,
18831915
}
18841916
}
18851917

1918+
if (unlikely((flags & RX_CMP_FLAGS_ITYPES_MASK) ==
1919+
RX_CMP_FLAGS_ITYPE_PTP_W_TS)) {
1920+
if (bp->flags & BNXT_FLAG_CHIP_P5) {
1921+
u32 cmpl_ts = le32_to_cpu(rxcmp1->rx_cmp_timestamp);
1922+
u64 ns, ts;
1923+
1924+
if (!bnxt_get_rx_ts_p5(bp, &ts, cmpl_ts)) {
1925+
struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
1926+
1927+
spin_lock_bh(&ptp->ptp_lock);
1928+
ns = timecounter_cyc2time(&ptp->tc, ts);
1929+
spin_unlock_bh(&ptp->ptp_lock);
1930+
memset(skb_hwtstamps(skb), 0,
1931+
sizeof(*skb_hwtstamps(skb)));
1932+
skb_hwtstamps(skb)->hwtstamp = ns_to_ktime(ns);
1933+
}
1934+
}
1935+
}
18861936
bnxt_deliver_skb(bp, bnapi, skb);
18871937
rc = 1;
18881938

@@ -7391,6 +7441,56 @@ int bnxt_hwrm_func_resc_qcaps(struct bnxt *bp, bool all)
73917441
return rc;
73927442
}
73937443

7444+
/* bp->hwrm_cmd_lock already held. */
7445+
static int __bnxt_hwrm_ptp_qcfg(struct bnxt *bp)
7446+
{
7447+
struct hwrm_port_mac_ptp_qcfg_output *resp = bp->hwrm_cmd_resp_addr;
7448+
struct hwrm_port_mac_ptp_qcfg_input req = {0};
7449+
struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
7450+
u8 flags;
7451+
int rc;
7452+
7453+
if (bp->hwrm_spec_code < 0x10801) {
7454+
rc = -ENODEV;
7455+
goto no_ptp;
7456+
}
7457+
7458+
req.port_id = cpu_to_le16(bp->pf.port_id);
7459+
bnxt_hwrm_cmd_hdr_init(bp, &req, HWRM_PORT_MAC_PTP_QCFG, -1, -1);
7460+
rc = _hwrm_send_message(bp, &req, sizeof(req), HWRM_CMD_TIMEOUT);
7461+
if (rc)
7462+
goto no_ptp;
7463+
7464+
flags = resp->flags;
7465+
if (!(flags & PORT_MAC_PTP_QCFG_RESP_FLAGS_HWRM_ACCESS)) {
7466+
rc = -ENODEV;
7467+
goto no_ptp;
7468+
}
7469+
if (!ptp) {
7470+
ptp = kzalloc(sizeof(*ptp), GFP_KERNEL);
7471+
if (!ptp)
7472+
return -ENOMEM;
7473+
ptp->bp = bp;
7474+
bp->ptp_cfg = ptp;
7475+
}
7476+
if (flags & PORT_MAC_PTP_QCFG_RESP_FLAGS_PARTIAL_DIRECT_ACCESS_REF_CLOCK) {
7477+
ptp->refclk_regs[0] = le32_to_cpu(resp->ts_ref_clock_reg_lower);
7478+
ptp->refclk_regs[1] = le32_to_cpu(resp->ts_ref_clock_reg_upper);
7479+
} else if (bp->flags & BNXT_FLAG_CHIP_P5) {
7480+
ptp->refclk_regs[0] = BNXT_TS_REG_TIMESYNC_TS0_LOWER;
7481+
ptp->refclk_regs[1] = BNXT_TS_REG_TIMESYNC_TS0_UPPER;
7482+
} else {
7483+
rc = -ENODEV;
7484+
goto no_ptp;
7485+
}
7486+
return 0;
7487+
7488+
no_ptp:
7489+
kfree(ptp);
7490+
bp->ptp_cfg = NULL;
7491+
return rc;
7492+
}
7493+
73947494
static int __bnxt_hwrm_func_qcaps(struct bnxt *bp)
73957495
{
73967496
int rc = 0;
@@ -7462,6 +7562,8 @@ static int __bnxt_hwrm_func_qcaps(struct bnxt *bp)
74627562
bp->flags &= ~BNXT_FLAG_WOL_CAP;
74637563
if (flags & FUNC_QCAPS_RESP_FLAGS_WOL_MAGICPKT_SUPPORTED)
74647564
bp->flags |= BNXT_FLAG_WOL_CAP;
7565+
if (flags & FUNC_QCAPS_RESP_FLAGS_PTP_SUPPORTED)
7566+
__bnxt_hwrm_ptp_qcfg(bp);
74657567
} else {
74667568
#ifdef CONFIG_BNXT_SRIOV
74677569
struct bnxt_vf_info *vf = &bp->vf;
@@ -10020,6 +10122,7 @@ static int __bnxt_open_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init)
1002010122
}
1002110123
}
1002210124

10125+
bnxt_ptp_start(bp);
1002310126
rc = bnxt_init_nic(bp, irq_re_init);
1002410127
if (rc) {
1002510128
netdev_err(bp->dev, "bnxt_init_nic err: %x\n", rc);
@@ -10335,6 +10438,12 @@ static int bnxt_ioctl(struct net_device *dev, struct ifreq *ifr, int cmd)
1033510438
return bnxt_hwrm_port_phy_write(bp, mdio->phy_id, mdio->reg_num,
1033610439
mdio->val_in);
1033710440

10441+
case SIOCSHWTSTAMP:
10442+
return bnxt_hwtstamp_set(dev, ifr);
10443+
10444+
case SIOCGHWTSTAMP:
10445+
return bnxt_hwtstamp_get(dev, ifr);
10446+
1033810447
default:
1033910448
/* do nothing */
1034010449
break;
@@ -12551,6 +12660,8 @@ static void bnxt_remove_one(struct pci_dev *pdev)
1255112660

1255212661
if (BNXT_PF(bp))
1255312662
devlink_port_type_clear(&bp->dl_port);
12663+
12664+
bnxt_ptp_clear(bp);
1255412665
pci_disable_pcie_error_reporting(pdev);
1255512666
unregister_netdev(dev);
1255612667
clear_bit(BNXT_STATE_IN_FW_RESET, &bp->state);
@@ -12571,6 +12682,8 @@ static void bnxt_remove_one(struct pci_dev *pdev)
1257112682
bnxt_dcb_free(bp);
1257212683
kfree(bp->edev);
1257312684
bp->edev = NULL;
12685+
kfree(bp->ptp_cfg);
12686+
bp->ptp_cfg = NULL;
1257412687
kfree(bp->fw_health);
1257512688
bp->fw_health = NULL;
1257612689
bnxt_cleanup_pci(bp);
@@ -13132,6 +13245,11 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
1313213245
rc);
1313313246
}
1313413247

13248+
if (bnxt_ptp_init(bp)) {
13249+
netdev_warn(dev, "PTP initialization failed.\n");
13250+
kfree(bp->ptp_cfg);
13251+
bp->ptp_cfg = NULL;
13252+
}
1313513253
bnxt_inv_fw_health_reg(bp);
1313613254
bnxt_dl_register(bp);
1313713255

@@ -13161,6 +13279,8 @@ static int bnxt_init_one(struct pci_dev *pdev, const struct pci_device_id *ent)
1316113279
bnxt_free_hwrm_short_cmd_req(bp);
1316213280
bnxt_free_hwrm_resources(bp);
1316313281
bnxt_ethtool_free(bp);
13282+
kfree(bp->ptp_cfg);
13283+
bp->ptp_cfg = NULL;
1316413284
kfree(bp->fw_health);
1316513285
bp->fw_health = NULL;
1316613286
bnxt_cleanup_pci(bp);

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

Lines changed: 9 additions & 1 deletion
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)
@@ -159,6 +161,7 @@ struct rx_cmp {
159161
#define RX_CMP_FLAGS_RSS_VALID (1 << 10)
160162
#define RX_CMP_FLAGS_UNUSED (1 << 11)
161163
#define RX_CMP_FLAGS_ITYPES_SHIFT 12
164+
#define RX_CMP_FLAGS_ITYPES_MASK 0xf000
162165
#define RX_CMP_FLAGS_ITYPE_UNKNOWN (0 << 12)
163166
#define RX_CMP_FLAGS_ITYPE_IP (1 << 12)
164167
#define RX_CMP_FLAGS_ITYPE_TCP (2 << 12)
@@ -240,7 +243,7 @@ struct rx_cmp_ext {
240243
#define RX_CMPL_CFA_CODE_MASK (0xffff << 16)
241244
#define RX_CMPL_CFA_CODE_SFT 16
242245

243-
__le32 rx_cmp_unused3;
246+
__le32 rx_cmp_timestamp;
244247
};
245248

246249
#define RX_CMP_L2_ERRORS \
@@ -1362,6 +1365,9 @@ struct bnxt_test_info {
13621365
#define BNXT_GRC_REG_CHIP_NUM 0x48
13631366
#define BNXT_GRC_REG_BASE 0x260000
13641367

1368+
#define BNXT_TS_REG_TIMESYNC_TS0_LOWER 0x640180c
1369+
#define BNXT_TS_REG_TIMESYNC_TS0_UPPER 0x6401810
1370+
13651371
#define BNXT_GRC_BASE_MASK 0xfffff000
13661372
#define BNXT_GRC_OFFSET_MASK 0x00000ffc
13671373

@@ -2042,6 +2048,8 @@ struct bnxt {
20422048

20432049
struct bpf_prog *xdp_prog;
20442050

2051+
struct bnxt_ptp_cfg *ptp_cfg;
2052+
20452053
/* devlink interface and vf-rep structs */
20462054
struct devlink *dl;
20472055
struct devlink_port dl_port;

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

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -19,9 +19,13 @@
1919
#include <linux/firmware.h>
2020
#include <linux/utsname.h>
2121
#include <linux/time.h>
22+
#include <linux/ptp_clock_kernel.h>
23+
#include <linux/net_tstamp.h>
24+
#include <linux/timecounter.h>
2225
#include "bnxt_hsi.h"
2326
#include "bnxt.h"
2427
#include "bnxt_xdp.h"
28+
#include "bnxt_ptp.h"
2529
#include "bnxt_ethtool.h"
2630
#include "bnxt_nvm_defs.h" /* NVRAM content constant and structure defs */
2731
#include "bnxt_fw_hdr.h" /* Firmware hdr constant and structure defs */
@@ -3926,6 +3930,35 @@ static int bnxt_get_dump_data(struct net_device *dev, struct ethtool_dump *dump,
39263930
return 0;
39273931
}
39283932

3933+
static int bnxt_get_ts_info(struct net_device *dev,
3934+
struct ethtool_ts_info *info)
3935+
{
3936+
struct bnxt *bp = netdev_priv(dev);
3937+
struct bnxt_ptp_cfg *ptp;
3938+
3939+
ptp = bp->ptp_cfg;
3940+
info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE |
3941+
SOF_TIMESTAMPING_RX_SOFTWARE |
3942+
SOF_TIMESTAMPING_SOFTWARE;
3943+
3944+
info->phc_index = -1;
3945+
if (!ptp)
3946+
return 0;
3947+
3948+
info->so_timestamping |= SOF_TIMESTAMPING_TX_HARDWARE |
3949+
SOF_TIMESTAMPING_RX_HARDWARE |
3950+
SOF_TIMESTAMPING_RAW_HARDWARE;
3951+
if (ptp->ptp_clock)
3952+
info->phc_index = ptp_clock_index(ptp->ptp_clock);
3953+
3954+
info->tx_types = (1 << HWTSTAMP_TX_OFF) | (1 << HWTSTAMP_TX_ON);
3955+
3956+
info->rx_filters = (1 << HWTSTAMP_FILTER_NONE) |
3957+
(1 << HWTSTAMP_FILTER_PTP_V2_L2_EVENT) |
3958+
(1 << HWTSTAMP_FILTER_PTP_V2_L4_EVENT);
3959+
return 0;
3960+
}
3961+
39293962
void bnxt_ethtool_init(struct bnxt *bp)
39303963
{
39313964
struct hwrm_selftest_qlist_output *resp = bp->hwrm_cmd_resp_addr;
@@ -4172,6 +4205,7 @@ const struct ethtool_ops bnxt_ethtool_ops = {
41724205
.nway_reset = bnxt_nway_reset,
41734206
.set_phys_id = bnxt_set_phys_id,
41744207
.self_test = bnxt_self_test,
4208+
.get_ts_info = bnxt_get_ts_info,
41754209
.reset = bnxt_reset,
41764210
.set_dump = bnxt_set_dump,
41774211
.get_dump_flag = bnxt_get_dump_flag,

0 commit comments

Comments
 (0)