Commit 24ac1ecd authored by Pavan Chebbi's avatar Pavan Chebbi Committed by David S. Miller

bnxt_en: Add driver support to use Real Time Counter for PTP

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: default avatarSomnath Kotur <somnath.kotur@broadcom.com>
Signed-off-by: default avatarPavan Chebbi <pavan.chebbi@broadcom.com>
Signed-off-by: default avatarMichael Chan <michael.chan@broadcom.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 740c342e
...@@ -7414,6 +7414,7 @@ static int __bnxt_hwrm_ptp_qcfg(struct bnxt *bp) ...@@ -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_output *resp;
struct hwrm_port_mac_ptp_qcfg_input *req; struct hwrm_port_mac_ptp_qcfg_input *req;
struct bnxt_ptp_cfg *ptp = bp->ptp_cfg; struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
bool phc_cfg;
u8 flags; u8 flags;
int rc; int rc;
...@@ -7456,7 +7457,8 @@ static int __bnxt_hwrm_ptp_qcfg(struct bnxt *bp) ...@@ -7456,7 +7457,8 @@ static int __bnxt_hwrm_ptp_qcfg(struct bnxt *bp)
rc = -ENODEV; rc = -ENODEV;
goto exit; 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) if (rc)
netdev_warn(bp->dev, "PTP initialization failed.\n"); netdev_warn(bp->dev, "PTP initialization failed.\n");
exit: exit:
...@@ -7514,6 +7516,8 @@ static int __bnxt_hwrm_func_qcaps(struct bnxt *bp) ...@@ -7514,6 +7516,8 @@ static int __bnxt_hwrm_func_qcaps(struct bnxt *bp)
bp->fw_cap |= BNXT_FW_CAP_EXT_HW_STATS_SUPPORTED; bp->fw_cap |= BNXT_FW_CAP_EXT_HW_STATS_SUPPORTED;
if (BNXT_PF(bp) && (flags_ext & FUNC_QCAPS_RESP_FLAGS_EXT_PTP_PPS_SUPPORTED)) if (BNXT_PF(bp) && (flags_ext & FUNC_QCAPS_RESP_FLAGS_EXT_PTP_PPS_SUPPORTED))
bp->fw_cap |= BNXT_FW_CAP_PTP_PPS; 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)) if (BNXT_PF(bp) && (flags_ext & FUNC_QCAPS_RESP_FLAGS_EXT_HOT_RESET_IF_SUPPORT))
bp->fw_cap |= BNXT_FW_CAP_HOT_RESET_IF; bp->fw_cap |= BNXT_FW_CAP_HOT_RESET_IF;
if (BNXT_PF(bp) && (flags_ext & FUNC_QCAPS_RESP_FLAGS_EXT_FW_LIVEPATCH_SUPPORTED)) if (BNXT_PF(bp) && (flags_ext & FUNC_QCAPS_RESP_FLAGS_EXT_FW_LIVEPATCH_SUPPORTED))
...@@ -10288,6 +10292,7 @@ static int __bnxt_open_nic(struct bnxt *bp, bool irq_re_init, bool link_re_init) ...@@ -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 */ /* VF-reps may need to be re-opened after the PF is re-opened */
if (BNXT_PF(bp)) if (BNXT_PF(bp))
bnxt_vf_reps_open(bp); bnxt_vf_reps_open(bp);
bnxt_ptp_init_rtc(bp, true);
return 0; return 0;
open_err_irq: open_err_irq:
......
...@@ -1957,6 +1957,7 @@ struct bnxt { ...@@ -1957,6 +1957,7 @@ struct bnxt {
#define BNXT_FW_CAP_EXT_STATS_SUPPORTED 0x00040000 #define BNXT_FW_CAP_EXT_STATS_SUPPORTED 0x00040000
#define BNXT_FW_CAP_ERR_RECOVER_RELOAD 0x00100000 #define BNXT_FW_CAP_ERR_RECOVER_RELOAD 0x00100000
#define BNXT_FW_CAP_HOT_RESET 0x00200000 #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_RX_STRIP 0x01000000
#define BNXT_FW_CAP_VLAN_TX_INSERT 0x02000000 #define BNXT_FW_CAP_VLAN_TX_INSERT 0x02000000
#define BNXT_FW_CAP_EXT_HW_STATS_SUPPORTED 0x04000000 #define BNXT_FW_CAP_EXT_HW_STATS_SUPPORTED 0x04000000
......
...@@ -19,6 +19,20 @@ ...@@ -19,6 +19,20 @@
#include "bnxt_hwrm.h" #include "bnxt_hwrm.h"
#include "bnxt_ptp.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) int bnxt_ptp_parse(struct sk_buff *skb, u16 *seq_id, u16 *hdr_off)
{ {
unsigned int ptp_class; unsigned int ptp_class;
...@@ -48,6 +62,9 @@ static int bnxt_ptp_settime(struct ptp_clock_info *ptp_info, ...@@ -48,6 +62,9 @@ static int bnxt_ptp_settime(struct ptp_clock_info *ptp_info,
ptp_info); ptp_info);
u64 ns = timespec64_to_ns(ts); 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); spin_lock_bh(&ptp->ptp_lock);
timecounter_init(&ptp->tc, &ptp->cc, ns); timecounter_init(&ptp->tc, &ptp->cc, ns);
spin_unlock_bh(&ptp->ptp_lock); spin_unlock_bh(&ptp->ptp_lock);
...@@ -730,6 +747,41 @@ static void bnxt_ptp_timecounter_init(struct bnxt *bp, bool init_tc) ...@@ -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())); 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) static void bnxt_ptp_free(struct bnxt *bp)
{ {
struct bnxt_ptp_cfg *ptp = bp->ptp_cfg; struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
...@@ -742,7 +794,7 @@ static void bnxt_ptp_free(struct bnxt *bp) ...@@ -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; struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
int rc; int rc;
...@@ -754,6 +806,13 @@ int bnxt_ptp_init(struct bnxt *bp) ...@@ -754,6 +806,13 @@ int bnxt_ptp_init(struct bnxt *bp)
if (rc) if (rc)
return 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)) if (ptp->ptp_clock && bnxt_pps_config_ok(bp))
return 0; return 0;
...@@ -762,7 +821,8 @@ int bnxt_ptp_init(struct bnxt *bp) ...@@ -762,7 +821,8 @@ int bnxt_ptp_init(struct bnxt *bp)
atomic_set(&ptp->tx_avail, BNXT_MAX_TX_TS); atomic_set(&ptp->tx_avail, BNXT_MAX_TX_TS);
spin_lock_init(&ptp->ptp_lock); 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; ptp->ptp_info = bnxt_ptp_caps;
if ((bp->fw_cap & BNXT_FW_CAP_PTP_PPS)) { if ((bp->fw_cap & BNXT_FW_CAP_PTP_PPS)) {
...@@ -774,8 +834,8 @@ int bnxt_ptp_init(struct bnxt *bp) ...@@ -774,8 +834,8 @@ int bnxt_ptp_init(struct bnxt *bp)
int err = PTR_ERR(ptp->ptp_clock); int err = PTR_ERR(ptp->ptp_clock);
ptp->ptp_clock = NULL; ptp->ptp_clock = NULL;
bnxt_unmap_ptp_regs(bp); rc = err;
return err; goto out;
} }
if (bp->flags & BNXT_FLAG_CHIP_P5) { if (bp->flags & BNXT_FLAG_CHIP_P5) {
spin_lock_bh(&ptp->ptp_lock); spin_lock_bh(&ptp->ptp_lock);
...@@ -785,6 +845,11 @@ int bnxt_ptp_init(struct bnxt *bp) ...@@ -785,6 +845,11 @@ int bnxt_ptp_init(struct bnxt *bp)
ptp_schedule_worker(ptp->ptp_clock, 0); ptp_schedule_worker(ptp->ptp_clock, 0);
} }
return 0; return 0;
out:
bnxt_ptp_free(bp);
bnxt_unmap_ptp_regs(bp);
return rc;
} }
void bnxt_ptp_clear(struct bnxt *bp) void bnxt_ptp_clear(struct bnxt *bp)
......
...@@ -137,6 +137,8 @@ int bnxt_hwtstamp_set(struct net_device *dev, struct ifreq *ifr); ...@@ -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_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_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_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); void bnxt_ptp_clear(struct bnxt *bp);
#endif #endif
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment