diff mbox series

[intel-next] ice: Fix E810 PTP reset flow

Message ID 20211214125149.460499-1-karol.kolacinski@intel.com
State Superseded
Headers show
Series [intel-next] ice: Fix E810 PTP reset flow | expand

Commit Message

Karol Kolacinski Dec. 14, 2021, 12:51 p.m. UTC
The PF reset does not reset PHC and PHY clocks so it's unnecessary to
stop them and reinitialize after the reset.
Configuring timestamping changes the VSI fields so it needs to be
performed after VSIs are initialized, which was not done in case of a
reset.

Signed-off-by: Karol Kolacinski <karol.kolacinski@intel.com>
---
 drivers/net/ethernet/intel/ice/ice_main.c |   7 +-
 drivers/net/ethernet/intel/ice/ice_ptp.c  | 200 ++++++++++++++++++----
 drivers/net/ethernet/intel/ice/ice_ptp.h  |   8 +
 3 files changed, 180 insertions(+), 35 deletions(-)

Comments

kernel test robot Dec. 14, 2021, 6:05 p.m. UTC | #1
Hi Karol,

Thank you for the patch! Yet something to improve:

[auto build test ERROR on v5.16-rc5]
[also build test ERROR on next-20211213]
[cannot apply to tnguy-next-queue/dev-queue]
[If your patch is applied to the wrong git tree, kindly drop us a note.
And when submitting patch, we suggest to use '--base' as documented in
https://git-scm.com/docs/git-format-patch]

url:    https://github.com/0day-ci/linux/commits/Karol-Kolacinski/ice-Fix-E810-PTP-reset-flow/20211214-205421
base:    2585cf9dfaaddf00b069673f27bb3f8530e2039c
config: arc-allyesconfig (https://download.01.org/0day-ci/archive/20211215/202112150216.KjZRqhcv-lkp@intel.com/config)
compiler: arceb-elf-gcc (GCC) 11.2.0
reproduce (this is a W=1 build):
        wget https://raw.githubusercontent.com/intel/lkp-tests/master/sbin/make.cross -O ~/bin/make.cross
        chmod +x ~/bin/make.cross
        # https://github.com/0day-ci/linux/commit/b0b4ffaf89f2043ff019a735373e6cf0b9439683
        git remote add linux-review https://github.com/0day-ci/linux
        git fetch --no-tags linux-review Karol-Kolacinski/ice-Fix-E810-PTP-reset-flow/20211214-205421
        git checkout b0b4ffaf89f2043ff019a735373e6cf0b9439683
        # save the config file to linux build tree
        mkdir build_dir
        COMPILER_INSTALL_PATH=$HOME/0day COMPILER=gcc-11.2.0 make.cross O=build_dir ARCH=arc SHELL=/bin/bash

If you fix the issue, kindly add following tag as appropriate
Reported-by: kernel test robot <lkp@intel.com>

All errors (new ones prefixed by >>):

   drivers/net/ethernet/intel/ice/ice_ptp.c: In function 'ice_ptp_reset':
>> drivers/net/ethernet/intel/ice/ice_ptp.c:1792:22: error: 'hw' undeclared (first use in this function)
    1792 |         u8 src_idx = hw->func_caps.ts_func_info.tmr_index_owned;
         |                      ^~
   drivers/net/ethernet/intel/ice/ice_ptp.c:1792:22: note: each undeclared identifier is reported only once for each function it appears in
>> drivers/net/ethernet/intel/ice/ice_ptp.c:1799:22: error: '__ICE_PFR_REQ' undeclared (first use in this function); did you mean 'ICE_PFR_REQ'?
    1799 |         if (test_bit(__ICE_PFR_REQ, pf->state))
         |                      ^~~~~~~~~~~~~
         |                      ICE_PFR_REQ
   drivers/net/ethernet/intel/ice/ice_ptp.c: In function 'ice_ptp_prepare_for_reset':
   drivers/net/ethernet/intel/ice/ice_ptp.c:1883:22: error: '__ICE_PFR_REQ' undeclared (first use in this function); did you mean 'ICE_PFR_REQ'?
    1883 |         if (test_bit(__ICE_PFR_REQ, pf->state))
         |                      ^~~~~~~~~~~~~
         |                      ICE_PFR_REQ


vim +/hw +1792 drivers/net/ethernet/intel/ice/ice_ptp.c

  1785	
  1786	/**
  1787	 * ice_ptp_reset - Initialize PTP hardware clock support after reset
  1788	 * @pf: Board private structure
  1789	 */
  1790	void ice_ptp_reset(struct ice_pf *pf)
  1791	{
> 1792		u8 src_idx = hw->func_caps.ts_func_info.tmr_index_owned;
  1793		struct ice_ptp *ptp = &pf->ptp;
  1794		struct ice_hw *hw = &pf->hw;
  1795		struct timespec64 ts;
  1796		int err = 1;
  1797		u64 time_diff;
  1798	
> 1799		if (test_bit(__ICE_PFR_REQ, pf->state))
  1800			goto pfr;
  1801	
  1802		wr32(hw, GLTSYN_SYNC_DLAY, 0);
  1803	
  1804		/* Enable source clocks */
  1805		wr32(hw, GLTSYN_ENA(src_idx), GLTSYN_ENA_TSYN_ENA_M);
  1806	
  1807		/* Enable PHY time sync */
  1808		err = ice_ptp_init_phy_e810(hw);
  1809		if (err)
  1810			goto err;
  1811	
  1812		/* Clear event status indications for auxiliary pins */
  1813		(void)rd32(hw, GLTSYN_STAT(src_idx));
  1814	
  1815		/* Acquire the global hardware lock */
  1816		if (!ice_ptp_lock(hw)) {
  1817			err = -EBUSY;
  1818			goto err;
  1819		}
  1820	
  1821		/* Write the increment time value to PHY and LAN */
  1822		err = ice_ptp_write_incval(hw, ICE_PTP_NOMINAL_INCVAL_E810);
  1823		if (err) {
  1824			ice_ptp_unlock(hw);
  1825			goto err;
  1826		}
  1827	
  1828		/* Write the initial Time value to PHY and LAN using the cached PHC
  1829		 * time before the reset and time difference between stopping and
  1830		 * starting the clock.
  1831		 */
  1832		if (ptp->cached_phc_time) {
  1833			time_diff = ktime_get_real_ns() - ptp->reset_time;
  1834			ts = ns_to_timespec64(ptp->cached_phc_time + time_diff);
  1835		} else {
  1836			ts = ktime_to_timespec64(ktime_get_real());
  1837		}
  1838		err = ice_ptp_write_init(pf, &ts);
  1839		if (err) {
  1840			ice_ptp_unlock(hw);
  1841			goto err;
  1842		}
  1843	
  1844		/* Release the global hardware lock */
  1845		ice_ptp_unlock(hw);
  1846	
  1847	pfr:
  1848		/* Init Tx structures */
  1849		if (ice_is_e810(&pf->hw))
  1850			err = ice_ptp_init_tx_e810(pf, &ptp->port.tx);
  1851		if (err)
  1852			goto err;
  1853	
  1854		set_bit(ICE_FLAG_PTP, pf->flags);
  1855	
  1856		/* Start periodic work going */
  1857		kthread_queue_delayed_work(ptp->kworker, &ptp->work, 0);
  1858	
  1859		dev_info(ice_pf_to_dev(pf), "PTP reset successful\n");
  1860		return;
  1861	
  1862	err:
  1863		dev_err(ice_pf_to_dev(pf), "PTP reset failed %d\n", err);
  1864	}
  1865	

---
0-DAY CI Kernel Test Service, Intel Corporation
https://lists.01.org/hyperkitty/list/kbuild-all@lists.01.org
diff mbox series

Patch

diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index a3ce54a78859..dc1c3d8e7272 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -539,7 +539,7 @@  ice_prepare_for_reset(struct ice_pf *pf, enum ice_reset_req reset_type)
 	ice_pf_dis_all_vsi(pf, false);
 
 	if (test_bit(ICE_FLAG_PTP_SUPPORTED, pf->flags))
-		ice_ptp_release(pf);
+		ice_ptp_prepare_for_reset(pf);
 
 	if (hw->port_info)
 		ice_sched_clear_port(hw->port_info);
@@ -6728,7 +6728,7 @@  static void ice_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type)
 	 * fail.
 	 */
 	if (test_bit(ICE_FLAG_PTP_SUPPORTED, pf->flags))
-		ice_ptp_init(pf);
+		ice_ptp_reset(pf);
 
 	/* rebuild PF VSI */
 	err = ice_vsi_rebuild_by_type(pf, ICE_VSI_PF);
@@ -6737,6 +6737,9 @@  static void ice_rebuild(struct ice_pf *pf, enum ice_reset_req reset_type)
 		goto err_vsi_rebuild;
 	}
 
+	/* configure PTP timestamping after VSI rebuild */
+		ice_ptp_cfg_timestamp(pf, false);
+
 	err = ice_vsi_rebuild_by_type(pf, ICE_VSI_SWITCHDEV_CTRL);
 	if (err) {
 		dev_err(dev, "Switchdev CTRL VSI rebuild failed: %d\n", err);
diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c
index bf7247c6f58e..450a4cbf9cef 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp.c
+++ b/drivers/net/ethernet/intel/ice/ice_ptp.c
@@ -313,7 +313,7 @@  static void ice_set_rx_tstamp(struct ice_pf *pf, bool on)
  * This function will configure timestamping during PTP initialization
  * and deinitialization
  */
-static void ice_ptp_cfg_timestamp(struct ice_pf *pf, bool ena)
+void ice_ptp_cfg_timestamp(struct ice_pf *pf, bool ena)
 {
 	ice_set_tx_tstamp(pf, ena);
 	ice_set_rx_tstamp(pf, ena);
@@ -1783,6 +1783,120 @@  static void ice_ptp_periodic_work(struct kthread_work *work)
 				   msecs_to_jiffies(500));
 }
 
+/**
+ * ice_ptp_reset - Initialize PTP hardware clock support after reset
+ * @pf: Board private structure
+ */
+void ice_ptp_reset(struct ice_pf *pf)
+{
+	u8 src_idx = hw->func_caps.ts_func_info.tmr_index_owned;
+	struct ice_ptp *ptp = &pf->ptp;
+	struct ice_hw *hw = &pf->hw;
+	struct timespec64 ts;
+	int err = 1;
+	u64 time_diff;
+
+	if (test_bit(__ICE_PFR_REQ, pf->state))
+		goto pfr;
+
+	wr32(hw, GLTSYN_SYNC_DLAY, 0);
+
+	/* Enable source clocks */
+	wr32(hw, GLTSYN_ENA(src_idx), GLTSYN_ENA_TSYN_ENA_M);
+
+	/* Enable PHY time sync */
+	err = ice_ptp_init_phy_e810(hw);
+	if (err)
+		goto err;
+
+	/* Clear event status indications for auxiliary pins */
+	(void)rd32(hw, GLTSYN_STAT(src_idx));
+
+	/* Acquire the global hardware lock */
+	if (!ice_ptp_lock(hw)) {
+		err = -EBUSY;
+		goto err;
+	}
+
+	/* Write the increment time value to PHY and LAN */
+	err = ice_ptp_write_incval(hw, ICE_PTP_NOMINAL_INCVAL_E810);
+	if (err) {
+		ice_ptp_unlock(hw);
+		goto err;
+	}
+
+	/* Write the initial Time value to PHY and LAN using the cached PHC
+	 * time before the reset and time difference between stopping and
+	 * starting the clock.
+	 */
+	if (ptp->cached_phc_time) {
+		time_diff = ktime_get_real_ns() - ptp->reset_time;
+		ts = ns_to_timespec64(ptp->cached_phc_time + time_diff);
+	} else {
+		ts = ktime_to_timespec64(ktime_get_real());
+	}
+	err = ice_ptp_write_init(pf, &ts);
+	if (err) {
+		ice_ptp_unlock(hw);
+		goto err;
+	}
+
+	/* Release the global hardware lock */
+	ice_ptp_unlock(hw);
+
+pfr:
+	/* Init Tx structures */
+	if (ice_is_e810(&pf->hw))
+		err = ice_ptp_init_tx_e810(pf, &ptp->port.tx);
+	if (err)
+		goto err;
+
+	set_bit(ICE_FLAG_PTP, pf->flags);
+
+	/* Start periodic work going */
+	kthread_queue_delayed_work(ptp->kworker, &ptp->work, 0);
+
+	dev_info(ice_pf_to_dev(pf), "PTP reset successful\n");
+	return;
+
+err:
+	dev_err(ice_pf_to_dev(pf), "PTP reset failed %d\n", err);
+}
+
+/**
+ * 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_cfg_timestamp(pf, false);
+
+	kthread_cancel_delayed_work_sync(&ptp->work);
+	kthread_cancel_work_sync(&ptp->extts_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
@@ -1793,7 +1907,6 @@  static void ice_ptp_periodic_work(struct kthread_work *work)
  */
 static int ice_ptp_init_owner(struct ice_pf *pf)
 {
-	struct device *dev = ice_pf_to_dev(pf);
 	struct ice_hw *hw = &pf->hw;
 	struct timespec64 ts;
 	u8 src_idx;
@@ -1852,11 +1965,48 @@  static int ice_ptp_init_owner(struct ice_pf *pf)
 err_clk:
 	pf->ptp.clock = NULL;
 err_exit:
-	dev_err(dev, "PTP failed to register clock, err %d\n", err);
-
 	return err;
 }
 
+/**
+ * ice_ptp_init_work - Initialize PTP work threads
+ * @pf: Board private structure
+ * @ptp: PF PTP structure
+ */
+static int ice_ptp_init_work(struct ice_pf *pf, struct ice_ptp *ptp)
+{
+	struct kthread_worker *kworker;
+
+	/* Initialize work functions */
+	kthread_init_delayed_work(&ptp->work, ice_ptp_periodic_work);
+	kthread_init_work(&ptp->extts_work, ice_ptp_extts_work);
+
+	/* Allocate a kworker for handling work required for the ports
+	 * connected to the PTP hardware clock.
+	 */
+	kworker = kthread_create_worker(0, "ice-ptp-%s",
+					dev_name(ice_pf_to_dev(pf)));
+	if (IS_ERR(kworker))
+		return PTR_ERR(kworker);
+
+	ptp->kworker = kworker;
+
+	/* Start periodic work going */
+	kthread_queue_delayed_work(ptp->kworker, &ptp->work, 0);
+
+	return 0;
+}
+
+/**
+ * ice_ptp_init_port - Initialize PTP port structure
+ * @pf: Board private structure
+ * @ptp_port: PTP port structure
+ */
+static int ice_ptp_init_port(struct ice_pf *pf, struct ice_ptp_port *ptp_port)
+{
+	return ice_ptp_init_tx_e810(pf, &ptp_port->tx);
+}
+
 /**
  * ice_ptp_init - Initialize the PTP support after device probe or reset
  * @pf: Board private structure
@@ -1867,8 +2017,7 @@  static int ice_ptp_init_owner(struct ice_pf *pf)
  */
 void ice_ptp_init(struct ice_pf *pf)
 {
-	struct device *dev = ice_pf_to_dev(pf);
-	struct kthread_worker *kworker;
+	struct ice_ptp *ptp = &pf->ptp;
 	struct ice_hw *hw = &pf->hw;
 	int err;
 
@@ -1880,44 +2029,29 @@  void ice_ptp_init(struct ice_pf *pf)
 	if (hw->func_caps.ts_func_info.src_tmr_owned) {
 		err = ice_ptp_init_owner(pf);
 		if (err)
-			return;
+			goto err;
 	}
 
-	/* Disable timestamping for both Tx and Rx */
-	ice_ptp_cfg_timestamp(pf, false);
-
-	/* Initialize the PTP port Tx timestamp tracker */
-	ice_ptp_init_tx_e810(pf, &pf->ptp.port.tx);
-
-	/* Initialize work functions */
-	kthread_init_delayed_work(&pf->ptp.work, ice_ptp_periodic_work);
-	kthread_init_work(&pf->ptp.extts_work, ice_ptp_extts_work);
-
-	/* Allocate a kworker for handling work required for the ports
-	 * connected to the PTP hardware clock.
-	 */
-	kworker = kthread_create_worker(0, "ice-ptp-%s", dev_name(dev));
-	if (IS_ERR(kworker)) {
-		err = PTR_ERR(kworker);
-		goto err_kworker;
-	}
-	pf->ptp.kworker = kworker;
+	err = ice_ptp_init_port(pf, &ptp->port);
+	if (err)
+		goto err;
 
 	set_bit(ICE_FLAG_PTP, pf->flags);
+	err = ice_ptp_init_work(pf, ptp);
+	if (err)
+		goto err;
 
-	/* Start periodic work going */
-	kthread_queue_delayed_work(pf->ptp.kworker, &pf->ptp.work, 0);
-
-	dev_info(dev, "PTP init successful\n");
+	dev_info(ice_pf_to_dev(pf), "PTP init successful\n");
 	return;
 
-err_kworker:
+err:
 	/* If we registered a PTP clock, release it */
 	if (pf->ptp.clock) {
-		ptp_clock_unregister(pf->ptp.clock);
+		ptp_clock_unregister(ptp->clock);
 		pf->ptp.clock = NULL;
 	}
-	dev_err(dev, "PTP failed %d\n", err);
+	clear_bit(ICE_FLAG_PTP, pf->flags);
+	dev_err(ice_pf_to_dev(pf), "PTP failed %d\n", err);
 }
 
 /**
diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.h b/drivers/net/ethernet/intel/ice/ice_ptp.h
index f71ad317d6c8..6f3bbf0718b0 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp.h
+++ b/drivers/net/ethernet/intel/ice/ice_ptp.h
@@ -121,6 +121,7 @@  struct ice_ptp_port {
  * @info: structure defining PTP hardware capabilities
  * @clock: pointer to registered PTP clock device
  * @tstamp_config: hardware timestamping configuration
+ * @reset_time: kernel time after clock stop on reset
  */
 struct ice_ptp {
 	struct ice_ptp_port port;
@@ -134,6 +135,7 @@  struct ice_ptp {
 	struct ptp_clock_info info;
 	struct ptp_clock *clock;
 	struct hwtstamp_config tstamp_config;
+	u64 reset_time;
 };
 
 #define __ptp_port_to_ptp(p) \
@@ -174,6 +176,7 @@  struct ice_ptp {
 struct ice_pf;
 int ice_ptp_set_ts_config(struct ice_pf *pf, struct ifreq *ifr);
 int ice_ptp_get_ts_config(struct ice_pf *pf, struct ifreq *ifr);
+void ice_ptp_cfg_timestamp(struct ice_pf *pf, bool ena);
 int ice_get_ptp_clock_index(struct ice_pf *pf);
 
 s8 ice_ptp_request_ts(struct ice_ptp_tx *tx, struct sk_buff *skb);
@@ -182,6 +185,8 @@  void ice_ptp_process_ts(struct ice_pf *pf);
 void
 ice_ptp_rx_hwtstamp(struct ice_rx_ring *rx_ring,
 		    union ice_32b_rx_flex_desc *rx_desc, struct sk_buff *skb);
+void ice_ptp_reset(struct ice_pf *pf);
+void ice_ptp_prepare_for_reset(struct ice_pf *pf);
 void ice_ptp_init(struct ice_pf *pf);
 void ice_ptp_release(struct ice_pf *pf);
 #else /* IS_ENABLED(CONFIG_PTP_1588_CLOCK) */
@@ -195,6 +200,7 @@  static inline int ice_ptp_get_ts_config(struct ice_pf *pf, struct ifreq *ifr)
 	return -EOPNOTSUPP;
 }
 
+static inline void ice_ptp_cfg_timestamp(struct ice_pf *pf, bool ena) { }
 static inline int ice_get_ptp_clock_index(struct ice_pf *pf)
 {
 	return -1;
@@ -210,6 +216,8 @@  static inline void ice_ptp_process_ts(struct ice_pf *pf) { }
 static inline void
 ice_ptp_rx_hwtstamp(struct ice_rx_ring *rx_ring,
 		    union ice_32b_rx_flex_desc *rx_desc, struct sk_buff *skb) { }
+static inline void ice_ptp_reset(struct ice_pf *pf) { }
+static inline void ice_ptp_prepare_for_reset(struct ice_pf *pf) { }
 static inline void ice_ptp_init(struct ice_pf *pf) { }
 static inline void ice_ptp_release(struct ice_pf *pf) { }
 #endif /* IS_ENABLED(CONFIG_PTP_1588_CLOCK) */