net: stmmac: Calculate CDC error only once
authorKurt Kanzenbach <kurt@linutronix.de>
Mon, 22 Nov 2021 11:19:31 +0000 (12:19 +0100)
committerJakub Kicinski <kuba@kernel.org>
Wed, 24 Nov 2021 04:11:05 +0000 (20:11 -0800)
The clock domain crossing error (CDC) is calculated at every fetch of Tx or Rx
timestamps. It includes a division. Especially on arm32 based systems it is
expensive. It also requires two conditionals in the hotpath.

Add a compensation value cache to struct plat_stmmacenet_data and subtract it
unconditionally in the RX/TX functions which spares the conditionals.

The value is initialized to 0 and if supported calculated in the PTP
initialization code.

Suggested-by: Thomas Gleixner <tglx@linutronix.de>
Signed-off-by: Kurt Kanzenbach <kurt@linutronix.de>
Link: https://lore.kernel.org/r/20211122111931.135135-1-kurt@linutronix.de
Signed-off-by: Jakub Kicinski <kuba@kernel.org>
drivers/net/ethernet/stmicro/stmmac/stmmac_main.c
drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
include/linux/stmmac.h

index 21111df..340076b 100644 (file)
@@ -511,14 +511,6 @@ bool stmmac_eee_init(struct stmmac_priv *priv)
        return true;
 }
 
-static inline u32 stmmac_cdc_adjust(struct stmmac_priv *priv)
-{
-       /* Correct the clk domain crossing(CDC) error */
-       if (priv->plat->has_gmac4 && priv->plat->clk_ptp_rate)
-               return (2 * NSEC_PER_SEC) / priv->plat->clk_ptp_rate;
-       return 0;
-}
-
 /* stmmac_get_tx_hwtstamp - get HW TX timestamps
  * @priv: driver private structure
  * @p : descriptor pointer
@@ -550,7 +542,7 @@ static void stmmac_get_tx_hwtstamp(struct stmmac_priv *priv,
        }
 
        if (found) {
-               ns -= stmmac_cdc_adjust(priv);
+               ns -= priv->plat->cdc_error_adj;
 
                memset(&shhwtstamp, 0, sizeof(struct skb_shared_hwtstamps));
                shhwtstamp.hwtstamp = ns_to_ktime(ns);
@@ -587,7 +579,7 @@ static void stmmac_get_rx_hwtstamp(struct stmmac_priv *priv, struct dma_desc *p,
        if (stmmac_get_rx_timestamp_status(priv, p, np, priv->adv_ts)) {
                stmmac_get_timestamp(priv, desc, priv->adv_ts, &ns);
 
-               ns -= stmmac_cdc_adjust(priv);
+               ns -= priv->plat->cdc_error_adj;
 
                netdev_dbg(priv->dev, "get valid RX hw timestamp %llu\n", ns);
                shhwtstamp = skb_hwtstamps(skb);
index 580cc03..e14c97c 100644 (file)
@@ -309,6 +309,11 @@ void stmmac_ptp_register(struct stmmac_priv *priv)
        if (priv->plat->ptp_max_adj)
                stmmac_ptp_clock_ops.max_adj = priv->plat->ptp_max_adj;
 
+       /* Calculate the clock domain crossing (CDC) error if necessary */
+       priv->plat->cdc_error_adj = 0;
+       if (priv->plat->has_gmac4 && priv->plat->clk_ptp_rate)
+               priv->plat->cdc_error_adj = (2 * NSEC_PER_SEC) / priv->plat->clk_ptp_rate;
+
        stmmac_ptp_clock_ops.n_per_out = priv->dma_cap.pps_out_num;
        stmmac_ptp_clock_ops.n_ext_ts = priv->dma_cap.aux_snapshot_n;
 
index a6f03b3..89b8e20 100644 (file)
@@ -241,6 +241,7 @@ struct plat_stmmacenet_data {
        unsigned int clk_ref_rate;
        unsigned int mult_fact_100ns;
        s32 ptp_max_adj;
+       u32 cdc_error_adj;
        struct reset_control *stmmac_rst;
        struct reset_control *stmmac_ahb_rst;
        struct stmmac_axi *axi;