Skip to content

Commit

Permalink
bnxt_en: Add driver support to use Real Time Counter for PTP
Browse files Browse the repository at this point in the history
Add support for RTC mode if it is supported by firmware.  In RTC
mode, the PHC is set to the 64-bit clock.  Because the legacy interface
is 48-bit, the driver still has to keep track of the upper 16 bits and
handle the rollover.

Cc: Richard Cochran <richardcochran@gmail.com>
Reviewed-by: Somnath Kotur <somnath.kotur@broadcom.com>
Signed-off-by: Pavan Chebbi <pavan.chebbi@broadcom.com>
Signed-off-by: Michael Chan <michael.chan@broadcom.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
Pavan Chebbi authored and David S. Miller committed Jan 26, 2022
1 parent 740c342 commit 24ac1ec
Show file tree
Hide file tree
Showing 4 changed files with 79 additions and 6 deletions.
7 changes: 6 additions & 1 deletion drivers/net/ethernet/broadcom/bnxt/bnxt.c
Original file line number Diff line number Diff line change
Expand Up @@ -7414,6 +7414,7 @@ static int __bnxt_hwrm_ptp_qcfg(struct bnxt *bp)
struct hwrm_port_mac_ptp_qcfg_output *resp;
struct hwrm_port_mac_ptp_qcfg_input *req;
struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
bool phc_cfg;
u8 flags;
int rc;

Expand Down Expand Up @@ -7456,7 +7457,8 @@ static int __bnxt_hwrm_ptp_qcfg(struct bnxt *bp)
rc = -ENODEV;
goto exit;
}
rc = bnxt_ptp_init(bp);
phc_cfg = (flags & PORT_MAC_PTP_QCFG_RESP_FLAGS_RTC_CONFIGURED) != 0;
rc = bnxt_ptp_init(bp, phc_cfg);
if (rc)
netdev_warn(bp->dev, "PTP initialization failed.\n");
exit:
Expand Down Expand Up @@ -7514,6 +7516,8 @@ static int __bnxt_hwrm_func_qcaps(struct bnxt *bp)
bp->fw_cap |= BNXT_FW_CAP_EXT_HW_STATS_SUPPORTED;
if (BNXT_PF(bp) && (flags_ext & FUNC_QCAPS_RESP_FLAGS_EXT_PTP_PPS_SUPPORTED))
bp->fw_cap |= BNXT_FW_CAP_PTP_PPS;
if (flags_ext & FUNC_QCAPS_RESP_FLAGS_EXT_PTP_64BIT_RTC_SUPPORTED)
bp->fw_cap |= BNXT_FW_CAP_PTP_RTC;
if (BNXT_PF(bp) && (flags_ext & FUNC_QCAPS_RESP_FLAGS_EXT_HOT_RESET_IF_SUPPORT))
bp->fw_cap |= BNXT_FW_CAP_HOT_RESET_IF;
if (BNXT_PF(bp) && (flags_ext & FUNC_QCAPS_RESP_FLAGS_EXT_FW_LIVEPATCH_SUPPORTED))
Expand Down Expand Up @@ -10288,6 +10292,7 @@ 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);
bnxt_ptp_init_rtc(bp, true);
return 0;

open_err_irq:
Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/broadcom/bnxt/bnxt.h
Original file line number Diff line number Diff line change
Expand Up @@ -1957,6 +1957,7 @@ struct bnxt {
#define BNXT_FW_CAP_EXT_STATS_SUPPORTED 0x00040000
#define BNXT_FW_CAP_ERR_RECOVER_RELOAD 0x00100000
#define BNXT_FW_CAP_HOT_RESET 0x00200000
#define BNXT_FW_CAP_PTP_RTC 0x00400000
#define BNXT_FW_CAP_VLAN_RX_STRIP 0x01000000
#define BNXT_FW_CAP_VLAN_TX_INSERT 0x02000000
#define BNXT_FW_CAP_EXT_HW_STATS_SUPPORTED 0x04000000
Expand Down
73 changes: 69 additions & 4 deletions drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,20 @@
#include "bnxt_hwrm.h"
#include "bnxt_ptp.h"

static int bnxt_ptp_cfg_settime(struct bnxt *bp, u64 time)
{
struct hwrm_func_ptp_cfg_input *req;
int rc;

rc = hwrm_req_init(bp, req, HWRM_FUNC_PTP_CFG);
if (rc)
return rc;

req->enables = cpu_to_le16(FUNC_PTP_CFG_REQ_ENABLES_PTP_SET_TIME);
req->ptp_set_time = cpu_to_le64(time);
return hwrm_req_send(bp, req);
}

int bnxt_ptp_parse(struct sk_buff *skb, u16 *seq_id, u16 *hdr_off)
{
unsigned int ptp_class;
Expand Down Expand Up @@ -48,6 +62,9 @@ static int bnxt_ptp_settime(struct ptp_clock_info *ptp_info,
ptp_info);
u64 ns = timespec64_to_ns(ts);

if (ptp->bp->fw_cap & BNXT_FW_CAP_PTP_RTC)
return bnxt_ptp_cfg_settime(ptp->bp, ns);

spin_lock_bh(&ptp->ptp_lock);
timecounter_init(&ptp->tc, &ptp->cc, ns);
spin_unlock_bh(&ptp->ptp_lock);
Expand Down Expand Up @@ -730,6 +747,41 @@ static void bnxt_ptp_timecounter_init(struct bnxt *bp, bool init_tc)
timecounter_init(&ptp->tc, &ptp->cc, ktime_to_ns(ktime_get_real()));
}

/* Caller holds ptp_lock */
void bnxt_ptp_rtc_timecounter_init(struct bnxt_ptp_cfg *ptp, u64 ns)
{
timecounter_init(&ptp->tc, &ptp->cc, ns);
/* For RTC, cycle_last must be in sync with the timecounter value. */
ptp->tc.cycle_last = ns & ptp->cc.mask;
}

int bnxt_ptp_init_rtc(struct bnxt *bp, bool phc_cfg)
{
struct timespec64 tsp;
u64 ns;
int rc;

if (!bp->ptp_cfg || !(bp->fw_cap & BNXT_FW_CAP_PTP_RTC))
return -ENODEV;

if (!phc_cfg) {
ktime_get_real_ts64(&tsp);
ns = timespec64_to_ns(&tsp);
rc = bnxt_ptp_cfg_settime(bp, ns);
if (rc)
return rc;
} else {
rc = bnxt_hwrm_port_ts_query(bp, PORT_TS_QUERY_REQ_FLAGS_CURRENT_TIME, &ns);
if (rc)
return rc;
}
spin_lock_bh(&bp->ptp_cfg->ptp_lock);
bnxt_ptp_rtc_timecounter_init(bp->ptp_cfg, ns);
spin_unlock_bh(&bp->ptp_cfg->ptp_lock);

return 0;
}

static void bnxt_ptp_free(struct bnxt *bp)
{
struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
Expand All @@ -742,7 +794,7 @@ static void bnxt_ptp_free(struct bnxt *bp)
}
}

int bnxt_ptp_init(struct bnxt *bp)
int bnxt_ptp_init(struct bnxt *bp, bool phc_cfg)
{
struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
int rc;
Expand All @@ -754,6 +806,13 @@ int bnxt_ptp_init(struct bnxt *bp)
if (rc)
return rc;

if (bp->fw_cap & BNXT_FW_CAP_PTP_RTC) {
bnxt_ptp_timecounter_init(bp, false);
rc = bnxt_ptp_init_rtc(bp, phc_cfg);
if (rc)
goto out;
}

if (ptp->ptp_clock && bnxt_pps_config_ok(bp))
return 0;

Expand All @@ -762,7 +821,8 @@ int bnxt_ptp_init(struct bnxt *bp)
atomic_set(&ptp->tx_avail, BNXT_MAX_TX_TS);
spin_lock_init(&ptp->ptp_lock);

bnxt_ptp_timecounter_init(bp, true);
if (!(bp->fw_cap & BNXT_FW_CAP_PTP_RTC))
bnxt_ptp_timecounter_init(bp, true);

ptp->ptp_info = bnxt_ptp_caps;
if ((bp->fw_cap & BNXT_FW_CAP_PTP_PPS)) {
Expand All @@ -774,8 +834,8 @@ int bnxt_ptp_init(struct bnxt *bp)
int err = PTR_ERR(ptp->ptp_clock);

ptp->ptp_clock = NULL;
bnxt_unmap_ptp_regs(bp);
return err;
rc = err;
goto out;
}
if (bp->flags & BNXT_FLAG_CHIP_P5) {
spin_lock_bh(&ptp->ptp_lock);
Expand All @@ -785,6 +845,11 @@ int bnxt_ptp_init(struct bnxt *bp)
ptp_schedule_worker(ptp->ptp_clock, 0);
}
return 0;

out:
bnxt_ptp_free(bp);
bnxt_unmap_ptp_regs(bp);
return rc;
}

void bnxt_ptp_clear(struct bnxt *bp)
Expand Down
4 changes: 3 additions & 1 deletion drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.h
Original file line number Diff line number Diff line change
Expand Up @@ -137,6 +137,8 @@ int bnxt_hwtstamp_set(struct net_device *dev, struct ifreq *ifr);
int bnxt_hwtstamp_get(struct net_device *dev, struct ifreq *ifr);
int bnxt_get_tx_ts_p5(struct bnxt *bp, struct sk_buff *skb);
int bnxt_get_rx_ts_p5(struct bnxt *bp, u64 *ts, u32 pkt_ts);
int bnxt_ptp_init(struct bnxt *bp);
void bnxt_ptp_rtc_timecounter_init(struct bnxt_ptp_cfg *ptp, u64 ns);
int bnxt_ptp_init_rtc(struct bnxt *bp, bool phc_cfg);
int bnxt_ptp_init(struct bnxt *bp, bool phc_cfg);
void bnxt_ptp_clear(struct bnxt *bp);
#endif

0 comments on commit 24ac1ec

Please sign in to comment.