|
@@ -662,6 +662,33 @@ static void ixgbe_ptp_clear_tx_timestamp(struct ixgbe_adapter *adapter)
|
|
|
clear_bit_unlock(__IXGBE_PTP_TX_IN_PROGRESS, &adapter->state);
|
|
|
}
|
|
|
|
|
|
+/**
|
|
|
+ * ixgbe_ptp_tx_hang - detect error case where Tx timestamp never finishes
|
|
|
+ * @adapter: private network adapter structure
|
|
|
+ */
|
|
|
+void ixgbe_ptp_tx_hang(struct ixgbe_adapter *adapter)
|
|
|
+{
|
|
|
+ bool timeout = time_is_before_jiffies(adapter->ptp_tx_start +
|
|
|
+ IXGBE_PTP_TX_TIMEOUT);
|
|
|
+
|
|
|
+ if (!adapter->ptp_tx_skb)
|
|
|
+ return;
|
|
|
+
|
|
|
+ if (!test_bit(__IXGBE_PTP_TX_IN_PROGRESS, &adapter->state))
|
|
|
+ return;
|
|
|
+
|
|
|
+ /* If we haven't received a timestamp within the timeout, it is
|
|
|
+ * reasonable to assume that it will never occur, so we can unlock the
|
|
|
+ * timestamp bit when this occurs.
|
|
|
+ */
|
|
|
+ if (timeout) {
|
|
|
+ cancel_work_sync(&adapter->ptp_tx_work);
|
|
|
+ ixgbe_ptp_clear_tx_timestamp(adapter);
|
|
|
+ adapter->tx_hwtstamp_timeouts++;
|
|
|
+ e_warn(drv, "clearing Tx timestamp hang\n");
|
|
|
+ }
|
|
|
+}
|
|
|
+
|
|
|
/**
|
|
|
* ixgbe_ptp_tx_hwtstamp - utility function which checks for TX time stamp
|
|
|
* @adapter: the private adapter struct
|