net: stmmac: switch to use interrupt for hw crosstimestamping
authorWong Vee Khee <vee.khee.wong@linux.intel.com>
Thu, 14 Jul 2022 07:54:27 +0000 (15:54 +0800)
committerDavid S. Miller <davem@davemloft.net>
Mon, 18 Jul 2022 10:14:35 +0000 (11:14 +0100)
Using current implementation of polling mode, there is high chances we
will hit into timeout error when running phc2sys. Hence, update the
implementation of hardware crosstimestamping to use the MAC interrupt
service routine instead of polling for TSIS bit in the MAC Timestamp
Interrupt Status register to be set.

Cc: Richard Cochran <richardcochran@gmail.com>
Signed-off-by: Wong Vee Khee <vee.khee.wong@linux.intel.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/stmicro/stmmac/dwmac-intel.c
drivers/net/ethernet/stmicro/stmmac/dwmac4.h
drivers/net/ethernet/stmicro/stmmac/dwmac4_core.c
drivers/net/ethernet/stmicro/stmmac/stmmac.h
drivers/net/ethernet/stmicro/stmmac/stmmac_hwtstamp.c
drivers/net/ethernet/stmicro/stmmac/stmmac_ptp.c
include/linux/stmmac.h

index 38fe77d1035e306c6d3fd13c3fb547d8bfd2cbec..3fe720c5dc9fcd11654fa4a51e291d0d2fe94707 100644 (file)
@@ -298,6 +298,11 @@ static void get_arttime(struct mii_bus *mii, int intel_adhoc_addr,
        *art_time = ns;
 }
 
+static int stmmac_cross_ts_isr(struct stmmac_priv *priv)
+{
+       return (readl(priv->ioaddr + GMAC_INT_STATUS) & GMAC_INT_TSIE);
+}
+
 static int intel_crosststamp(ktime_t *device,
                             struct system_counterval_t *system,
                             void *ctx)
@@ -313,8 +318,6 @@ static int intel_crosststamp(ktime_t *device,
        u32 num_snapshot;
        u32 gpio_value;
        u32 acr_value;
-       int ret;
-       u32 v;
        int i;
 
        if (!boot_cpu_has(X86_FEATURE_ART))
@@ -328,6 +331,8 @@ static int intel_crosststamp(ktime_t *device,
        if (priv->plat->ext_snapshot_en)
                return -EBUSY;
 
+       priv->plat->int_snapshot_en = 1;
+
        mutex_lock(&priv->aux_ts_lock);
        /* Enable Internal snapshot trigger */
        acr_value = readl(ptpaddr + PTP_ACR);
@@ -347,6 +352,7 @@ static int intel_crosststamp(ktime_t *device,
                break;
        default:
                mutex_unlock(&priv->aux_ts_lock);
+               priv->plat->int_snapshot_en = 0;
                return -EINVAL;
        }
        writel(acr_value, ptpaddr + PTP_ACR);
@@ -368,13 +374,12 @@ static int intel_crosststamp(ktime_t *device,
        gpio_value |= GMAC_GPO1;
        writel(gpio_value, ioaddr + GMAC_GPIO_STATUS);
 
-       /* Poll for time sync operation done */
-       ret = readl_poll_timeout(priv->ioaddr + GMAC_INT_STATUS, v,
-                                (v & GMAC_INT_TSIE), 100, 10000);
-
-       if (ret == -ETIMEDOUT) {
-               pr_err("%s: Wait for time sync operation timeout\n", __func__);
-               return ret;
+       /* Time sync done Indication - Interrupt method */
+       if (!wait_event_interruptible_timeout(priv->tstamp_busy_wait,
+                                             stmmac_cross_ts_isr(priv),
+                                             HZ / 100)) {
+               priv->plat->int_snapshot_en = 0;
+               return -ETIMEDOUT;
        }
 
        num_snapshot = (readl(ioaddr + GMAC_TIMESTAMP_STATUS) &
@@ -392,6 +397,7 @@ static int intel_crosststamp(ktime_t *device,
        }
 
        system->cycles *= intel_priv->crossts_adj;
+       priv->plat->int_snapshot_en = 0;
 
        return 0;
 }
@@ -576,6 +582,7 @@ static int intel_mgbe_common_data(struct pci_dev *pdev,
 
        plat->has_crossts = true;
        plat->crosststamp = intel_crosststamp;
+       plat->int_snapshot_en = 0;
 
        /* Setup MSI vector offset specific to Intel mGbE controller */
        plat->msi_mac_vec = 29;
index 462ca7ed095a2a8e8d4b5462191d02c756797098..71dad409f78b075eeaed6d2bacee3b47092aca84 100644 (file)
 #define        GMAC_PCS_IRQ_DEFAULT    (GMAC_INT_RGSMIIS | GMAC_INT_PCS_LINK | \
                                 GMAC_INT_PCS_ANE)
 
-#define        GMAC_INT_DEFAULT_ENABLE (GMAC_INT_PMT_EN | GMAC_INT_LPI_EN)
+#define        GMAC_INT_DEFAULT_ENABLE (GMAC_INT_PMT_EN | GMAC_INT_LPI_EN | \
+                                GMAC_INT_TSIE)
 
 enum dwmac4_irq_status {
        time_stamp_irq = 0x00001000,
index fd41db65fe1df41fe53d24f19d6a39f04173bf10..d5299dd13e8582c2334d1b5056dce9612340885b 100644 (file)
@@ -23,6 +23,7 @@
 static void dwmac4_core_init(struct mac_device_info *hw,
                             struct net_device *dev)
 {
+       struct stmmac_priv *priv = netdev_priv(dev);
        void __iomem *ioaddr = hw->pcsr;
        u32 value = readl(ioaddr + GMAC_CONFIG);
 
@@ -58,6 +59,9 @@ static void dwmac4_core_init(struct mac_device_info *hw,
                value |= GMAC_INT_FPE_EN;
 
        writel(value, ioaddr + GMAC_INT_EN);
+
+       if (GMAC_INT_DEFAULT_ENABLE & GMAC_INT_TSIE)
+               init_waitqueue_head(&priv->tstamp_busy_wait);
 }
 
 static void dwmac4_rx_queue_enable(struct mac_device_info *hw,
index 57970ae2178dab8a559a66e658443af91bb997bd..f9e83964aa7ea63beac580bf6fe906e9b252884a 100644 (file)
@@ -266,6 +266,7 @@ struct stmmac_priv {
        rwlock_t ptp_lock;
        /* Protects auxiliary snapshot registers from concurrent access. */
        struct mutex aux_ts_lock;
+       wait_queue_head_t tstamp_busy_wait;
 
        void __iomem *mmcaddr;
        void __iomem *ptpaddr;
index 92d32940aff00660663e709fd8b7196500e96e16..764832f4dae1a7b241e07d8f30e725eb6c83a870 100644 (file)
@@ -179,6 +179,11 @@ static void timestamp_interrupt(struct stmmac_priv *priv)
        u64 ptp_time;
        int i;
 
+       if (priv->plat->int_snapshot_en) {
+               wake_up(&priv->tstamp_busy_wait);
+               return;
+       }
+
        tsync_int = readl(priv->ioaddr + GMAC_INT_STATUS) & GMAC_INT_TSIE;
 
        if (!tsync_int)
index e45fb191d8e6ef86317b40f4743172204a191773..4d11980dcd64dc063b5cf3fda361f84560f01ef7 100644 (file)
@@ -175,11 +175,10 @@ static int stmmac_enable(struct ptp_clock_info *ptp,
        struct stmmac_priv *priv =
            container_of(ptp, struct stmmac_priv, ptp_clock_ops);
        void __iomem *ptpaddr = priv->ptpaddr;
-       void __iomem *ioaddr = priv->hw->pcsr;
        struct stmmac_pps_cfg *cfg;
-       u32 intr_value, acr_value;
        int ret = -EOPNOTSUPP;
        unsigned long flags;
+       u32 acr_value;
 
        switch (rq->type) {
        case PTP_CLK_REQ_PEROUT:
@@ -213,19 +212,10 @@ static int stmmac_enable(struct ptp_clock_info *ptp,
                        netdev_dbg(priv->dev, "Auxiliary Snapshot %d enabled.\n",
                                   priv->plat->ext_snapshot_num >>
                                   PTP_ACR_ATSEN_SHIFT);
-                       /* Enable Timestamp Interrupt */
-                       intr_value = readl(ioaddr + GMAC_INT_EN);
-                       intr_value |= GMAC_INT_TSIE;
-                       writel(intr_value, ioaddr + GMAC_INT_EN);
-
                } else {
                        netdev_dbg(priv->dev, "Auxiliary Snapshot %d disabled.\n",
                                   priv->plat->ext_snapshot_num >>
                                   PTP_ACR_ATSEN_SHIFT);
-                       /* Disable Timestamp Interrupt */
-                       intr_value = readl(ioaddr + GMAC_INT_EN);
-                       intr_value &= ~GMAC_INT_TSIE;
-                       writel(intr_value, ioaddr + GMAC_INT_EN);
                }
                writel(acr_value, ptpaddr + PTP_ACR);
                mutex_unlock(&priv->aux_ts_lock);
index 29917850f07946b57dfdbd8c5063220c547d5d5d..8df475db88c040456e887696ac725f1b50451c69 100644 (file)
@@ -260,6 +260,7 @@ struct plat_stmmacenet_data {
        bool has_crossts;
        int int_snapshot_num;
        int ext_snapshot_num;
+       bool int_snapshot_en;
        bool ext_snapshot_en;
        bool multi_msi_en;
        int msi_mac_vec;