aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMatthew Vick <matthew.vick@intel.com>2012-12-13 02:20:34 -0500
committerJeff Kirsher <jeffrey.t.kirsher@intel.com>2013-01-18 07:56:11 -0500
commit428f1f715131ea5ae32e29502541ce007f556b5b (patch)
tree5f9ca421ac948de9a6119870d7e2f7a4867b1132
parentb66e2397cd277cf2bec2628b3ed35865df2609e5 (diff)
igb: Add timeout for PTP Tx work item
When transmitting a packet that must return a Tx timestamp, a work item gets scheduled to poll for the Tx timestamp being completed in hardware. Add a timeout on this work item of 15 seconds from when the driver gets the skb, after which it will stop polling. Report via stats and system log if this occurs. Cc: Richard Cochran <richardcochran@gmail.com> Signed-off-by: Matthew Vick <matthew.vick@intel.com> Acked-by: Jacob Keller <Jacob.e.keller@intel.com> Tested-by: Aaron Brown <aaron.f.brown@intel.com> Signed-off-by: Jeff Kirsher <jeffrey.t.kirsher@intel.com>
-rw-r--r--drivers/net/ethernet/intel/igb/igb.h2
-rw-r--r--drivers/net/ethernet/intel/igb/igb_ethtool.c1
-rw-r--r--drivers/net/ethernet/intel/igb/igb_main.c1
-rw-r--r--drivers/net/ethernet/intel/igb/igb_ptp.c10
4 files changed, 14 insertions, 0 deletions
diff --git a/drivers/net/ethernet/intel/igb/igb.h b/drivers/net/ethernet/intel/igb/igb.h
index 8372c002102c..8c6f59d95b20 100644
--- a/drivers/net/ethernet/intel/igb/igb.h
+++ b/drivers/net/ethernet/intel/igb/igb.h
@@ -414,9 +414,11 @@ struct igb_adapter {
414 struct delayed_work ptp_overflow_work; 414 struct delayed_work ptp_overflow_work;
415 struct work_struct ptp_tx_work; 415 struct work_struct ptp_tx_work;
416 struct sk_buff *ptp_tx_skb; 416 struct sk_buff *ptp_tx_skb;
417 unsigned long ptp_tx_start;
417 spinlock_t tmreg_lock; 418 spinlock_t tmreg_lock;
418 struct cyclecounter cc; 419 struct cyclecounter cc;
419 struct timecounter tc; 420 struct timecounter tc;
421 u32 tx_hwtstamp_timeouts;
420 422
421 char fw_version[32]; 423 char fw_version[32];
422#ifdef CONFIG_IGB_HWMON 424#ifdef CONFIG_IGB_HWMON
diff --git a/drivers/net/ethernet/intel/igb/igb_ethtool.c b/drivers/net/ethernet/intel/igb/igb_ethtool.c
index 61803032fdd3..6f2579c50d8e 100644
--- a/drivers/net/ethernet/intel/igb/igb_ethtool.c
+++ b/drivers/net/ethernet/intel/igb/igb_ethtool.c
@@ -92,6 +92,7 @@ static const struct igb_stats igb_gstrings_stats[] = {
92 IGB_STAT("os2bmc_tx_by_bmc", stats.b2ospc), 92 IGB_STAT("os2bmc_tx_by_bmc", stats.b2ospc),
93 IGB_STAT("os2bmc_tx_by_host", stats.o2bspc), 93 IGB_STAT("os2bmc_tx_by_host", stats.o2bspc),
94 IGB_STAT("os2bmc_rx_by_host", stats.b2ogprc), 94 IGB_STAT("os2bmc_rx_by_host", stats.b2ogprc),
95 IGB_STAT("tx_hwtstamp_timeouts", tx_hwtstamp_timeouts),
95}; 96};
96 97
97#define IGB_NETDEV_STAT(_net_stat) { \ 98#define IGB_NETDEV_STAT(_net_stat) { \
diff --git a/drivers/net/ethernet/intel/igb/igb_main.c b/drivers/net/ethernet/intel/igb/igb_main.c
index 9dd3da540cd0..9540a814a225 100644
--- a/drivers/net/ethernet/intel/igb/igb_main.c
+++ b/drivers/net/ethernet/intel/igb/igb_main.c
@@ -4618,6 +4618,7 @@ netdev_tx_t igb_xmit_frame_ring(struct sk_buff *skb,
4618 tx_flags |= IGB_TX_FLAGS_TSTAMP; 4618 tx_flags |= IGB_TX_FLAGS_TSTAMP;
4619 4619
4620 adapter->ptp_tx_skb = skb_get(skb); 4620 adapter->ptp_tx_skb = skb_get(skb);
4621 adapter->ptp_tx_start = jiffies;
4621 if (adapter->hw.mac.type == e1000_82576) 4622 if (adapter->hw.mac.type == e1000_82576)
4622 schedule_work(&adapter->ptp_tx_work); 4623 schedule_work(&adapter->ptp_tx_work);
4623 } 4624 }
diff --git a/drivers/net/ethernet/intel/igb/igb_ptp.c b/drivers/net/ethernet/intel/igb/igb_ptp.c
index ab3429729bde..086af4683544 100644
--- a/drivers/net/ethernet/intel/igb/igb_ptp.c
+++ b/drivers/net/ethernet/intel/igb/igb_ptp.c
@@ -70,6 +70,7 @@
70 */ 70 */
71 71
72#define IGB_SYSTIM_OVERFLOW_PERIOD (HZ * 60 * 9) 72#define IGB_SYSTIM_OVERFLOW_PERIOD (HZ * 60 * 9)
73#define IGB_PTP_TX_TIMEOUT (HZ * 15)
73#define INCPERIOD_82576 (1 << E1000_TIMINCA_16NS_SHIFT) 74#define INCPERIOD_82576 (1 << E1000_TIMINCA_16NS_SHIFT)
74#define INCVALUE_82576_MASK ((1 << E1000_TIMINCA_16NS_SHIFT) - 1) 75#define INCVALUE_82576_MASK ((1 << E1000_TIMINCA_16NS_SHIFT) - 1)
75#define INCVALUE_82576 (16 << IGB_82576_TSYNC_SHIFT) 76#define INCVALUE_82576 (16 << IGB_82576_TSYNC_SHIFT)
@@ -396,6 +397,15 @@ void igb_ptp_tx_work(struct work_struct *work)
396 if (!adapter->ptp_tx_skb) 397 if (!adapter->ptp_tx_skb)
397 return; 398 return;
398 399
400 if (time_is_before_jiffies(adapter->ptp_tx_start +
401 IGB_PTP_TX_TIMEOUT)) {
402 dev_kfree_skb_any(adapter->ptp_tx_skb);
403 adapter->ptp_tx_skb = NULL;
404 adapter->tx_hwtstamp_timeouts++;
405 dev_warn(&adapter->pdev->dev, "clearing Tx timestamp hang");
406 return;
407 }
408
399 tsynctxctl = rd32(E1000_TSYNCTXCTL); 409 tsynctxctl = rd32(E1000_TSYNCTXCTL);
400 if (tsynctxctl & E1000_TSYNCTXCTL_VALID) 410 if (tsynctxctl & E1000_TSYNCTXCTL_VALID)
401 igb_ptp_tx_hwtstamp(adapter); 411 igb_ptp_tx_hwtstamp(adapter);