Donate to e Foundation | Murena handsets with /e/OS | Own a part of Murena! Learn more

Commit 59c871c5 authored by Jakub Kicinski's avatar Jakub Kicinski Committed by Jeff Kirsher
Browse files

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: default avatarJakub Kicinski <kubakici@wp.pl>
Tested-by: default avatarAaron Brown <aaron.f.brown@intel.com>
Signed-off-by: default avatarJeff Kirsher <jeffrey.t.kirsher@intel.com>
parent 13c2884f
Loading
Loading
Loading
Loading
+2 −0
Original line number Original line Diff line number Diff line
@@ -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 {
	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;
+1 −0
Original line number Original line Diff line number Diff line
@@ -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)
+7 −0
Original line number Original line Diff line number Diff line
@@ -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,
			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);