e1000e: add timeout for TX HW time stamping work
authorJakub Kicinski <kubakici@wp.pl>
Sat, 15 Mar 2014 14:55:00 +0000 (14:55 +0000)
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>
Fri, 28 Mar 2014 13:54:01 +0000 (06:54 -0700)
Hardware may fail to report time stamp e.g.:
 - when hardware time stamping is not enabled
 - when time stamp is requested shortly after ifup

Timeout time stamp reading work to prevent it from
scheduling itself indefinitely. Report timeout events
via system log and device stats.

Signed-off-by: Jakub Kicinski <kubakici@wp.pl>
Tested-by: Aaron Brown <aaron.f.brown@intel.com>
Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
drivers/net/ethernet/intel/e1000e/e1000.h
drivers/net/ethernet/intel/e1000e/ethtool.c
drivers/net/ethernet/intel/e1000e/netdev.c

index 5325e3e2154e0929b3a56a4b3542cee52f217deb..1471c5464a89e72d87aa571d4a1b15d791a3f015 100644 (file)
@@ -262,6 +262,7 @@ struct e1000_adapter {
        u32 tx_head_addr;
        u32 tx_fifo_size;
        u32 tx_dma_failed;
+       u32 tx_hwtstamp_timeouts;
 
        /* Rx */
        bool (*clean_rx) (struct e1000_ring *ring, int *work_done,
@@ -334,6 +335,7 @@ struct e1000_adapter {
        struct hwtstamp_config hwtstamp_config;
        struct delayed_work systim_overflow_work;
        struct sk_buff *tx_hwtstamp_skb;
+       unsigned long tx_hwtstamp_start;
        struct work_struct tx_hwtstamp_work;
        spinlock_t systim_lock; /* protects SYSTIML/H regsters */
        struct cyclecounter cc;
index 3c2898d0c2aa3ef0779e22e79167be37ba71e8ee..cad250bc1b99fc81d51fb8956eee74c9acc3bc7e 100644 (file)
@@ -104,6 +104,7 @@ static const struct e1000_stats e1000_gstrings_stats[] = {
        E1000_STAT("rx_hwtstamp_cleared", rx_hwtstamp_cleared),
        E1000_STAT("uncorr_ecc_errors", uncorr_errors),
        E1000_STAT("corr_ecc_errors", corr_errors),
+       E1000_STAT("tx_hwtstamp_timeouts", tx_hwtstamp_timeouts),
 };
 
 #define E1000_GLOBAL_STATS_LEN ARRAY_SIZE(e1000_gstrings_stats)
index 6bd1832e3f3e72636f4d478e278e1a8b0f8f1569..b8d252fcad1843bf16b4208d5bf531dd173c8764 100644 (file)
@@ -1163,6 +1163,12 @@ static void e1000e_tx_hwtstamp_work(struct work_struct *work)
                skb_tstamp_tx(adapter->tx_hwtstamp_skb, &shhwtstamps);
                dev_kfree_skb_any(adapter->tx_hwtstamp_skb);
                adapter->tx_hwtstamp_skb = NULL;
+       } else if (time_after(jiffies, adapter->tx_hwtstamp_start
+                             + adapter->tx_timeout_factor * HZ)) {
+               dev_kfree_skb_any(adapter->tx_hwtstamp_skb);
+               adapter->tx_hwtstamp_skb = NULL;
+               adapter->tx_hwtstamp_timeouts++;
+               e_warn("clearing Tx timestamp hang");
        } else {
                /* reschedule to check later */
                schedule_work(&adapter->tx_hwtstamp_work);
@@ -5567,6 +5573,7 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
                        skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
                        tx_flags |= E1000_TX_FLAGS_HWTSTAMP;
                        adapter->tx_hwtstamp_skb = skb_get(skb);
+                       adapter->tx_hwtstamp_start = jiffies;
                        schedule_work(&adapter->tx_hwtstamp_work);
                } else {
                        skb_tx_timestamp(skb);