From 1c358fedecd1f0121ba21d3b2a2144145ae24326 Mon Sep 17 00:00:00 2001 From: Danielle Ratson Date: Sun, 24 Jul 2022 11:03:15 +0300 Subject: [PATCH 01/15] mlxsw: Rename mlxsw_reg_mtptptp_pack() to mlxsw_reg_mtptpt_pack() The right name of the register is MTPTPT, which refers to Monitoring Precision Time Protocol Trap Register. Therefore, rename the function mlxsw_reg_mtptptp_pack() to mlxsw_reg_mtptpt_pack(). Signed-off-by: Danielle Ratson Signed-off-by: Amit Cohen Reviewed-by: Petr Machata Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 6 +++--- drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c | 2 +- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 17ce28e65464f..0ed2a805ce834 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -11045,9 +11045,9 @@ MLXSW_ITEM32(reg, mtptpt, trap_id, 0x00, 0, 4); */ MLXSW_ITEM32(reg, mtptpt, message_type, 0x04, 0, 16); -static inline void mlxsw_reg_mtptptp_pack(char *payload, - enum mlxsw_reg_mtptpt_trap_id trap_id, - u16 message_type) +static inline void mlxsw_reg_mtptpt_pack(char *payload, + enum mlxsw_reg_mtptpt_trap_id trap_id, + u16 message_type) { MLXSW_REG_ZERO(mtptpt, payload); mlxsw_reg_mtptpt_trap_id_set(payload, trap_id); diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c index 35422e64d89fc..a976c7fbb04a1 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c @@ -694,7 +694,7 @@ static int mlxsw_sp_ptp_mtptpt_set(struct mlxsw_sp *mlxsw_sp, { char mtptpt_pl[MLXSW_REG_MTPTPT_LEN]; - mlxsw_reg_mtptptp_pack(mtptpt_pl, trap_id, message_type); + mlxsw_reg_mtptpt_pack(mtptpt_pl, trap_id, message_type); return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mtptpt), mtptpt_pl); } From 97b05cfb68aef12c649c5f8b6e787d143c9e5c8f Mon Sep 17 00:00:00 2001 From: Danielle Ratson Date: Sun, 24 Jul 2022 11:03:16 +0300 Subject: [PATCH 02/15] mlxsw: reg: Add MTUTC register's fields for supporting PTP in Spectrum-2 The MTUTC register configures the HW UTC counter. Add the relevant fields and operations to support PTP in Spectrum-2 and update mlxsw_reg_mtutc_pack() with the new fields for a future use. Signed-off-by: Danielle Ratson Signed-off-by: Amit Cohen Reviewed-by: Petr Machata Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 31 +++++++++++++++++-- .../ethernet/mellanox/mlxsw/spectrum_ptp.c | 4 +-- 2 files changed, 31 insertions(+), 4 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 0ed2a805ce834..5665a60afc3ff 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -10347,6 +10347,8 @@ MLXSW_REG_DEFINE(mtutc, MLXSW_REG_MTUTC_ID, MLXSW_REG_MTUTC_LEN); enum mlxsw_reg_mtutc_operation { MLXSW_REG_MTUTC_OPERATION_SET_TIME_AT_NEXT_SEC = 0, + MLXSW_REG_MTUTC_OPERATION_SET_TIME_IMMEDIATE = 1, + MLXSW_REG_MTUTC_OPERATION_ADJUST_TIME = 2, MLXSW_REG_MTUTC_OPERATION_ADJUST_FREQ = 3, }; @@ -10359,25 +10361,50 @@ MLXSW_ITEM32(reg, mtutc, operation, 0x00, 0, 4); /* reg_mtutc_freq_adjustment * Frequency adjustment: Every PPS the HW frequency will be * adjusted by this value. Units of HW clock, where HW counts - * 10^9 HW clocks for 1 HW second. + * 10^9 HW clocks for 1 HW second. Range is from -50,000,000 to +50,000,000. + * In Spectrum-2, the field is reversed, positive values mean to decrease the + * frequency. * Access: RW */ MLXSW_ITEM32(reg, mtutc, freq_adjustment, 0x04, 0, 32); +#define MLXSW_REG_MTUTC_MAX_FREQ_ADJ (50 * 1000 * 1000) + /* reg_mtutc_utc_sec * UTC seconds. * Access: WO */ MLXSW_ITEM32(reg, mtutc, utc_sec, 0x10, 0, 32); +/* reg_mtutc_utc_nsec + * UTC nSecs. + * Range 0..(10^9-1) + * Updated when operation is SET_TIME_IMMEDIATE. + * Reserved on Spectrum-1. + * Access: WO + */ +MLXSW_ITEM32(reg, mtutc, utc_nsec, 0x14, 0, 30); + +/* reg_mtutc_time_adjustment + * Time adjustment. + * Units of nSec. + * Range is from -32768 to +32767. + * Updated when operation is ADJUST_TIME. + * Reserved on Spectrum-1. + * Access: WO + */ +MLXSW_ITEM32(reg, mtutc, time_adjustment, 0x18, 0, 32); + static inline void mlxsw_reg_mtutc_pack(char *payload, enum mlxsw_reg_mtutc_operation oper, - u32 freq_adj, u32 utc_sec) + u32 freq_adj, u32 utc_sec, u32 utc_nsec, u32 time_adj) { MLXSW_REG_ZERO(mtutc, payload); mlxsw_reg_mtutc_operation_set(payload, oper); mlxsw_reg_mtutc_freq_adjustment_set(payload, freq_adj); mlxsw_reg_mtutc_utc_sec_set(payload, utc_sec); + mlxsw_reg_mtutc_utc_nsec_set(payload, utc_nsec); + mlxsw_reg_mtutc_time_adjustment_set(payload, time_adj); } /* MCQI - Management Component Query Information diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c index a976c7fbb04a1..39586673b3951 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c @@ -107,7 +107,7 @@ mlxsw_sp1_ptp_phc_adjfreq(struct mlxsw_sp_ptp_clock *clock, int freq_adj) char mtutc_pl[MLXSW_REG_MTUTC_LEN]; mlxsw_reg_mtutc_pack(mtutc_pl, MLXSW_REG_MTUTC_OPERATION_ADJUST_FREQ, - freq_adj, 0); + freq_adj, 0, 0, 0); return mlxsw_reg_write(mlxsw_core, MLXSW_REG(mtutc), mtutc_pl); } @@ -144,7 +144,7 @@ mlxsw_sp1_ptp_phc_settime(struct mlxsw_sp_ptp_clock *clock, u64 nsec) mlxsw_reg_mtutc_pack(mtutc_pl, MLXSW_REG_MTUTC_OPERATION_SET_TIME_AT_NEXT_SEC, - 0, next_sec); + 0, next_sec, 0, 0); return mlxsw_reg_write(mlxsw_core, MLXSW_REG(mtutc), mtutc_pl); } From 731416e9ae5d5c3d5491aeef4fda53a191e8822d Mon Sep 17 00:00:00 2001 From: Danielle Ratson Date: Sun, 24 Jul 2022 11:03:17 +0300 Subject: [PATCH 03/15] mlxsw: reg: Add Monitoring Time Precision Correction Port Configuration Register In Spectrum-2, all the packets are time stamped, the MTPCPC register is used to configure the types of packets that will adjust the correction field and which port will trap PTP packets. If ingress correction is set on a port for a given packet type, then when such a packet is received via the port, the current time stamp is subtracted from the correction field. If egress correction is set on a port for a given packet type, then when such a packet is transmitted via the port, the current time stamp is added to the correction field. Assuming the systems is configured correctly, the above means that the correction field will contain the transient delay between the ports. Add this register for a future use in order to support PTP in Spectrum-2. Signed-off-by: Danielle Ratson Signed-off-by: Amit Cohen Reviewed-by: Petr Machata Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/reg.h | 62 +++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 5665a60afc3ff..ddab5476c8b2b 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/reg.h +++ b/drivers/net/ethernet/mellanox/mlxsw/reg.h @@ -11081,6 +11081,67 @@ static inline void mlxsw_reg_mtptpt_pack(char *payload, mlxsw_reg_mtptpt_message_type_set(payload, message_type); } +/* MTPCPC - Monitoring Time Precision Correction Port Configuration Register + * ------------------------------------------------------------------------- + */ +#define MLXSW_REG_MTPCPC_ID 0x9093 +#define MLXSW_REG_MTPCPC_LEN 0x2C + +MLXSW_REG_DEFINE(mtpcpc, MLXSW_REG_MTPCPC_ID, MLXSW_REG_MTPCPC_LEN); + +/* reg_mtpcpc_pport + * Per port: + * 0: config is global. When reading - the local_port is 1. + * 1: config is per port. + * Access: Index + */ +MLXSW_ITEM32(reg, mtpcpc, pport, 0x00, 31, 1); + +/* reg_mtpcpc_local_port + * Local port number. + * Supported to/from CPU port. + * Reserved when pport = 0. + * Access: Index + */ +MLXSW_ITEM32_LP(reg, mtpcpc, 0x00, 16, 0x00, 12); + +/* reg_mtpcpc_ptp_trap_en + * Enable PTP traps. + * The trap_id is configured by MTPTPT. + * Access: RW + */ +MLXSW_ITEM32(reg, mtpcpc, ptp_trap_en, 0x04, 0, 1); + +/* reg_mtpcpc_ing_correction_message_type + * Bitwise vector of PTP message types to update correction-field at ingress. + * MessageType field as defined by IEEE 1588 Each bit corresponds to a value + * (e.g. Bit0: Sync, Bit1: Delay_Req). Supported also from CPU port. + * Default all 0 + * Access: RW + */ +MLXSW_ITEM32(reg, mtpcpc, ing_correction_message_type, 0x10, 0, 16); + +/* reg_mtpcpc_egr_correction_message_type + * Bitwise vector of PTP message types to update correction-field at egress. + * MessageType field as defined by IEEE 1588 Each bit corresponds to a value + * (e.g. Bit0: Sync, Bit1: Delay_Req). Supported also from CPU port. + * Default all 0 + * Access: RW + */ +MLXSW_ITEM32(reg, mtpcpc, egr_correction_message_type, 0x14, 0, 16); + +static inline void mlxsw_reg_mtpcpc_pack(char *payload, bool pport, + u16 local_port, bool ptp_trap_en, + u16 ing, u16 egr) +{ + MLXSW_REG_ZERO(mtpcpc, payload); + mlxsw_reg_mtpcpc_pport_set(payload, pport); + mlxsw_reg_mtpcpc_local_port_set(payload, pport ? local_port : 0); + mlxsw_reg_mtpcpc_ptp_trap_en_set(payload, ptp_trap_en); + mlxsw_reg_mtpcpc_ing_correction_message_type_set(payload, ing); + mlxsw_reg_mtpcpc_egr_correction_message_type_set(payload, egr); +} + /* MFGD - Monitoring FW General Debug Register * ------------------------------------------- */ @@ -12797,6 +12858,7 @@ static const struct mlxsw_reg_info *mlxsw_reg_infos[] = { MLXSW_REG(mtpppc), MLXSW_REG(mtpptr), MLXSW_REG(mtptpt), + MLXSW_REG(mtpcpc), MLXSW_REG(mfgd), MLXSW_REG(mgpir), MLXSW_REG(mbct), From aa98487cc96b798ff7c13eb251b1174264759928 Mon Sep 17 00:00:00 2001 From: Danielle Ratson Date: Sun, 24 Jul 2022 11:03:18 +0300 Subject: [PATCH 04/15] mlxsw: pci_hw: Add 'time_stamp' and 'time_stamp_type' fields to CQEv2 The Completion Queue Element version 2 (CQEv2) includes various metadata fields of packets. Add 'time_stamp' and 'time_stamp_type' fields along with functions to extract the seconds and nanoseconds for a future use. Signed-off-by: Danielle Ratson Reviewed-by: Petr Machata Signed-off-by: Amit Cohen Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/pci_hw.h | 78 ++++++++++++++++++++ 1 file changed, 78 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci_hw.h b/drivers/net/ethernet/mellanox/mlxsw/pci_hw.h index 7b531228d6c0f..543eb8c8a9839 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/pci_hw.h +++ b/drivers/net/ethernet/mellanox/mlxsw/pci_hw.h @@ -217,6 +217,25 @@ MLXSW_ITEM32(pci, cqe0, dqn, 0x0C, 1, 5); MLXSW_ITEM32(pci, cqe12, dqn, 0x0C, 1, 6); mlxsw_pci_cqe_item_helpers(dqn, 0, 12, 12); +/* pci_cqe_time_stamp_low + * Time stamp of the CQE + * Format according to time_stamp_type: + * 0: uSec - 1.024uSec (default for devices which do not support + * time_stamp_type). Only bits 15:0 are valid + * 1: FRC - Free Running Clock - units of 1nSec + * 2: UTC - time_stamp[37:30] = Sec + * - time_stamp[29:0] = nSec + * 3: Mirror_UTC. UTC time stamp of the original packet that has + * MIRROR_SESSION traps + * - time_stamp[37:30] = Sec + * - time_stamp[29:0] = nSec + * Formats 0..2 are configured by + * CONFIG_PROFILE.cqe_time_stamp_type for PTP traps + * Format 3 is used for MIRROR_SESSION traps + * Note that Spectrum does not reveal FRC, UTC and Mirror_UTC + */ +MLXSW_ITEM32(pci, cqe2, time_stamp_low, 0x0C, 16, 16); + #define MLXSW_PCI_CQE2_MIRROR_TCLASS_INVALID 0x1F /* pci_cqe_mirror_tclass @@ -280,8 +299,67 @@ MLXSW_ITEM32(pci, cqe2, user_def_val_orig_pkt_len, 0x14, 0, 20); */ MLXSW_ITEM32(pci, cqe2, mirror_reason, 0x18, 24, 8); +enum mlxsw_pci_cqe_time_stamp_type { + MLXSW_PCI_CQE_TIME_STAMP_TYPE_USEC, + MLXSW_PCI_CQE_TIME_STAMP_TYPE_FRC, + MLXSW_PCI_CQE_TIME_STAMP_TYPE_UTC, + MLXSW_PCI_CQE_TIME_STAMP_TYPE_MIRROR_UTC, +}; + +/* pci_cqe_time_stamp_type + * Time stamp type: + * 0: uSec - 1.024uSec (default for devices which do not support + * time_stamp_type) + * 1: FRC - Free Running Clock - units of 1nSec + * 2: UTC + * 3: Mirror_UTC. UTC time stamp of the original packet that has + * MIRROR_SESSION traps + */ +MLXSW_ITEM32(pci, cqe2, time_stamp_type, 0x18, 22, 2); + #define MLXSW_PCI_CQE2_MIRROR_LATENCY_INVALID 0xFFFFFF +/* pci_cqe_time_stamp_high + * Time stamp of the CQE + * Format according to time_stamp_type: + * 0: uSec - 1.024uSec (default for devices which do not support + * time_stamp_type). Only bits 15:0 are valid + * 1: FRC - Free Running Clock - units of 1nSec + * 2: UTC - time_stamp[37:30] = Sec + * - time_stamp[29:0] = nSec + * 3: Mirror_UTC. UTC time stamp of the original packet that has + * MIRROR_SESSION traps + * - time_stamp[37:30] = Sec + * - time_stamp[29:0] = nSec + * Formats 0..2 are configured by + * CONFIG_PROFILE.cqe_time_stamp_type for PTP traps + * Format 3 is used for MIRROR_SESSION traps + * Note that Spectrum does not reveal FRC, UTC and Mirror_UTC + */ +MLXSW_ITEM32(pci, cqe2, time_stamp_high, 0x18, 0, 22); + +static inline u64 mlxsw_pci_cqe2_time_stamp_get(const char *cqe) +{ + u64 ts_high = mlxsw_pci_cqe2_time_stamp_high_get(cqe); + u64 ts_low = mlxsw_pci_cqe2_time_stamp_low_get(cqe); + + return ts_high << 16 | ts_low; +} + +static inline u8 mlxsw_pci_cqe2_time_stamp_sec_get(const char *cqe) +{ + u64 full_ts = mlxsw_pci_cqe2_time_stamp_get(cqe); + + return full_ts >> 30 & 0xFF; +} + +static inline u32 mlxsw_pci_cqe2_time_stamp_nsec_get(const char *cqe) +{ + u64 full_ts = mlxsw_pci_cqe2_time_stamp_get(cqe); + + return full_ts & 0x3FFFFFFF; +} + /* pci_cqe_mirror_latency * End-to-end latency of the original packet that does mirroring to the CPU. * Value of 0xFFFFFF means that the latency is invalid. Units are according to From 577d80238ff7a9226051b33b65b4c223d26a9cae Mon Sep 17 00:00:00 2001 From: Danielle Ratson Date: Sun, 24 Jul 2022 11:03:19 +0300 Subject: [PATCH 05/15] mlxsw: cmd: Add UTC related fields to query firmware command Add UTC sec and nsec PCI BAR and offset to query firmware command for a future use. Signed-off-by: Danielle Ratson Signed-off-by: Amit Cohen Reviewed-by: Petr Machata Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/cmd.h | 26 +++++++++++++++++++++++ 1 file changed, 26 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/cmd.h b/drivers/net/ethernet/mellanox/mlxsw/cmd.h index 666d6b6e4dbfb..e5ac5d2673483 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/cmd.h +++ b/drivers/net/ethernet/mellanox/mlxsw/cmd.h @@ -329,6 +329,32 @@ MLXSW_ITEM64(cmd_mbox, query_fw, free_running_clock_offset, 0x50, 0, 64); */ MLXSW_ITEM32(cmd_mbox, query_fw, fr_rn_clk_bar, 0x58, 30, 2); +/* cmd_mbox_query_fw_utc_sec_offset + * The offset of the UTC_Sec page + */ +MLXSW_ITEM64(cmd_mbox, query_fw, utc_sec_offset, 0x70, 0, 64); + +/* cmd_mbox_query_fw_utc_sec_bar + * PCI base address register (BAR) of the UTC_Sec page + * 0: BAR 0 + * 1: 64 bit BAR + * Reserved on SwitchX/-2, Switch-IB/2, Spectrum-1 + */ +MLXSW_ITEM32(cmd_mbox, query_fw, utc_sec_bar, 0x78, 30, 2); + +/* cmd_mbox_query_fw_utc_nsec_offset + * The offset of the UTC_nSec page + */ +MLXSW_ITEM64(cmd_mbox, query_fw, utc_nsec_offset, 0x80, 0, 64); + +/* cmd_mbox_query_fw_utc_nsec_bar + * PCI base address register (BAR) of the UTC_nSec page + * 0: BAR 0 + * 1: 64 bit BAR + * Reserved on SwitchX/-2, Switch-IB/2, Spectrum-1 + */ +MLXSW_ITEM32(cmd_mbox, query_fw, utc_nsec_bar, 0x88, 30, 2); + /* QUERY_BOARDINFO - Query Board Information * ----------------------------------------- * OpMod == 0 (N/A), INMmod == 0 (N/A) From 291fcb937e951a1db0c35ead766a660e5eeb9d68 Mon Sep 17 00:00:00 2001 From: Danielle Ratson Date: Sun, 24 Jul 2022 11:03:20 +0300 Subject: [PATCH 06/15] mlxsw: Set time stamp type as part of config profile The type of time stamp field in the CQE is configured via the CONFIG_PROFILE command during driver initialization. Add the definition of the relevant fields to the command's payload and set the type to UTC for Spectrum-2 and above. This configuration can be done as part of the preparations to PTP support, as the type of the time stamp will not break any existing behavior. Signed-off-by: Danielle Ratson Reviewed-by: Petr Machata Signed-off-by: Amit Cohen Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/cmd.h | 26 +++++++++++++++++++ drivers/net/ethernet/mellanox/mlxsw/core.h | 4 ++- drivers/net/ethernet/mellanox/mlxsw/pci.c | 7 +++++ .../net/ethernet/mellanox/mlxsw/spectrum.c | 2 ++ 4 files changed, 38 insertions(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/cmd.h b/drivers/net/ethernet/mellanox/mlxsw/cmd.h index e5ac5d2673483..60232fb8ccd7a 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/cmd.h +++ b/drivers/net/ethernet/mellanox/mlxsw/cmd.h @@ -689,6 +689,12 @@ MLXSW_ITEM32(cmd_mbox, config_profile, set_kvd_hash_double_size, 0x0C, 26, 1); */ MLXSW_ITEM32(cmd_mbox, config_profile, set_cqe_version, 0x08, 0, 1); +/* cmd_mbox_config_set_cqe_time_stamp_type + * Capability bit. Setting a bit to 1 configures the profile + * according to the mailbox contents. + */ +MLXSW_ITEM32(cmd_mbox, config_profile, set_cqe_time_stamp_type, 0x08, 2, 1); + /* cmd_mbox_config_profile_max_vepa_channels * Maximum number of VEPA channels per port (0 through 16) * 0 - multi-channel VEPA is disabled @@ -884,6 +890,26 @@ MLXSW_ITEM32_INDEXED(cmd_mbox, config_profile, swid_config_type, MLXSW_ITEM32_INDEXED(cmd_mbox, config_profile, swid_config_properties, 0x60, 0, 8, 0x08, 0x00, false); +enum mlxsw_cmd_mbox_config_profile_cqe_time_stamp_type { + /* uSec - 1.024uSec (default). Only bits 15:0 are valid. */ + MLXSW_CMD_MBOX_CONFIG_PROFILE_CQE_TIME_STAMP_TYPE_USEC, + /* FRC - Free Running Clock, units of 1nSec. + * Reserved when SwitchX/-2, Switch-IB/2 and Spectrum-1. + */ + MLXSW_CMD_MBOX_CONFIG_PROFILE_CQE_TIME_STAMP_TYPE_FRC, + /* UTC. time_stamp[37:30] = Sec, time_stamp[29:0] = nSec. + * Reserved when SwitchX/2, Switch-IB/2 and Spectrum-1. + */ + MLXSW_CMD_MBOX_CONFIG_PROFILE_CQE_TIME_STAMP_TYPE_UTC, +}; + +/* cmd_mbox_config_profile_cqe_time_stamp_type + * CQE time_stamp_type for non-mirror-packets. + * Configured if set_cqe_time_stamp_type is set. + * Reserved when SwitchX/-2, Switch-IB/2 and Spectrum-1. + */ +MLXSW_ITEM32(cmd_mbox, config_profile, cqe_time_stamp_type, 0xB0, 8, 2); + /* cmd_mbox_config_profile_cqe_version * CQE version: * 0: CQE version is 0 diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h index a3491ef2aa7e2..6b05586052dd8 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core.h @@ -296,7 +296,8 @@ struct mlxsw_config_profile { used_ar_sec:1, used_adaptive_routing_group_cap:1, used_ubridge:1, - used_kvd_sizes:1; + used_kvd_sizes:1, + used_cqe_time_stamp_type:1; u8 max_vepa_channels; u16 max_mid; u16 max_pgt; @@ -319,6 +320,7 @@ struct mlxsw_config_profile { u32 kvd_linear_size; u8 kvd_hash_single_parts; u8 kvd_hash_double_parts; + u8 cqe_time_stamp_type; struct mlxsw_swid_config swid_config[MLXSW_CONFIG_PROFILE_SWID_COUNT]; }; diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.c b/drivers/net/ethernet/mellanox/mlxsw/pci.c index 41f0f68bc911a..57792e87dee2b 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/pci.c +++ b/drivers/net/ethernet/mellanox/mlxsw/pci.c @@ -1267,6 +1267,13 @@ static int mlxsw_pci_config_profile(struct mlxsw_pci *mlxsw_pci, char *mbox, mlxsw_cmd_mbox_config_profile_cqe_version_set(mbox, 1); } + if (profile->used_cqe_time_stamp_type) { + mlxsw_cmd_mbox_config_profile_set_cqe_time_stamp_type_set(mbox, + 1); + mlxsw_cmd_mbox_config_profile_cqe_time_stamp_type_set(mbox, + profile->cqe_time_stamp_type); + } + return mlxsw_cmd_config_profile_set(mlxsw_pci->core, mbox); } diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 209587cf7529e..fa48b2631ea87 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -3411,6 +3411,8 @@ static const struct mlxsw_config_profile mlxsw_sp2_config_profile = { .type = MLXSW_PORT_SWID_TYPE_ETH, } }, + .used_cqe_time_stamp_type = 1, + .cqe_time_stamp_type = MLXSW_CMD_MBOX_CONFIG_PROFILE_CQE_TIME_STAMP_TYPE_UTC, }; static void From 81016180e3f46f2f9ad0b62561db0793ee81227f Mon Sep 17 00:00:00 2001 From: Danielle Ratson Date: Sun, 24 Jul 2022 11:03:21 +0300 Subject: [PATCH 07/15] mlxsw: spectrum: Fix the shift of FID field in TX header Currently, the field FID in TX header is defined, but is not used as it is relevant only for data packets. mlxsw driver currently sends all host-generated traffic as control packets and not as data packets. In Spectrum-2 and Spectrum-3, the correction field of PTP packets which are sent as control packets is not updated at egress port. To overcome this limitation while adding support for PTP, some packets will be sent as data packets. Fix the wrong shift in the definition, to allow using the field later. Signed-off-by: Danielle Ratson Signed-off-by: Amit Cohen Reviewed-by: Petr Machata Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index fa48b2631ea87..bd7552e8dd5cf 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -166,7 +166,7 @@ MLXSW_ITEM32(tx, hdr, port_mid, 0x04, 16, 16); * set, otherwise calculated based on the packet's VID using VID to FID mapping. * Valid for data packets only. */ -MLXSW_ITEM32(tx, hdr, fid, 0x08, 0, 16); +MLXSW_ITEM32(tx, hdr, fid, 0x08, 16, 16); /* tx_hdr_type * 0 - Data packets From 448e9cb3631ea57e4c41ea688f1689af2ed7fd60 Mon Sep 17 00:00:00 2001 From: Amit Cohen Date: Sun, 24 Jul 2022 11:03:22 +0300 Subject: [PATCH 08/15] mlxsw: resources: Add resource identifier for maximum number of FIDs Add a resource identifier for maximum number of FIDs so that it could be later used to query the information from firmware. In Spectrum-2 and Spectrum-3, the correction field of PTP packets which are sent as control packets is not updated at egress port. To overcome this limitation, some packets will be sent as data packets. The header should include FID, which is supposed to be 'Max FID + port - 1'. As preparation, add the required resource, to be able to query the value from firmware later. Signed-off-by: Amit Cohen Reviewed-by: Petr Machata Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/resources.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/drivers/net/ethernet/mellanox/mlxsw/resources.h b/drivers/net/ethernet/mellanox/mlxsw/resources.h index 826e47fb4586d..19ae0d1c74a8d 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/resources.h +++ b/drivers/net/ethernet/mellanox/mlxsw/resources.h @@ -24,6 +24,7 @@ enum mlxsw_res_id { MLXSW_RES_ID_COUNTER_SIZE_PACKETS_BYTES, MLXSW_RES_ID_COUNTER_SIZE_ROUTER_BASIC, MLXSW_RES_ID_MAX_SYSTEM_PORT, + MLXSW_RES_ID_FID, MLXSW_RES_ID_MAX_LAG, MLXSW_RES_ID_MAX_LAG_MEMBERS, MLXSW_RES_ID_GUARANTEED_SHARED_BUFFER, @@ -83,6 +84,7 @@ static u16 mlxsw_res_ids[] = { [MLXSW_RES_ID_COUNTER_SIZE_PACKETS_BYTES] = 0x2443, [MLXSW_RES_ID_COUNTER_SIZE_ROUTER_BASIC] = 0x2449, [MLXSW_RES_ID_MAX_SYSTEM_PORT] = 0x2502, + [MLXSW_RES_ID_FID] = 0x2512, [MLXSW_RES_ID_MAX_LAG] = 0x2520, [MLXSW_RES_ID_MAX_LAG_MEMBERS] = 0x2521, [MLXSW_RES_ID_GUARANTEED_SHARED_BUFFER] = 0x2805, /* Bytes */ From 33a9583f9a02d2d8d820f41eb1ed83e06a016bba Mon Sep 17 00:00:00 2001 From: Danielle Ratson Date: Sun, 24 Jul 2022 11:03:23 +0300 Subject: [PATCH 09/15] mlxsw: Rename 'read_frc_capable' bit to 'read_clock_capable' Rename the 'read_frc_capable' bit to 'read_clock_capable' since now it can be both the FRC and UTC clocks. Signed-off-by: Danielle Ratson Reviewed-by: Petr Machata Signed-off-by: Amit Cohen Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/core.h | 2 +- drivers/net/ethernet/mellanox/mlxsw/pci.c | 2 +- drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 2 +- 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/core.h b/drivers/net/ethernet/mellanox/mlxsw/core.h index 6b05586052dd8..9d2e8a8d3a756 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/core.h +++ b/drivers/net/ethernet/mellanox/mlxsw/core.h @@ -487,7 +487,7 @@ struct mlxsw_bus_info { u8 vsd[MLXSW_CMD_BOARDINFO_VSD_LEN]; u8 psid[MLXSW_CMD_BOARDINFO_PSID_LEN]; u8 low_frequency:1, - read_frc_capable:1; + read_clock_capable:1; }; struct mlxsw_hwmon; diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.c b/drivers/net/ethernet/mellanox/mlxsw/pci.c index 57792e87dee2b..0f452c8dabbd5 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/pci.c +++ b/drivers/net/ethernet/mellanox/mlxsw/pci.c @@ -1923,7 +1923,7 @@ static int mlxsw_pci_probe(struct pci_dev *pdev, const struct pci_device_id *id) mlxsw_pci->bus_info.device_kind = driver_name; mlxsw_pci->bus_info.device_name = pci_name(mlxsw_pci->pdev); mlxsw_pci->bus_info.dev = &pdev->dev; - mlxsw_pci->bus_info.read_frc_capable = true; + mlxsw_pci->bus_info.read_clock_capable = true; mlxsw_pci->id = id; err = mlxsw_core_bus_device_register(&mlxsw_pci->bus_info, diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index bd7552e8dd5cf..641078060b02d 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c @@ -3096,7 +3096,7 @@ static int mlxsw_sp_init(struct mlxsw_core *mlxsw_core, goto err_router_init; } - if (mlxsw_sp->bus_info->read_frc_capable) { + if (mlxsw_sp->bus_info->read_clock_capable) { /* NULL is a valid return value from clock_init */ mlxsw_sp->clock = mlxsw_sp->ptp_ops->clock_init(mlxsw_sp, From 22d950b79ea70b69386b3b131051fbe22f065bdf Mon Sep 17 00:00:00 2001 From: Amit Cohen Date: Sun, 24 Jul 2022 11:03:24 +0300 Subject: [PATCH 10/15] mlxsw: spectrum_ptp: Initialize the clock to zero as part of initialization As lately recommended in the mailing list[1], set the clock to zero time as part of initialization. The idea is that when the clock reads 'Jan 1, 1970', then it is clearly wrong and user will not mistakenly think that the clock is set correctly. If as part of initialization, the driver sets the clock, user might see correct date and time (maybe with a small shift) and assume that there is no need to sync the clock. Fix the existing code of Spectrum-1 to set the 'timecounter' to zero. [1]: https://lore.kernel.org/netdev/20220201191041.GB7009@hoboy.vegasvil.org/ Signed-off-by: Amit Cohen Reviewed-by: Petr Machata Signed-off-by: Ido Schimmel Acked-by: Richard Cochran Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c index 39586673b3951..eab3d63ad2ac2 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c @@ -267,8 +267,7 @@ mlxsw_sp1_ptp_clock_init(struct mlxsw_sp *mlxsw_sp, struct device *dev) clock->cycles.mask = CLOCKSOURCE_MASK(MLXSW_SP1_PTP_CLOCK_MASK); clock->core = mlxsw_sp->core; - timecounter_init(&clock->tc, &clock->cycles, - ktime_to_ns(ktime_get_real())); + timecounter_init(&clock->tc, &clock->cycles, 0); /* Calculate period in seconds to call the overflow watchdog - to make * sure counter is checked at least twice every wrap around. From 9468322963894fd7a6138f9bfe3aca88129738d8 Mon Sep 17 00:00:00 2001 From: Amit Cohen Date: Sun, 24 Jul 2022 11:03:25 +0300 Subject: [PATCH 11/15] mlxsw: pci: Simplify FRC clock reading Currently, the reading of FRC values (high and low) is done using macro which calls to a function. In addition, to calculate the offset of FRC, a simple macro is used. This code can be simplified by adding an helper function and calculating the offset explicitly instead of using an additional macro for that. Add the helper function and convert the existing code. This helper will be used later to read UTC clock. Signed-off-by: Amit Cohen Reviewed-by: Petr Machata Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/pci.c | 18 ++++++++++++------ drivers/net/ethernet/mellanox/mlxsw/pci_hw.h | 3 --- 2 files changed, 12 insertions(+), 9 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci.c b/drivers/net/ethernet/mellanox/mlxsw/pci.c index 0f452c8dabbd5..83659fb0559a4 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/pci.c +++ b/drivers/net/ethernet/mellanox/mlxsw/pci.c @@ -505,6 +505,12 @@ static void mlxsw_pci_cq_fini(struct mlxsw_pci *mlxsw_pci, mlxsw_cmd_hw2sw_cq(mlxsw_pci->core, q->num); } +static unsigned int mlxsw_pci_read32_off(struct mlxsw_pci *mlxsw_pci, + ptrdiff_t off) +{ + return ioread32be(mlxsw_pci->hw_addr + off); +} + static void mlxsw_pci_cqe_sdq_handle(struct mlxsw_pci *mlxsw_pci, struct mlxsw_pci_queue *q, u16 consumer_counter_limit, @@ -1809,19 +1815,19 @@ static int mlxsw_pci_cmd_exec(void *bus_priv, u16 opcode, u8 opcode_mod, static u32 mlxsw_pci_read_frc_h(void *bus_priv) { struct mlxsw_pci *mlxsw_pci = bus_priv; - u64 frc_offset; + u64 frc_offset_h; - frc_offset = mlxsw_pci->free_running_clock_offset; - return mlxsw_pci_read32(mlxsw_pci, FREE_RUNNING_CLOCK_H(frc_offset)); + frc_offset_h = mlxsw_pci->free_running_clock_offset; + return mlxsw_pci_read32_off(mlxsw_pci, frc_offset_h); } static u32 mlxsw_pci_read_frc_l(void *bus_priv) { struct mlxsw_pci *mlxsw_pci = bus_priv; - u64 frc_offset; + u64 frc_offset_l; - frc_offset = mlxsw_pci->free_running_clock_offset; - return mlxsw_pci_read32(mlxsw_pci, FREE_RUNNING_CLOCK_L(frc_offset)); + frc_offset_l = mlxsw_pci->free_running_clock_offset + 4; + return mlxsw_pci_read32_off(mlxsw_pci, frc_offset_l); } static const struct mlxsw_bus mlxsw_pci_bus = { diff --git a/drivers/net/ethernet/mellanox/mlxsw/pci_hw.h b/drivers/net/ethernet/mellanox/mlxsw/pci_hw.h index 543eb8c8a9839..48dbfea0a2a1d 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/pci_hw.h +++ b/drivers/net/ethernet/mellanox/mlxsw/pci_hw.h @@ -41,9 +41,6 @@ #define MLXSW_PCI_DOORBELL(offset, type_offset, num) \ ((offset) + (type_offset) + (num) * 4) -#define MLXSW_PCI_FREE_RUNNING_CLOCK_H(offset) (offset) -#define MLXSW_PCI_FREE_RUNNING_CLOCK_L(offset) ((offset) + 4) - #define MLXSW_PCI_CQS_MAX 96 #define MLXSW_PCI_EQS_COUNT 2 #define MLXSW_PCI_EQ_ASYNC_NUM 0 From e8fea346b5563b719f9437b71d788c1bd825c027 Mon Sep 17 00:00:00 2001 From: Amit Cohen Date: Sun, 24 Jul 2022 11:03:26 +0300 Subject: [PATCH 12/15] mlxsw: spectrum_ptp: Use 'struct mlxsw_sp_ptp_state' per ASIC Currently, there is one shared structure that holds the required structures and details for PTP. Most of the existing fields are relevant only for Spectrum-1 (hash table, lock for hash table, delayed work, and more). Rename the structure to be specific for Spectrum-1 and align the existing code. Add a common structure which includes 'struct mlxsw_sp *mlxsw_sp' and will be returned from ptp_init() operation, as the definition is shared between all ASICs' operations. Signed-off-by: Amit Cohen Reviewed-by: Petr Machata Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- .../ethernet/mellanox/mlxsw/spectrum_ptp.c | 51 +++++++++++++------ 1 file changed, 35 insertions(+), 16 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c index eab3d63ad2ac2..c5ceb4326074d 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c @@ -29,6 +29,10 @@ struct mlxsw_sp_ptp_state { struct mlxsw_sp *mlxsw_sp; +}; + +struct mlxsw_sp1_ptp_state { + struct mlxsw_sp_ptp_state common; struct rhltable unmatched_ht; spinlock_t unmatched_lock; /* protects the HT */ struct delayed_work ht_gc_dw; @@ -70,6 +74,13 @@ struct mlxsw_sp_ptp_clock { struct delayed_work overflow_work; }; +static struct mlxsw_sp1_ptp_state * +mlxsw_sp1_ptp_state(struct mlxsw_sp *mlxsw_sp) +{ + return container_of(mlxsw_sp->ptp_state, struct mlxsw_sp1_ptp_state, + common); +} + static u64 __mlxsw_sp1_ptp_read_frc(struct mlxsw_sp_ptp_clock *clock, struct ptp_system_timestamp *sts) { @@ -347,7 +358,7 @@ mlxsw_sp1_ptp_unmatched_save(struct mlxsw_sp *mlxsw_sp, u64 timestamp) { int cycles = MLXSW_SP1_PTP_HT_GC_TIMEOUT / MLXSW_SP1_PTP_HT_GC_INTERVAL; - struct mlxsw_sp_ptp_state *ptp_state = mlxsw_sp->ptp_state; + struct mlxsw_sp1_ptp_state *ptp_state = mlxsw_sp1_ptp_state(mlxsw_sp); struct mlxsw_sp1_ptp_unmatched *unmatched; int err; @@ -358,7 +369,7 @@ mlxsw_sp1_ptp_unmatched_save(struct mlxsw_sp *mlxsw_sp, unmatched->key = key; unmatched->skb = skb; unmatched->timestamp = timestamp; - unmatched->gc_cycle = mlxsw_sp->ptp_state->gc_cycle + cycles; + unmatched->gc_cycle = ptp_state->gc_cycle + cycles; err = rhltable_insert(&ptp_state->unmatched_ht, &unmatched->ht_node, mlxsw_sp1_ptp_unmatched_ht_params); @@ -372,11 +383,12 @@ static struct mlxsw_sp1_ptp_unmatched * mlxsw_sp1_ptp_unmatched_lookup(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp1_ptp_key key, int *p_length) { + struct mlxsw_sp1_ptp_state *ptp_state = mlxsw_sp1_ptp_state(mlxsw_sp); struct mlxsw_sp1_ptp_unmatched *unmatched, *last = NULL; struct rhlist_head *tmp, *list; int length = 0; - list = rhltable_lookup(&mlxsw_sp->ptp_state->unmatched_ht, &key, + list = rhltable_lookup(&ptp_state->unmatched_ht, &key, mlxsw_sp1_ptp_unmatched_ht_params); rhl_for_each_entry_rcu(unmatched, tmp, list, ht_node) { last = unmatched; @@ -391,7 +403,9 @@ static int mlxsw_sp1_ptp_unmatched_remove(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp1_ptp_unmatched *unmatched) { - return rhltable_remove(&mlxsw_sp->ptp_state->unmatched_ht, + struct mlxsw_sp1_ptp_state *ptp_state = mlxsw_sp1_ptp_state(mlxsw_sp); + + return rhltable_remove(&ptp_state->unmatched_ht, &unmatched->ht_node, mlxsw_sp1_ptp_unmatched_ht_params); } @@ -480,13 +494,14 @@ static void mlxsw_sp1_ptp_got_piece(struct mlxsw_sp *mlxsw_sp, struct mlxsw_sp1_ptp_key key, struct sk_buff *skb, u64 timestamp) { + struct mlxsw_sp1_ptp_state *ptp_state = mlxsw_sp1_ptp_state(mlxsw_sp); struct mlxsw_sp1_ptp_unmatched *unmatched; int length; int err; rcu_read_lock(); - spin_lock(&mlxsw_sp->ptp_state->unmatched_lock); + spin_lock(&ptp_state->unmatched_lock); unmatched = mlxsw_sp1_ptp_unmatched_lookup(mlxsw_sp, key, &length); if (skb && unmatched && unmatched->timestamp) { @@ -514,7 +529,7 @@ static void mlxsw_sp1_ptp_got_piece(struct mlxsw_sp *mlxsw_sp, WARN_ON_ONCE(err); } - spin_unlock(&mlxsw_sp->ptp_state->unmatched_lock); + spin_unlock(&ptp_state->unmatched_lock); if (unmatched) mlxsw_sp1_ptp_unmatched_finish(mlxsw_sp, unmatched); @@ -610,9 +625,10 @@ void mlxsw_sp1_ptp_transmitted(struct mlxsw_sp *mlxsw_sp, } static void -mlxsw_sp1_ptp_ht_gc_collect(struct mlxsw_sp_ptp_state *ptp_state, +mlxsw_sp1_ptp_ht_gc_collect(struct mlxsw_sp1_ptp_state *ptp_state, struct mlxsw_sp1_ptp_unmatched *unmatched) { + struct mlxsw_sp *mlxsw_sp = ptp_state->common.mlxsw_sp; struct mlxsw_sp_ptp_port_dir_stats *stats; struct mlxsw_sp_port *mlxsw_sp_port; int err; @@ -635,7 +651,7 @@ mlxsw_sp1_ptp_ht_gc_collect(struct mlxsw_sp_ptp_state *ptp_state, /* The packet was matched with timestamp during the walk. */ goto out; - mlxsw_sp_port = ptp_state->mlxsw_sp->ports[unmatched->key.local_port]; + mlxsw_sp_port = mlxsw_sp->ports[unmatched->key.local_port]; if (mlxsw_sp_port) { stats = unmatched->key.ingress ? &mlxsw_sp_port->ptp.stats.rx_gcd : @@ -652,7 +668,7 @@ mlxsw_sp1_ptp_ht_gc_collect(struct mlxsw_sp_ptp_state *ptp_state, * netif_receive_skb(), in process context, is seen elsewhere in the * kernel, notably in pktgen. */ - mlxsw_sp1_ptp_unmatched_finish(ptp_state->mlxsw_sp, unmatched); + mlxsw_sp1_ptp_unmatched_finish(mlxsw_sp, unmatched); out: local_bh_enable(); @@ -662,12 +678,12 @@ static void mlxsw_sp1_ptp_ht_gc(struct work_struct *work) { struct delayed_work *dwork = to_delayed_work(work); struct mlxsw_sp1_ptp_unmatched *unmatched; - struct mlxsw_sp_ptp_state *ptp_state; + struct mlxsw_sp1_ptp_state *ptp_state; struct rhashtable_iter iter; u32 gc_cycle; void *obj; - ptp_state = container_of(dwork, struct mlxsw_sp_ptp_state, ht_gc_dw); + ptp_state = container_of(dwork, struct mlxsw_sp1_ptp_state, ht_gc_dw); gc_cycle = ptp_state->gc_cycle++; rhltable_walk_enter(&ptp_state->unmatched_ht, &iter); @@ -808,7 +824,7 @@ static int mlxsw_sp1_ptp_shaper_params_set(struct mlxsw_sp *mlxsw_sp) struct mlxsw_sp_ptp_state *mlxsw_sp1_ptp_init(struct mlxsw_sp *mlxsw_sp) { - struct mlxsw_sp_ptp_state *ptp_state; + struct mlxsw_sp1_ptp_state *ptp_state; u16 message_type; int err; @@ -819,7 +835,7 @@ struct mlxsw_sp_ptp_state *mlxsw_sp1_ptp_init(struct mlxsw_sp *mlxsw_sp) ptp_state = kzalloc(sizeof(*ptp_state), GFP_KERNEL); if (!ptp_state) return ERR_PTR(-ENOMEM); - ptp_state->mlxsw_sp = mlxsw_sp; + ptp_state->common.mlxsw_sp = mlxsw_sp; spin_lock_init(&ptp_state->unmatched_lock); @@ -852,7 +868,7 @@ struct mlxsw_sp_ptp_state *mlxsw_sp1_ptp_init(struct mlxsw_sp *mlxsw_sp) INIT_DELAYED_WORK(&ptp_state->ht_gc_dw, mlxsw_sp1_ptp_ht_gc); mlxsw_core_schedule_dw(&ptp_state->ht_gc_dw, MLXSW_SP1_PTP_HT_GC_INTERVAL); - return ptp_state; + return &ptp_state->common; err_fifo_clr: mlxsw_sp_ptp_mtptpt_set(mlxsw_sp, MLXSW_REG_MTPTPT_TRAP_ID_PTP1, 0); @@ -865,9 +881,12 @@ struct mlxsw_sp_ptp_state *mlxsw_sp1_ptp_init(struct mlxsw_sp *mlxsw_sp) return ERR_PTR(err); } -void mlxsw_sp1_ptp_fini(struct mlxsw_sp_ptp_state *ptp_state) +void mlxsw_sp1_ptp_fini(struct mlxsw_sp_ptp_state *ptp_state_common) { - struct mlxsw_sp *mlxsw_sp = ptp_state->mlxsw_sp; + struct mlxsw_sp *mlxsw_sp = ptp_state_common->mlxsw_sp; + struct mlxsw_sp1_ptp_state *ptp_state; + + ptp_state = mlxsw_sp1_ptp_state(mlxsw_sp); cancel_delayed_work_sync(&ptp_state->ht_gc_dw); mlxsw_sp1_ptp_mtpppc_set(mlxsw_sp, 0, 0); From 9bfe3c16fc23eb826e360c225e8a73556d60d1cb Mon Sep 17 00:00:00 2001 From: Amit Cohen Date: Sun, 24 Jul 2022 11:03:27 +0300 Subject: [PATCH 13/15] mlxsw: spectrum_ptp: Use 'struct mlxsw_sp_ptp_clock' per ASIC Currently, there is one shared structure that holds the required structures for PTP clock. Most of the existing fields are relevant only for Spectrum-1 (cycles, timecounter, and more). Rename the structure to be specific for Spectrum-1 and align the existing code. Add a common structure which includes the structures which will be used also for Spectrum-2. This structure will be returned from clock_init() operation, as the definition is shared between all ASICs' operations. Signed-off-by: Amit Cohen Reviewed-by: Petr Machata Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- .../ethernet/mellanox/mlxsw/spectrum_ptp.c | 75 +++++++++++-------- 1 file changed, 44 insertions(+), 31 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c index c5ceb4326074d..99611dcc54743 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c @@ -64,12 +64,16 @@ static const struct rhashtable_params mlxsw_sp1_ptp_unmatched_ht_params = { struct mlxsw_sp_ptp_clock { struct mlxsw_core *core; + struct ptp_clock *ptp; + struct ptp_clock_info ptp_info; +}; + +struct mlxsw_sp1_ptp_clock { + struct mlxsw_sp_ptp_clock common; spinlock_t lock; /* protect this structure */ struct cyclecounter cycles; struct timecounter tc; u32 nominal_c_mult; - struct ptp_clock *ptp; - struct ptp_clock_info ptp_info; unsigned long overflow_period; struct delayed_work overflow_work; }; @@ -81,10 +85,16 @@ mlxsw_sp1_ptp_state(struct mlxsw_sp *mlxsw_sp) common); } -static u64 __mlxsw_sp1_ptp_read_frc(struct mlxsw_sp_ptp_clock *clock, +static struct mlxsw_sp1_ptp_clock * +mlxsw_sp1_ptp_clock(struct ptp_clock_info *ptp) +{ + return container_of(ptp, struct mlxsw_sp1_ptp_clock, common.ptp_info); +} + +static u64 __mlxsw_sp1_ptp_read_frc(struct mlxsw_sp1_ptp_clock *clock, struct ptp_system_timestamp *sts) { - struct mlxsw_core *mlxsw_core = clock->core; + struct mlxsw_core *mlxsw_core = clock->common.core; u32 frc_h1, frc_h2, frc_l; frc_h1 = mlxsw_core_read_frc_h(mlxsw_core); @@ -105,8 +115,8 @@ static u64 __mlxsw_sp1_ptp_read_frc(struct mlxsw_sp_ptp_clock *clock, static u64 mlxsw_sp1_ptp_read_frc(const struct cyclecounter *cc) { - struct mlxsw_sp_ptp_clock *clock = - container_of(cc, struct mlxsw_sp_ptp_clock, cycles); + struct mlxsw_sp1_ptp_clock *clock = + container_of(cc, struct mlxsw_sp1_ptp_clock, cycles); return __mlxsw_sp1_ptp_read_frc(clock, NULL) & cc->mask; } @@ -133,9 +143,9 @@ static u64 mlxsw_sp1_ptp_ns2cycles(const struct timecounter *tc, u64 nsec) } static int -mlxsw_sp1_ptp_phc_settime(struct mlxsw_sp_ptp_clock *clock, u64 nsec) +mlxsw_sp1_ptp_phc_settime(struct mlxsw_sp1_ptp_clock *clock, u64 nsec) { - struct mlxsw_core *mlxsw_core = clock->core; + struct mlxsw_core *mlxsw_core = clock->common.core; u64 next_sec, next_sec_in_nsec, cycles; char mtutc_pl[MLXSW_REG_MTUTC_LEN]; char mtpps_pl[MLXSW_REG_MTPPS_LEN]; @@ -161,8 +171,7 @@ mlxsw_sp1_ptp_phc_settime(struct mlxsw_sp_ptp_clock *clock, u64 nsec) static int mlxsw_sp1_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm) { - struct mlxsw_sp_ptp_clock *clock = - container_of(ptp, struct mlxsw_sp_ptp_clock, ptp_info); + struct mlxsw_sp1_ptp_clock *clock = mlxsw_sp1_ptp_clock(ptp); int neg_adj = 0; u32 diff; u64 adj; @@ -185,13 +194,12 @@ static int mlxsw_sp1_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm) clock->nominal_c_mult + diff; spin_unlock_bh(&clock->lock); - return mlxsw_sp1_ptp_phc_adjfreq(clock, neg_adj ? -ppb : ppb); + return mlxsw_sp1_ptp_phc_adjfreq(&clock->common, neg_adj ? -ppb : ppb); } static int mlxsw_sp1_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta) { - struct mlxsw_sp_ptp_clock *clock = - container_of(ptp, struct mlxsw_sp_ptp_clock, ptp_info); + struct mlxsw_sp1_ptp_clock *clock = mlxsw_sp1_ptp_clock(ptp); u64 nsec; spin_lock_bh(&clock->lock); @@ -206,8 +214,7 @@ static int mlxsw_sp1_ptp_gettimex(struct ptp_clock_info *ptp, struct timespec64 *ts, struct ptp_system_timestamp *sts) { - struct mlxsw_sp_ptp_clock *clock = - container_of(ptp, struct mlxsw_sp_ptp_clock, ptp_info); + struct mlxsw_sp1_ptp_clock *clock = mlxsw_sp1_ptp_clock(ptp); u64 cycles, nsec; spin_lock_bh(&clock->lock); @@ -223,8 +230,7 @@ static int mlxsw_sp1_ptp_gettimex(struct ptp_clock_info *ptp, static int mlxsw_sp1_ptp_settime(struct ptp_clock_info *ptp, const struct timespec64 *ts) { - struct mlxsw_sp_ptp_clock *clock = - container_of(ptp, struct mlxsw_sp_ptp_clock, ptp_info); + struct mlxsw_sp1_ptp_clock *clock = mlxsw_sp1_ptp_clock(ptp); u64 nsec = timespec64_to_ns(ts); spin_lock_bh(&clock->lock); @@ -248,9 +254,9 @@ static const struct ptp_clock_info mlxsw_sp1_ptp_clock_info = { static void mlxsw_sp1_ptp_clock_overflow(struct work_struct *work) { struct delayed_work *dwork = to_delayed_work(work); - struct mlxsw_sp_ptp_clock *clock; + struct mlxsw_sp1_ptp_clock *clock; - clock = container_of(dwork, struct mlxsw_sp_ptp_clock, overflow_work); + clock = container_of(dwork, struct mlxsw_sp1_ptp_clock, overflow_work); spin_lock_bh(&clock->lock); timecounter_read(&clock->tc); @@ -262,7 +268,7 @@ struct mlxsw_sp_ptp_clock * mlxsw_sp1_ptp_clock_init(struct mlxsw_sp *mlxsw_sp, struct device *dev) { u64 overflow_cycles, nsec, frac = 0; - struct mlxsw_sp_ptp_clock *clock; + struct mlxsw_sp1_ptp_clock *clock; int err; clock = kzalloc(sizeof(*clock), GFP_KERNEL); @@ -276,7 +282,7 @@ mlxsw_sp1_ptp_clock_init(struct mlxsw_sp *mlxsw_sp, struct device *dev) clock->cycles.shift); clock->nominal_c_mult = clock->cycles.mult; clock->cycles.mask = CLOCKSOURCE_MASK(MLXSW_SP1_PTP_CLOCK_MASK); - clock->core = mlxsw_sp->core; + clock->common.core = mlxsw_sp->core; timecounter_init(&clock->tc, &clock->cycles, 0); @@ -296,15 +302,15 @@ mlxsw_sp1_ptp_clock_init(struct mlxsw_sp *mlxsw_sp, struct device *dev) INIT_DELAYED_WORK(&clock->overflow_work, mlxsw_sp1_ptp_clock_overflow); mlxsw_core_schedule_dw(&clock->overflow_work, 0); - clock->ptp_info = mlxsw_sp1_ptp_clock_info; - clock->ptp = ptp_clock_register(&clock->ptp_info, dev); - if (IS_ERR(clock->ptp)) { - err = PTR_ERR(clock->ptp); + clock->common.ptp_info = mlxsw_sp1_ptp_clock_info; + clock->common.ptp = ptp_clock_register(&clock->common.ptp_info, dev); + if (IS_ERR(clock->common.ptp)) { + err = PTR_ERR(clock->common.ptp); dev_err(dev, "ptp_clock_register failed %d\n", err); goto err_ptp_clock_register; } - return clock; + return &clock->common; err_ptp_clock_register: cancel_delayed_work_sync(&clock->overflow_work); @@ -312,9 +318,12 @@ mlxsw_sp1_ptp_clock_init(struct mlxsw_sp *mlxsw_sp, struct device *dev) return ERR_PTR(err); } -void mlxsw_sp1_ptp_clock_fini(struct mlxsw_sp_ptp_clock *clock) +void mlxsw_sp1_ptp_clock_fini(struct mlxsw_sp_ptp_clock *clock_common) { - ptp_clock_unregister(clock->ptp); + struct mlxsw_sp1_ptp_clock *clock = + container_of(clock_common, struct mlxsw_sp1_ptp_clock, common); + + ptp_clock_unregister(clock_common->ptp); cancel_delayed_work_sync(&clock->overflow_work); kfree(clock); } @@ -451,12 +460,16 @@ static void mlxsw_sp1_packet_timestamp(struct mlxsw_sp *mlxsw_sp, struct sk_buff *skb, u64 timestamp) { + struct mlxsw_sp_ptp_clock *clock_common = mlxsw_sp->clock; + struct mlxsw_sp1_ptp_clock *clock = + container_of(clock_common, struct mlxsw_sp1_ptp_clock, common); + struct skb_shared_hwtstamps hwtstamps; u64 nsec; - spin_lock_bh(&mlxsw_sp->clock->lock); - nsec = timecounter_cyc2time(&mlxsw_sp->clock->tc, timestamp); - spin_unlock_bh(&mlxsw_sp->clock->lock); + spin_lock_bh(&clock->lock); + nsec = timecounter_cyc2time(&clock->tc, timestamp); + spin_unlock_bh(&clock->lock); hwtstamps.hwtstamp = ns_to_ktime(nsec); mlxsw_sp1_ptp_packet_finish(mlxsw_sp, skb, From 4017d929649271541b1c7955fbf48fbe9296f46f Mon Sep 17 00:00:00 2001 From: Amit Cohen Date: Sun, 24 Jul 2022 11:03:28 +0300 Subject: [PATCH 14/15] mlxsw: spectrum_ptp: Rename mlxsw_sp_ptp_get_message_types() Spectrum-1 and Spectrum-2 differ in their time stamping capabilities. The former can be configured to time stamp only a subset of received PTP events (e.g., only Sync), whereas the latter will time stamp all PTP events or none. In preparation for Spectrum-2 PTP support, rename the function that parses the hardware time stamping configuration upon %SIOCSHWTSTAMP to be Spectrum-1 specific. Signed-off-by: Amit Cohen Reviewed-by: Petr Machata Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c | 11 ++++++----- 1 file changed, 6 insertions(+), 5 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c index 99611dcc54743..4df97ddbf5b90 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c @@ -918,9 +918,10 @@ int mlxsw_sp1_ptp_hwtstamp_get(struct mlxsw_sp_port *mlxsw_sp_port, return 0; } -static int mlxsw_sp_ptp_get_message_types(const struct hwtstamp_config *config, - u16 *p_ing_types, u16 *p_egr_types, - enum hwtstamp_rx_filters *p_rx_filter) +static int +mlxsw_sp1_ptp_get_message_types(const struct hwtstamp_config *config, + u16 *p_ing_types, u16 *p_egr_types, + enum hwtstamp_rx_filters *p_rx_filter) { enum hwtstamp_rx_filters rx_filter = config->rx_filter; enum hwtstamp_tx_types tx_type = config->tx_type; @@ -1081,8 +1082,8 @@ int mlxsw_sp1_ptp_hwtstamp_set(struct mlxsw_sp_port *mlxsw_sp_port, u16 egr_types; int err; - err = mlxsw_sp_ptp_get_message_types(config, &ing_types, &egr_types, - &rx_filter); + err = mlxsw_sp1_ptp_get_message_types(config, &ing_types, &egr_types, + &rx_filter); if (err) return err; From a168e13f84488611f5b9453fab45649ac2d560ee Mon Sep 17 00:00:00 2001 From: Amit Cohen Date: Sun, 24 Jul 2022 11:03:29 +0300 Subject: [PATCH 15/15] mlxsw: spectrum_ptp: Rename mlxsw_sp1_ptp_phc_adjfreq() The function mlxsw_sp_ptp_phc_adjfreq() configures MTUTC register to adjust hardware frequency by a given value. This configuration will be same for Spectrum-2. In preparation for Spectrum-2 PTP support, rename the function to not be Spectrum-1 specific. Later, it will be used for Spectrum-2 also. Signed-off-by: Amit Cohen Reviewed-by: Petr Machata Signed-off-by: Ido Schimmel Signed-off-by: David S. Miller --- drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c index 4df97ddbf5b90..5116d7ebe2580 100644 --- a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c +++ b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c @@ -122,7 +122,7 @@ static u64 mlxsw_sp1_ptp_read_frc(const struct cyclecounter *cc) } static int -mlxsw_sp1_ptp_phc_adjfreq(struct mlxsw_sp_ptp_clock *clock, int freq_adj) +mlxsw_sp_ptp_phc_adjfreq(struct mlxsw_sp_ptp_clock *clock, int freq_adj) { struct mlxsw_core *mlxsw_core = clock->core; char mtutc_pl[MLXSW_REG_MTUTC_LEN]; @@ -194,7 +194,7 @@ static int mlxsw_sp1_ptp_adjfine(struct ptp_clock_info *ptp, long scaled_ppm) clock->nominal_c_mult + diff; spin_unlock_bh(&clock->lock); - return mlxsw_sp1_ptp_phc_adjfreq(&clock->common, neg_adj ? -ppb : ppb); + return mlxsw_sp_ptp_phc_adjfreq(&clock->common, neg_adj ? -ppb : ppb); } static int mlxsw_sp1_ptp_adjtime(struct ptp_clock_info *ptp, s64 delta)