Simplify TSYN IRQ processing by moving it to a separate function and
having appropriate behavior per PHY model, instead of multiple
conditions not related to HW, but to specific timestamping modes.

Reviewed-by: Przemek Kitszel <przemyslaw.kits...@intel.com>
Signed-off-by: Karol Kolacinski <karol.kolacin...@intel.com>
---
 drivers/net/ethernet/intel/ice/ice_main.c | 18 +------
 drivers/net/ethernet/intel/ice/ice_ptp.c  | 60 +++++++++++++++++++++++
 drivers/net/ethernet/intel/ice/ice_ptp.h  |  6 +++
 3 files changed, 68 insertions(+), 16 deletions(-)

diff --git a/drivers/net/ethernet/intel/ice/ice_main.c 
b/drivers/net/ethernet/intel/ice/ice_main.c
index e2990993b16f..c4d4993ce9e3 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -3273,22 +3273,8 @@ static irqreturn_t ice_misc_intr(int __always_unused 
irq, void *data)
 
        if (oicr & PFINT_OICR_TSYN_TX_M) {
                ena_mask &= ~PFINT_OICR_TSYN_TX_M;
-               if (ice_pf_state_is_nominal(pf) &&
-                   pf->hw.dev_caps.ts_dev_info.ts_ll_int_read) {
-                       struct ice_ptp_tx *tx = &pf->ptp.port.tx;
-                       unsigned long flags;
-                       u8 idx;
-
-                       spin_lock_irqsave(&tx->lock, flags);
-                       idx = find_next_bit_wrap(tx->in_use, tx->len,
-                                                tx->last_ll_ts_idx_read + 1);
-                       if (idx != tx->len)
-                               ice_ptp_req_tx_single_tstamp(tx, idx);
-                       spin_unlock_irqrestore(&tx->lock, flags);
-               } else if (ice_ptp_pf_handles_tx_interrupt(pf)) {
-                       set_bit(ICE_MISC_THREAD_TX_TSTAMP, pf->misc_thread);
-                       ret = IRQ_WAKE_THREAD;
-               }
+
+               ret = ice_ptp_ts_irq(pf);
        }
 
        if (oicr & PFINT_OICR_TSYN_EVNT_M) {
diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c 
b/drivers/net/ethernet/intel/ice/ice_ptp.c
index 8307fa69daaa..6fae3841bdaa 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp.c
+++ b/drivers/net/ethernet/intel/ice/ice_ptp.c
@@ -2764,6 +2764,66 @@ enum ice_tx_tstamp_work ice_ptp_process_ts(struct ice_pf 
*pf)
        }
 }
 
+/**
+ * ice_ptp_ts_irq - Process the PTP Tx timestamps in IRQ context
+ * @pf: Board private structure
+ *
+ * Returns: IRQ_WAKE_THREAD if Tx timestamp read has to be handled in the 
bottom
+ * half of the interrupt and IRQ_HANDLED otherwise.
+ */
+irqreturn_t ice_ptp_ts_irq(struct ice_pf *pf)
+{
+       struct ice_hw *hw = &pf->hw;
+
+       switch (hw->ptp.phy_model) {
+       case ICE_PHY_E810:
+               /* E810 capable of low latency timestamping with interrupt can
+                * request a single timestamp in the top half and wait for
+                * a second LL TS interrupt from the FW when it's ready.
+                */
+               if (hw->dev_caps.ts_dev_info.ts_ll_int_read) {
+                       struct ice_ptp_tx *tx = &pf->ptp.port.tx;
+                       unsigned long flags;
+                       u8 idx;
+
+                       if (!ice_pf_state_is_nominal(pf))
+                               return IRQ_HANDLED;
+
+                       spin_lock_irqsave(&tx->lock, flags);
+                       idx = find_next_bit_wrap(tx->in_use, tx->len,
+                                                tx->last_ll_ts_idx_read + 1);
+                       if (idx != tx->len)
+                               ice_ptp_req_tx_single_tstamp(tx, idx);
+                       spin_unlock_irqrestore(&tx->lock, flags);
+
+                       return IRQ_HANDLED;
+               }
+               fallthrough; /* non-LL_TS E810 */
+       case ICE_PHY_E82X:
+       case ICE_PHY_ETH56G:
+               /* All other devices process timestamps in the bottom half due
+                * to sleeping or polling.
+                */
+               if (!ice_ptp_pf_handles_tx_interrupt(pf))
+                       return IRQ_HANDLED;
+
+               set_bit(ICE_MISC_THREAD_TX_TSTAMP, pf->misc_thread);
+               return IRQ_WAKE_THREAD;
+       case ICE_PHY_E830:
+               /* E830 can read timestamps in the top half using rd32() */
+               if (ice_ptp_process_ts(pf) == ICE_TX_TSTAMP_WORK_PENDING) {
+                       /* Process outstanding Tx timestamps. If there
+                        * is more work, re-arm the interrupt to trigger again.
+                        */
+                       wr32(hw, PFINT_OICR, PFINT_OICR_TSYN_TX_M);
+                       ice_flush(hw);
+               }
+               return IRQ_HANDLED;
+       default:
+               return IRQ_HANDLED;
+       }
+}
+
 /**
  * ice_ptp_maybe_trigger_tx_interrupt - Trigger Tx timstamp interrupt
  * @pf: Board private structure
diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.h 
b/drivers/net/ethernet/intel/ice/ice_ptp.h
index aaf1ba79aa2e..5b786e972388 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp.h
+++ b/drivers/net/ethernet/intel/ice/ice_ptp.h
@@ -303,6 +303,7 @@ s8 ice_ptp_request_ts(struct ice_ptp_tx *tx, struct sk_buff 
*skb);
 void ice_ptp_req_tx_single_tstamp(struct ice_ptp_tx *tx, u8 idx);
 void ice_ptp_complete_tx_single_tstamp(struct ice_ptp_tx *tx);
 enum ice_tx_tstamp_work ice_ptp_process_ts(struct ice_pf *pf);
+irqreturn_t ice_ptp_ts_irq(struct ice_pf *pf);
 
 u64 ice_ptp_get_rx_hwts(const union ice_32b_rx_flex_desc *rx_desc,
                        const struct ice_pkt_ctx *pkt_ctx);
@@ -341,6 +342,11 @@ static inline bool ice_ptp_process_ts(struct ice_pf *pf)
        return true;
 }
 
+static inline irqreturn_t ice_ptp_ts_irq(struct ice_pf *pf)
+{
+       return IRQ_HANDLED;
+}
+
 static inline u64
 ice_ptp_get_rx_hwts(const union ice_32b_rx_flex_desc *rx_desc,
                    const struct ice_pkt_ctx *pkt_ctx)
-- 
2.45.2

Reply via email to