From patchwork Fri Jul 26 11:34:43 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Karol Kolacinski X-Patchwork-Id: 13742674 X-Patchwork-Delegate: kuba@kernel.org Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.21]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 1AA4E17A5B1 for ; Fri, 26 Jul 2024 11:36:38 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.21 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721993800; cv=none; b=guOcdJPH3dm7NsyzJb7pT1fwM/zkfh8fQptlhCSpsvaqKSO8uIzaX/d+WV6ilUfvlmZXElvTfy5GG5tlTJJXsFWIIBn/JWGdMtm3ou5Hv9eb8DnAlrJnu0g2k//rfKasP11gH+v10AcKM1ryH+MB5iKFA0aHHiLsgY7g8jchvUo= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721993800; c=relaxed/simple; bh=RGcTmWZ5e9QDB0NCtZbs7CQRP2Ywi/ENLoFUmQUeg3w=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=BaaXdp2Mn8ch0C5RbZPGQeyHLHjweRxZR6+9gT7rsYFACv8flaKXFi0ZY0JbPZFioAK6H9srQueiVWGiJowTYX8RLVzGa+35ePMo0cIc8s71My7R7HpBhVtViwWw0xhQ5Zk0b2FqI4E7Wipb1o4KX5048BQhls6XHkXJTHVG85I= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=CZH0cpGC; arc=none smtp.client-ip=198.175.65.21 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="CZH0cpGC" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1721993798; x=1753529798; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=RGcTmWZ5e9QDB0NCtZbs7CQRP2Ywi/ENLoFUmQUeg3w=; b=CZH0cpGCqI4JzRpIniBvvYUeDHhHrIhQm5z+9PG7NovoVSokLOc1UX20 RzPeF+QQ+hrVndls7e7fvh3tObcktZAcaAN0lQiuNY6GyUde87z3IP57d R03si3RWotM6o6wF5QbppeB74fVD8cUpF5hcQFtMTCuYFZNgtsapbbWCo PVBWlC3p8X0AFnLfAu0InlEHhGNKRGtQafcqxqY+8cEM+Odzv6kwgDlHv T4O5SkIbvNNvL7H/cVpcgcVhgtBTwqZDMqERalez11yyyAgK/YMV5juEl hurKW2p7Bn+CwLGZDaWQmF3jtIIg0w7QW3bYsxSRGnvmuF7syiyeE7bVw g==; X-CSE-ConnectionGUID: kx/sPL4GSyK1QcU92E2g0w== X-CSE-MsgGUID: a0HS5TNxRumwc3M8RcXCPA== X-IronPort-AV: E=McAfee;i="6700,10204,11144"; a="19743236" X-IronPort-AV: E=Sophos;i="6.09,238,1716274800"; d="scan'208";a="19743236" Received: from fmviesa002.fm.intel.com ([10.60.135.142]) by orvoesa113.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Jul 2024 04:36:38 -0700 X-CSE-ConnectionGUID: At2RtyeoTpOEoT7CxNqW/g== X-CSE-MsgGUID: J6T6FwF5SFC7IakP282+rw== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.09,238,1716274800"; d="scan'208";a="76466875" Received: from kkolacin-desk1.igk.intel.com ([10.102.102.132]) by fmviesa002.fm.intel.com with ESMTP; 26 Jul 2024 04:36:35 -0700 From: Karol Kolacinski To: intel-wired-lan@lists.osuosl.org Cc: netdev@vger.kernel.org, anthony.l.nguyen@intel.com, przemyslaw.kitszel@intel.com, Michal Michalik , Milena Olech , Paul Greenwalt , Karol Kolacinski Subject: [PATCH v4 iwl-next 1/4] ice: Implement PTP support for E830 devices Date: Fri, 26 Jul 2024 13:34:43 +0200 Message-ID: <20240726113631.200083-7-karol.kolacinski@intel.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240726113631.200083-6-karol.kolacinski@intel.com> References: <20240726113631.200083-6-karol.kolacinski@intel.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: kuba@kernel.org From: Michal Michalik 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 Co-developed-by: Milena Olech Signed-off-by: Milena Olech Co-developed-by: Paul Greenwalt Signed-off-by: Paul Greenwalt Signed-off-by: Michal Michalik Co-developed-by: Karol Kolacinski Signed-off-by: Karol Kolacinski --- V3 -> V4: Fixed kdoc for other ice_is_e***() and other _e830() functions in ice_ptp_hw.c 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 | 17 +- 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 | 208 ++++++++++++++++-- drivers/net/ethernet/intel/ice/ice_ptp_hw.h | 25 ++- drivers/net/ethernet/intel/ice/ice_type.h | 1 + 7 files changed, 237 insertions(+), 30 deletions(-) diff --git a/drivers/net/ethernet/intel/ice/ice_common.c b/drivers/net/ethernet/intel/ice/ice_common.c index 009716a12a26..8c4e6a9a1b43 100644 --- a/drivers/net/ethernet/intel/ice/ice_common.c +++ b/drivers/net/ethernet/intel/ice/ice_common.c @@ -197,7 +197,7 @@ bool ice_is_generic_mac(struct ice_hw *hw) * ice_is_e810 * @hw: pointer to the hardware structure * - * returns true if the device is E810 based, false if not. + * Return: true if the device is E810 based, false if not. */ bool ice_is_e810(struct ice_hw *hw) { @@ -208,7 +208,7 @@ bool ice_is_e810(struct ice_hw *hw) * ice_is_e810t * @hw: pointer to the hardware structure * - * returns true if the device is E810T based, false if not. + * Return: true if the device is E810T based, false if not. */ bool ice_is_e810t(struct ice_hw *hw) { @@ -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..a4f5b00ee38d 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,151 @@ 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. + * + * Return: 0 on success + */ +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. + * + * Return: 0 on success + */ +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. + * + * Return: 0 on success, negative error code when PHY write failed + */ +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. + * + * Return: 0 on success + */ +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 + * + * Return: 0 on success + */ +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 +5627,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 +5725,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 +5797,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 +5849,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 +5960,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 +6084,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 +6111,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 */ From patchwork Fri Jul 26 11:34:44 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Karol Kolacinski X-Patchwork-Id: 13742675 X-Patchwork-Delegate: kuba@kernel.org Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.21]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B982D17A932 for ; Fri, 26 Jul 2024 11:36:39 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.21 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721993801; cv=none; b=iq98STkdD5UytJms/T1mYZuLEIGJyI45e9Gy7jz8EX2AhCs3tlc7HAaLX5wcjbFJRhQPmBB3SNMItXntWtxczrlpSiFU/TE+Vl7Lr8PM615T6GhKcFaOgiilikJ6mtHmiNAJTrA+AQaTDle4lX/VIqyIYWd8hNwsFKcUomnZj+E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721993801; c=relaxed/simple; bh=FjMpMmIT0x18VX/rDm1YTI4HdwVyInUD/V9X5Ed6Te4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=sFecZtg4VnAtNIgPRJq7Btj+5iAKMeqWVcfneUsPlC3O5MlhCN96vIjt1k5YQkIPB4iDwHwE74gVP3xdoRWq874783Gbs1toMcftanTIEvRBxnvW/SXbPnUS0A1dydva0BOqzaqV48ZpCgQjQO2YSIk/L7Vpw38PqHx1YDeMCtU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=EueBcq+d; arc=none smtp.client-ip=198.175.65.21 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="EueBcq+d" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1721993800; x=1753529800; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=FjMpMmIT0x18VX/rDm1YTI4HdwVyInUD/V9X5Ed6Te4=; b=EueBcq+dU4238NASJgtDgVVdB0/i6XxE5YYpEX74XI/yATC7hRkl0jZC pT2VmIXZkH45171nub8prGUYvk//mToqc1LyKVjZ5nq805fXQvK7dzwLH uBH+94hAFq8u4uwN9ZdjtgZG+JWS+jwZjzv0hMM86Z7hG9kx9kDQKFvh/ CWojIuNiJuvLG0hPiBBfLRsc94B8AcYEhb+pg1CuL9gA9S+FHxQfjThSC xb4ZSeYbgNyhJF8drwgf69MD3UO5waJog3TFUBfHMLr3eHt1Uegeg4Gqf m9xHRZLsEEmiJn8siEkrkNXzhHYvfL79lqBCVnFl3ak/NtTelBdCeVf0k w==; X-CSE-ConnectionGUID: aIFd19vMRb2CTsYUvMGXIw== X-CSE-MsgGUID: rh9gFGRxQbqQZz+ZtQ0Q+w== X-IronPort-AV: E=McAfee;i="6700,10204,11144"; a="19743239" X-IronPort-AV: E=Sophos;i="6.09,238,1716274800"; d="scan'208";a="19743239" Received: from fmviesa002.fm.intel.com ([10.60.135.142]) by orvoesa113.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Jul 2024 04:36:39 -0700 X-CSE-ConnectionGUID: VKj5vduFTTaw5IEq5B9WqA== X-CSE-MsgGUID: nfCN+aauRqqqrBqU0U+O6w== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.09,238,1716274800"; d="scan'208";a="76466889" Received: from kkolacin-desk1.igk.intel.com ([10.102.102.132]) by fmviesa002.fm.intel.com with ESMTP; 26 Jul 2024 04:36:38 -0700 From: Karol Kolacinski To: intel-wired-lan@lists.osuosl.org Cc: netdev@vger.kernel.org, anthony.l.nguyen@intel.com, przemyslaw.kitszel@intel.com, Karol Kolacinski Subject: [PATCH v4 iwl-next 2/4] ice: Process TSYN IRQ in a separate function Date: Fri, 26 Jul 2024 13:34:44 +0200 Message-ID: <20240726113631.200083-8-karol.kolacinski@intel.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240726113631.200083-6-karol.kolacinski@intel.com> References: <20240726113631.200083-6-karol.kolacinski@intel.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: kuba@kernel.org 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 Signed-off-by: Karol Kolacinski --- 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 8ea52c4ff2b3..068b813c8586 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) From patchwork Fri Jul 26 11:34:45 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Karol Kolacinski X-Patchwork-Id: 13742676 X-Patchwork-Delegate: kuba@kernel.org Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.21]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 00ED917B402 for ; Fri, 26 Jul 2024 11:36:40 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.21 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721993802; cv=none; b=qumGOHYJKCxq3oMx5GEB9CyXCsLdq56tdESxG5dq6W8fsLci6xePRiEbov6yT/m2K4dIR7xpR/TI1GLljOCEYiYHqJeVK982el20utKym30RY2azJJ2/8VsPj2gHtVCqWzDmSOlS4WALjrPOWR8eVLsdSjMesJYPzzHowePF5cE= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721993802; c=relaxed/simple; bh=sky5o4wepqyG1F6/bIPcy/tMbHWgWd3pmIyc5uaWDBs=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=IgEEc3+wFdVJv4yBOADoKCMe9ILVIp9lvH9guWRepyK8+0VsywowG0bhNjSBlDC3KoqMNBsIt0qP1pLzlXxlpYKZl/IxhOAbhbhIy6kHASDhg7MJZj7VssQVBkPKJTm50wMMfZYJlpwhfkQxtPMyuAtdZ7iOkhEMbxLiFNM9y2g= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=Ok8/eNCL; arc=none smtp.client-ip=198.175.65.21 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="Ok8/eNCL" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1721993801; x=1753529801; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=sky5o4wepqyG1F6/bIPcy/tMbHWgWd3pmIyc5uaWDBs=; b=Ok8/eNCLNeNTWNfUbIyyUL0tGRQhPBbYIlwheu3Xy/k1hgzL4nacA8Ha t3lWwfYEg5grrlzmEUKoL5obesfj6syhShabY/lRtardfZDr3Tiok5d4t 1ReJGLI4OdBMeamk+fQVDXZ9pujLyJ41QqfoPjU3ckU8NuKDUUr/aij0B cHivJbFCOEwfpfdlA8+5syNWPg/8Zc2rPOkY7XjikvbvbncjBc3WK5I7G GUWn5RfYfZBKDrEpvFhkwyG0kO+px3jl5U7gb1T8QEiOiUrLbmnsqNRi7 YResYGJJwUge0+wTKh5pSSVrWsw6nxSfrvpPxR2dcH1Osch8GHNlFfq1x g==; X-CSE-ConnectionGUID: dQ7/jUm9QteYK0e4voIZ2g== X-CSE-MsgGUID: G6D0da6BTLCoYxbZBzNrIg== X-IronPort-AV: E=McAfee;i="6700,10204,11144"; a="19743245" X-IronPort-AV: E=Sophos;i="6.09,238,1716274800"; d="scan'208";a="19743245" Received: from fmviesa002.fm.intel.com ([10.60.135.142]) by orvoesa113.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Jul 2024 04:36:41 -0700 X-CSE-ConnectionGUID: Ucipt+5oSPGWaa0Kbz/RAQ== X-CSE-MsgGUID: /tTQd2OAQNaCE8DcZcgA8Q== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.09,238,1716274800"; d="scan'208";a="76466907" Received: from kkolacin-desk1.igk.intel.com ([10.102.102.132]) by fmviesa002.fm.intel.com with ESMTP; 26 Jul 2024 04:36:39 -0700 From: Karol Kolacinski To: intel-wired-lan@lists.osuosl.org Cc: netdev@vger.kernel.org, anthony.l.nguyen@intel.com, przemyslaw.kitszel@intel.com, Karol Kolacinski Subject: [PATCH v4 iwl-next 3/4] ice: Add timestamp ready bitmap for E830 products Date: Fri, 26 Jul 2024 13:34:45 +0200 Message-ID: <20240726113631.200083-9-karol.kolacinski@intel.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240726113631.200083-6-karol.kolacinski@intel.com> References: <20240726113631.200083-6-karol.kolacinski@intel.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: kuba@kernel.org E830 PHY supports timestamp ready bitmap. Enable the bitmap by refactoring tx init function. Reviewed-by: Przemek Kitszel Signed-off-by: Karol Kolacinski --- 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 From patchwork Fri Jul 26 11:34:46 2024 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Karol Kolacinski X-Patchwork-Id: 13742677 X-Patchwork-Delegate: kuba@kernel.org Received: from mgamail.intel.com (mgamail.intel.com [198.175.65.21]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 48D5817A5AF for ; Fri, 26 Jul 2024 11:36:43 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=198.175.65.21 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721993805; cv=none; b=sJ94i8syRDWVBKETiGzrPKOUAZNKjynrHtQddN5Dyky93YC4TDuPAc4c6pXrFSDEeqnZb2MUGx+EVJCwUbzi8C3Q2yTrYnzGyJwI1aHYNil+pTFG1RZvI6dOOLn0Dh7z1j9wcIe8OnKYlLQ6E/7yHqlJqxY/zdSOVIHGc68NgUk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1721993805; c=relaxed/simple; bh=AMyZjo5K59cgFxPDkM0jd6dOUHY7F8nBo+/T+CPDjH0=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=pQ8Lg3QJEA/xmAd3jxTGIpXuoAudlZAjpeV6Au8+RBW2TjwfZPpKKkzADEOO6oEP5XdFQZK1NgatqXGSfUvIHyp5EvZXSvXY0FChftHUsKcPhqFIkF2FNK7Ed1SIYpQw6uGh9ugBfNPiv9g2lfa2z+6ZuOxtfZIqjGOlhdnU4YI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com; spf=pass smtp.mailfrom=intel.com; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b=i8Wpztdm; arc=none smtp.client-ip=198.175.65.21 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=intel.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=intel.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=intel.com header.i=@intel.com header.b="i8Wpztdm" DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=intel.com; i=@intel.com; q=dns/txt; s=Intel; t=1721993803; x=1753529803; h=from:to:cc:subject:date:message-id:in-reply-to: references:mime-version:content-transfer-encoding; bh=AMyZjo5K59cgFxPDkM0jd6dOUHY7F8nBo+/T+CPDjH0=; b=i8WpztdmmTKwYVkOag09tUI3G4iA7lChAPcH+5kVcsqWDKEHUMTRsEgN I5ZxyVH8Y3LAJgBRp5E9dUoh90gtu2we5aDUo+V2iXZ0jdNYWuSh9yjY3 D3NBHjMjYfPWd+umA4VDreXGWOFFSwcv0H811zGif3a94mQbqiU+EyDKy PmX200MfDB0RZVIc2XOc1F9dZNJx7iQxfxXA7/8ghZeIzA8MsbRIV2aUK kfzNRu4qU3TsBf1SuTdn48/ndPdGg/EFeBiF9G8V1dz8keLmec4+i5gjD RMyWppe86iKffMsNre0Wc1ki2nMWGMsDB/D3M8kD+SNgsbT2f54mPUWPT w==; X-CSE-ConnectionGUID: UmHCiTbDT6yYrsbkxv6TVg== X-CSE-MsgGUID: vDqFZpBDQeKR9v5iAT9vgg== X-IronPort-AV: E=McAfee;i="6700,10204,11144"; a="19743247" X-IronPort-AV: E=Sophos;i="6.09,238,1716274800"; d="scan'208";a="19743247" Received: from fmviesa002.fm.intel.com ([10.60.135.142]) by orvoesa113.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 26 Jul 2024 04:36:43 -0700 X-CSE-ConnectionGUID: 5CK/P7LNQu2igWCJLNJCxA== X-CSE-MsgGUID: QnWv8fJLRXiitZhARg4Y/A== X-ExtLoop1: 1 X-IronPort-AV: E=Sophos;i="6.09,238,1716274800"; d="scan'208";a="76466932" Received: from kkolacin-desk1.igk.intel.com ([10.102.102.132]) by fmviesa002.fm.intel.com with ESMTP; 26 Jul 2024 04:36:41 -0700 From: Karol Kolacinski To: intel-wired-lan@lists.osuosl.org Cc: netdev@vger.kernel.org, anthony.l.nguyen@intel.com, przemyslaw.kitszel@intel.com, Jacob Keller , Karol Kolacinski Subject: [PATCH v4 iwl-next 4/4] ice: combine cross timestamp functions for E82x and E830 Date: Fri, 26 Jul 2024 13:34:46 +0200 Message-ID: <20240726113631.200083-10-karol.kolacinski@intel.com> X-Mailer: git-send-email 2.45.2 In-Reply-To: <20240726113631.200083-6-karol.kolacinski@intel.com> References: <20240726113631.200083-6-karol.kolacinski@intel.com> Precedence: bulk X-Mailing-List: netdev@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 X-Patchwork-Delegate: kuba@kernel.org From: Jacob Keller 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 which is interesting but not quite what we're looking for... Reviewed-by: Przemek Kitszel Signed-off-by: Jacob Keller Signed-off-by: Karol Kolacinski --- 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 068b813c8586..b2ac375c278f 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 #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); }