igb: offer a PTP Hardware Clock instead of the timecompare method
authorRichard Cochran <richardcochran@gmail.com>
Fri, 16 Mar 2012 10:55:37 +0000 (10:55 +0000)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Wed, 4 Apr 2012 07:48:13 +0000 (00:48 -0700)
This commit removes the legacy timecompare code from the igb driver and
offers a tunable PHC instead.

Signed-off-by: Richard Cochran <richardcochran@gmail.com>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
drivers/net/ethernet/intel/Kconfig
drivers/net/ethernet/intel/igb/Makefile
drivers/net/ethernet/intel/igb/igb.h
drivers/net/ethernet/intel/igb/igb_main.c
drivers/net/ethernet/intel/igb/igb_ptp.c

index 7621316..90142aa 100644 (file)
@@ -120,6 +120,17 @@ config IGB_DCA
          driver.  DCA is a method for warming the CPU cache before data
          is used, with the intent of lessening the impact of cache misses.
 
+config IGB_PTP
+       bool "PTP Hardware Clock (PHC)"
+       default y
+       depends on IGB && PTP_1588_CLOCK
+       ---help---
+         Say Y here if you want to use PTP Hardware Clock (PHC) in the
+         driver.  Only the basic clock operations have been implemented.
+
+         Every timestamp and clock read operations must consult the
+         overflow counter to form a correct time value.
+
 config IGBVF
        tristate "Intel(R) 82576 Virtual Function Ethernet support"
        depends on PCI
index 6565c46..4bd16e2 100644 (file)
@@ -35,3 +35,4 @@ obj-$(CONFIG_IGB) += igb.o
 igb-objs := igb_main.o igb_ethtool.o e1000_82575.o \
            e1000_mac.o e1000_nvm.o e1000_phy.o e1000_mbx.o
 
+igb-$(CONFIG_IGB_PTP) += igb_ptp.o
index f0265e8..3758ad2 100644 (file)
@@ -35,7 +35,6 @@
 #include "e1000_82575.h"
 
 #include <linux/clocksource.h>
-#include <linux/timecompare.h>
 #include <linux/net_tstamp.h>
 #include <linux/ptp_clock_kernel.h>
 #include <linux/bitops.h>
@@ -329,9 +328,6 @@ struct igb_adapter {
 
        /* OS defined structs */
        struct pci_dev *pdev;
-       struct cyclecounter cycles;
-       struct timecounter clock;
-       struct timecompare compare;
        struct hwtstamp_config hwtstamp_config;
 
        spinlock_t stats64_lock;
@@ -386,7 +382,6 @@ struct igb_adapter {
 #define IGB_DMCTLX_DCFLUSH_DIS     0x80000000  /* Disable DMA Coal Flush */
 
 #define IGB_82576_TSYNC_SHIFT 19
-#define IGB_82580_TSYNC_SHIFT 24
 #define IGB_TS_HDR_LEN        16
 enum e1000_state_t {
        __IGB_TESTING,
@@ -422,7 +417,15 @@ extern void igb_update_stats(struct igb_adapter *, struct rtnl_link_stats64 *);
 extern bool igb_has_link(struct igb_adapter *adapter);
 extern void igb_set_ethtool_ops(struct net_device *);
 extern void igb_power_up_link(struct igb_adapter *);
+#ifdef CONFIG_IGB_PTP
+extern void igb_ptp_init(struct igb_adapter *adapter);
+extern void igb_ptp_remove(struct igb_adapter *adapter);
 
+extern void igb_systim_to_hwtstamp(struct igb_adapter *adapter,
+                                  struct skb_shared_hwtstamps *hwtstamps,
+                                  u64 systim);
+
+#endif
 static inline s32 igb_reset_phy(struct e1000_hw *hw)
 {
        if (hw->phy.ops.reset)
index 5ec3159..f022ff7 100644 (file)
@@ -114,7 +114,6 @@ static void igb_free_all_rx_resources(struct igb_adapter *);
 static void igb_setup_mrqc(struct igb_adapter *);
 static int igb_probe(struct pci_dev *, const struct pci_device_id *);
 static void __devexit igb_remove(struct pci_dev *pdev);
-static void igb_init_hw_timer(struct igb_adapter *adapter);
 static int igb_sw_init(struct igb_adapter *);
 static int igb_open(struct net_device *);
 static int igb_close(struct net_device *);
@@ -565,33 +564,6 @@ exit:
        return;
 }
 
-
-/**
- * igb_read_clock - read raw cycle counter (to be used by time counter)
- */
-static cycle_t igb_read_clock(const struct cyclecounter *tc)
-{
-       struct igb_adapter *adapter =
-               container_of(tc, struct igb_adapter, cycles);
-       struct e1000_hw *hw = &adapter->hw;
-       u64 stamp = 0;
-       int shift = 0;
-
-       /*
-        * The timestamp latches on lowest register read. For the 82580
-        * the lowest register is SYSTIMR instead of SYSTIML.  However we never
-        * adjusted TIMINCA so SYSTIMR will just read as all 0s so ignore it.
-        */
-       if (hw->mac.type >= e1000_82580) {
-               stamp = rd32(E1000_SYSTIMR) >> 8;
-               shift = IGB_82580_TSYNC_SHIFT;
-       }
-
-       stamp |= (u64)rd32(E1000_SYSTIML) << shift;
-       stamp |= (u64)rd32(E1000_SYSTIMH) << (shift + 32);
-       return stamp;
-}
-
 /**
  * igb_get_hw_dev - return device
  * used by hardware layer to print debugging information
@@ -2110,9 +2082,11 @@ static int __devinit igb_probe(struct pci_dev *pdev,
        }
 
 #endif
+#ifdef CONFIG_IGB_PTP
        /* do hw tstamp init after resetting */
-       igb_init_hw_timer(adapter);
+       igb_ptp_init(adapter);
 
+#endif
        dev_info(&pdev->dev, "Intel(R) Gigabit Ethernet Network Connection\n");
        /* print bus type/speed/width info */
        dev_info(&pdev->dev, "%s: (PCIe:%s:%s) %pM\n",
@@ -2184,7 +2158,10 @@ static void __devexit igb_remove(struct pci_dev *pdev)
        struct e1000_hw *hw = &adapter->hw;
 
        pm_runtime_get_noresume(&pdev->dev);
+#ifdef CONFIG_IGB_PTP
+       igb_ptp_remove(adapter);
 
+#endif
        /*
         * The watchdog timer may be rescheduled, so explicitly
         * disable watchdog from being rescheduled.
@@ -2304,112 +2281,6 @@ out:
 }
 
 /**
- * igb_init_hw_timer - Initialize hardware timer used with IEEE 1588 timestamp
- * @adapter: board private structure to initialize
- *
- * igb_init_hw_timer initializes the function pointer and values for the hw
- * timer found in hardware.
- **/
-static void igb_init_hw_timer(struct igb_adapter *adapter)
-{
-       struct e1000_hw *hw = &adapter->hw;
-
-       switch (hw->mac.type) {
-       case e1000_i350:
-       case e1000_82580:
-               memset(&adapter->cycles, 0, sizeof(adapter->cycles));
-               adapter->cycles.read = igb_read_clock;
-               adapter->cycles.mask = CLOCKSOURCE_MASK(64);
-               adapter->cycles.mult = 1;
-               /*
-                * The 82580 timesync updates the system timer every 8ns by 8ns
-                * and the value cannot be shifted.  Instead we need to shift
-                * the registers to generate a 64bit timer value.  As a result
-                * SYSTIMR/L/H, TXSTMPL/H, RXSTMPL/H all have to be shifted by
-                * 24 in order to generate a larger value for synchronization.
-                */
-               adapter->cycles.shift = IGB_82580_TSYNC_SHIFT;
-               /* disable system timer temporarily by setting bit 31 */
-               wr32(E1000_TSAUXC, 0x80000000);
-               wrfl();
-
-               /* Set registers so that rollover occurs soon to test this. */
-               wr32(E1000_SYSTIMR, 0x00000000);
-               wr32(E1000_SYSTIML, 0x80000000);
-               wr32(E1000_SYSTIMH, 0x000000FF);
-               wrfl();
-
-               /* enable system timer by clearing bit 31 */
-               wr32(E1000_TSAUXC, 0x0);
-               wrfl();
-
-               timecounter_init(&adapter->clock,
-                                &adapter->cycles,
-                                ktime_to_ns(ktime_get_real()));
-               /*
-                * Synchronize our NIC clock against system wall clock. NIC
-                * time stamp reading requires ~3us per sample, each sample
-                * was pretty stable even under load => only require 10
-                * samples for each offset comparison.
-                */
-               memset(&adapter->compare, 0, sizeof(adapter->compare));
-               adapter->compare.source = &adapter->clock;
-               adapter->compare.target = ktime_get_real;
-               adapter->compare.num_samples = 10;
-               timecompare_update(&adapter->compare, 0);
-               break;
-       case e1000_82576:
-               /*
-                * Initialize hardware timer: we keep it running just in case
-                * that some program needs it later on.
-                */
-               memset(&adapter->cycles, 0, sizeof(adapter->cycles));
-               adapter->cycles.read = igb_read_clock;
-               adapter->cycles.mask = CLOCKSOURCE_MASK(64);
-               adapter->cycles.mult = 1;
-               /**
-                * Scale the NIC clock cycle by a large factor so that
-                * relatively small clock corrections can be added or
-                * subtracted at each clock tick. The drawbacks of a large
-                * factor are a) that the clock register overflows more quickly
-                * (not such a big deal) and b) that the increment per tick has
-                * to fit into 24 bits.  As a result we need to use a shift of
-                * 19 so we can fit a value of 16 into the TIMINCA register.
-                */
-               adapter->cycles.shift = IGB_82576_TSYNC_SHIFT;
-               wr32(E1000_TIMINCA,
-                               (1 << E1000_TIMINCA_16NS_SHIFT) |
-                               (16 << IGB_82576_TSYNC_SHIFT));
-
-               /* Set registers so that rollover occurs soon to test this. */
-               wr32(E1000_SYSTIML, 0x00000000);
-               wr32(E1000_SYSTIMH, 0xFF800000);
-               wrfl();
-
-               timecounter_init(&adapter->clock,
-                                &adapter->cycles,
-                                ktime_to_ns(ktime_get_real()));
-               /*
-                * Synchronize our NIC clock against system wall clock. NIC
-                * time stamp reading requires ~3us per sample, each sample
-                * was pretty stable even under load => only require 10
-                * samples for each offset comparison.
-                */
-               memset(&adapter->compare, 0, sizeof(adapter->compare));
-               adapter->compare.source = &adapter->clock;
-               adapter->compare.target = ktime_get_real;
-               adapter->compare.num_samples = 10;
-               timecompare_update(&adapter->compare, 0);
-               break;
-       case e1000_82575:
-               /* 82575 does not support timesync */
-       default:
-               break;
-       }
-
-}
-
-/**
  * igb_sw_init - Initialize general software structures (struct igb_adapter)
  * @adapter: board private structure to initialize
  *
@@ -5718,35 +5589,7 @@ static int igb_poll(struct napi_struct *napi, int budget)
        return 0;
 }
 
-/**
- * igb_systim_to_hwtstamp - convert system time value to hw timestamp
- * @adapter: board private structure
- * @shhwtstamps: timestamp structure to update
- * @regval: unsigned 64bit system time value.
- *
- * We need to convert the system time value stored in the RX/TXSTMP registers
- * into a hwtstamp which can be used by the upper level timestamping functions
- */
-static void igb_systim_to_hwtstamp(struct igb_adapter *adapter,
-                                   struct skb_shared_hwtstamps *shhwtstamps,
-                                   u64 regval)
-{
-       u64 ns;
-
-       /*
-        * The 82580 starts with 1ns at bit 0 in RX/TXSTMPL, shift this up to
-        * 24 to match clock shift we setup earlier.
-        */
-       if (adapter->hw.mac.type >= e1000_82580)
-               regval <<= IGB_82580_TSYNC_SHIFT;
-
-       ns = timecounter_cyc2time(&adapter->clock, regval);
-       timecompare_update(&adapter->compare, ns);
-       memset(shhwtstamps, 0, sizeof(struct skb_shared_hwtstamps));
-       shhwtstamps->hwtstamp = ns_to_ktime(ns);
-       shhwtstamps->syststamp = timecompare_transform(&adapter->compare, ns);
-}
-
+#ifdef CONFIG_IGB_PTP
 /**
  * igb_tx_hwtstamp - utility function which checks for TX time stamp
  * @q_vector: pointer to q_vector containing needed info
@@ -5776,6 +5619,7 @@ static void igb_tx_hwtstamp(struct igb_q_vector *q_vector,
        skb_tstamp_tx(buffer_info->skb, &shhwtstamps);
 }
 
+#endif
 /**
  * igb_clean_tx_irq - Reclaim resources after transmit completes
  * @q_vector: pointer to q_vector containing needed info
@@ -5819,9 +5663,11 @@ static bool igb_clean_tx_irq(struct igb_q_vector *q_vector)
                total_bytes += tx_buffer->bytecount;
                total_packets += tx_buffer->gso_segs;
 
+#ifdef CONFIG_IGB_PTP
                /* retrieve hardware timestamp */
                igb_tx_hwtstamp(q_vector, tx_buffer);
 
+#endif
                /* free the skb */
                dev_kfree_skb_any(tx_buffer->skb);
                tx_buffer->skb = NULL;
@@ -5993,6 +5839,7 @@ static inline void igb_rx_hash(struct igb_ring *ring,
                skb->rxhash = le32_to_cpu(rx_desc->wb.lower.hi_dword.rss);
 }
 
+#ifdef CONFIG_IGB_PTP
 static void igb_rx_hwtstamp(struct igb_q_vector *q_vector,
                            union e1000_adv_rx_desc *rx_desc,
                            struct sk_buff *skb)
@@ -6032,6 +5879,7 @@ static void igb_rx_hwtstamp(struct igb_q_vector *q_vector,
        igb_systim_to_hwtstamp(adapter, skb_hwtstamps(skb), regval);
 }
 
+#endif
 static void igb_rx_vlan(struct igb_ring *ring,
                        union e1000_adv_rx_desc *rx_desc,
                        struct sk_buff *skb)
@@ -6142,7 +5990,9 @@ static bool igb_clean_rx_irq(struct igb_q_vector *q_vector, int budget)
                        goto next_desc;
                }
 
+#ifdef CONFIG_IGB_PTP
                igb_rx_hwtstamp(q_vector, rx_desc, skb);
+#endif
                igb_rx_hash(rx_ring, rx_desc, skb);
                igb_rx_checksum(rx_ring, rx_desc, skb);
                igb_rx_vlan(rx_ring, rx_desc, skb);
index c8254cf..c9b71c5 100644 (file)
@@ -27,6 +27,9 @@
 #define ISGN                   0x80000000
 
 /*
+ * The 82580 timesync updates the system timer every 8ns by 8ns,
+ * and this update value cannot be reprogrammed.
+ *
  * Neither the 82576 nor the 82580 offer registers wide enough to hold
  * nanoseconds time values for very long. For the 82580, SYSTIM always
  * counts nanoseconds, but the upper 24 bits are not availible. The
  * field are needed to provide the nominal 16 nanosecond period,
  * leaving 19 bits for fractional nanoseconds.
  *
+ * We scale the NIC clock cycle by a large factor so that relatively
+ * small clock corrections can be added or subtracted at each clock
+ * tick. The drawbacks of a large factor are a) that the clock
+ * register overflows more quickly (not such a big deal) and b) that
+ * the increment per tick has to fit into 24 bits.  As a result we
+ * need to use a shift of 19 so we can fit a value of 16 into the
+ * TIMINCA register.
+ *
  *
  *             SYSTIMH            SYSTIML
  *        +--------------+   +---+---+------+
@@ -95,6 +106,11 @@ static cycle_t igb_82580_systim_read(const struct cyclecounter *cc)
        struct igb_adapter *igb = container_of(cc, struct igb_adapter, cc);
        struct e1000_hw *hw = &igb->hw;
 
+       /*
+        * The timestamp latches on lowest register read. For the 82580
+        * the lowest register is SYSTIMR instead of SYSTIML.  However we only
+        * need to provide nanosecond resolution, so we just ignore it.
+        */
        jk = rd32(E1000_SYSTIMR);
        lo = rd32(E1000_SYSTIML);
        hi = rd32(E1000_SYSTIMH);
@@ -320,3 +336,46 @@ void igb_ptp_remove(struct igb_adapter *adapter)
                         adapter->netdev->name);
        }
 }
+
+/**
+ * igb_systim_to_hwtstamp - convert system time value to hw timestamp
+ * @adapter: board private structure
+ * @hwtstamps: timestamp structure to update
+ * @systim: unsigned 64bit system time value.
+ *
+ * We need to convert the system time value stored in the RX/TXSTMP registers
+ * into a hwtstamp which can be used by the upper level timestamping functions.
+ *
+ * The 'tmreg_lock' spinlock is used to protect the consistency of the
+ * system time value. This is needed because reading the 64 bit time
+ * value involves reading two (or three) 32 bit registers. The first
+ * read latches the value. Ditto for writing.
+ *
+ * In addition, here have extended the system time with an overflow
+ * counter in software.
+ **/
+void igb_systim_to_hwtstamp(struct igb_adapter *adapter,
+                           struct skb_shared_hwtstamps *hwtstamps,
+                           u64 systim)
+{
+       u64 ns;
+       unsigned long flags;
+
+       switch (adapter->hw.mac.type) {
+       case e1000_i350:
+       case e1000_82580:
+       case e1000_82576:
+               break;
+       default:
+               return;
+       }
+
+       spin_lock_irqsave(&adapter->tmreg_lock, flags);
+
+       ns = timecounter_cyc2time(&adapter->tc, systim);
+
+       spin_unlock_irqrestore(&adapter->tmreg_lock, flags);
+
+       memset(hwtstamps, 0, sizeof(*hwtstamps));
+       hwtstamps->hwtstamp = ns_to_ktime(ns);
+}