]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
bnxt_en: optimize gettimex64
authorVadim Fedorenko <vadfed@meta.com>
Thu, 14 Nov 2024 11:48:20 +0000 (03:48 -0800)
committerJakub Kicinski <kuba@kernel.org>
Fri, 15 Nov 2024 22:26:05 +0000 (14:26 -0800)
Current implementation of gettimex64() makes at least 3 PCIe reads to
get current PHC time. It takes at least 2.2us to get this value back to
userspace. At the same time there is cached value of upper bits of PHC
available for packet timestamps already. This patch reuses cached value
to speed up reading of PHC time.

Signed-off-by: Vadim Fedorenko <vadfed@meta.com>
Reviewed-by: Michael Chan <michael.chan@broadcom.com>
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
Link: https://patch.msgid.link/20241114114820.1411660-1-vadfed@meta.com
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.c
drivers/net/ethernet/broadcom/bnxt/bnxt_ptp.h

index 91e7e08fabb102bb3061c27ba2a22c73b1be5d7c..075ccd589845ca7b5626ceb6f0ca4a4e3107804a 100644 (file)
@@ -112,6 +112,28 @@ static int bnxt_refclk_read(struct bnxt *bp, struct ptp_system_timestamp *sts,
        return rc;
 }
 
+static int bnxt_refclk_read_low(struct bnxt *bp, struct ptp_system_timestamp *sts,
+                               u32 *low)
+{
+       struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
+       unsigned long flags;
+
+       /* We have to serialize reg access and FW reset */
+       read_seqlock_excl_irqsave(&ptp->ptp_lock, flags);
+
+       if (test_bit(BNXT_STATE_IN_FW_RESET, &bp->state)) {
+               read_sequnlock_excl_irqrestore(&ptp->ptp_lock, flags);
+               return -EIO;
+       }
+
+       ptp_read_system_prets(sts);
+       *low = readl(bp->bar0 + ptp->refclk_mapped_regs[0]);
+       ptp_read_system_postts(sts);
+
+       read_sequnlock_excl_irqrestore(&ptp->ptp_lock, flags);
+       return 0;
+}
+
 static void bnxt_ptp_get_current_time(struct bnxt *bp)
 {
        struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
@@ -163,12 +185,14 @@ static int bnxt_ptp_gettimex(struct ptp_clock_info *ptp_info,
        struct bnxt_ptp_cfg *ptp = container_of(ptp_info, struct bnxt_ptp_cfg,
                                                ptp_info);
        u64 ns, cycles;
+       u32 low;
        int rc;
 
-       rc = bnxt_refclk_read(ptp->bp, sts, &cycles);
+       rc = bnxt_refclk_read_low(ptp->bp, sts, &low);
        if (rc)
                return rc;
 
+       cycles = bnxt_extend_cycles_32b_to_48b(ptp, low);
        ns = bnxt_timecounter_cyc2time(ptp, cycles);
        *ts = ns_to_timespec64(ns);
 
@@ -801,15 +825,11 @@ void bnxt_get_tx_ts_p5(struct bnxt *bp, struct sk_buff *skb, u16 prod)
 int bnxt_get_rx_ts_p5(struct bnxt *bp, u64 *ts, u32 pkt_ts)
 {
        struct bnxt_ptp_cfg *ptp = bp->ptp_cfg;
-       u64 time;
 
        if (!ptp)
                return -ENODEV;
 
-       time = (u64)READ_ONCE(ptp->old_time) << BNXT_HI_TIMER_SHIFT;
-       *ts = (time & BNXT_HI_TIMER_MASK) | pkt_ts;
-       if (pkt_ts < (time & BNXT_LO_TIMER_MASK))
-               *ts += BNXT_LO_TIMER_MASK + 1;
+       *ts = bnxt_extend_cycles_32b_to_48b(ptp, pkt_ts);
 
        return 0;
 }
index 4df4c2f373e0c9f33f0b326f8a7602e748ed8f39..c7851f8c971c5e34d13f9cafba6a5fa9bef490f5 100644 (file)
@@ -182,4 +182,15 @@ static inline u64 bnxt_timecounter_cyc2time(struct bnxt_ptp_cfg *ptp, u64 ts)
 
        return ns;
 }
+
+static inline u64 bnxt_extend_cycles_32b_to_48b(struct bnxt_ptp_cfg *ptp, u32 ts)
+{
+       u64 time, cycles;
+
+       time = (u64)READ_ONCE(ptp->old_time) << BNXT_HI_TIMER_SHIFT;
+       cycles = (time & BNXT_HI_TIMER_MASK) | ts;
+       if (ts < (time & BNXT_LO_TIMER_MASK))
+               cycles += BNXT_LO_TIMER_MASK + 1;
+       return cycles;
+}
 #endif