提交 59c871c5 编写于 作者: J Jakub Kicinski 提交者: Jeff Kirsher

e1000e: add timeout for TX HW time stamping work

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: NJakub Kicinski <kubakici@wp.pl>
Tested-by: NAaron Brown <aaron.f.brown@intel.com>
Signed-off-by: NJeff Kirsher <jeffrey.t.kirsher@intel.com>
上级 13c2884f
...@@ -262,6 +262,7 @@ struct e1000_adapter { ...@@ -262,6 +262,7 @@ struct e1000_adapter {
u32 tx_head_addr; u32 tx_head_addr;
u32 tx_fifo_size; u32 tx_fifo_size;
u32 tx_dma_failed; u32 tx_dma_failed;
u32 tx_hwtstamp_timeouts;
/* Rx */ /* Rx */
bool (*clean_rx) (struct e1000_ring *ring, int *work_done, bool (*clean_rx) (struct e1000_ring *ring, int *work_done,
...@@ -334,6 +335,7 @@ struct e1000_adapter { ...@@ -334,6 +335,7 @@ struct e1000_adapter {
struct hwtstamp_config hwtstamp_config; struct hwtstamp_config hwtstamp_config;
struct delayed_work systim_overflow_work; struct delayed_work systim_overflow_work;
struct sk_buff *tx_hwtstamp_skb; struct sk_buff *tx_hwtstamp_skb;
unsigned long tx_hwtstamp_start;
struct work_struct tx_hwtstamp_work; struct work_struct tx_hwtstamp_work;
spinlock_t systim_lock; /* protects SYSTIML/H regsters */ spinlock_t systim_lock; /* protects SYSTIML/H regsters */
struct cyclecounter cc; struct cyclecounter cc;
......
...@@ -104,6 +104,7 @@ static const struct e1000_stats e1000_gstrings_stats[] = { ...@@ -104,6 +104,7 @@ static const struct e1000_stats e1000_gstrings_stats[] = {
E1000_STAT("rx_hwtstamp_cleared", rx_hwtstamp_cleared), E1000_STAT("rx_hwtstamp_cleared", rx_hwtstamp_cleared),
E1000_STAT("uncorr_ecc_errors", uncorr_errors), E1000_STAT("uncorr_ecc_errors", uncorr_errors),
E1000_STAT("corr_ecc_errors", corr_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) #define E1000_GLOBAL_STATS_LEN ARRAY_SIZE(e1000_gstrings_stats)
......
...@@ -1163,6 +1163,12 @@ static void e1000e_tx_hwtstamp_work(struct work_struct *work) ...@@ -1163,6 +1163,12 @@ static void e1000e_tx_hwtstamp_work(struct work_struct *work)
skb_tstamp_tx(adapter->tx_hwtstamp_skb, &shhwtstamps); skb_tstamp_tx(adapter->tx_hwtstamp_skb, &shhwtstamps);
dev_kfree_skb_any(adapter->tx_hwtstamp_skb); dev_kfree_skb_any(adapter->tx_hwtstamp_skb);
adapter->tx_hwtstamp_skb = NULL; 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 { } else {
/* reschedule to check later */ /* reschedule to check later */
schedule_work(&adapter->tx_hwtstamp_work); schedule_work(&adapter->tx_hwtstamp_work);
...@@ -5567,6 +5573,7 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb, ...@@ -5567,6 +5573,7 @@ static netdev_tx_t e1000_xmit_frame(struct sk_buff *skb,
skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS; skb_shinfo(skb)->tx_flags |= SKBTX_IN_PROGRESS;
tx_flags |= E1000_TX_FLAGS_HWTSTAMP; tx_flags |= E1000_TX_FLAGS_HWTSTAMP;
adapter->tx_hwtstamp_skb = skb_get(skb); adapter->tx_hwtstamp_skb = skb_get(skb);
adapter->tx_hwtstamp_start = jiffies;
schedule_work(&adapter->tx_hwtstamp_work); schedule_work(&adapter->tx_hwtstamp_work);
} else { } else {
skb_tx_timestamp(skb); skb_tx_timestamp(skb);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册