ice: introduce PTP state machine
authorJacob Keller <jacob.e.keller@intel.com>
Thu, 25 Jan 2024 21:57:49 +0000 (13:57 -0800)
committerPaolo Abeni <pabeni@redhat.com>
Tue, 30 Jan 2024 10:49:03 +0000 (11:49 +0100)
Add PTP state machine so that the driver can correctly identify PTP
state around resets.
When the driver got information about ungraceful reset, PTP was not
prepared for reset and it returned error. When this situation occurs,
prepare PTP before rebuilding its structures.

Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Co-developed-by: Karol Kolacinski <karol.kolacinski@intel.com>
Signed-off-by: Karol Kolacinski <karol.kolacinski@intel.com>
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
Reviewed-by: Simon Horman <horms@kernel.org>
Tested-by: Pucha Himasekhar Reddy <himasekharx.reddy.pucha@intel.com> (A Contingent worker at Intel)
Signed-off-by: Tony Nguyen <anthony.l.nguyen@intel.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
drivers/net/ethernet/intel/ice/ice.h
drivers/net/ethernet/intel/ice/ice_ethtool.c
drivers/net/ethernet/intel/ice/ice_ptp.c
drivers/net/ethernet/intel/ice/ice_ptp.h

index 367b613d92c05d2dc73b0373d9d59c1bff34bc05..97c2a5fb5dbfc9728bb522860626aecd664fb1fe 100644 (file)
@@ -493,7 +493,6 @@ enum ice_pf_flags {
        ICE_FLAG_DCB_ENA,
        ICE_FLAG_FD_ENA,
        ICE_FLAG_PTP_SUPPORTED,         /* PTP is supported by NVM */
-       ICE_FLAG_PTP,                   /* PTP is enabled by software */
        ICE_FLAG_ADV_FEATURES,
        ICE_FLAG_TC_MQPRIO,             /* support for Multi queue TC */
        ICE_FLAG_CLS_FLOWER,
index a19b06f18e400529a4bb1f16131511438f1bde59..55fcf17d503e2d386f64733991cd5f45df74abb3 100644 (file)
@@ -3360,7 +3360,7 @@ ice_get_ts_info(struct net_device *dev, struct ethtool_ts_info *info)
        struct ice_pf *pf = ice_netdev_to_pf(dev);
 
        /* only report timestamping if PTP is enabled */
-       if (!test_bit(ICE_FLAG_PTP, pf->flags))
+       if (pf->ptp.state != ICE_PTP_READY)
                return ethtool_op_get_ts_info(dev, info);
 
        info->so_timestamping = SOF_TIMESTAMPING_TX_SOFTWARE |
index 3b6605c8585ebdb6c0e0131ea6bf4d9d462f7e56..8ed4af219f9b413047868adf0651780db3185e68 100644 (file)
@@ -1430,7 +1430,7 @@ void ice_ptp_link_change(struct ice_pf *pf, u8 port, bool linkup)
        struct ice_ptp_port *ptp_port;
        struct ice_hw *hw = &pf->hw;
 
-       if (!test_bit(ICE_FLAG_PTP, pf->flags))
+       if (pf->ptp.state != ICE_PTP_READY)
                return;
 
        if (WARN_ON_ONCE(port >= ICE_NUM_EXTERNAL_PORTS))
@@ -2162,7 +2162,7 @@ int ice_ptp_get_ts_config(struct ice_pf *pf, struct ifreq *ifr)
 {
        struct hwtstamp_config *config;
 
-       if (!test_bit(ICE_FLAG_PTP, pf->flags))
+       if (pf->ptp.state != ICE_PTP_READY)
                return -EIO;
 
        config = &pf->ptp.tstamp_config;
@@ -2232,7 +2232,7 @@ int ice_ptp_set_ts_config(struct ice_pf *pf, struct ifreq *ifr)
        struct hwtstamp_config config;
        int err;
 
-       if (!test_bit(ICE_FLAG_PTP, pf->flags))
+       if (pf->ptp.state != ICE_PTP_READY)
                return -EAGAIN;
 
        if (copy_from_user(&config, ifr->ifr_data, sizeof(config)))
@@ -2616,7 +2616,7 @@ static void ice_ptp_periodic_work(struct kthread_work *work)
        struct ice_pf *pf = container_of(ptp, struct ice_pf, ptp);
        int err;
 
-       if (!test_bit(ICE_FLAG_PTP, pf->flags))
+       if (pf->ptp.state != ICE_PTP_READY)
                return;
 
        err = ice_ptp_update_cached_phctime(pf);
@@ -2628,6 +2628,42 @@ static void ice_ptp_periodic_work(struct kthread_work *work)
                                   msecs_to_jiffies(err ? 10 : 500));
 }
 
+/**
+ * ice_ptp_prepare_for_reset - Prepare PTP for reset
+ * @pf: Board private structure
+ */
+void ice_ptp_prepare_for_reset(struct ice_pf *pf)
+{
+       struct ice_ptp *ptp = &pf->ptp;
+       u8 src_tmr;
+
+       if (ptp->state != ICE_PTP_READY)
+               return;
+
+       ptp->state = ICE_PTP_RESETTING;
+
+       /* Disable timestamping for both Tx and Rx */
+       ice_ptp_disable_timestamp_mode(pf);
+
+       kthread_cancel_delayed_work_sync(&ptp->work);
+
+       if (test_bit(ICE_PFR_REQ, pf->state))
+               return;
+
+       ice_ptp_release_tx_tracker(pf, &pf->ptp.port.tx);
+
+       /* Disable periodic outputs */
+       ice_ptp_disable_all_clkout(pf);
+
+       src_tmr = ice_get_ptp_src_clock_index(&pf->hw);
+
+       /* Disable source clock */
+       wr32(&pf->hw, GLTSYN_ENA(src_tmr), (u32)~GLTSYN_ENA_TSYN_ENA_M);
+
+       /* Acquire PHC and system timer to restore after reset */
+       ptp->reset_time = ktime_get_real_ns();
+}
+
 /**
  * ice_ptp_reset - Initialize PTP hardware clock support after reset
  * @pf: Board private structure
@@ -2640,6 +2676,14 @@ void ice_ptp_reset(struct ice_pf *pf)
        int err, itr = 1;
        u64 time_diff;
 
+       if (ptp->state == ICE_PTP_READY) {
+               ice_ptp_prepare_for_reset(pf);
+       } else if (ptp->state != ICE_PTP_RESETTING) {
+               err = -EINVAL;
+               dev_err(ice_pf_to_dev(pf), "PTP was not initialized\n");
+               goto err;
+       }
+
        if (test_bit(ICE_PFR_REQ, pf->state) ||
            !ice_pf_src_tmr_owned(pf))
                goto pfr;
@@ -2700,7 +2744,7 @@ pfr:
        if (err)
                goto err;
 
-       set_bit(ICE_FLAG_PTP, pf->flags);
+       ptp->state = ICE_PTP_READY;
 
        /* Restart the PHY timestamping block */
        if (!test_bit(ICE_PFR_REQ, pf->state) &&
@@ -2714,6 +2758,7 @@ pfr:
        return;
 
 err:
+       ptp->state = ICE_PTP_ERROR;
        dev_err(ice_pf_to_dev(pf), "PTP reset failed %d\n", err);
 }
 
@@ -2922,39 +2967,6 @@ int ice_ptp_clock_index(struct ice_pf *pf)
        return clock ? ptp_clock_index(clock) : -1;
 }
 
-/**
- * ice_ptp_prepare_for_reset - Prepare PTP for reset
- * @pf: Board private structure
- */
-void ice_ptp_prepare_for_reset(struct ice_pf *pf)
-{
-       struct ice_ptp *ptp = &pf->ptp;
-       u8 src_tmr;
-
-       clear_bit(ICE_FLAG_PTP, pf->flags);
-
-       /* Disable timestamping for both Tx and Rx */
-       ice_ptp_disable_timestamp_mode(pf);
-
-       kthread_cancel_delayed_work_sync(&ptp->work);
-
-       if (test_bit(ICE_PFR_REQ, pf->state))
-               return;
-
-       ice_ptp_release_tx_tracker(pf, &pf->ptp.port.tx);
-
-       /* Disable periodic outputs */
-       ice_ptp_disable_all_clkout(pf);
-
-       src_tmr = ice_get_ptp_src_clock_index(&pf->hw);
-
-       /* Disable source clock */
-       wr32(&pf->hw, GLTSYN_ENA(src_tmr), (u32)~GLTSYN_ENA_TSYN_ENA_M);
-
-       /* Acquire PHC and system timer to restore after reset */
-       ptp->reset_time = ktime_get_real_ns();
-}
-
 /**
  * ice_ptp_init_owner - Initialize PTP_1588_CLOCK device
  * @pf: Board private structure
@@ -3195,6 +3207,8 @@ void ice_ptp_init(struct ice_pf *pf)
        struct ice_hw *hw = &pf->hw;
        int err;
 
+       ptp->state = ICE_PTP_INITIALIZING;
+
        ice_ptp_init_phy_model(hw);
 
        ice_ptp_init_tx_interrupt_mode(pf);
@@ -3219,12 +3233,13 @@ void ice_ptp_init(struct ice_pf *pf)
        /* Configure initial Tx interrupt settings */
        ice_ptp_cfg_tx_interrupt(pf);
 
-       set_bit(ICE_FLAG_PTP, pf->flags);
-       err = ice_ptp_init_work(pf, ptp);
+       err = ice_ptp_create_auxbus_device(pf);
        if (err)
                goto err;
 
-       err = ice_ptp_create_auxbus_device(pf);
+       ptp->state = ICE_PTP_READY;
+
+       err = ice_ptp_init_work(pf, ptp);
        if (err)
                goto err;
 
@@ -3237,7 +3252,7 @@ err:
                ptp_clock_unregister(ptp->clock);
                pf->ptp.clock = NULL;
        }
-       clear_bit(ICE_FLAG_PTP, pf->flags);
+       ptp->state = ICE_PTP_ERROR;
        dev_err(ice_pf_to_dev(pf), "PTP failed %d\n", err);
 }
 
@@ -3250,9 +3265,11 @@ err:
  */
 void ice_ptp_release(struct ice_pf *pf)
 {
-       if (!test_bit(ICE_FLAG_PTP, pf->flags))
+       if (pf->ptp.state != ICE_PTP_READY)
                return;
 
+       pf->ptp.state = ICE_PTP_UNINIT;
+
        /* Disable timestamping for both Tx and Rx */
        ice_ptp_disable_timestamp_mode(pf);
 
@@ -3260,8 +3277,6 @@ void ice_ptp_release(struct ice_pf *pf)
 
        ice_ptp_release_tx_tracker(pf, &pf->ptp.port.tx);
 
-       clear_bit(ICE_FLAG_PTP, pf->flags);
-
        kthread_cancel_delayed_work_sync(&pf->ptp.work);
 
        ice_ptp_port_phy_stop(&pf->ptp.port);
@@ -3271,6 +3286,9 @@ void ice_ptp_release(struct ice_pf *pf)
                pf->ptp.kworker = NULL;
        }
 
+       if (ice_pf_src_tmr_owned(pf))
+               ice_ptp_unregister_auxbus_driver(pf);
+
        if (!pf->ptp.clock)
                return;
 
@@ -3280,7 +3298,5 @@ void ice_ptp_release(struct ice_pf *pf)
        ptp_clock_unregister(pf->ptp.clock);
        pf->ptp.clock = NULL;
 
-       ice_ptp_unregister_auxbus_driver(pf);
-
        dev_info(ice_pf_to_dev(pf), "Removed PTP clock\n");
 }
index 087dd32d876234565e368ece0b959a0fddb0583c..2457380142e10ce0fa57c43455ce76ae71d1348b 100644 (file)
@@ -203,8 +203,17 @@ struct ice_ptp_port_owner {
 
 #define GLTSYN_TGT_H_IDX_MAX           4
 
+enum ice_ptp_state {
+       ICE_PTP_UNINIT = 0,
+       ICE_PTP_INITIALIZING,
+       ICE_PTP_READY,
+       ICE_PTP_RESETTING,
+       ICE_PTP_ERROR,
+};
+
 /**
  * struct ice_ptp - data used for integrating with CONFIG_PTP_1588_CLOCK
+ * @state: current state of PTP state machine
  * @tx_interrupt_mode: the TX interrupt mode for the PTP clock
  * @port: data for the PHY port initialization procedure
  * @ports_owner: data for the auxiliary driver owner
@@ -227,6 +236,7 @@ struct ice_ptp_port_owner {
  * @late_cached_phc_updates: number of times cached PHC update is late
  */
 struct ice_ptp {
+       enum ice_ptp_state state;
        enum ice_ptp_tx_interrupt tx_interrupt_mode;
        struct ice_ptp_port port;
        struct ice_ptp_port_owner ports_owner;