* [PATCH v3 iwl-next 0/4] ice: Implement PTP support for E830 devices
@ 2024-07-25 9:34 Karol Kolacinski
2024-07-25 9:34 ` [PATCH v3 iwl-next 1/4] " Karol Kolacinski
` (3 more replies)
0 siblings, 4 replies; 16+ messages in thread
From: Karol Kolacinski @ 2024-07-25 9:34 UTC (permalink / raw)
To: intel-wired-lan
Cc: netdev, anthony.l.nguyen, przemyslaw.kitszel, Karol Kolacinski
Add specific functions and definitions for E830 devices to enable
PTP support.
Refactor processing of timestamping interrupt and cross timestamp
to avoid code redundancy.
Jacob Keller (1):
ice: combine cross timestamp functions for E82x and E830
Karol Kolacinski (2):
ice: Process TSYN IRQ in a separate function
ice: Add timestamp ready bitmap for E830 products
Michal Michalik (1):
ice: Implement PTP support for E830 devices
drivers/net/ethernet/intel/Kconfig | 10 +-
drivers/net/ethernet/intel/ice/ice_common.c | 13 +-
drivers/net/ethernet/intel/ice/ice_common.h | 1 +
.../net/ethernet/intel/ice/ice_hw_autogen.h | 12 +
drivers/net/ethernet/intel/ice/ice_main.c | 25 +-
drivers/net/ethernet/intel/ice/ice_osdep.h | 3 +
drivers/net/ethernet/intel/ice/ice_ptp.c | 356 ++++++++++++------
drivers/net/ethernet/intel/ice/ice_ptp.h | 9 +-
drivers/net/ethernet/intel/ice/ice_ptp_hw.c | 199 +++++++++-
drivers/net/ethernet/intel/ice/ice_ptp_hw.h | 25 +-
drivers/net/ethernet/intel/ice/ice_type.h | 1 +
11 files changed, 497 insertions(+), 157 deletions(-)
V2 -> V3: Rebased and fixed kdoc in "ice: Implement PTP support for
E830 devices"
V1 -> V2: Fixed compilation issue in "ice: Implement PTP support for
E830 devices"
base-commit: 0942d0846f6305b3ac645a7294470df8fe6c3dd0
--
2.45.2
^ permalink raw reply [flat|nested] 16+ messages in thread
* [PATCH v3 iwl-next 1/4] ice: Implement PTP support for E830 devices
2024-07-25 9:34 [PATCH v3 iwl-next 0/4] ice: Implement PTP support for E830 devices Karol Kolacinski
@ 2024-07-25 9:34 ` Karol Kolacinski
2024-07-26 13:17 ` [Intel-wired-lan] " Alexander Lobakin
2024-07-25 9:34 ` [PATCH v3 iwl-next 2/4] ice: Process TSYN IRQ in a separate function Karol Kolacinski
` (2 subsequent siblings)
3 siblings, 1 reply; 16+ messages in thread
From: Karol Kolacinski @ 2024-07-25 9:34 UTC (permalink / raw)
To: intel-wired-lan
Cc: netdev, anthony.l.nguyen, przemyslaw.kitszel, Michal Michalik,
Milena Olech, Paul Greenwalt, Karol Kolacinski
From: Michal Michalik <michal.michalik@intel.com>
Add specific functions and definitions for E830 devices to enable
PTP support.
Introduce new PHY model ICE_PHY_E830.
E830 devices support direct write to GLTSYN_ registers without shadow
registers and 64 bit read of PHC time.
Reviewed-by: Przemek Kitszel <przemyslaw.kitszel@intel.com>
Co-developed-by: Milena Olech <milena.olech@intel.com>
Signed-off-by: Milena Olech <milena.olech@intel.com>
Co-developed-by: Paul Greenwalt <paul.greenwalt@intel.com>
Signed-off-by: Paul Greenwalt <paul.greenwalt@intel.com>
Signed-off-by: Michal Michalik <michal.michalik@intel.com>
Co-developed-by: Karol Kolacinski <karol.kolacinski@intel.com>
Signed-off-by: Karol Kolacinski <karol.kolacinski@intel.com>
---
V2 -> V3: Fixed kdoc for ice_is_e***() and ice_ptp_init_phy_e830()
V1 -> V2: Fixed compilation issue with GENMASK bits higher than 32
drivers/net/ethernet/intel/ice/ice_common.c | 13 +-
drivers/net/ethernet/intel/ice/ice_common.h | 1 +
.../net/ethernet/intel/ice/ice_hw_autogen.h | 4 +
drivers/net/ethernet/intel/ice/ice_ptp.c | 11 +-
drivers/net/ethernet/intel/ice/ice_ptp_hw.c | 199 ++++++++++++++++--
drivers/net/ethernet/intel/ice/ice_ptp_hw.h | 25 ++-
drivers/net/ethernet/intel/ice/ice_type.h | 1 +
7 files changed, 226 insertions(+), 28 deletions(-)
diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c
index 009716a12a26..8bff63d3d664 100644
--- a/drivers/net/ethernet/intel/ice/ice_common.c
+++ b/drivers/net/ethernet/intel/ice/ice_common.c
@@ -267,7 +267,7 @@ bool ice_is_e822(struct ice_hw *hw)
* ice_is_e823
* @hw: pointer to the hardware structure
*
- * returns true if the device is E823-L or E823-C based, false if not.
+ * Return: true if the device is E823-L or E823-C based, false if not.
*/
bool ice_is_e823(struct ice_hw *hw)
{
@@ -307,6 +307,17 @@ bool ice_is_e825c(struct ice_hw *hw)
}
}
+/**
+ * ice_is_e830
+ * @hw: pointer to the hardware structure
+ *
+ * Return: true if the device is E830 based, false if not.
+ */
+bool ice_is_e830(const struct ice_hw *hw)
+{
+ return hw->mac_type == ICE_MAC_E830;
+}
+
/**
* ice_clear_pf_cfg - Clear PF configuration
* @hw: pointer to the hardware structure
diff --git a/drivers/net/ethernet/intel/ice/ice_common.h b/drivers/net/ethernet/intel/ice/ice_common.h
index 27208a60cece..21a4d9734168 100644
--- a/drivers/net/ethernet/intel/ice/ice_common.h
+++ b/drivers/net/ethernet/intel/ice/ice_common.h
@@ -279,6 +279,7 @@ bool ice_is_e810t(struct ice_hw *hw);
bool ice_is_e822(struct ice_hw *hw);
bool ice_is_e823(struct ice_hw *hw);
bool ice_is_e825c(struct ice_hw *hw);
+bool ice_is_e830(const struct ice_hw *hw);
int
ice_sched_query_elem(struct ice_hw *hw, u32 node_teid,
struct ice_aqc_txsched_elem_data *buf);
diff --git a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h
index 91cbae1eec89..646089f3e26c 100644
--- a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h
+++ b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h
@@ -533,10 +533,14 @@
#define PFPM_WUS_MAG_M BIT(1)
#define PFPM_WUS_MNG_M BIT(3)
#define PFPM_WUS_FW_RST_WK_M BIT(31)
+#define E830_PRTMAC_TS_TX_MEM_VALID_H 0x001E2020
+#define E830_PRTMAC_TS_TX_MEM_VALID_L 0x001E2000
#define E830_PRTMAC_CL01_PS_QNT 0x001E32A0
#define E830_PRTMAC_CL01_PS_QNT_CL0_M GENMASK(15, 0)
#define E830_PRTMAC_CL01_QNT_THR 0x001E3320
#define E830_PRTMAC_CL01_QNT_THR_CL0_M GENMASK(15, 0)
+#define E830_PRTTSYN_TXTIME_H(_i) (0x001E5800 + ((_i) * 32))
+#define E830_PRTTSYN_TXTIME_L(_i) (0x001E5000 + ((_i) * 32))
#define VFINT_DYN_CTLN(_i) (0x00003800 + ((_i) * 4))
#define VFINT_DYN_CTLN_CLEARPBA_M BIT(1)
diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c
index 825c7fa71a4c..2c5397d7a686 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp.c
+++ b/drivers/net/ethernet/intel/ice/ice_ptp.c
@@ -298,6 +298,15 @@ ice_ptp_read_src_clk_reg(struct ice_pf *pf, struct ptp_system_timestamp *sts)
/* Read the system timestamp pre PHC read */
ptp_read_system_prets(sts);
+ if (ice_is_e830(hw)) {
+ u64 clk_time = rd64(hw, E830_GLTSYN_TIME_L(tmr_idx));
+
+ /* Read the system timestamp post PHC read */
+ ptp_read_system_postts(sts);
+
+ return clk_time;
+ }
+
lo = rd32(hw, GLTSYN_TIME_L(tmr_idx));
/* Read the system timestamp post PHC read */
@@ -2626,7 +2635,7 @@ static void ice_ptp_set_caps(struct ice_pf *pf)
info->enable = ice_ptp_gpio_enable;
info->verify = ice_verify_pin;
- if (ice_is_e810(&pf->hw))
+ if (ice_is_e810(&pf->hw) || ice_is_e830(&pf->hw))
ice_ptp_set_funcs_e810(pf);
else
ice_ptp_set_funcs_e82x(pf);
diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c
index 6dff422b7f4e..f7e2df8c0eb2 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.c
+++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.c
@@ -897,6 +897,17 @@ static void ice_ptp_exec_tmr_cmd(struct ice_hw *hw)
ice_flush(hw);
}
+/**
+ * ice_ptp_cfg_sync_delay - Configure PHC to PHY synchronization delay
+ * @hw: pointer to HW struct
+ * @delay: delay between PHC and PHY SYNC command execution in nanoseconds
+ */
+static void ice_ptp_cfg_sync_delay(struct ice_hw *hw, u32 delay)
+{
+ wr32(hw, GLTSYN_SYNC_DLAY, delay);
+ ice_flush(hw);
+}
+
/* 56G PHY device functions
*
* The following functions operate on devices with the ETH 56G PHY.
@@ -1520,7 +1531,8 @@ static int ice_read_ptp_tstamp_eth56g(struct ice_hw *hw, u8 port, u8 idx,
* lower 8 bits in the low register, and the upper 32 bits in the high
* register.
*/
- *tstamp = ((u64)hi) << TS_PHY_HIGH_S | ((u64)lo & TS_PHY_LOW_M);
+ *tstamp = FIELD_PREP(PHY_40B_HIGH_M, hi) |
+ FIELD_PREP(PHY_40B_LOW_M, lo);
return 0;
}
@@ -3201,7 +3213,8 @@ ice_read_phy_tstamp_e82x(struct ice_hw *hw, u8 quad, u8 idx, u64 *tstamp)
* lower 8 bits in the low register, and the upper 32 bits in the high
* register.
*/
- *tstamp = FIELD_PREP(TS_PHY_HIGH_M, hi) | FIELD_PREP(TS_PHY_LOW_M, lo);
+ *tstamp = FIELD_PREP(PHY_40B_HIGH_M, hi) |
+ FIELD_PREP(PHY_40B_LOW_M, lo);
return 0;
}
@@ -4955,7 +4968,8 @@ ice_read_phy_tstamp_e810(struct ice_hw *hw, u8 lport, u8 idx, u64 *tstamp)
/* For E810 devices, the timestamp is reported with the lower 32 bits
* in the low register, and the upper 8 bits in the high register.
*/
- *tstamp = ((u64)hi) << TS_HIGH_S | ((u64)lo & TS_LOW_M);
+ *tstamp = FIELD_PREP(PHY_EXT_40B_HIGH_M, hi) |
+ FIELD_PREP(PHY_EXT_40B_LOW_M, lo);
return 0;
}
@@ -5018,8 +5032,7 @@ static int ice_ptp_init_phc_e810(struct ice_hw *hw)
u8 tmr_idx;
int err;
- /* Ensure synchronization delay is zero */
- wr32(hw, GLTSYN_SYNC_DLAY, 0);
+ ice_ptp_cfg_sync_delay(hw, ICE_E810_E830_SYNC_DELAY);
tmr_idx = hw->func_caps.ts_func_info.tmr_index_owned;
err = ice_write_phy_reg_e810(hw, ETH_GLTSYN_ENA(tmr_idx),
@@ -5407,11 +5420,142 @@ static void ice_ptp_init_phy_e810(struct ice_ptp_hw *ptp)
ptp->ports_per_phy = 4;
}
+/* E830 functions
+ *
+ * The following functions operate on the E830 series devices.
+ *
+ */
+
+/**
+ * ice_ptp_init_phc_e830 - Perform E830 specific PHC initialization
+ * @hw: pointer to HW struct
+ *
+ * Perform E830-specific PTP hardware clock initialization steps.
+ *
+ * Return: 0 on success
+ */
+static int ice_ptp_init_phc_e830(struct ice_hw *hw)
+{
+ ice_ptp_cfg_sync_delay(hw, ICE_E810_E830_SYNC_DELAY);
+ return 0;
+}
+
+/**
+ * ice_ptp_write_direct_incval_e830 - Prep PHY port increment value change
+ * @hw: pointer to HW struct
+ * @incval: The new 40bit increment value to prepare
+ *
+ * Prepare the PHY port for a new increment value by programming the PHC
+ * GLTSYN_INCVAL_L and GLTSYN_INCVAL_H registers. The actual change is
+ * completed by FW automatically.
+ */
+static int ice_ptp_write_direct_incval_e830(struct ice_hw *hw, u64 incval)
+{
+ u8 tmr_idx = hw->func_caps.ts_func_info.tmr_index_owned;
+
+ wr32(hw, GLTSYN_INCVAL_L(tmr_idx), lower_32_bits(incval));
+ wr32(hw, GLTSYN_INCVAL_H(tmr_idx), upper_32_bits(incval));
+
+ return 0;
+}
+
+/**
+ * ice_ptp_write_direct_phc_time_e830 - Prepare PHY port with initial time
+ * @hw: Board private structure
+ * @time: Time to initialize the PHY port clock to
+ *
+ * Program the PHY port ETH_GLTSYN_SHTIME registers in preparation setting the
+ * initial clock time. The time will not actually be programmed until the
+ * driver issues an ICE_PTP_INIT_TIME command.
+ *
+ * The time value is the upper 32 bits of the PHY timer, usually in units of
+ * nominal nanoseconds.
+ */
+static int ice_ptp_write_direct_phc_time_e830(struct ice_hw *hw, u64 time)
+{
+ u8 tmr_idx = hw->func_caps.ts_func_info.tmr_index_owned;
+
+ wr32(hw, GLTSYN_TIME_0(tmr_idx), 0);
+ wr32(hw, GLTSYN_TIME_L(tmr_idx), lower_32_bits(time));
+ wr32(hw, GLTSYN_TIME_H(tmr_idx), upper_32_bits(time));
+
+ return 0;
+}
+
+/**
+ * ice_ptp_port_cmd_e830 - Prepare all external PHYs for a timer command
+ * @hw: pointer to HW struct
+ * @cmd: Command to be sent to the port
+ *
+ * Prepare the external PHYs connected to this device for a timer sync
+ * command.
+ */
+static int ice_ptp_port_cmd_e830(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd)
+{
+ u32 val = ice_ptp_tmr_cmd_to_port_reg(hw, cmd);
+
+ return ice_write_phy_reg_e810(hw, E830_ETH_GLTSYN_CMD, val);
+}
+
+/**
+ * ice_read_phy_tstamp_e830 - Read a PHY timestamp out of the external PHY
+ * @hw: pointer to the HW struct
+ * @lport: the lport to read from
+ * @idx: the timestamp index to read
+ * @tstamp: on return, the 40bit timestamp value
+ *
+ * Read a 40bit timestamp value out of the timestamp block of the external PHY
+ * on the E830 device.
+ */
+static int
+ice_read_phy_tstamp_e830(struct ice_hw *hw, u8 lport, u8 idx, u64 *tstamp)
+{
+ u32 hi, lo;
+
+ hi = rd32(hw, E830_HIGH_TX_MEMORY_BANK(idx, lport));
+ lo = rd32(hw, E830_LOW_TX_MEMORY_BANK(idx, lport));
+
+ /* For E830 devices, the timestamp is reported with the lower 32 bits
+ * in the low register, and the upper 8 bits in the high register.
+ */
+ *tstamp = FIELD_PREP(PHY_EXT_40B_HIGH_M, hi) |
+ FIELD_PREP(PHY_EXT_40B_LOW_M, lo);
+
+ return 0;
+}
+
+/**
+ * ice_get_phy_tx_tstamp_ready_e830 - 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
+ *
+ */
+static int
+ice_get_phy_tx_tstamp_ready_e830(struct ice_hw *hw, u8 port, u64 *tstamp_ready)
+{
+ *tstamp_ready = rd32(hw, E830_PRTMAC_TS_TX_MEM_VALID_H);
+ *tstamp_ready <<= 32;
+ *tstamp_ready |= rd32(hw, E830_PRTMAC_TS_TX_MEM_VALID_L);
+
+ return 0;
+}
+
+/**
+ * ice_ptp_init_phy_e830 - initialize PHY parameters
+ * @ptp: pointer to the PTP HW struct
+ */
+static void ice_ptp_init_phy_e830(struct ice_ptp_hw *ptp)
+{
+ ptp->phy_model = ICE_PHY_E830;
+ ptp->num_lports = 8;
+ ptp->ports_per_phy = 4;
+}
+
/* Device agnostic functions
*
- * The following functions implement shared behavior common to both E822 and
- * E810 devices, possibly calling a device specific implementation where
- * necessary.
+ * The following functions implement shared behavior common to all devices,
+ * possibly calling a device specific implementation where necessary.
*/
/**
@@ -5474,12 +5618,14 @@ void ice_ptp_init_hw(struct ice_hw *hw)
{
struct ice_ptp_hw *ptp = &hw->ptp;
- if (ice_is_e822(hw) || ice_is_e823(hw))
- ice_ptp_init_phy_e82x(ptp);
- else if (ice_is_e810(hw))
+ if (ice_is_e810(hw))
ice_ptp_init_phy_e810(ptp);
+ else if (ice_is_e822(hw) || ice_is_e823(hw))
+ ice_ptp_init_phy_e82x(ptp);
else if (ice_is_e825c(hw))
ice_ptp_init_phy_e825c(hw);
+ else if (ice_is_e830(hw))
+ ice_ptp_init_phy_e830(ptp);
else
ptp->phy_model = ICE_PHY_UNSUP;
}
@@ -5570,6 +5716,8 @@ static int ice_ptp_port_cmd(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd)
switch (hw->ptp.phy_model) {
case ICE_PHY_E810:
return ice_ptp_port_cmd_e810(hw, cmd);
+ case ICE_PHY_E830:
+ return ice_ptp_port_cmd_e830(hw, cmd);
default:
break;
}
@@ -5640,6 +5788,10 @@ int ice_ptp_init_time(struct ice_hw *hw, u64 time)
tmr_idx = hw->func_caps.ts_func_info.tmr_index_owned;
/* Source timers */
+ /* For E830 we don't need to use shadow registers, its automatic */
+ if (hw->ptp.phy_model == ICE_PHY_E830)
+ return ice_ptp_write_direct_phc_time_e830(hw, time);
+
wr32(hw, GLTSYN_SHTIME_L(tmr_idx), lower_32_bits(time));
wr32(hw, GLTSYN_SHTIME_H(tmr_idx), upper_32_bits(time));
wr32(hw, GLTSYN_SHTIME_0(tmr_idx), 0);
@@ -5688,6 +5840,10 @@ int ice_ptp_write_incval(struct ice_hw *hw, u64 incval)
tmr_idx = hw->func_caps.ts_func_info.tmr_index_owned;
+ /* For E830 we don't need to use shadow registers, its automatic */
+ if (hw->ptp.phy_model == ICE_PHY_E830)
+ return ice_ptp_write_direct_incval_e830(hw, incval);
+
/* Shadow Adjust */
wr32(hw, GLTSYN_SHADJ_L(tmr_idx), lower_32_bits(incval));
wr32(hw, GLTSYN_SHADJ_H(tmr_idx), upper_32_bits(incval));
@@ -5795,12 +5951,14 @@ int ice_ptp_adj_clock(struct ice_hw *hw, s32 adj)
int ice_read_phy_tstamp(struct ice_hw *hw, u8 block, u8 idx, u64 *tstamp)
{
switch (hw->ptp.phy_model) {
- case ICE_PHY_ETH56G:
- return ice_read_ptp_tstamp_eth56g(hw, block, idx, tstamp);
case ICE_PHY_E810:
return ice_read_phy_tstamp_e810(hw, block, idx, tstamp);
case ICE_PHY_E82X:
return ice_read_phy_tstamp_e82x(hw, block, idx, tstamp);
+ case ICE_PHY_E830:
+ return ice_read_phy_tstamp_e830(hw, block, idx, tstamp);
+ case ICE_PHY_ETH56G:
+ return ice_read_ptp_tstamp_eth56g(hw, block, idx, tstamp);
default:
return -EOPNOTSUPP;
}
@@ -5917,12 +6075,14 @@ int ice_ptp_init_phc(struct ice_hw *hw)
(void)rd32(hw, GLTSYN_STAT(src_idx));
switch (hw->ptp.phy_model) {
- case ICE_PHY_ETH56G:
- return ice_ptp_init_phc_eth56g(hw);
case ICE_PHY_E810:
return ice_ptp_init_phc_e810(hw);
case ICE_PHY_E82X:
return ice_ptp_init_phc_e82x(hw);
+ case ICE_PHY_E830:
+ return ice_ptp_init_phc_e830(hw);
+ case ICE_PHY_ETH56G:
+ return ice_ptp_init_phc_eth56g(hw);
default:
return -EOPNOTSUPP;
}
@@ -5942,15 +6102,18 @@ 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)
{
switch (hw->ptp.phy_model) {
- case ICE_PHY_ETH56G:
- return ice_get_phy_tx_tstamp_ready_eth56g(hw, block,
- tstamp_ready);
case ICE_PHY_E810:
return ice_get_phy_tx_tstamp_ready_e810(hw, block,
tstamp_ready);
case ICE_PHY_E82X:
return ice_get_phy_tx_tstamp_ready_e82x(hw, block,
tstamp_ready);
+ case ICE_PHY_E830:
+ return ice_get_phy_tx_tstamp_ready_e830(hw, block,
+ tstamp_ready);
+ case ICE_PHY_ETH56G:
+ return ice_get_phy_tx_tstamp_ready_eth56g(hw, block,
+ tstamp_ready);
break;
default:
return -EOPNOTSUPP;
diff --git a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h
index fc946fcd28b9..81b8864b529f 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp_hw.h
+++ b/drivers/net/ethernet/intel/ice/ice_ptp_hw.h
@@ -327,6 +327,7 @@ extern const struct ice_vernier_info_e82x e822_vernier[NUM_ICE_PTP_LNK_SPD];
#define ICE_E810_PLL_FREQ 812500000
#define ICE_PTP_NOMINAL_INCVAL_E810 0x13b13b13bULL
#define ICE_E810_OUT_PROP_DELAY_NS 1
+#define ICE_E810_E830_SYNC_DELAY 0
#define ICE_E825C_OUT_PROP_DELAY_NS 11
/* Device agnostic functions */
@@ -670,18 +671,21 @@ static inline u64 ice_get_base_incval(struct ice_hw *hw)
/* E810 timer command register */
#define E810_ETH_GLTSYN_CMD 0x03000344
+/* E830 timer command register */
+#define E830_ETH_GLTSYN_CMD 0x00088814
+
+/* E810 PHC time register */
+#define E830_GLTSYN_TIME_L(_tmr_idx) (0x0008A000 + 0x1000 * (_tmr_idx))
+
/* Source timer incval macros */
#define INCVAL_HIGH_M 0xFF
-/* Timestamp block macros */
+/* PHY 40b registers macros */
+#define PHY_EXT_40B_LOW_M GENMASK(31, 0)
+#define PHY_EXT_40B_HIGH_M GENMASK_ULL(39, 32)
+#define PHY_40B_LOW_M GENMASK(7, 0)
+#define PHY_40B_HIGH_M GENMASK_ULL(39, 8)
#define TS_VALID BIT(0)
-#define TS_LOW_M 0xFFFFFFFF
-#define TS_HIGH_M 0xFF
-#define TS_HIGH_S 32
-
-#define TS_PHY_LOW_M 0xFF
-#define TS_PHY_HIGH_M 0xFFFFFFFF
-#define TS_PHY_HIGH_S 8
#define BYTES_PER_IDX_ADDR_L_U 8
#define BYTES_PER_IDX_ADDR_L 4
@@ -705,6 +709,11 @@ static inline u64 ice_get_base_incval(struct ice_hw *hw)
#define LOW_TX_MEMORY_BANK_START 0x03090000
#define HIGH_TX_MEMORY_BANK_START 0x03090004
+#define E830_LOW_TX_MEMORY_BANK(slot, port) \
+ (E830_PRTTSYN_TXTIME_L(slot) + 0x8 * (port))
+#define E830_HIGH_TX_MEMORY_BANK(slot, port) \
+ (E830_PRTTSYN_TXTIME_H(slot) + 0x8 * (port))
+
/* SMA controller pin control */
#define ICE_SMA1_DIR_EN BIT(4)
#define ICE_SMA1_TX_EN BIT(5)
diff --git a/drivers/net/ethernet/intel/ice/ice_type.h b/drivers/net/ethernet/intel/ice/ice_type.h
index 45768796691f..7fead101be7f 100644
--- a/drivers/net/ethernet/intel/ice/ice_type.h
+++ b/drivers/net/ethernet/intel/ice/ice_type.h
@@ -866,6 +866,7 @@ enum ice_phy_model {
ICE_PHY_E810 = 1,
ICE_PHY_E82X,
ICE_PHY_ETH56G,
+ ICE_PHY_E830,
};
/* Global Link Topology */
--
2.45.2
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v3 iwl-next 2/4] ice: Process TSYN IRQ in a separate function
2024-07-25 9:34 [PATCH v3 iwl-next 0/4] ice: Implement PTP support for E830 devices Karol Kolacinski
2024-07-25 9:34 ` [PATCH v3 iwl-next 1/4] " Karol Kolacinski
@ 2024-07-25 9:34 ` Karol Kolacinski
2024-07-26 13:22 ` [Intel-wired-lan] " Alexander Lobakin
2024-07-25 9:34 ` [PATCH v3 iwl-next 3/4] ice: Add timestamp ready bitmap for E830 products Karol Kolacinski
2024-07-25 9:34 ` [PATCH v3 iwl-next 4/4] ice: combine cross timestamp functions for E82x and E830 Karol Kolacinski
3 siblings, 1 reply; 16+ messages in thread
From: Karol Kolacinski @ 2024-07-25 9:34 UTC (permalink / raw)
To: intel-wired-lan
Cc: netdev, anthony.l.nguyen, przemyslaw.kitszel, Karol Kolacinski
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.kitszel@intel.com>
Signed-off-by: Karol Kolacinski <karol.kolacinski@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 ab675fe8eacd..753c942c64f1 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -3275,22 +3275,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 2c5397d7a686..19f6c2408ec2 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp.c
+++ b/drivers/net/ethernet/intel/ice/ice_ptp.c
@@ -2748,6 +2748,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 b8ab162a5538..5122b3a862fb 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp.h
+++ b/drivers/net/ethernet/intel/ice/ice_ptp.h
@@ -322,6 +322,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);
@@ -360,6 +361,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
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v3 iwl-next 3/4] ice: Add timestamp ready bitmap for E830 products
2024-07-25 9:34 [PATCH v3 iwl-next 0/4] ice: Implement PTP support for E830 devices Karol Kolacinski
2024-07-25 9:34 ` [PATCH v3 iwl-next 1/4] " Karol Kolacinski
2024-07-25 9:34 ` [PATCH v3 iwl-next 2/4] ice: Process TSYN IRQ in a separate function Karol Kolacinski
@ 2024-07-25 9:34 ` Karol Kolacinski
2024-07-26 13:25 ` [Intel-wired-lan] " Alexander Lobakin
2024-07-25 9:34 ` [PATCH v3 iwl-next 4/4] ice: combine cross timestamp functions for E82x and E830 Karol Kolacinski
3 siblings, 1 reply; 16+ messages in thread
From: Karol Kolacinski @ 2024-07-25 9:34 UTC (permalink / raw)
To: intel-wired-lan
Cc: netdev, anthony.l.nguyen, przemyslaw.kitszel, Karol Kolacinski
E830 PHY supports timestamp ready bitmap.
Enable the bitmap by refactoring tx init function.
Reviewed-by: Przemek Kitszel <przemyslaw.kitszel@intel.com>
Signed-off-by: Karol Kolacinski <karol.kolacinski@intel.com>
---
drivers/net/ethernet/intel/ice/ice_ptp.c | 47 +++++-------------------
drivers/net/ethernet/intel/ice/ice_ptp.h | 3 +-
2 files changed, 11 insertions(+), 39 deletions(-)
diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c
index 19f6c2408ec2..9f0eff040a95 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp.c
+++ b/drivers/net/ethernet/intel/ice/ice_ptp.c
@@ -942,28 +942,6 @@ ice_ptp_release_tx_tracker(struct ice_pf *pf, struct ice_ptp_tx *tx)
tx->len = 0;
}
-/**
- * ice_ptp_init_tx_eth56g - Initialize tracking for Tx timestamps
- * @pf: Board private structure
- * @tx: the Tx tracking structure to initialize
- * @port: the port this structure tracks
- *
- * Initialize the Tx timestamp tracker for this port. ETH56G PHYs
- * have independent memory blocks for all ports.
- *
- * Return: 0 for success, -ENOMEM when failed to allocate Tx tracker
- */
-static int ice_ptp_init_tx_eth56g(struct ice_pf *pf, struct ice_ptp_tx *tx,
- u8 port)
-{
- tx->block = port;
- tx->offset = 0;
- tx->len = INDEX_PER_PORT_ETH56G;
- tx->has_ready_bitmap = 1;
-
- return ice_ptp_alloc_tx_tracker(tx);
-}
-
/**
* ice_ptp_init_tx_e82x - Initialize tracking for Tx timestamps
* @pf: Board private structure
@@ -987,24 +965,25 @@ ice_ptp_init_tx_e82x(struct ice_pf *pf, struct ice_ptp_tx *tx, u8 port)
}
/**
- * ice_ptp_init_tx_e810 - Initialize tracking for Tx timestamps
+ * ice_ptp_init_tx - Initialize tracking for Tx timestamps
* @pf: Board private structure
* @tx: the Tx tracking structure to initialize
+ * @port: the port this structure tracks
*
- * Initialize the Tx timestamp tracker for this PF. For E810 devices, each
- * port has its own block of timestamps, independent of the other ports.
+ * Initialize the Tx timestamp tracker for this PF. For all PHYs except E82X,
+ * each port has its own block of timestamps, independent of the other ports.
*/
-static int
-ice_ptp_init_tx_e810(struct ice_pf *pf, struct ice_ptp_tx *tx)
+static int ice_ptp_init_tx(struct ice_pf *pf, struct ice_ptp_tx *tx, u8 port)
{
- tx->block = pf->hw.port_info->lport;
+ tx->block = port;
tx->offset = 0;
- tx->len = INDEX_PER_PORT_E810;
+ tx->len = INDEX_PER_PORT;
+
/* The E810 PHY does not provide a timestamp ready bitmap. Instead,
* verify new timestamps against cached copy of the last read
* timestamp.
*/
- tx->has_ready_bitmap = 0;
+ tx->has_ready_bitmap = pf->hw.ptp.phy_model != ICE_PHY_E810;
return ice_ptp_alloc_tx_tracker(tx);
}
@@ -3335,19 +3314,13 @@ static int ice_ptp_init_port(struct ice_pf *pf, struct ice_ptp_port *ptp_port)
mutex_init(&ptp_port->ps_lock);
switch (hw->ptp.phy_model) {
- case ICE_PHY_ETH56G:
- return ice_ptp_init_tx_eth56g(pf, &ptp_port->tx,
- ptp_port->port_num);
- case ICE_PHY_E810:
- return ice_ptp_init_tx_e810(pf, &ptp_port->tx);
case ICE_PHY_E82X:
kthread_init_delayed_work(&ptp_port->ov_work,
ice_ptp_wait_for_offsets);
-
return ice_ptp_init_tx_e82x(pf, &ptp_port->tx,
ptp_port->port_num);
default:
- return -ENODEV;
+ return ice_ptp_init_tx(pf, &ptp_port->tx, ptp_port->port_num);
}
}
diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.h b/drivers/net/ethernet/intel/ice/ice_ptp.h
index 5122b3a862fb..eae15b3b0286 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp.h
+++ b/drivers/net/ethernet/intel/ice/ice_ptp.h
@@ -128,8 +128,7 @@ struct ice_ptp_tx {
/* Quad and port information for initializing timestamp blocks */
#define INDEX_PER_QUAD 64
#define INDEX_PER_PORT_E82X 16
-#define INDEX_PER_PORT_E810 64
-#define INDEX_PER_PORT_ETH56G 64
+#define INDEX_PER_PORT 64
/**
* struct ice_ptp_port - data used to initialize an external port for PTP
--
2.45.2
^ permalink raw reply related [flat|nested] 16+ messages in thread
* [PATCH v3 iwl-next 4/4] ice: combine cross timestamp functions for E82x and E830
2024-07-25 9:34 [PATCH v3 iwl-next 0/4] ice: Implement PTP support for E830 devices Karol Kolacinski
` (2 preceding siblings ...)
2024-07-25 9:34 ` [PATCH v3 iwl-next 3/4] ice: Add timestamp ready bitmap for E830 products Karol Kolacinski
@ 2024-07-25 9:34 ` Karol Kolacinski
2024-07-25 16:31 ` Jacob Keller
2024-07-26 13:37 ` [Intel-wired-lan] " Alexander Lobakin
3 siblings, 2 replies; 16+ messages in thread
From: Karol Kolacinski @ 2024-07-25 9:34 UTC (permalink / raw)
To: intel-wired-lan
Cc: netdev, anthony.l.nguyen, przemyslaw.kitszel, Jacob Keller,
Karol Kolacinski
From: Jacob Keller <jacob.e.keller@intel.com>
The E830 and E82x devices use essentially the same logic for performing
a crosstimestamp. The only difference is that E830 hardware has
different offsets. Instead of having two implementations, combine them
into a single ice_capture_crosststamp() function.
Also combine the wrapper functions which call
get_device_system_crosststamp() into a single ice_ptp_getcrosststamp()
function.
To support both hardware types, the ice_capture_crosststamp function
must be able to determine the appropriate registers to access. To handle
this, pass a custom context structure instead of the PF pointer. This
structure, ice_crosststamp_ctx, contains a pointer to the PF, and
a pointer to the device configuration structure. This new structure also
will make it easier to implement historic snapshot support in a future
commit.
The device configuration structure is a static const data which defines
the offsets and flags for the various registers. This includes the lock
register, the cross timestamp control register, the upper and lower ART
system time capture registers, and the upper and lower device time
capture registers for each timer index.
This does add extra data to the .text of the module (and thus kernel),
but it also removes 2 near duplicate functions for enabling E830
support.
Use the configuration structure to access all of the registers in
ice_capture_crosststamp(). Ensure that we don't over-run the device time
array by checking that the timer index is 0 or 1. Previously this was
simply assumed, and it would cause the device to read an incorrect and
likely garbage register.
It does feel like there should be a kernel interface for managing
register offsets like this, but the closest thing I saw was
<linux/regmap.h> which is interesting but not quite what we're looking
for...
Reviewed-by: Przemek Kitszel <przemyslaw.kitszel@intel.com>
Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
Signed-off-by: Karol Kolacinski <karol.kolacinski@intel.com>
---
drivers/net/ethernet/intel/Kconfig | 10 +-
.../net/ethernet/intel/ice/ice_hw_autogen.h | 8 +
drivers/net/ethernet/intel/ice/ice_main.c | 7 +
drivers/net/ethernet/intel/ice/ice_osdep.h | 3 +
drivers/net/ethernet/intel/ice/ice_ptp.c | 242 +++++++++++++-----
5 files changed, 194 insertions(+), 76 deletions(-)
diff --git a/drivers/net/ethernet/intel/Kconfig b/drivers/net/ethernet/intel/Kconfig
index 0375c7448a57..7c4f3948385c 100644
--- a/drivers/net/ethernet/intel/Kconfig
+++ b/drivers/net/ethernet/intel/Kconfig
@@ -332,14 +332,14 @@ config ICE_SWITCHDEV
If unsure, say N.
config ICE_HWTS
- bool "Support HW cross-timestamp on platforms with PTM support"
+ bool "Support HW cross-timestamp on supported platforms"
default y
- depends on ICE && X86
+ depends on ICE && X86 && PCIE_PTM
help
Say Y to enable hardware supported cross-timestamping on platforms
- with PCIe PTM support. The cross-timestamp is available through
- the PTP clock driver precise cross-timestamp ioctl
- (PTP_SYS_OFFSET_PRECISE).
+ with PCIe PTM support for E830 devices and all E82X platforms. The
+ cross-timestamp is available through the PTP clock driver precise
+ cross-timestamp ioctl (PTP_SYS_OFFSET_PRECISE).
config FM10K
tristate "Intel(R) FM10000 Ethernet Switch Host Interface Support"
diff --git a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h
index 646089f3e26c..495b182ea13b 100644
--- a/drivers/net/ethernet/intel/ice/ice_hw_autogen.h
+++ b/drivers/net/ethernet/intel/ice/ice_hw_autogen.h
@@ -541,6 +541,14 @@
#define E830_PRTMAC_CL01_QNT_THR_CL0_M GENMASK(15, 0)
#define E830_PRTTSYN_TXTIME_H(_i) (0x001E5800 + ((_i) * 32))
#define E830_PRTTSYN_TXTIME_L(_i) (0x001E5000 + ((_i) * 32))
+#define E830_GLPTM_ART_CTL 0x00088B50
+#define E830_GLPTM_ART_CTL_ACTIVE_M BIT(0)
+#define E830_GLPTM_ART_TIME_H 0x00088B54
+#define E830_GLPTM_ART_TIME_L 0x00088B58
+#define E830_GLTSYN_PTMTIME_H(_i) (0x00088B48 + ((_i) * 4))
+#define E830_GLTSYN_PTMTIME_L(_i) (0x00088B40 + ((_i) * 4))
+#define E830_PFPTM_SEM 0x00088B00
+#define E830_PFPTM_SEM_BUSY_M BIT(0)
#define VFINT_DYN_CTLN(_i) (0x00003800 + ((_i) * 4))
#define VFINT_DYN_CTLN_CLEARPBA_M BIT(1)
diff --git a/drivers/net/ethernet/intel/ice/ice_main.c b/drivers/net/ethernet/intel/ice/ice_main.c
index 753c942c64f1..e6853c8888ec 100644
--- a/drivers/net/ethernet/intel/ice/ice_main.c
+++ b/drivers/net/ethernet/intel/ice/ice_main.c
@@ -5060,6 +5060,12 @@ static int ice_init(struct ice_pf *pf)
if (err)
return err;
+ if (ice_is_e830(&pf->hw)) {
+ err = pci_enable_ptm(pf->pdev, NULL);
+ if (err)
+ dev_dbg(ice_pf_to_dev(pf), "PCIe PTM not supported by PCIe bus/controller\n");
+ }
+
err = ice_alloc_vsis(pf);
if (err)
goto err_alloc_vsis;
@@ -5290,6 +5296,7 @@ ice_probe(struct pci_dev *pdev, const struct pci_device_id __always_unused *ent)
hw->subsystem_device_id = pdev->subsystem_device;
hw->bus.device = PCI_SLOT(pdev->devfn);
hw->bus.func = PCI_FUNC(pdev->devfn);
+
ice_set_ctrlq_len(hw);
pf->msg_enable = netif_msg_init(debug, ICE_DFLT_NETIF_M);
diff --git a/drivers/net/ethernet/intel/ice/ice_osdep.h b/drivers/net/ethernet/intel/ice/ice_osdep.h
index a2562f04267f..c03ab0207e0a 100644
--- a/drivers/net/ethernet/intel/ice/ice_osdep.h
+++ b/drivers/net/ethernet/intel/ice/ice_osdep.h
@@ -23,6 +23,9 @@
#define wr64(a, reg, value) writeq((value), ((a)->hw_addr + (reg)))
#define rd64(a, reg) readq((a)->hw_addr + (reg))
+#define rd32_poll_timeout(a, addr, val, cond, delay_us, timeout_us) \
+ read_poll_timeout(rd32, val, cond, delay_us, timeout_us, false, a, addr)
+
#define ice_flush(a) rd32((a), GLGEN_STAT)
#define ICE_M(m, s) ((m ## U) << (s))
diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c
index 9f0eff040a95..ac3944fec2d3 100644
--- a/drivers/net/ethernet/intel/ice/ice_ptp.c
+++ b/drivers/net/ethernet/intel/ice/ice_ptp.c
@@ -1,6 +1,7 @@
// SPDX-License-Identifier: GPL-2.0
/* Copyright (C) 2021, Intel Corporation. */
+#include <linux/iopoll.h>
#include "ice.h"
#include "ice_lib.h"
#include "ice_trace.h"
@@ -2138,91 +2139,154 @@ static int ice_ptp_adjtime(struct ptp_clock_info *info, s64 delta)
#ifdef CONFIG_ICE_HWTS
/**
- * ice_ptp_get_syncdevicetime - Get the cross time stamp info
+ * struct ice_crosststamp_cfg - Device cross timestamp configuration
+ * @lock_reg: The hardware semaphore lock to use
+ * @lock_busy: Bit in the semaphore lock indicating the lock is busy
+ * @ctl_reg: The hardware register to request cross timestamp
+ * @ctl_active: Bit in the control register to request cross timestamp
+ * @art_time_l: Lower 32-bits of ART system time
+ * @art_time_h: Upper 32-bits of ART system time
+ * @dev_time_l: Lower 32-bits of device time (per timer index)
+ * @dev_time_h: Upper 32-bits of device time (per timer index)
+ */
+struct ice_crosststamp_cfg {
+ /* HW semaphore lock register */
+ u32 lock_reg;
+ u32 lock_busy;
+
+ /* Capture control register */
+ u32 ctl_reg;
+ u32 ctl_active;
+
+ /* Time storage */
+ u32 art_time_l;
+ u32 art_time_h;
+ u32 dev_time_l[2];
+ u32 dev_time_h[2];
+};
+
+static const struct ice_crosststamp_cfg ice_crosststamp_cfg_e82x = {
+ .lock_reg = PFHH_SEM,
+ .lock_busy = PFHH_SEM_BUSY_M,
+ .ctl_reg = GLHH_ART_CTL,
+ .ctl_active = GLHH_ART_CTL_ACTIVE_M,
+ .art_time_l = GLHH_ART_TIME_L,
+ .art_time_h = GLHH_ART_TIME_H,
+ .dev_time_l[0] = GLTSYN_HHTIME_L(0),
+ .dev_time_h[0] = GLTSYN_HHTIME_H(0),
+ .dev_time_l[1] = GLTSYN_HHTIME_L(1),
+ .dev_time_h[1] = GLTSYN_HHTIME_H(1),
+};
+
+static const struct ice_crosststamp_cfg ice_crosststamp_cfg_e830 = {
+ .lock_reg = E830_PFPTM_SEM,
+ .lock_busy = E830_PFPTM_SEM_BUSY_M,
+ .ctl_reg = E830_GLPTM_ART_CTL,
+ .ctl_active = E830_GLPTM_ART_CTL_ACTIVE_M,
+ .art_time_l = E830_GLPTM_ART_TIME_L,
+ .art_time_h = E830_GLPTM_ART_TIME_H,
+ .dev_time_l[0] = E830_GLTSYN_PTMTIME_L(0),
+ .dev_time_h[0] = E830_GLTSYN_PTMTIME_H(0),
+ .dev_time_l[1] = E830_GLTSYN_PTMTIME_L(1),
+ .dev_time_h[1] = E830_GLTSYN_PTMTIME_H(1),
+};
+
+/**
+ * struct ice_crosststamp_ctx - Device cross timestamp context
+ * @snapshot: snapshot of system clocks for historic interpolation
+ * @pf: pointer to the PF private structure
+ * @cfg: pointer to hardware configuration for cross timestamp
+ */
+struct ice_crosststamp_ctx {
+ struct system_time_snapshot snapshot;
+ struct ice_pf *pf;
+ const struct ice_crosststamp_cfg *cfg;
+};
+
+/**
+ * ice_capture_crosststamp - Capture a device/system cross timestamp
* @device: Current device time
* @system: System counter value read synchronously with device time
- * @ctx: Context provided by timekeeping code
+ * @__ctx: Context passed from ice_ptp_getcrosststamp
*
* Read device and system (ART) clock simultaneously and return the corrected
* clock values in ns.
+ *
+ * Return: zero on success, or a negative error code on failure.
*/
-static int
-ice_ptp_get_syncdevicetime(ktime_t *device,
- struct system_counterval_t *system,
- void *ctx)
+static int ice_capture_crosststamp(ktime_t *device,
+ struct system_counterval_t *system,
+ void *__ctx)
{
- struct ice_pf *pf = (struct ice_pf *)ctx;
- struct ice_hw *hw = &pf->hw;
- u32 hh_lock, hh_art_ctl;
- int i;
+ struct ice_crosststamp_ctx *ctx = __ctx;
+ const struct ice_crosststamp_cfg *cfg;
+ u32 lock, ctl, ts_lo, ts_hi, tmr_idx;
+ struct ice_pf *pf;
+ struct ice_hw *hw;
+ int err;
+ u64 ts;
-#define MAX_HH_HW_LOCK_TRIES 5
-#define MAX_HH_CTL_LOCK_TRIES 100
+ cfg = ctx->cfg;
+ pf = ctx->pf;
+ hw = &pf->hw;
- for (i = 0; i < MAX_HH_HW_LOCK_TRIES; i++) {
- /* Get the HW lock */
- hh_lock = rd32(hw, PFHH_SEM + (PFTSYN_SEM_BYTES * hw->pf_id));
- if (hh_lock & PFHH_SEM_BUSY_M) {
- usleep_range(10000, 15000);
- continue;
- }
- break;
- }
- if (hh_lock & PFHH_SEM_BUSY_M) {
- dev_err(ice_pf_to_dev(pf), "PTP failed to get hh lock\n");
+ tmr_idx = hw->func_caps.ts_func_info.tmr_index_assoc;
+ if (tmr_idx > 1)
+ return -EINVAL;
+
+ /* Poll until we obtain the cross-timestamp hardware semaphore */
+ err = rd32_poll_timeout(hw, cfg->lock_reg, lock,
+ !(lock & cfg->lock_busy),
+ 10 * USEC_PER_MSEC, 50 * USEC_PER_MSEC);
+ if (err) {
+ dev_err(ice_pf_to_dev(pf), "PTP failed to get cross timestamp lock\n");
return -EBUSY;
}
+ /* Snapshot system time for historic interpolation */
+ ktime_get_snapshot(&ctx->snapshot);
+
/* Program cmd to master timer */
ice_ptp_src_cmd(hw, ICE_PTP_READ_TIME);
/* Start the ART and device clock sync sequence */
- hh_art_ctl = rd32(hw, GLHH_ART_CTL);
- hh_art_ctl = hh_art_ctl | GLHH_ART_CTL_ACTIVE_M;
- wr32(hw, GLHH_ART_CTL, hh_art_ctl);
-
- for (i = 0; i < MAX_HH_CTL_LOCK_TRIES; i++) {
- /* Wait for sync to complete */
- hh_art_ctl = rd32(hw, GLHH_ART_CTL);
- if (hh_art_ctl & GLHH_ART_CTL_ACTIVE_M) {
- udelay(1);
- continue;
- } else {
- u32 hh_ts_lo, hh_ts_hi, tmr_idx;
- u64 hh_ts;
-
- tmr_idx = hw->func_caps.ts_func_info.tmr_index_assoc;
- /* Read ART time */
- hh_ts_lo = rd32(hw, GLHH_ART_TIME_L);
- hh_ts_hi = rd32(hw, GLHH_ART_TIME_H);
- hh_ts = ((u64)hh_ts_hi << 32) | hh_ts_lo;
- system->cycles = hh_ts;
- system->cs_id = CSID_X86_ART;
- /* Read Device source clock time */
- hh_ts_lo = rd32(hw, GLTSYN_HHTIME_L(tmr_idx));
- hh_ts_hi = rd32(hw, GLTSYN_HHTIME_H(tmr_idx));
- hh_ts = ((u64)hh_ts_hi << 32) | hh_ts_lo;
- *device = ns_to_ktime(hh_ts);
- break;
- }
- }
+ ctl = rd32(hw, cfg->ctl_reg);
+ ctl |= cfg->ctl_active;
+ wr32(hw, cfg->ctl_reg, ctl);
+ /* Poll until hardware completes the capture */
+ err = rd32_poll_timeout(hw, cfg->ctl_reg, ctl, !(ctl & cfg->ctl_active),
+ 5, 20 * USEC_PER_MSEC);
+ if (err)
+ goto err_timeout;
+
+ /* Read ART system time */
+ ts_lo = rd32(hw, cfg->art_time_l);
+ ts_hi = rd32(hw, cfg->art_time_h);
+ ts = ((u64)ts_hi << 32) | ts_lo;
+ system->cycles = ts;
+ system->cs_id = CSID_X86_ART;
+
+ /* Read Device source clock time */
+ ts_lo = rd32(hw, cfg->dev_time_l[tmr_idx]);
+ ts_hi = rd32(hw, cfg->dev_time_h[tmr_idx]);
+ ts = ((u64)ts_hi << 32) | ts_lo;
+ *device = ns_to_ktime(ts);
+
+err_timeout:
/* Clear the master timer */
ice_ptp_src_cmd(hw, ICE_PTP_NOP);
/* Release HW lock */
- hh_lock = rd32(hw, PFHH_SEM + (PFTSYN_SEM_BYTES * hw->pf_id));
- hh_lock = hh_lock & ~PFHH_SEM_BUSY_M;
- wr32(hw, PFHH_SEM + (PFTSYN_SEM_BYTES * hw->pf_id), hh_lock);
-
- if (i == MAX_HH_CTL_LOCK_TRIES)
- return -ETIMEDOUT;
+ lock = rd32(hw, cfg->lock_reg);
+ lock &= ~cfg->lock_busy;
+ wr32(hw, cfg->lock_reg, lock);
- return 0;
+ return err;
}
/**
- * ice_ptp_getcrosststamp_e82x - Capture a device cross timestamp
+ * ice_ptp_getcrosststamp - Capture a device cross timestamp
* @info: the driver's PTP info structure
* @cts: The memory to fill the cross timestamp info
*
@@ -2230,23 +2294,35 @@ ice_ptp_get_syncdevicetime(ktime_t *device,
* clock. Fill the cross timestamp information and report it back to the
* caller.
*
- * This is only valid for E822 and E823 devices which have support for
- * generating the cross timestamp via PCIe PTM.
- *
* In order to correctly correlate the ART timestamp back to the TSC time, the
* CPU must have X86_FEATURE_TSC_KNOWN_FREQ.
+ *
+ * Return: zero on success, or a negative error code on failure.
*/
-static int
-ice_ptp_getcrosststamp_e82x(struct ptp_clock_info *info,
- struct system_device_crosststamp *cts)
+static int ice_ptp_getcrosststamp(struct ptp_clock_info *info,
+ struct system_device_crosststamp *cts)
{
struct ice_pf *pf = ptp_info_to_pf(info);
+ struct ice_crosststamp_ctx ctx = {};
+
+ ctx.pf = pf;
+
+ switch (pf->hw.ptp.phy_model) {
+ case ICE_PHY_E82X:
+ ctx.cfg = &ice_crosststamp_cfg_e82x;
+ break;
+ case ICE_PHY_E830:
+ ctx.cfg = &ice_crosststamp_cfg_e830;
+ break;
+ default:
+ return -EOPNOTSUPP;
+ }
- return get_device_system_crosststamp(ice_ptp_get_syncdevicetime,
- pf, NULL, cts);
+ return get_device_system_crosststamp(ice_capture_crosststamp, &ctx,
+ &ctx.snapshot, cts);
}
-#endif /* CONFIG_ICE_HWTS */
+#endif /* CONFIG_ICE_HWTS */
/**
* ice_ptp_get_ts_config - ioctl interface to read the timestamping config
* @pf: Board private structure
@@ -2523,7 +2599,7 @@ static void ice_ptp_set_funcs_e82x(struct ice_pf *pf)
#ifdef CONFIG_ICE_HWTS
if (boot_cpu_has(X86_FEATURE_ART) &&
boot_cpu_has(X86_FEATURE_TSC_KNOWN_FREQ))
- pf->ptp.info.getcrosststamp = ice_ptp_getcrosststamp_e82x;
+ pf->ptp.info.getcrosststamp = ice_ptp_getcrosststamp;
#endif /* CONFIG_ICE_HWTS */
if (ice_is_e825c(&pf->hw)) {
@@ -2592,6 +2668,28 @@ static void ice_ptp_set_funcs_e810(struct ice_pf *pf)
}
}
+/**
+ * ice_ptp_set_funcs_e830 - Set specialized functions for E830 support
+ * @pf: Board private structure
+ *
+ * Assign functions to the PTP capabiltiies structure for E830 devices.
+ * Functions which operate across all device families should be set directly
+ * in ice_ptp_set_caps. Only add functions here which are distinct for E830
+ * devices.
+ */
+static void ice_ptp_set_funcs_e830(struct ice_pf *pf)
+{
+#ifdef CONFIG_ICE_HWTS
+ if (pcie_ptm_enabled(pf->pdev) &&
+ boot_cpu_has(X86_FEATURE_ART) &&
+ boot_cpu_has(X86_FEATURE_TSC_KNOWN_FREQ))
+ pf->ptp.info.getcrosststamp = ice_ptp_getcrosststamp;
+#endif /* CONFIG_ICE_HWTS */
+
+ /* Rest of the config is the same as base E810 */
+ ice_ptp_set_funcs_e810(pf);
+}
+
/**
* ice_ptp_set_caps - Set PTP capabilities
* @pf: Board private structure
@@ -2614,8 +2712,10 @@ static void ice_ptp_set_caps(struct ice_pf *pf)
info->enable = ice_ptp_gpio_enable;
info->verify = ice_verify_pin;
- if (ice_is_e810(&pf->hw) || ice_is_e830(&pf->hw))
+ if (ice_is_e810(&pf->hw))
ice_ptp_set_funcs_e810(pf);
+ if (ice_is_e830(&pf->hw))
+ ice_ptp_set_funcs_e830(pf);
else
ice_ptp_set_funcs_e82x(pf);
}
--
2.45.2
^ permalink raw reply related [flat|nested] 16+ messages in thread
* Re: [PATCH v3 iwl-next 4/4] ice: combine cross timestamp functions for E82x and E830
2024-07-25 9:34 ` [PATCH v3 iwl-next 4/4] ice: combine cross timestamp functions for E82x and E830 Karol Kolacinski
@ 2024-07-25 16:31 ` Jacob Keller
2024-07-26 13:37 ` [Intel-wired-lan] " Alexander Lobakin
1 sibling, 0 replies; 16+ messages in thread
From: Jacob Keller @ 2024-07-25 16:31 UTC (permalink / raw)
To: Karol Kolacinski, intel-wired-lan
Cc: netdev, anthony.l.nguyen, przemyslaw.kitszel
On 7/25/2024 2:34 AM, Karol Kolacinski wrote:
> From: Jacob Keller <jacob.e.keller@intel.com>
>
> The E830 and E82x devices use essentially the same logic for performing
> a crosstimestamp. The only difference is that E830 hardware has
> different offsets. Instead of having two implementations, combine them
> into a single ice_capture_crosststamp() function.
>
> Also combine the wrapper functions which call
> get_device_system_crosststamp() into a single ice_ptp_getcrosststamp()
> function.
>
The commit message could probably be updated since I think this is
referring to E830 code which is only in our internal branch. I guess you
must have squashed this together with the original E830 implementation
rather than sending that up and then this refactor/cleanup?
Not a huge deal, but it is somewhat confusing when reading the actual
patch code.
Thanks,
Jake
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [Intel-wired-lan] [PATCH v3 iwl-next 1/4] ice: Implement PTP support for E830 devices
2024-07-25 9:34 ` [PATCH v3 iwl-next 1/4] " Karol Kolacinski
@ 2024-07-26 13:17 ` Alexander Lobakin
0 siblings, 0 replies; 16+ messages in thread
From: Alexander Lobakin @ 2024-07-26 13:17 UTC (permalink / raw)
To: Karol Kolacinski
Cc: intel-wired-lan, Paul Greenwalt, Michal Michalik, netdev,
anthony.l.nguyen, przemyslaw.kitszel, Milena Olech
From: Karol Kolacinski <karol.kolacinski@intel.com>
Date: Thu, 25 Jul 2024 11:34:48 +0200
> From: Michal Michalik <michal.michalik@intel.com>
>
> Add specific functions and definitions for E830 devices to enable
> PTP support.
> Introduce new PHY model ICE_PHY_E830.
> E830 devices support direct write to GLTSYN_ registers without shadow
> registers and 64 bit read of PHC time.
>
> Reviewed-by: Przemek Kitszel <przemyslaw.kitszel@intel.com>
> Co-developed-by: Milena Olech <milena.olech@intel.com>
> Signed-off-by: Milena Olech <milena.olech@intel.com>
> Co-developed-by: Paul Greenwalt <paul.greenwalt@intel.com>
> Signed-off-by: Paul Greenwalt <paul.greenwalt@intel.com>
> Signed-off-by: Michal Michalik <michal.michalik@intel.com>
> Co-developed-by: Karol Kolacinski <karol.kolacinski@intel.com>
> Signed-off-by: Karol Kolacinski <karol.kolacinski@intel.com>
> ---
> V2 -> V3: Fixed kdoc for ice_is_e***() and ice_ptp_init_phy_e830()
> V1 -> V2: Fixed compilation issue with GENMASK bits higher than 32
>
> drivers/net/ethernet/intel/ice/ice_common.c | 13 +-
> drivers/net/ethernet/intel/ice/ice_common.h | 1 +
> .../net/ethernet/intel/ice/ice_hw_autogen.h | 4 +
> drivers/net/ethernet/intel/ice/ice_ptp.c | 11 +-
> drivers/net/ethernet/intel/ice/ice_ptp_hw.c | 199 ++++++++++++++++--
> drivers/net/ethernet/intel/ice/ice_ptp_hw.h | 25 ++-
> drivers/net/ethernet/intel/ice/ice_type.h | 1 +
> 7 files changed, 226 insertions(+), 28 deletions(-)
>
> diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c
> index 009716a12a26..8bff63d3d664 100644
> --- a/drivers/net/ethernet/intel/ice/ice_common.c
> +++ b/drivers/net/ethernet/intel/ice/ice_common.c
> @@ -267,7 +267,7 @@ bool ice_is_e822(struct ice_hw *hw)
> * ice_is_e823
> * @hw: pointer to the hardware structure
> *
> - * returns true if the device is E823-L or E823-C based, false if not.
> + * Return: true if the device is E823-L or E823-C based, false if not.
I'd move this, together with FIELD_{GET,PREP}() conversion, to a
separate commit maybe (one is enough).
> */
> bool ice_is_e823(struct ice_hw *hw)
> {
> @@ -307,6 +307,17 @@ bool ice_is_e825c(struct ice_hw *hw)
> }
> }
>
> +/**
> + * ice_is_e830
> + * @hw: pointer to the hardware structure
> + *
> + * Return: true if the device is E830 based, false if not.
> + */
> +bool ice_is_e830(const struct ice_hw *hw)
> +{
> + return hw->mac_type == ICE_MAC_E830;
> +}
I think making this one check external instead of a static inline only
increases object code size. Can't they reside in the header?
[...]
> +/**
> + * ice_ptp_init_phc_e830 - Perform E830 specific PHC initialization
> + * @hw: pointer to HW struct
> + *
> + * Perform E830-specific PTP hardware clock initialization steps.
> + *
> + * Return: 0 on success
> + */
> +static int ice_ptp_init_phc_e830(struct ice_hw *hw)
> +{
> + ice_ptp_cfg_sync_delay(hw, ICE_E810_E830_SYNC_DELAY);
> + return 0;
Can't this and the below functions be void since they always return zero?
> +}
> +
> +/**
> + * ice_ptp_write_direct_incval_e830 - Prep PHY port increment value change
> + * @hw: pointer to HW struct
> + * @incval: The new 40bit increment value to prepare
> + *
> + * Prepare the PHY port for a new increment value by programming the PHC
> + * GLTSYN_INCVAL_L and GLTSYN_INCVAL_H registers. The actual change is
> + * completed by FW automatically.
> + */
> +static int ice_ptp_write_direct_incval_e830(struct ice_hw *hw, u64 incval)
const @hw (below as well)?
[...]
> @@ -5474,12 +5618,14 @@ void ice_ptp_init_hw(struct ice_hw *hw)
> {
> struct ice_ptp_hw *ptp = &hw->ptp;
>
> - if (ice_is_e822(hw) || ice_is_e823(hw))
> - ice_ptp_init_phy_e82x(ptp);
> - else if (ice_is_e810(hw))
> + if (ice_is_e810(hw))
> ice_ptp_init_phy_e810(ptp);
> + else if (ice_is_e822(hw) || ice_is_e823(hw))
> + ice_ptp_init_phy_e82x(ptp);
> else if (ice_is_e825c(hw))
> ice_ptp_init_phy_e825c(hw);
> + else if (ice_is_e830(hw))
> + ice_ptp_init_phy_e830(ptp);
> else
> ptp->phy_model = ICE_PHY_UNSUP;
Since at least most of these functions just check for one field, can't
this be one switch-case on that fields (if you open-code that check)?
> }
> @@ -5570,6 +5716,8 @@ static int ice_ptp_port_cmd(struct ice_hw *hw, enum ice_ptp_tmr_cmd cmd)
> switch (hw->ptp.phy_model) {
> case ICE_PHY_E810:
> return ice_ptp_port_cmd_e810(hw, cmd);
> + case ICE_PHY_E830:
> + return ice_ptp_port_cmd_e830(hw, cmd);
> default:
> break;
> }
> @@ -5640,6 +5788,10 @@ int ice_ptp_init_time(struct ice_hw *hw, u64 time)
> tmr_idx = hw->func_caps.ts_func_info.tmr_index_owned;
>
> /* Source timers */
> + /* For E830 we don't need to use shadow registers, its automatic */
^^^
it's
[...]
Thanks,
Olek
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [Intel-wired-lan] [PATCH v3 iwl-next 2/4] ice: Process TSYN IRQ in a separate function
2024-07-25 9:34 ` [PATCH v3 iwl-next 2/4] ice: Process TSYN IRQ in a separate function Karol Kolacinski
@ 2024-07-26 13:22 ` Alexander Lobakin
0 siblings, 0 replies; 16+ messages in thread
From: Alexander Lobakin @ 2024-07-26 13:22 UTC (permalink / raw)
To: Karol Kolacinski
Cc: intel-wired-lan, netdev, anthony.l.nguyen, przemyslaw.kitszel
From: Karol Kolacinski <karol.kolacinski@intel.com>
Date: Thu, 25 Jul 2024 11:34:49 +0200
> 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.kitszel@intel.com>
> Signed-off-by: Karol Kolacinski <karol.kolacinski@intel.com>
[...]
> +/**
> + * 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
In the previous commit, you used 'Return:', here you have 'Returns:'.
Perhaps you may want to keep the style consistent :)
> + * 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);
It's top half, right? If so, you don't need _irqsave versions, just
spin_lock/unlock().
_irqsave/restore are only to be used in either BH or process context to
temporarily disable interrupts to avoid concurrent access with TH (e.g.
this block).
> + 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;
> + }
> +}
[...]
Thanks,
Olek
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [Intel-wired-lan] [PATCH v3 iwl-next 3/4] ice: Add timestamp ready bitmap for E830 products
2024-07-25 9:34 ` [PATCH v3 iwl-next 3/4] ice: Add timestamp ready bitmap for E830 products Karol Kolacinski
@ 2024-07-26 13:25 ` Alexander Lobakin
0 siblings, 0 replies; 16+ messages in thread
From: Alexander Lobakin @ 2024-07-26 13:25 UTC (permalink / raw)
To: Karol Kolacinski
Cc: intel-wired-lan, netdev, anthony.l.nguyen, przemyslaw.kitszel
From: Karol Kolacinski <karol.kolacinski@intel.com>
Date: Thu, 25 Jul 2024 11:34:50 +0200
> E830 PHY supports timestamp ready bitmap.
> Enable the bitmap by refactoring tx init function.
>
> Reviewed-by: Przemek Kitszel <przemyslaw.kitszel@intel.com>
> Signed-off-by: Karol Kolacinski <karol.kolacinski@intel.com>
[...]
> @@ -987,24 +965,25 @@ ice_ptp_init_tx_e82x(struct ice_pf *pf, struct ice_ptp_tx *tx, u8 port)
> }
>
> /**
> - * ice_ptp_init_tx_e810 - Initialize tracking for Tx timestamps
> + * ice_ptp_init_tx - Initialize tracking for Tx timestamps
> * @pf: Board private structure
> * @tx: the Tx tracking structure to initialize
> + * @port: the port this structure tracks
> *
> - * Initialize the Tx timestamp tracker for this PF. For E810 devices, each
> - * port has its own block of timestamps, independent of the other ports.
> + * Initialize the Tx timestamp tracker for this PF. For all PHYs except E82X,
> + * each port has its own block of timestamps, independent of the other ports.
A 'Return:' block?
> */
> -static int
> -ice_ptp_init_tx_e810(struct ice_pf *pf, struct ice_ptp_tx *tx)
> +static int ice_ptp_init_tx(struct ice_pf *pf, struct ice_ptp_tx *tx, u8 port)
> {
> - tx->block = pf->hw.port_info->lport;
> + tx->block = port;
> tx->offset = 0;
> - tx->len = INDEX_PER_PORT_E810;
> + tx->len = INDEX_PER_PORT;
> +
> /* The E810 PHY does not provide a timestamp ready bitmap. Instead,
> * verify new timestamps against cached copy of the last read
> * timestamp.
> */
> - tx->has_ready_bitmap = 0;
> + tx->has_ready_bitmap = pf->hw.ptp.phy_model != ICE_PHY_E810;
>
> return ice_ptp_alloc_tx_tracker(tx);
> }
[...]
Thanks,
Olek
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [Intel-wired-lan] [PATCH v3 iwl-next 4/4] ice: combine cross timestamp functions for E82x and E830
2024-07-25 9:34 ` [PATCH v3 iwl-next 4/4] ice: combine cross timestamp functions for E82x and E830 Karol Kolacinski
2024-07-25 16:31 ` Jacob Keller
@ 2024-07-26 13:37 ` Alexander Lobakin
2024-07-26 23:16 ` Jacob Keller
2024-08-05 16:21 ` Kolacinski, Karol
1 sibling, 2 replies; 16+ messages in thread
From: Alexander Lobakin @ 2024-07-26 13:37 UTC (permalink / raw)
To: Karol Kolacinski
Cc: intel-wired-lan, Jacob Keller, netdev, anthony.l.nguyen,
przemyslaw.kitszel
From: Karol Kolacinski <karol.kolacinski@intel.com>
Date: Thu, 25 Jul 2024 11:34:51 +0200
> From: Jacob Keller <jacob.e.keller@intel.com>
>
> The E830 and E82x devices use essentially the same logic for performing
> a crosstimestamp. The only difference is that E830 hardware has
> different offsets. Instead of having two implementations, combine them
> into a single ice_capture_crosststamp() function.
>
> Also combine the wrapper functions which call
> get_device_system_crosststamp() into a single ice_ptp_getcrosststamp()
> function.
>
> To support both hardware types, the ice_capture_crosststamp function
> must be able to determine the appropriate registers to access. To handle
> this, pass a custom context structure instead of the PF pointer. This
> structure, ice_crosststamp_ctx, contains a pointer to the PF, and
> a pointer to the device configuration structure. This new structure also
> will make it easier to implement historic snapshot support in a future
> commit.
>
> The device configuration structure is a static const data which defines
> the offsets and flags for the various registers. This includes the lock
> register, the cross timestamp control register, the upper and lower ART
> system time capture registers, and the upper and lower device time
> capture registers for each timer index.
>
> This does add extra data to the .text of the module (and thus kernel),
> but it also removes 2 near duplicate functions for enabling E830
> support.
>
> Use the configuration structure to access all of the registers in
> ice_capture_crosststamp(). Ensure that we don't over-run the device time
> array by checking that the timer index is 0 or 1. Previously this was
> simply assumed, and it would cause the device to read an incorrect and
> likely garbage register.
>
> It does feel like there should be a kernel interface for managing
> register offsets like this, but the closest thing I saw was
> <linux/regmap.h> which is interesting but not quite what we're looking
> for...
>
> Reviewed-by: Przemek Kitszel <przemyslaw.kitszel@intel.com>
> Signed-off-by: Jacob Keller <jacob.e.keller@intel.com>
> Signed-off-by: Karol Kolacinski <karol.kolacinski@intel.com>
[...]
> diff --git a/drivers/net/ethernet/intel/ice/ice_osdep.h b/drivers/net/ethernet/intel/ice/ice_osdep.h
> index a2562f04267f..c03ab0207e0a 100644
> --- a/drivers/net/ethernet/intel/ice/ice_osdep.h
> +++ b/drivers/net/ethernet/intel/ice/ice_osdep.h
> @@ -23,6 +23,9 @@
> #define wr64(a, reg, value) writeq((value), ((a)->hw_addr + (reg)))
> #define rd64(a, reg) readq((a)->hw_addr + (reg))
>
> +#define rd32_poll_timeout(a, addr, val, cond, delay_us, timeout_us) \
> + read_poll_timeout(rd32, val, cond, delay_us, timeout_us, false, a, addr)
> +
> #define ice_flush(a) rd32((a), GLGEN_STAT)
> #define ICE_M(m, s) ((m ## U) << (s))
>
> diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c
> index 9f0eff040a95..ac3944fec2d3 100644
> --- a/drivers/net/ethernet/intel/ice/ice_ptp.c
> +++ b/drivers/net/ethernet/intel/ice/ice_ptp.c
> @@ -1,6 +1,7 @@
> // SPDX-License-Identifier: GPL-2.0
> /* Copyright (C) 2021, Intel Corporation. */
>
> +#include <linux/iopoll.h>
read_poll_timeout() is used in osdep.h, but you include it here.
You should either define rd32_poll_timeout() here instead of the header
or move this include to osdep.h.
> #include "ice.h"
> #include "ice_lib.h"
> #include "ice_trace.h"
[...]
> -static int
> -ice_ptp_getcrosststamp_e82x(struct ptp_clock_info *info,
> - struct system_device_crosststamp *cts)
> +static int ice_ptp_getcrosststamp(struct ptp_clock_info *info,
> + struct system_device_crosststamp *cts)
> {
> struct ice_pf *pf = ptp_info_to_pf(info);
> + struct ice_crosststamp_ctx ctx = {};
> +
> + ctx.pf = pf;
struct ice_crosststamp_ctx ctx = {
.pf = pf,
};
> +
> + switch (pf->hw.ptp.phy_model) {
> + case ICE_PHY_E82X:
> + ctx.cfg = &ice_crosststamp_cfg_e82x;
> + break;
> + case ICE_PHY_E830:
> + ctx.cfg = &ice_crosststamp_cfg_e830;
> + break;
> + default:
> + return -EOPNOTSUPP;
> + }
>
> - return get_device_system_crosststamp(ice_ptp_get_syncdevicetime,
> - pf, NULL, cts);
> + return get_device_system_crosststamp(ice_capture_crosststamp, &ctx,
> + &ctx.snapshot, cts);
> }
> -#endif /* CONFIG_ICE_HWTS */
>
> +#endif /* CONFIG_ICE_HWTS */
> /**
> * ice_ptp_get_ts_config - ioctl interface to read the timestamping config
> * @pf: Board private structure
> @@ -2523,7 +2599,7 @@ static void ice_ptp_set_funcs_e82x(struct ice_pf *pf)
> #ifdef CONFIG_ICE_HWTS
> if (boot_cpu_has(X86_FEATURE_ART) &&
> boot_cpu_has(X86_FEATURE_TSC_KNOWN_FREQ))
> - pf->ptp.info.getcrosststamp = ice_ptp_getcrosststamp_e82x;
> + pf->ptp.info.getcrosststamp = ice_ptp_getcrosststamp;
>
> #endif /* CONFIG_ICE_HWTS */
> if (ice_is_e825c(&pf->hw)) {
> @@ -2592,6 +2668,28 @@ static void ice_ptp_set_funcs_e810(struct ice_pf *pf)
> }
> }
>
> +/**
> + * ice_ptp_set_funcs_e830 - Set specialized functions for E830 support
> + * @pf: Board private structure
> + *
> + * Assign functions to the PTP capabiltiies structure for E830 devices.
> + * Functions which operate across all device families should be set directly
> + * in ice_ptp_set_caps. Only add functions here which are distinct for E830
> + * devices.
> + */
> +static void ice_ptp_set_funcs_e830(struct ice_pf *pf)
> +{
> +#ifdef CONFIG_ICE_HWTS
> + if (pcie_ptm_enabled(pf->pdev) &&
> + boot_cpu_has(X86_FEATURE_ART) &&
> + boot_cpu_has(X86_FEATURE_TSC_KNOWN_FREQ))
> + pf->ptp.info.getcrosststamp = ice_ptp_getcrosststamp;
> +#endif /* CONFIG_ICE_HWTS */
I've seen this pattern in several drivers already. I really feel like it
needs a generic wrapper.
I mean, there should be something like
arch/x86/include/asm/ptm.h (not sure about the name)
where you put let's say
static inline bool arch_has_ptm(struct pci_device *pdev)
Same for
include/asm-generic/ptm.h
there it will be `return false`.
In include/asm-generic/Kbuild, you add
mandatory-y += ptm.h.
Then, include/linux/ptm.h should include <asm/ptm.h> and in your driver
sources, you include <linux/ptm.h> and check
if (arch_has_ptm(pdev))
pf->ptp.info.getcrosststamp = ice_ptp_getcrosststamp;
It's just a draft, adjust accordingly.
Checking for x86 features in the driver doesn't look good. Especially
when you add ARM64 or whatever support in future.
> +
> + /* Rest of the config is the same as base E810 */
> + ice_ptp_set_funcs_e810(pf);
> +}
Thanks,
Olek
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [Intel-wired-lan] [PATCH v3 iwl-next 4/4] ice: combine cross timestamp functions for E82x and E830
2024-07-26 13:37 ` [Intel-wired-lan] " Alexander Lobakin
@ 2024-07-26 23:16 ` Jacob Keller
2024-08-05 16:21 ` Kolacinski, Karol
1 sibling, 0 replies; 16+ messages in thread
From: Jacob Keller @ 2024-07-26 23:16 UTC (permalink / raw)
To: Alexander Lobakin, Karol Kolacinski
Cc: intel-wired-lan, netdev, anthony.l.nguyen, przemyslaw.kitszel
On 7/26/2024 6:37 AM, Alexander Lobakin wrote:
>> diff --git a/drivers/net/ethernet/intel/ice/ice_osdep.h b/drivers/net/ethernet/intel/ice/ice_osdep.h
>> index a2562f04267f..c03ab0207e0a 100644
>> --- a/drivers/net/ethernet/intel/ice/ice_osdep.h
>> +++ b/drivers/net/ethernet/intel/ice/ice_osdep.h
>> @@ -23,6 +23,9 @@
>> #define wr64(a, reg, value) writeq((value), ((a)->hw_addr + (reg)))
>> #define rd64(a, reg) readq((a)->hw_addr + (reg))
>>
>> +#define rd32_poll_timeout(a, addr, val, cond, delay_us, timeout_us) \
>> + read_poll_timeout(rd32, val, cond, delay_us, timeout_us, false, a, addr)
>> +
>> #define ice_flush(a) rd32((a), GLGEN_STAT)
>> #define ICE_M(m, s) ((m ## U) << (s))
>>
>> diff --git a/drivers/net/ethernet/intel/ice/ice_ptp.c b/drivers/net/ethernet/intel/ice/ice_ptp.c
>> index 9f0eff040a95..ac3944fec2d3 100644
>> --- a/drivers/net/ethernet/intel/ice/ice_ptp.c
>> +++ b/drivers/net/ethernet/intel/ice/ice_ptp.c
>> @@ -1,6 +1,7 @@
>> // SPDX-License-Identifier: GPL-2.0
>> /* Copyright (C) 2021, Intel Corporation. */
>>
>> +#include <linux/iopoll.h>
>
> read_poll_timeout() is used in osdep.h, but you include it here.
> You should either define rd32_poll_timeout() here instead of the header
> or move this include to osdep.h.
>
Please move the include to ice_osdep.h, as there are some other places
where we will want to use rd32_poll_timeout (such as in ice_controlq.c,
and others).
Thanks,
Jake
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [Intel-wired-lan] [PATCH v3 iwl-next 4/4] ice: combine cross timestamp functions for E82x and E830
2024-07-26 13:37 ` [Intel-wired-lan] " Alexander Lobakin
2024-07-26 23:16 ` Jacob Keller
@ 2024-08-05 16:21 ` Kolacinski, Karol
2024-08-07 13:54 ` Alexander Lobakin
1 sibling, 1 reply; 16+ messages in thread
From: Kolacinski, Karol @ 2024-08-05 16:21 UTC (permalink / raw)
To: Lobakin, Aleksander
Cc: intel-wired-lan@lists.osuosl.org, Keller, Jacob E,
netdev@vger.kernel.org, Nguyen, Anthony L, Kitszel, Przemyslaw
From: Aleksander Lobakin <aleksander.lobakin@intel.com>
Date: Fri, 26 Jul 2024 15:37 +0200
> > +/**
> > + * ice_ptp_set_funcs_e830 - Set specialized functions for E830 support
> > + * @pf: Board private structure
> > + *
> > + * Assign functions to the PTP capabiltiies structure for E830 devices.
> > + * Functions which operate across all device families should be set directly
> > + * in ice_ptp_set_caps. Only add functions here which are distinct for E830
> > + * devices.
> > + */
> > +static void ice_ptp_set_funcs_e830(struct ice_pf *pf)
> > +{
> > +#ifdef CONFIG_ICE_HWTS
> > + if (pcie_ptm_enabled(pf->pdev) &&
> > + boot_cpu_has(X86_FEATURE_ART) &&
> > + boot_cpu_has(X86_FEATURE_TSC_KNOWN_FREQ))
> > + pf->ptp.info.getcrosststamp = ice_ptp_getcrosststamp;
> > +#endif /* CONFIG_ICE_HWTS */
>
> I've seen this pattern in several drivers already. I really feel like it
> needs a generic wrapper.
> I mean, there should be something like
>
> arch/x86/include/asm/ptm.h (not sure about the name)
>
> where you put let's say
>
> static inline bool arch_has_ptm(struct pci_device *pdev)
>
> Same for
>
> include/asm-generic/ptm.h
>
> there it will be `return false`.
>
> In include/asm-generic/Kbuild, you add
>
> mandatory-y += ptm.h.
>
> Then, include/linux/ptm.h should include <asm/ptm.h> and in your driver
> sources, you include <linux/ptm.h> and check
>
> if (arch_has_ptm(pdev))
> pf->ptp.info.getcrosststamp = ice_ptp_getcrosststamp;
>
> It's just a draft, adjust accordingly.
>
> Checking for x86 features in the driver doesn't look good. Especially
> when you add ARM64 or whatever support in future.
For PTM, we check only pcie_ptm_enabled(). PTM is a PCIE feature
supported regardless of arch.
The two other checks are for the x86 Always Running Timer (ART) and x86
TimeStamp Counter (TSC) features. Those are not tied to PTM, but are
necessary for crosstimestamping on devices supported by ice driver.
I guess I can remove checks from E82X since all of those are SoC, so
HW always supports this.
For E830, I see no other way, than to check the ART feature. This is
what the HW latches in its registers.
I think we could drop TSC_KNOWN_FREQ check since there's new logic
around get_device_system_crosststamp() and cycles conversion.
Thanks,
Karol
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [Intel-wired-lan] [PATCH v3 iwl-next 4/4] ice: combine cross timestamp functions for E82x and E830
2024-08-05 16:21 ` Kolacinski, Karol
@ 2024-08-07 13:54 ` Alexander Lobakin
2024-08-07 14:26 ` Kolacinski, Karol
0 siblings, 1 reply; 16+ messages in thread
From: Alexander Lobakin @ 2024-08-07 13:54 UTC (permalink / raw)
To: Kolacinski, Karol
Cc: intel-wired-lan@lists.osuosl.org, Keller, Jacob E,
netdev@vger.kernel.org, Nguyen, Anthony L, Kitszel, Przemyslaw
From: Kolacinski, Karol <karol.kolacinski@intel.com>
Date: Mon, 5 Aug 2024 18:21:39 +0200
> From: Aleksander Lobakin <aleksander.lobakin@intel.com>
> Date: Fri, 26 Jul 2024 15:37 +0200
>>> +/**
>>> + * ice_ptp_set_funcs_e830 - Set specialized functions for E830 support
>>> + * @pf: Board private structure
>>> + *
>>> + * Assign functions to the PTP capabiltiies structure for E830 devices.
>>> + * Functions which operate across all device families should be set directly
>>> + * in ice_ptp_set_caps. Only add functions here which are distinct for E830
>>> + * devices.
>>> + */
>>> +static void ice_ptp_set_funcs_e830(struct ice_pf *pf)
>>> +{
>>> +#ifdef CONFIG_ICE_HWTS
>>> + if (pcie_ptm_enabled(pf->pdev) &&
>>> + boot_cpu_has(X86_FEATURE_ART) &&
>>> + boot_cpu_has(X86_FEATURE_TSC_KNOWN_FREQ))
>>> + pf->ptp.info.getcrosststamp = ice_ptp_getcrosststamp;
>>> +#endif /* CONFIG_ICE_HWTS */
>>
>> I've seen this pattern in several drivers already. I really feel like it
>> needs a generic wrapper.
>> I mean, there should be something like
>>
>> arch/x86/include/asm/ptm.h (not sure about the name)
>>
>> where you put let's say
>>
>> static inline bool arch_has_ptm(struct pci_device *pdev)
>>
>> Same for
>>
>> include/asm-generic/ptm.h
>>
>> there it will be `return false`.
>>
>> In include/asm-generic/Kbuild, you add
>>
>> mandatory-y += ptm.h.
>>
>> Then, include/linux/ptm.h should include <asm/ptm.h> and in your driver
>> sources, you include <linux/ptm.h> and check
>>
>> if (arch_has_ptm(pdev))
>> pf->ptp.info.getcrosststamp = ice_ptp_getcrosststamp;
>>
>> It's just a draft, adjust accordingly.
>>
>> Checking for x86 features in the driver doesn't look good. Especially
>> when you add ARM64 or whatever support in future.
>
> For PTM, we check only pcie_ptm_enabled(). PTM is a PCIE feature
> supported regardless of arch.
>
> The two other checks are for the x86 Always Running Timer (ART) and x86
> TimeStamp Counter (TSC) features. Those are not tied to PTM, but are
> necessary for crosstimestamping on devices supported by ice driver.
Ah okay, it's not tied.
So, instead of asm/ptm.h, it should be named somehow else :D
But this X86_FEATURE_ART + X86_FEATURE_TSC_KNOWN_FREQ check really
should be abstracted to something like arch_has_crosststamp() or
arch_has_tstamp(), dunno. Maybe to the already existing asm/timex.h?
Then, implementing this for ARM64 would be easier, as instead of adding
more ifdefs and checks you'd just implement arch_has_tstamp() in its
timex.h (I've seen Milena'd been playing with PTP on ARM).
At least that's how I see it. But if it's fine for the maintainers to
have arch-specific ifdefs and the same code pattern in several drivers,
I'm fine, too :D
>
> I guess I can remove checks from E82X since all of those are SoC, so
> HW always supports this.
>
> For E830, I see no other way, than to check the ART feature. This is
> what the HW latches in its registers.
> I think we could drop TSC_KNOWN_FREQ check since there's new logic
> around get_device_system_crosststamp() and cycles conversion.
>
> Thanks,
> Karol
Thanks,
Olek
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [Intel-wired-lan] [PATCH v3 iwl-next 4/4] ice: combine cross timestamp functions for E82x and E830
2024-08-07 13:54 ` Alexander Lobakin
@ 2024-08-07 14:26 ` Kolacinski, Karol
2024-08-08 13:00 ` Alexander Lobakin
0 siblings, 1 reply; 16+ messages in thread
From: Kolacinski, Karol @ 2024-08-07 14:26 UTC (permalink / raw)
To: Lobakin, Aleksander
Cc: intel-wired-lan@lists.osuosl.org, Keller, Jacob E,
netdev@vger.kernel.org, Nguyen, Anthony L, Kitszel, Przemyslaw
From: Aleksander Lobakin <aleksander.lobakin@intel.com>
Date: Wed, 07 Aug 2024 15:54 +0200
>>>> +static void ice_ptp_set_funcs_e830(struct ice_pf *pf)
>>>> +{
>>>> +#ifdef CONFIG_ICE_HWTS
>>>> + if (pcie_ptm_enabled(pf->pdev) &&
>>>> + boot_cpu_has(X86_FEATURE_ART) &&
>>>> + boot_cpu_has(X86_FEATURE_TSC_KNOWN_FREQ))
>>>> + pf->ptp.info.getcrosststamp = ice_ptp_getcrosststamp;
>>>> +#endif /* CONFIG_ICE_HWTS */
>>>
>>> I've seen this pattern in several drivers already. I really feel like it
>>> needs a generic wrapper.
>>> I mean, there should be something like
>>>
>>> arch/x86/include/asm/ptm.h (not sure about the name)
>>>
>>> where you put let's say
>>>
>>> static inline bool arch_has_ptm(struct pci_device *pdev)
>>>
>>> Same for
>>>
>>> include/asm-generic/ptm.h
>>>
>>> there it will be `return false`.
>>>
>>> In include/asm-generic/Kbuild, you add
>>>
>>> mandatory-y += ptm.h.
>>>
>>> Then, include/linux/ptm.h should include <asm/ptm.h> and in your driver
>>> sources, you include <linux/ptm.h> and check
>>>
>>> if (arch_has_ptm(pdev))
>>> pf->ptp.info.getcrosststamp = ice_ptp_getcrosststamp;
>>>
>>> It's just a draft, adjust accordingly.
>>>
>>> Checking for x86 features in the driver doesn't look good. Especially
>>> when you add ARM64 or whatever support in future.
>>
>> For PTM, we check only pcie_ptm_enabled(). PTM is a PCIE feature
>> supported regardless of arch.
>>
>> The two other checks are for the x86 Always Running Timer (ART) and x86
>> TimeStamp Counter (TSC) features. Those are not tied to PTM, but are
>> necessary for crosstimestamping on devices supported by ice driver.
>
> Ah okay, it's not tied.
> So, instead of asm/ptm.h, it should be named somehow else :D
>
> But this X86_FEATURE_ART + X86_FEATURE_TSC_KNOWN_FREQ check really
> should be abstracted to something like arch_has_crosststamp() or
> arch_has_tstamp(), dunno. Maybe to the already existing asm/timex.h?
> Then, implementing this for ARM64 would be easier, as instead of adding
> more ifdefs and checks you'd just implement arch_has_tstamp() in its
> timex.h (I've seen Milena'd been playing with PTP on ARM).
> At least that's how I see it. But if it's fine for the maintainers to
> have arch-specific ifdefs and the same code pattern in several drivers,
> I'm fine, too :D
Technically, neither ART nor TSC are directly related to the PTP cross
timestamp. It's just the implementation on Intel NICs, where those
NICs use x86 ART to crosstimestamp.
For cross timestamp on ARM, it's also HW specific and depends on which
timer the HW uses for timestamping. I'm not really sure what's the HW
protocol in this case and if e.g. E830 can latch other timers than
x86 ART in its ART_TIME registers.
get_device_system_crosststamp() supports multiple clock sources defined
in enum clocksource_ids. Maybe instead of checking ART flag, the driver
could get clocksources and if CSID_X86_ART is available, it would assign
the pointer to crosststamp function, but I'm not convinced.
Thanks,
Karol
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [Intel-wired-lan] [PATCH v3 iwl-next 4/4] ice: combine cross timestamp functions for E82x and E830
2024-08-07 14:26 ` Kolacinski, Karol
@ 2024-08-08 13:00 ` Alexander Lobakin
2024-08-08 14:20 ` Jakub Kicinski
0 siblings, 1 reply; 16+ messages in thread
From: Alexander Lobakin @ 2024-08-08 13:00 UTC (permalink / raw)
To: Kolacinski, Karol
Cc: intel-wired-lan@lists.osuosl.org, Keller, Jacob E,
netdev@vger.kernel.org, Nguyen, Anthony L, Kitszel, Przemyslaw
From: Kolacinski, Karol <karol.kolacinski@intel.com>
Date: Wed, 7 Aug 2024 16:26:29 +0200
> From: Aleksander Lobakin <aleksander.lobakin@intel.com>
> Date: Wed, 07 Aug 2024 15:54 +0200
>>>>> +static void ice_ptp_set_funcs_e830(struct ice_pf *pf)
>>>>> +{
>>>>> +#ifdef CONFIG_ICE_HWTS
>>>>> + if (pcie_ptm_enabled(pf->pdev) &&
>>>>> + boot_cpu_has(X86_FEATURE_ART) &&
>>>>> + boot_cpu_has(X86_FEATURE_TSC_KNOWN_FREQ))
>>>>> + pf->ptp.info.getcrosststamp = ice_ptp_getcrosststamp;
>>>>> +#endif /* CONFIG_ICE_HWTS */
>>>>
>>>> I've seen this pattern in several drivers already. I really feel like it
>>>> needs a generic wrapper.
>>>> I mean, there should be something like
>>>>
>>>> arch/x86/include/asm/ptm.h (not sure about the name)
>>>>
>>>> where you put let's say
>>>>
>>>> static inline bool arch_has_ptm(struct pci_device *pdev)
>>>>
>>>> Same for
>>>>
>>>> include/asm-generic/ptm.h
>>>>
>>>> there it will be `return false`.
>>>>
>>>> In include/asm-generic/Kbuild, you add
>>>>
>>>> mandatory-y += ptm.h.
>>>>
>>>> Then, include/linux/ptm.h should include <asm/ptm.h> and in your driver
>>>> sources, you include <linux/ptm.h> and check
>>>>
>>>> if (arch_has_ptm(pdev))
>>>> pf->ptp.info.getcrosststamp = ice_ptp_getcrosststamp;
>>>>
>>>> It's just a draft, adjust accordingly.
>>>>
>>>> Checking for x86 features in the driver doesn't look good. Especially
>>>> when you add ARM64 or whatever support in future.
>>>
>>> For PTM, we check only pcie_ptm_enabled(). PTM is a PCIE feature
>>> supported regardless of arch.
>>>
>>> The two other checks are for the x86 Always Running Timer (ART) and x86
>>> TimeStamp Counter (TSC) features. Those are not tied to PTM, but are
>>> necessary for crosstimestamping on devices supported by ice driver.
>>
>> Ah okay, it's not tied.
>> So, instead of asm/ptm.h, it should be named somehow else :D
>>
>> But this X86_FEATURE_ART + X86_FEATURE_TSC_KNOWN_FREQ check really
>> should be abstracted to something like arch_has_crosststamp() or
>> arch_has_tstamp(), dunno. Maybe to the already existing asm/timex.h?
>> Then, implementing this for ARM64 would be easier, as instead of adding
>> more ifdefs and checks you'd just implement arch_has_tstamp() in its
>> timex.h (I've seen Milena'd been playing with PTP on ARM).
>> At least that's how I see it. But if it's fine for the maintainers to
>> have arch-specific ifdefs and the same code pattern in several drivers,
>> I'm fine, too :D
>
> Technically, neither ART nor TSC are directly related to the PTP cross
> timestamp. It's just the implementation on Intel NICs, where those
> NICs use x86 ART to crosstimestamp.
>
> For cross timestamp on ARM, it's also HW specific and depends on which
> timer the HW uses for timestamping. I'm not really sure what's the HW
> protocol in this case and if e.g. E830 can latch other timers than
> x86 ART in its ART_TIME registers.
>
> get_device_system_crosststamp() supports multiple clock sources defined
> in enum clocksource_ids. Maybe instead of checking ART flag, the driver
> could get clocksources and if CSID_X86_ART is available, it would assign
> the pointer to crosststamp function, but I'm not convinced.
I mean, I'm fine with the arch-specific definitions in the driver as
long as the netdev maintainers are fine. Or maybe they could propose
some generic solution.
>
> Thanks,
> Karol
Thanks,
Olek
^ permalink raw reply [flat|nested] 16+ messages in thread
* Re: [Intel-wired-lan] [PATCH v3 iwl-next 4/4] ice: combine cross timestamp functions for E82x and E830
2024-08-08 13:00 ` Alexander Lobakin
@ 2024-08-08 14:20 ` Jakub Kicinski
0 siblings, 0 replies; 16+ messages in thread
From: Jakub Kicinski @ 2024-08-08 14:20 UTC (permalink / raw)
To: Alexander Lobakin
Cc: Kolacinski, Karol, intel-wired-lan@lists.osuosl.org,
Keller, Jacob E, netdev@vger.kernel.org, Nguyen, Anthony L,
Kitszel, Przemyslaw
On Thu, 8 Aug 2024 15:00:52 +0200 Alexander Lobakin wrote:
> > Technically, neither ART nor TSC are directly related to the PTP cross
> > timestamp. It's just the implementation on Intel NICs, where those
> > NICs use x86 ART to crosstimestamp.
> >
> > For cross timestamp on ARM, it's also HW specific and depends on which
> > timer the HW uses for timestamping. I'm not really sure what's the HW
> > protocol in this case and if e.g. E830 can latch other timers than
> > x86 ART in its ART_TIME registers.
> >
> > get_device_system_crosststamp() supports multiple clock sources defined
> > in enum clocksource_ids. Maybe instead of checking ART flag, the driver
> > could get clocksources and if CSID_X86_ART is available, it would assign
> > the pointer to crosststamp function, but I'm not convinced.
>
> I mean, I'm fine with the arch-specific definitions in the driver as
> long as the netdev maintainers are fine. Or maybe they could propose
> some generic solution.
I don't like it either, FWIW, but it seems like this is what everyone
is doing. Please do CC tglx / the time maintainers on the next version
and net-next submission. I get the feeling they will wake up in a year
telling us we did it all wrong, but hey, all we can do now is CC them..
^ permalink raw reply [flat|nested] 16+ messages in thread
end of thread, other threads:[~2024-08-08 14:21 UTC | newest]
Thread overview: 16+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-07-25 9:34 [PATCH v3 iwl-next 0/4] ice: Implement PTP support for E830 devices Karol Kolacinski
2024-07-25 9:34 ` [PATCH v3 iwl-next 1/4] " Karol Kolacinski
2024-07-26 13:17 ` [Intel-wired-lan] " Alexander Lobakin
2024-07-25 9:34 ` [PATCH v3 iwl-next 2/4] ice: Process TSYN IRQ in a separate function Karol Kolacinski
2024-07-26 13:22 ` [Intel-wired-lan] " Alexander Lobakin
2024-07-25 9:34 ` [PATCH v3 iwl-next 3/4] ice: Add timestamp ready bitmap for E830 products Karol Kolacinski
2024-07-26 13:25 ` [Intel-wired-lan] " Alexander Lobakin
2024-07-25 9:34 ` [PATCH v3 iwl-next 4/4] ice: combine cross timestamp functions for E82x and E830 Karol Kolacinski
2024-07-25 16:31 ` Jacob Keller
2024-07-26 13:37 ` [Intel-wired-lan] " Alexander Lobakin
2024-07-26 23:16 ` Jacob Keller
2024-08-05 16:21 ` Kolacinski, Karol
2024-08-07 13:54 ` Alexander Lobakin
2024-08-07 14:26 ` Kolacinski, Karol
2024-08-08 13:00 ` Alexander Lobakin
2024-08-08 14:20 ` Jakub Kicinski
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).