diff options
author | David S. Miller <davem@davemloft.net> | 2022-07-25 13:58:56 +0100 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2022-07-25 13:58:56 +0100 |
commit | 360f9f3152a909d977173159b302a348f5582631 (patch) | |
tree | eb381dbc90ec83644e75dd02144d1976886e22c3 | |
parent | e222dc8d8408788e906a5c0dd5f01fbe7f6cd1d3 (diff) | |
parent | a168e13f84488611f5b9453fab45649ac2d560ee (diff) |
Merge branch 'mlxsw-Spectrum-2-PTP-preparations'
Ido Schimmel says:
====================
mlxsw: Spectrum-2 PTP preparations
This patchset includes various preparations required for Spectrum-2 PTP
support.
Most of the changes are non-functional (e.g., renaming, adding
registers). The only intentional user visible change is in patch #10
where the PHC time is initialized to zero in accordance with the
recommendation of the PTP maintainer.
====================
Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r-- | drivers/net/ethernet/mellanox/mlxsw/cmd.h | 52 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlxsw/core.h | 6 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlxsw/pci.c | 27 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlxsw/pci_hw.h | 81 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlxsw/reg.h | 99 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlxsw/resources.h | 2 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlxsw/spectrum.c | 6 | ||||
-rw-r--r-- | drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c | 148 |
8 files changed, 344 insertions, 77 deletions
diff --git a/drivers/net/ethernet/mellanox/mlxsw/cmd.h b/drivers/net/ethernet/mellanox/mlxsw/cmd.h index 666d6b6e4dbf..60232fb8ccd7 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) @@ -663,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 @@ -858,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 a3491ef2aa7e..9d2e8a8d3a75 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]; }; @@ -485,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 41f0f68bc911..83659fb0559a 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, @@ -1267,6 +1273,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); } @@ -1802,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 = { @@ -1916,7 +1929,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/pci_hw.h b/drivers/net/ethernet/mellanox/mlxsw/pci_hw.h index 7b531228d6c0..48dbfea0a2a1 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 @@ -217,6 +214,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 +296,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 diff --git a/drivers/net/ethernet/mellanox/mlxsw/reg.h b/drivers/net/ethernet/mellanox/mlxsw/reg.h index 17ce28e65464..ddab5476c8b2 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 @@ -11045,15 +11072,76 @@ 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); 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 * ------------------------------------------- */ @@ -12770,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), diff --git a/drivers/net/ethernet/mellanox/mlxsw/resources.h b/drivers/net/ethernet/mellanox/mlxsw/resources.h index 826e47fb4586..19ae0d1c74a8 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 */ diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum.c index 209587cf7529..641078060b02 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 @@ -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, @@ -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 diff --git a/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c b/drivers/net/ethernet/mellanox/mlxsw/spectrum_ptp.c index 35422e64d89f..5116d7ebe258 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; @@ -60,20 +64,37 @@ 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; }; -static u64 __mlxsw_sp1_ptp_read_frc(struct mlxsw_sp_ptp_clock *clock, +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 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); @@ -94,20 +115,20 @@ 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; } 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]; 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); } @@ -122,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]; @@ -144,14 +165,13 @@ 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); } 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; @@ -174,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_sp_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); @@ -195,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); @@ -212,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); @@ -237,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); @@ -251,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); @@ -265,10 +282,9 @@ 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, - 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. @@ -286,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); @@ -302,9 +318,12 @@ err_ptp_clock_register: 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); } @@ -348,7 +367,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; @@ -359,7 +378,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); @@ -373,11 +392,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; @@ -392,7 +412,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); } @@ -438,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, @@ -481,13 +507,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) { @@ -515,7 +542,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); @@ -611,9 +638,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; @@ -636,7 +664,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 : @@ -653,7 +681,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(); @@ -663,12 +691,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); @@ -694,7 +722,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); } @@ -809,7 +837,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; @@ -820,7 +848,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); @@ -853,7 +881,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); @@ -866,9 +894,12 @@ err_hashtable_init: 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); @@ -887,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; @@ -1050,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; |