struct ice_ptp_port *ptp_port;
        bool ts_handled = true;
        struct ice_pf *pf;
+       struct ice_hw *hw;
+       u64 tstamp_ready;
+       int err;
        u8 idx;
 
        if (!tx->init)
 
        ptp_port = container_of(tx, struct ice_ptp_port, tx);
        pf = ptp_port_to_pf(ptp_port);
+       hw = &pf->hw;
+
+       /* Read the Tx ready status first */
+       err = ice_get_phy_tx_tstamp_ready(hw, tx->block, &tstamp_ready);
+       if (err)
+               return false;
 
        for_each_set_bit(idx, tx->in_use, tx->len) {
                struct skb_shared_hwtstamps shhwtstamps = {};
                u64 raw_tstamp = 0, tstamp;
                bool drop_ts = false;
                struct sk_buff *skb;
-               int err;
 
                /* Drop packets which have waited for more than 2 seconds */
                if (time_is_before_jiffies(tx->tstamps[idx].start + 2 * HZ)) {
 
                        /* Count the number of Tx timestamps that timed out */
                        pf->ptp.tx_hwtstamp_timeouts++;
+               }
 
-                       goto skip_ts_read;
+               /* Only read a timestamp from the PHY if its marked as ready
+                * by the tstamp_ready register. This avoids unnecessary
+                * reading of timestamps which are not yet valid. This is
+                * important as we must read all timestamps which are valid
+                * and only timestamps which are valid during each interrupt.
+                * If we do not, the hardware logic for generating a new
+                * interrupt can get stuck on some devices.
+                */
+               if (!(tstamp_ready & BIT_ULL(phy_idx))) {
+                       if (drop_ts)
+                               goto skip_ts_read;
+
+                       continue;
                }
 
                ice_trace(tx_tstamp_fw_req, tx->tstamps[idx].skb, idx);
 
-               err = ice_read_phy_tstamp(&pf->hw, tx->block, phy_idx,
-                                         &raw_tstamp);
+               err = ice_read_phy_tstamp(hw, tx->block, phy_idx, &raw_tstamp);
                if (err)
                        continue;
 
                ice_trace(tx_tstamp_fw_done, tx->tstamps[idx].skb, idx);
 
-               /* Check if the timestamp is invalid or stale */
-               if (!(raw_tstamp & ICE_PTP_TS_VALID) ||
+               /* For PHYs which don't implement a proper timestamp ready
+                * bitmap, verify that the timestamp value is different
+                * from the last cached timestamp. If it is not, skip this for
+                * now assuming it hasn't yet been captured by hardware.
+                */
+               if (!drop_ts && tx->verify_cached &&
                    raw_tstamp == tx->tstamps[idx].cached_tstamp)
                        continue;
 
+               /* Discard any timestamp value without the valid bit set */
+               if (!(raw_tstamp & ICE_PTP_TS_VALID))
+                       drop_ts = true;
+
 skip_ts_read:
                spin_lock(&tx->lock);
-               if (raw_tstamp)
+               if (tx->verify_cached && raw_tstamp)
                        tx->tstamps[idx].cached_tstamp = raw_tstamp;
                clear_bit(idx, tx->in_use);
                skb = tx->tstamps[idx].skb;
        tx->block = port / ICE_PORTS_PER_QUAD;
        tx->offset = (port % ICE_PORTS_PER_QUAD) * INDEX_PER_PORT_E822;
        tx->len = INDEX_PER_PORT_E822;
+       tx->verify_cached = 0;
 
        return ice_ptp_alloc_tx_tracker(tx);
 }
        tx->block = pf->hw.port_info->lport;
        tx->offset = 0;
        tx->len = INDEX_PER_PORT_E810;
+       /* The E810 PHY does not provide a timestamp ready bitmap. Instead,
+        * verify new timestamps against cached copy of the last read
+        * timestamp.
+        */
+       tx->verify_cached = 1;
 
        return ice_ptp_alloc_tx_tracker(tx);
 }
 
  * we discard old requests that were not fulfilled within a 2 second time
  * window.
  * Timestamp values in the PHY are read only and do not get cleared except at
- * hardware reset or when a new timestamp value is captured. The cached_tstamp
- * field is used to detect the case where a new timestamp has not yet been
- * captured, ensuring that we avoid sending stale timestamp data to the stack.
+ * hardware reset or when a new timestamp value is captured.
+ *
+ * Some PHY types do not provide a "ready" bitmap indicating which timestamp
+ * indexes are valid. In these cases, we use a cached_tstamp to keep track of
+ * the last timestamp we read for a given index. If the current timestamp
+ * value is the same as the cached value, we assume a new timestamp hasn't
+ * been captured. This avoids reporting stale timestamps to the stack. This is
+ * only done if the verify_cached flag is set in ice_ptp_tx structure.
  */
 struct ice_tx_tstamp {
        struct sk_buff *skb;
  * @init: if true, the tracker is initialized;
  * @calibrating: if true, the PHY is calibrating the Tx offset. During this
  *               window, timestamps are temporarily disabled.
+ * @verify_cached: if true, verify new timestamp differs from last read value
  */
 struct ice_ptp_tx {
        spinlock_t lock; /* lock protecting in_use bitmap */
        u8 block;
        u8 offset;
        u8 len;
-       u8 init;
-       u8 calibrating;
+       u8 init : 1;
+       u8 calibrating : 1;
+       u8 verify_cached : 1;
 };
 
 /* Quad and port information for initializing timestamp blocks */
 
        return 0;
 }
 
+/**
+ * ice_get_phy_tx_tstamp_ready_e822 - Read Tx memory status register
+ * @hw: pointer to the HW struct
+ * @quad: the timestamp quad to read from
+ * @tstamp_ready: contents of the Tx memory status register
+ *
+ * Read the Q_REG_TX_MEMORY_STATUS register indicating which timestamps in
+ * the PHY are ready. A set bit means the corresponding timestamp is valid and
+ * ready to be captured from the PHY timestamp block.
+ */
+static int
+ice_get_phy_tx_tstamp_ready_e822(struct ice_hw *hw, u8 quad, u64 *tstamp_ready)
+{
+       u32 hi, lo;
+       int err;
+
+       err = ice_read_quad_reg_e822(hw, quad, Q_REG_TX_MEMORY_STATUS_U, &hi);
+       if (err) {
+               ice_debug(hw, ICE_DBG_PTP, "Failed to read TX_MEMORY_STATUS_U for quad %u, err %d\n",
+                         quad, err);
+               return err;
+       }
+
+       err = ice_read_quad_reg_e822(hw, quad, Q_REG_TX_MEMORY_STATUS_L, &lo);
+       if (err) {
+               ice_debug(hw, ICE_DBG_PTP, "Failed to read TX_MEMORY_STATUS_L for quad %u, err %d\n",
+                         quad, err);
+               return err;
+       }
+
+       *tstamp_ready = (u64)hi << 32 | (u64)lo;
+
+       return 0;
+}
+
 /* E810 functions
  *
  * The following functions operate on the E810 series devices which use
                return ice_clear_phy_tstamp_e822(hw, block, idx);
 }
 
+/**
+ * ice_get_phy_tx_tstamp_ready_e810 - Read Tx memory status register
+ * @hw: pointer to the HW struct
+ * @port: the PHY port to read
+ * @tstamp_ready: contents of the Tx memory status register
+ *
+ * E810 devices do not use a Tx memory status register. Instead simply
+ * indicate that all timestamps are currently ready.
+ */
+static int
+ice_get_phy_tx_tstamp_ready_e810(struct ice_hw *hw, u8 port, u64 *tstamp_ready)
+{
+       *tstamp_ready = 0xFFFFFFFFFFFFFFFF;
+       return 0;
+}
+
 /* E810T SMA functions
  *
  * The following functions operate specifically on E810T hardware and are used
        else
                return ice_ptp_init_phc_e822(hw);
 }
+
+/**
+ * ice_get_phy_tx_tstamp_ready - Read PHY Tx memory status indication
+ * @hw: pointer to the HW struct
+ * @block: the timestamp block to check
+ * @tstamp_ready: storage for the PHY Tx memory status information
+ *
+ * Check the PHY for Tx timestamp memory status. This reports a 64 bit value
+ * which indicates which timestamps in the block may be captured. A set bit
+ * means the timestamp can be read. An unset bit means the timestamp is not
+ * ready and software should avoid reading the register.
+ */
+int ice_get_phy_tx_tstamp_ready(struct ice_hw *hw, u8 block, u64 *tstamp_ready)
+{
+       if (ice_is_e810(hw))
+               return ice_get_phy_tx_tstamp_ready_e810(hw, block,
+                                                       tstamp_ready);
+       else
+               return ice_get_phy_tx_tstamp_ready_e822(hw, block,
+                                                       tstamp_ready);
+}
 
 int ice_clear_phy_tstamp(struct ice_hw *hw, u8 block, u8 idx);
 void ice_ptp_reset_ts_memory(struct ice_hw *hw);
 int ice_ptp_init_phc(struct ice_hw *hw);
+int ice_get_phy_tx_tstamp_ready(struct ice_hw *hw, u8 block, u64 *tstamp_ready);
 
 /* E822 family functions */
 int ice_read_phy_reg_e822(struct ice_hw *hw, u8 port, u16 offset, u32 *val);