From: Petr Oros <[email protected]>

ice_ptp_flush_tx_tracker() frees every tracked request, but a request
whose timestamp is still being captured by the PHY at that moment is
freed without touching the PHY entry. The ready bit published shortly
after has no tracked owner, and the PHY does not raise another Tx
timestamp interrupt until every outstanding ready bit is read, so
delivery for the whole quad degrades to the periodic work.

Wait up to 10 ms for in-flight captures to publish their ready bits
before flushing, so the flush clears them together with the rest.

Note that the ice_ptp_flush_tx_tracker() function was introduced along with
the original E810 support, but that device does not have a ready bitmap.
Only later devices (E822, E825, E830) have the bitmap and potential issues
with internal tracking. Thus, skip the wait for E810 by checking the
tx->has_ready_bitmap flag.

Fixes: 10e4b4a3a3e1 ("ice: check Tx timestamp memory register for ready 
timestamps")
Signed-off-by: Petr Oros <[email protected]>
Reviewed-by: Maciek Machnikowski <[email protected]>
Signed-off-by: Jacob Keller <[email protected]>
---
 drivers/net/ethernet/intel/ice/ice_ptp.c | 43 ++++++++++++++++++++++++++++++++
 1 file changed, 43 insertions(+)

diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c 
b/drivers/net/ethernet/intel/ice/ice_ptp.c
index 657cd78ec738..142d9e1c1f2e 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp.c
+++ b/drivers/net/ethernet/intel/ice/ice_ptp.c
@@ -744,6 +744,47 @@ ice_ptp_alloc_tx_tracker(struct ice_ptp_tx *tx)
        return 0;
 }
 
+static bool
+ice_ptp_is_tracker_drained(struct ice_pf *pf, struct ice_ptp_tx *tx)
+{
+       struct ice_hw *hw = &pf->hw;
+       bool pending = false;
+       u64 tstamp_ready;
+       u8 idx;
+
+       /* If HW reset is ongoing, we can't access SBQ */
+       if (hw->reset_ongoing)
+               return true;
+
+       if (ice_get_phy_tx_tstamp_ready(hw, tx->block, &tstamp_ready))
+               return true;
+
+       for_each_set_bit(idx, tx->in_use, tx->len) {
+               if (!(tstamp_ready & BIT_ULL(idx + tx->offset)))
+                       pending = true;
+       }
+
+       return !pending;
+}
+
+static void
+ice_ptp_wait_for_tracker_drain(struct ice_pf *pf, struct ice_ptp_tx *tx)
+{
+       bool drained;
+       int err;
+
+       if (!tx->has_ready_bitmap)
+               return;
+
+       err = read_poll_timeout(ice_ptp_is_tracker_drained,
+                               drained, drained, 500, 10 * USEC_PER_MSEC, 
false,
+                               pf, tx);
+       if (err) {
+               dev_dbg(ice_pf_to_dev(pf), "Timed out waiting for in-flight Tx 
timestamps on block %u\n",
+                       tx->block);
+       }
+}
+
 /**
  * ice_ptp_flush_tx_tracker - Flush any remaining timestamps from the tracker
  * @pf: Board private structure
@@ -760,6 +801,8 @@ ice_ptp_flush_tx_tracker(struct ice_pf *pf, struct 
ice_ptp_tx *tx)
        int err;
        u8 idx;
 
+       ice_ptp_wait_for_tracker_drain(pf, tx);
+
        err = ice_get_phy_tx_tstamp_ready(hw, tx->block, &tstamp_ready);
        if (err) {
                dev_dbg(ice_pf_to_dev(pf), "Failed to get the Tx tstamp ready 
bitmap for block %u, err %d\n",

-- 
2.56.0.rc0.395.gd1f3524e15dc

Reply via email to