162306a36Sopenharmony_ci// SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0 262306a36Sopenharmony_ci/* Copyright (c) 2020 Mellanox Technologies. All rights reserved */ 362306a36Sopenharmony_ci 462306a36Sopenharmony_ci#include "reg.h" 562306a36Sopenharmony_ci#include "core.h" 662306a36Sopenharmony_ci#include "spectrum.h" 762306a36Sopenharmony_ci#include "core_env.h" 862306a36Sopenharmony_ci 962306a36Sopenharmony_cistatic const char mlxsw_sp_driver_version[] = "1.0"; 1062306a36Sopenharmony_ci 1162306a36Sopenharmony_cistatic void mlxsw_sp_port_get_drvinfo(struct net_device *dev, 1262306a36Sopenharmony_ci struct ethtool_drvinfo *drvinfo) 1362306a36Sopenharmony_ci{ 1462306a36Sopenharmony_ci struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); 1562306a36Sopenharmony_ci struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 1662306a36Sopenharmony_ci 1762306a36Sopenharmony_ci strscpy(drvinfo->driver, mlxsw_sp->bus_info->device_kind, 1862306a36Sopenharmony_ci sizeof(drvinfo->driver)); 1962306a36Sopenharmony_ci strscpy(drvinfo->version, mlxsw_sp_driver_version, 2062306a36Sopenharmony_ci sizeof(drvinfo->version)); 2162306a36Sopenharmony_ci snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version), 2262306a36Sopenharmony_ci "%d.%d.%d", 2362306a36Sopenharmony_ci mlxsw_sp->bus_info->fw_rev.major, 2462306a36Sopenharmony_ci mlxsw_sp->bus_info->fw_rev.minor, 2562306a36Sopenharmony_ci mlxsw_sp->bus_info->fw_rev.subminor); 2662306a36Sopenharmony_ci strscpy(drvinfo->bus_info, mlxsw_sp->bus_info->device_name, 2762306a36Sopenharmony_ci sizeof(drvinfo->bus_info)); 2862306a36Sopenharmony_ci} 2962306a36Sopenharmony_ci 3062306a36Sopenharmony_cistruct mlxsw_sp_ethtool_link_ext_state_opcode_mapping { 3162306a36Sopenharmony_ci u32 status_opcode; 3262306a36Sopenharmony_ci enum ethtool_link_ext_state link_ext_state; 3362306a36Sopenharmony_ci u8 link_ext_substate; 3462306a36Sopenharmony_ci}; 3562306a36Sopenharmony_ci 3662306a36Sopenharmony_cistatic const struct mlxsw_sp_ethtool_link_ext_state_opcode_mapping 3762306a36Sopenharmony_cimlxsw_sp_link_ext_state_opcode_map[] = { 3862306a36Sopenharmony_ci {2, ETHTOOL_LINK_EXT_STATE_AUTONEG, 3962306a36Sopenharmony_ci ETHTOOL_LINK_EXT_SUBSTATE_AN_NO_PARTNER_DETECTED}, 4062306a36Sopenharmony_ci {3, ETHTOOL_LINK_EXT_STATE_AUTONEG, 4162306a36Sopenharmony_ci ETHTOOL_LINK_EXT_SUBSTATE_AN_ACK_NOT_RECEIVED}, 4262306a36Sopenharmony_ci {4, ETHTOOL_LINK_EXT_STATE_AUTONEG, 4362306a36Sopenharmony_ci ETHTOOL_LINK_EXT_SUBSTATE_AN_NEXT_PAGE_EXCHANGE_FAILED}, 4462306a36Sopenharmony_ci {36, ETHTOOL_LINK_EXT_STATE_AUTONEG, 4562306a36Sopenharmony_ci ETHTOOL_LINK_EXT_SUBSTATE_AN_NO_PARTNER_DETECTED_FORCE_MODE}, 4662306a36Sopenharmony_ci {38, ETHTOOL_LINK_EXT_STATE_AUTONEG, 4762306a36Sopenharmony_ci ETHTOOL_LINK_EXT_SUBSTATE_AN_FEC_MISMATCH_DURING_OVERRIDE}, 4862306a36Sopenharmony_ci {39, ETHTOOL_LINK_EXT_STATE_AUTONEG, 4962306a36Sopenharmony_ci ETHTOOL_LINK_EXT_SUBSTATE_AN_NO_HCD}, 5062306a36Sopenharmony_ci 5162306a36Sopenharmony_ci {5, ETHTOOL_LINK_EXT_STATE_LINK_TRAINING_FAILURE, 5262306a36Sopenharmony_ci ETHTOOL_LINK_EXT_SUBSTATE_LT_KR_FRAME_LOCK_NOT_ACQUIRED}, 5362306a36Sopenharmony_ci {6, ETHTOOL_LINK_EXT_STATE_LINK_TRAINING_FAILURE, 5462306a36Sopenharmony_ci ETHTOOL_LINK_EXT_SUBSTATE_LT_KR_LINK_INHIBIT_TIMEOUT}, 5562306a36Sopenharmony_ci {7, ETHTOOL_LINK_EXT_STATE_LINK_TRAINING_FAILURE, 5662306a36Sopenharmony_ci ETHTOOL_LINK_EXT_SUBSTATE_LT_KR_LINK_PARTNER_DID_NOT_SET_RECEIVER_READY}, 5762306a36Sopenharmony_ci {8, ETHTOOL_LINK_EXT_STATE_LINK_TRAINING_FAILURE, 0}, 5862306a36Sopenharmony_ci {14, ETHTOOL_LINK_EXT_STATE_LINK_TRAINING_FAILURE, 5962306a36Sopenharmony_ci ETHTOOL_LINK_EXT_SUBSTATE_LT_REMOTE_FAULT}, 6062306a36Sopenharmony_ci 6162306a36Sopenharmony_ci {9, ETHTOOL_LINK_EXT_STATE_LINK_LOGICAL_MISMATCH, 6262306a36Sopenharmony_ci ETHTOOL_LINK_EXT_SUBSTATE_LLM_PCS_DID_NOT_ACQUIRE_BLOCK_LOCK}, 6362306a36Sopenharmony_ci {10, ETHTOOL_LINK_EXT_STATE_LINK_LOGICAL_MISMATCH, 6462306a36Sopenharmony_ci ETHTOOL_LINK_EXT_SUBSTATE_LLM_PCS_DID_NOT_ACQUIRE_AM_LOCK}, 6562306a36Sopenharmony_ci {11, ETHTOOL_LINK_EXT_STATE_LINK_LOGICAL_MISMATCH, 6662306a36Sopenharmony_ci ETHTOOL_LINK_EXT_SUBSTATE_LLM_PCS_DID_NOT_GET_ALIGN_STATUS}, 6762306a36Sopenharmony_ci {12, ETHTOOL_LINK_EXT_STATE_LINK_LOGICAL_MISMATCH, 6862306a36Sopenharmony_ci ETHTOOL_LINK_EXT_SUBSTATE_LLM_FC_FEC_IS_NOT_LOCKED}, 6962306a36Sopenharmony_ci {13, ETHTOOL_LINK_EXT_STATE_LINK_LOGICAL_MISMATCH, 7062306a36Sopenharmony_ci ETHTOOL_LINK_EXT_SUBSTATE_LLM_RS_FEC_IS_NOT_LOCKED}, 7162306a36Sopenharmony_ci 7262306a36Sopenharmony_ci {15, ETHTOOL_LINK_EXT_STATE_BAD_SIGNAL_INTEGRITY, 0}, 7362306a36Sopenharmony_ci {17, ETHTOOL_LINK_EXT_STATE_BAD_SIGNAL_INTEGRITY, 7462306a36Sopenharmony_ci ETHTOOL_LINK_EXT_SUBSTATE_BSI_LARGE_NUMBER_OF_PHYSICAL_ERRORS}, 7562306a36Sopenharmony_ci {42, ETHTOOL_LINK_EXT_STATE_BAD_SIGNAL_INTEGRITY, 7662306a36Sopenharmony_ci ETHTOOL_LINK_EXT_SUBSTATE_BSI_UNSUPPORTED_RATE}, 7762306a36Sopenharmony_ci 7862306a36Sopenharmony_ci {1024, ETHTOOL_LINK_EXT_STATE_NO_CABLE, 0}, 7962306a36Sopenharmony_ci 8062306a36Sopenharmony_ci {16, ETHTOOL_LINK_EXT_STATE_CABLE_ISSUE, 8162306a36Sopenharmony_ci ETHTOOL_LINK_EXT_SUBSTATE_CI_UNSUPPORTED_CABLE}, 8262306a36Sopenharmony_ci {20, ETHTOOL_LINK_EXT_STATE_CABLE_ISSUE, 8362306a36Sopenharmony_ci ETHTOOL_LINK_EXT_SUBSTATE_CI_UNSUPPORTED_CABLE}, 8462306a36Sopenharmony_ci {29, ETHTOOL_LINK_EXT_STATE_CABLE_ISSUE, 8562306a36Sopenharmony_ci ETHTOOL_LINK_EXT_SUBSTATE_CI_UNSUPPORTED_CABLE}, 8662306a36Sopenharmony_ci {1025, ETHTOOL_LINK_EXT_STATE_CABLE_ISSUE, 8762306a36Sopenharmony_ci ETHTOOL_LINK_EXT_SUBSTATE_CI_UNSUPPORTED_CABLE}, 8862306a36Sopenharmony_ci {1029, ETHTOOL_LINK_EXT_STATE_CABLE_ISSUE, 8962306a36Sopenharmony_ci ETHTOOL_LINK_EXT_SUBSTATE_CI_UNSUPPORTED_CABLE}, 9062306a36Sopenharmony_ci {1031, ETHTOOL_LINK_EXT_STATE_CABLE_ISSUE, 0}, 9162306a36Sopenharmony_ci 9262306a36Sopenharmony_ci {1027, ETHTOOL_LINK_EXT_STATE_EEPROM_ISSUE, 0}, 9362306a36Sopenharmony_ci 9462306a36Sopenharmony_ci {23, ETHTOOL_LINK_EXT_STATE_CALIBRATION_FAILURE, 0}, 9562306a36Sopenharmony_ci 9662306a36Sopenharmony_ci {1032, ETHTOOL_LINK_EXT_STATE_POWER_BUDGET_EXCEEDED, 0}, 9762306a36Sopenharmony_ci 9862306a36Sopenharmony_ci {1030, ETHTOOL_LINK_EXT_STATE_OVERHEAT, 0}, 9962306a36Sopenharmony_ci 10062306a36Sopenharmony_ci {1042, ETHTOOL_LINK_EXT_STATE_MODULE, 10162306a36Sopenharmony_ci ETHTOOL_LINK_EXT_SUBSTATE_MODULE_CMIS_NOT_READY}, 10262306a36Sopenharmony_ci}; 10362306a36Sopenharmony_ci 10462306a36Sopenharmony_cistatic void 10562306a36Sopenharmony_cimlxsw_sp_port_set_link_ext_state(struct mlxsw_sp_ethtool_link_ext_state_opcode_mapping 10662306a36Sopenharmony_ci link_ext_state_mapping, 10762306a36Sopenharmony_ci struct ethtool_link_ext_state_info *link_ext_state_info) 10862306a36Sopenharmony_ci{ 10962306a36Sopenharmony_ci switch (link_ext_state_mapping.link_ext_state) { 11062306a36Sopenharmony_ci case ETHTOOL_LINK_EXT_STATE_AUTONEG: 11162306a36Sopenharmony_ci link_ext_state_info->autoneg = 11262306a36Sopenharmony_ci link_ext_state_mapping.link_ext_substate; 11362306a36Sopenharmony_ci break; 11462306a36Sopenharmony_ci case ETHTOOL_LINK_EXT_STATE_LINK_TRAINING_FAILURE: 11562306a36Sopenharmony_ci link_ext_state_info->link_training = 11662306a36Sopenharmony_ci link_ext_state_mapping.link_ext_substate; 11762306a36Sopenharmony_ci break; 11862306a36Sopenharmony_ci case ETHTOOL_LINK_EXT_STATE_LINK_LOGICAL_MISMATCH: 11962306a36Sopenharmony_ci link_ext_state_info->link_logical_mismatch = 12062306a36Sopenharmony_ci link_ext_state_mapping.link_ext_substate; 12162306a36Sopenharmony_ci break; 12262306a36Sopenharmony_ci case ETHTOOL_LINK_EXT_STATE_BAD_SIGNAL_INTEGRITY: 12362306a36Sopenharmony_ci link_ext_state_info->bad_signal_integrity = 12462306a36Sopenharmony_ci link_ext_state_mapping.link_ext_substate; 12562306a36Sopenharmony_ci break; 12662306a36Sopenharmony_ci case ETHTOOL_LINK_EXT_STATE_CABLE_ISSUE: 12762306a36Sopenharmony_ci link_ext_state_info->cable_issue = 12862306a36Sopenharmony_ci link_ext_state_mapping.link_ext_substate; 12962306a36Sopenharmony_ci break; 13062306a36Sopenharmony_ci case ETHTOOL_LINK_EXT_STATE_MODULE: 13162306a36Sopenharmony_ci link_ext_state_info->module = 13262306a36Sopenharmony_ci link_ext_state_mapping.link_ext_substate; 13362306a36Sopenharmony_ci break; 13462306a36Sopenharmony_ci default: 13562306a36Sopenharmony_ci break; 13662306a36Sopenharmony_ci } 13762306a36Sopenharmony_ci 13862306a36Sopenharmony_ci link_ext_state_info->link_ext_state = link_ext_state_mapping.link_ext_state; 13962306a36Sopenharmony_ci} 14062306a36Sopenharmony_ci 14162306a36Sopenharmony_cistatic int 14262306a36Sopenharmony_cimlxsw_sp_port_get_link_ext_state(struct net_device *dev, 14362306a36Sopenharmony_ci struct ethtool_link_ext_state_info *link_ext_state_info) 14462306a36Sopenharmony_ci{ 14562306a36Sopenharmony_ci struct mlxsw_sp_ethtool_link_ext_state_opcode_mapping link_ext_state_mapping; 14662306a36Sopenharmony_ci struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); 14762306a36Sopenharmony_ci char pddr_pl[MLXSW_REG_PDDR_LEN]; 14862306a36Sopenharmony_ci int opcode, err, i; 14962306a36Sopenharmony_ci u32 status_opcode; 15062306a36Sopenharmony_ci 15162306a36Sopenharmony_ci if (netif_carrier_ok(dev)) 15262306a36Sopenharmony_ci return -ENODATA; 15362306a36Sopenharmony_ci 15462306a36Sopenharmony_ci mlxsw_reg_pddr_pack(pddr_pl, mlxsw_sp_port->local_port, 15562306a36Sopenharmony_ci MLXSW_REG_PDDR_PAGE_SELECT_TROUBLESHOOTING_INFO); 15662306a36Sopenharmony_ci 15762306a36Sopenharmony_ci opcode = MLXSW_REG_PDDR_TRBLSH_GROUP_OPCODE_MONITOR; 15862306a36Sopenharmony_ci mlxsw_reg_pddr_trblsh_group_opcode_set(pddr_pl, opcode); 15962306a36Sopenharmony_ci 16062306a36Sopenharmony_ci err = mlxsw_reg_query(mlxsw_sp_port->mlxsw_sp->core, MLXSW_REG(pddr), 16162306a36Sopenharmony_ci pddr_pl); 16262306a36Sopenharmony_ci if (err) 16362306a36Sopenharmony_ci return err; 16462306a36Sopenharmony_ci 16562306a36Sopenharmony_ci status_opcode = mlxsw_reg_pddr_trblsh_status_opcode_get(pddr_pl); 16662306a36Sopenharmony_ci if (!status_opcode) 16762306a36Sopenharmony_ci return -ENODATA; 16862306a36Sopenharmony_ci 16962306a36Sopenharmony_ci for (i = 0; i < ARRAY_SIZE(mlxsw_sp_link_ext_state_opcode_map); i++) { 17062306a36Sopenharmony_ci link_ext_state_mapping = mlxsw_sp_link_ext_state_opcode_map[i]; 17162306a36Sopenharmony_ci if (link_ext_state_mapping.status_opcode == status_opcode) { 17262306a36Sopenharmony_ci mlxsw_sp_port_set_link_ext_state(link_ext_state_mapping, 17362306a36Sopenharmony_ci link_ext_state_info); 17462306a36Sopenharmony_ci return 0; 17562306a36Sopenharmony_ci } 17662306a36Sopenharmony_ci } 17762306a36Sopenharmony_ci 17862306a36Sopenharmony_ci return -ENODATA; 17962306a36Sopenharmony_ci} 18062306a36Sopenharmony_ci 18162306a36Sopenharmony_cistatic void mlxsw_sp_port_get_pauseparam(struct net_device *dev, 18262306a36Sopenharmony_ci struct ethtool_pauseparam *pause) 18362306a36Sopenharmony_ci{ 18462306a36Sopenharmony_ci struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); 18562306a36Sopenharmony_ci 18662306a36Sopenharmony_ci pause->rx_pause = mlxsw_sp_port->link.rx_pause; 18762306a36Sopenharmony_ci pause->tx_pause = mlxsw_sp_port->link.tx_pause; 18862306a36Sopenharmony_ci} 18962306a36Sopenharmony_ci 19062306a36Sopenharmony_cistatic int mlxsw_sp_port_pause_set(struct mlxsw_sp_port *mlxsw_sp_port, 19162306a36Sopenharmony_ci struct ethtool_pauseparam *pause) 19262306a36Sopenharmony_ci{ 19362306a36Sopenharmony_ci char pfcc_pl[MLXSW_REG_PFCC_LEN]; 19462306a36Sopenharmony_ci 19562306a36Sopenharmony_ci mlxsw_reg_pfcc_pack(pfcc_pl, mlxsw_sp_port->local_port); 19662306a36Sopenharmony_ci mlxsw_reg_pfcc_pprx_set(pfcc_pl, pause->rx_pause); 19762306a36Sopenharmony_ci mlxsw_reg_pfcc_pptx_set(pfcc_pl, pause->tx_pause); 19862306a36Sopenharmony_ci 19962306a36Sopenharmony_ci return mlxsw_reg_write(mlxsw_sp_port->mlxsw_sp->core, MLXSW_REG(pfcc), 20062306a36Sopenharmony_ci pfcc_pl); 20162306a36Sopenharmony_ci} 20262306a36Sopenharmony_ci 20362306a36Sopenharmony_ci/* Maximum delay buffer needed in case of PAUSE frames. Similar to PFC delay, but is 20462306a36Sopenharmony_ci * measured in bytes. Assumes 100m cable and does not take into account MTU. 20562306a36Sopenharmony_ci */ 20662306a36Sopenharmony_ci#define MLXSW_SP_PAUSE_DELAY_BYTES 19476 20762306a36Sopenharmony_ci 20862306a36Sopenharmony_cistatic int mlxsw_sp_port_set_pauseparam(struct net_device *dev, 20962306a36Sopenharmony_ci struct ethtool_pauseparam *pause) 21062306a36Sopenharmony_ci{ 21162306a36Sopenharmony_ci struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); 21262306a36Sopenharmony_ci bool pause_en = pause->tx_pause || pause->rx_pause; 21362306a36Sopenharmony_ci struct mlxsw_sp_hdroom orig_hdroom; 21462306a36Sopenharmony_ci struct mlxsw_sp_hdroom hdroom; 21562306a36Sopenharmony_ci int prio; 21662306a36Sopenharmony_ci int err; 21762306a36Sopenharmony_ci 21862306a36Sopenharmony_ci if (mlxsw_sp_port->dcb.pfc && mlxsw_sp_port->dcb.pfc->pfc_en) { 21962306a36Sopenharmony_ci netdev_err(dev, "PFC already enabled on port\n"); 22062306a36Sopenharmony_ci return -EINVAL; 22162306a36Sopenharmony_ci } 22262306a36Sopenharmony_ci 22362306a36Sopenharmony_ci if (pause->autoneg) { 22462306a36Sopenharmony_ci netdev_err(dev, "PAUSE frames autonegotiation isn't supported\n"); 22562306a36Sopenharmony_ci return -EINVAL; 22662306a36Sopenharmony_ci } 22762306a36Sopenharmony_ci 22862306a36Sopenharmony_ci orig_hdroom = *mlxsw_sp_port->hdroom; 22962306a36Sopenharmony_ci 23062306a36Sopenharmony_ci hdroom = orig_hdroom; 23162306a36Sopenharmony_ci if (pause_en) 23262306a36Sopenharmony_ci hdroom.delay_bytes = MLXSW_SP_PAUSE_DELAY_BYTES; 23362306a36Sopenharmony_ci else 23462306a36Sopenharmony_ci hdroom.delay_bytes = 0; 23562306a36Sopenharmony_ci 23662306a36Sopenharmony_ci for (prio = 0; prio < IEEE_8021QAZ_MAX_TCS; prio++) 23762306a36Sopenharmony_ci hdroom.prios.prio[prio].lossy = !pause_en; 23862306a36Sopenharmony_ci 23962306a36Sopenharmony_ci mlxsw_sp_hdroom_bufs_reset_lossiness(&hdroom); 24062306a36Sopenharmony_ci mlxsw_sp_hdroom_bufs_reset_sizes(mlxsw_sp_port, &hdroom); 24162306a36Sopenharmony_ci 24262306a36Sopenharmony_ci err = mlxsw_sp_hdroom_configure(mlxsw_sp_port, &hdroom); 24362306a36Sopenharmony_ci if (err) { 24462306a36Sopenharmony_ci netdev_err(dev, "Failed to configure port's headroom\n"); 24562306a36Sopenharmony_ci return err; 24662306a36Sopenharmony_ci } 24762306a36Sopenharmony_ci 24862306a36Sopenharmony_ci err = mlxsw_sp_port_pause_set(mlxsw_sp_port, pause); 24962306a36Sopenharmony_ci if (err) { 25062306a36Sopenharmony_ci netdev_err(dev, "Failed to set PAUSE parameters\n"); 25162306a36Sopenharmony_ci goto err_port_pause_configure; 25262306a36Sopenharmony_ci } 25362306a36Sopenharmony_ci 25462306a36Sopenharmony_ci mlxsw_sp_port->link.rx_pause = pause->rx_pause; 25562306a36Sopenharmony_ci mlxsw_sp_port->link.tx_pause = pause->tx_pause; 25662306a36Sopenharmony_ci 25762306a36Sopenharmony_ci return 0; 25862306a36Sopenharmony_ci 25962306a36Sopenharmony_cierr_port_pause_configure: 26062306a36Sopenharmony_ci mlxsw_sp_hdroom_configure(mlxsw_sp_port, &orig_hdroom); 26162306a36Sopenharmony_ci return err; 26262306a36Sopenharmony_ci} 26362306a36Sopenharmony_ci 26462306a36Sopenharmony_cistruct mlxsw_sp_port_hw_stats { 26562306a36Sopenharmony_ci char str[ETH_GSTRING_LEN]; 26662306a36Sopenharmony_ci u64 (*getter)(const char *payload); 26762306a36Sopenharmony_ci bool cells_bytes; 26862306a36Sopenharmony_ci}; 26962306a36Sopenharmony_ci 27062306a36Sopenharmony_cistatic struct mlxsw_sp_port_hw_stats mlxsw_sp_port_hw_stats[] = { 27162306a36Sopenharmony_ci { 27262306a36Sopenharmony_ci .str = "a_frames_transmitted_ok", 27362306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_a_frames_transmitted_ok_get, 27462306a36Sopenharmony_ci }, 27562306a36Sopenharmony_ci { 27662306a36Sopenharmony_ci .str = "a_frames_received_ok", 27762306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_a_frames_received_ok_get, 27862306a36Sopenharmony_ci }, 27962306a36Sopenharmony_ci { 28062306a36Sopenharmony_ci .str = "a_frame_check_sequence_errors", 28162306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_a_frame_check_sequence_errors_get, 28262306a36Sopenharmony_ci }, 28362306a36Sopenharmony_ci { 28462306a36Sopenharmony_ci .str = "a_alignment_errors", 28562306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_a_alignment_errors_get, 28662306a36Sopenharmony_ci }, 28762306a36Sopenharmony_ci { 28862306a36Sopenharmony_ci .str = "a_octets_transmitted_ok", 28962306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_a_octets_transmitted_ok_get, 29062306a36Sopenharmony_ci }, 29162306a36Sopenharmony_ci { 29262306a36Sopenharmony_ci .str = "a_octets_received_ok", 29362306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_a_octets_received_ok_get, 29462306a36Sopenharmony_ci }, 29562306a36Sopenharmony_ci { 29662306a36Sopenharmony_ci .str = "a_multicast_frames_xmitted_ok", 29762306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_a_multicast_frames_xmitted_ok_get, 29862306a36Sopenharmony_ci }, 29962306a36Sopenharmony_ci { 30062306a36Sopenharmony_ci .str = "a_broadcast_frames_xmitted_ok", 30162306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_a_broadcast_frames_xmitted_ok_get, 30262306a36Sopenharmony_ci }, 30362306a36Sopenharmony_ci { 30462306a36Sopenharmony_ci .str = "a_multicast_frames_received_ok", 30562306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_a_multicast_frames_received_ok_get, 30662306a36Sopenharmony_ci }, 30762306a36Sopenharmony_ci { 30862306a36Sopenharmony_ci .str = "a_broadcast_frames_received_ok", 30962306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_a_broadcast_frames_received_ok_get, 31062306a36Sopenharmony_ci }, 31162306a36Sopenharmony_ci { 31262306a36Sopenharmony_ci .str = "a_in_range_length_errors", 31362306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_a_in_range_length_errors_get, 31462306a36Sopenharmony_ci }, 31562306a36Sopenharmony_ci { 31662306a36Sopenharmony_ci .str = "a_out_of_range_length_field", 31762306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_a_out_of_range_length_field_get, 31862306a36Sopenharmony_ci }, 31962306a36Sopenharmony_ci { 32062306a36Sopenharmony_ci .str = "a_frame_too_long_errors", 32162306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_a_frame_too_long_errors_get, 32262306a36Sopenharmony_ci }, 32362306a36Sopenharmony_ci { 32462306a36Sopenharmony_ci .str = "a_symbol_error_during_carrier", 32562306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_a_symbol_error_during_carrier_get, 32662306a36Sopenharmony_ci }, 32762306a36Sopenharmony_ci { 32862306a36Sopenharmony_ci .str = "a_mac_control_frames_transmitted", 32962306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_a_mac_control_frames_transmitted_get, 33062306a36Sopenharmony_ci }, 33162306a36Sopenharmony_ci { 33262306a36Sopenharmony_ci .str = "a_mac_control_frames_received", 33362306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_a_mac_control_frames_received_get, 33462306a36Sopenharmony_ci }, 33562306a36Sopenharmony_ci { 33662306a36Sopenharmony_ci .str = "a_unsupported_opcodes_received", 33762306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_a_unsupported_opcodes_received_get, 33862306a36Sopenharmony_ci }, 33962306a36Sopenharmony_ci { 34062306a36Sopenharmony_ci .str = "a_pause_mac_ctrl_frames_received", 34162306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_a_pause_mac_ctrl_frames_received_get, 34262306a36Sopenharmony_ci }, 34362306a36Sopenharmony_ci { 34462306a36Sopenharmony_ci .str = "a_pause_mac_ctrl_frames_xmitted", 34562306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_a_pause_mac_ctrl_frames_transmitted_get, 34662306a36Sopenharmony_ci }, 34762306a36Sopenharmony_ci}; 34862306a36Sopenharmony_ci 34962306a36Sopenharmony_ci#define MLXSW_SP_PORT_HW_STATS_LEN ARRAY_SIZE(mlxsw_sp_port_hw_stats) 35062306a36Sopenharmony_ci 35162306a36Sopenharmony_cistatic struct mlxsw_sp_port_hw_stats mlxsw_sp_port_hw_rfc_2863_stats[] = { 35262306a36Sopenharmony_ci { 35362306a36Sopenharmony_ci .str = "if_in_discards", 35462306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_if_in_discards_get, 35562306a36Sopenharmony_ci }, 35662306a36Sopenharmony_ci { 35762306a36Sopenharmony_ci .str = "if_out_discards", 35862306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_if_out_discards_get, 35962306a36Sopenharmony_ci }, 36062306a36Sopenharmony_ci { 36162306a36Sopenharmony_ci .str = "if_out_errors", 36262306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_if_out_errors_get, 36362306a36Sopenharmony_ci }, 36462306a36Sopenharmony_ci}; 36562306a36Sopenharmony_ci 36662306a36Sopenharmony_ci#define MLXSW_SP_PORT_HW_RFC_2863_STATS_LEN \ 36762306a36Sopenharmony_ci ARRAY_SIZE(mlxsw_sp_port_hw_rfc_2863_stats) 36862306a36Sopenharmony_ci 36962306a36Sopenharmony_cistatic struct mlxsw_sp_port_hw_stats mlxsw_sp_port_hw_rfc_2819_stats[] = { 37062306a36Sopenharmony_ci { 37162306a36Sopenharmony_ci .str = "ether_stats_undersize_pkts", 37262306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_ether_stats_undersize_pkts_get, 37362306a36Sopenharmony_ci }, 37462306a36Sopenharmony_ci { 37562306a36Sopenharmony_ci .str = "ether_stats_oversize_pkts", 37662306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_ether_stats_oversize_pkts_get, 37762306a36Sopenharmony_ci }, 37862306a36Sopenharmony_ci { 37962306a36Sopenharmony_ci .str = "ether_stats_fragments", 38062306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_ether_stats_fragments_get, 38162306a36Sopenharmony_ci }, 38262306a36Sopenharmony_ci { 38362306a36Sopenharmony_ci .str = "ether_pkts64octets", 38462306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_ether_stats_pkts64octets_get, 38562306a36Sopenharmony_ci }, 38662306a36Sopenharmony_ci { 38762306a36Sopenharmony_ci .str = "ether_pkts65to127octets", 38862306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_ether_stats_pkts65to127octets_get, 38962306a36Sopenharmony_ci }, 39062306a36Sopenharmony_ci { 39162306a36Sopenharmony_ci .str = "ether_pkts128to255octets", 39262306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_ether_stats_pkts128to255octets_get, 39362306a36Sopenharmony_ci }, 39462306a36Sopenharmony_ci { 39562306a36Sopenharmony_ci .str = "ether_pkts256to511octets", 39662306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_ether_stats_pkts256to511octets_get, 39762306a36Sopenharmony_ci }, 39862306a36Sopenharmony_ci { 39962306a36Sopenharmony_ci .str = "ether_pkts512to1023octets", 40062306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_ether_stats_pkts512to1023octets_get, 40162306a36Sopenharmony_ci }, 40262306a36Sopenharmony_ci { 40362306a36Sopenharmony_ci .str = "ether_pkts1024to1518octets", 40462306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_ether_stats_pkts1024to1518octets_get, 40562306a36Sopenharmony_ci }, 40662306a36Sopenharmony_ci { 40762306a36Sopenharmony_ci .str = "ether_pkts1519to2047octets", 40862306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_ether_stats_pkts1519to2047octets_get, 40962306a36Sopenharmony_ci }, 41062306a36Sopenharmony_ci { 41162306a36Sopenharmony_ci .str = "ether_pkts2048to4095octets", 41262306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_ether_stats_pkts2048to4095octets_get, 41362306a36Sopenharmony_ci }, 41462306a36Sopenharmony_ci { 41562306a36Sopenharmony_ci .str = "ether_pkts4096to8191octets", 41662306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_ether_stats_pkts4096to8191octets_get, 41762306a36Sopenharmony_ci }, 41862306a36Sopenharmony_ci { 41962306a36Sopenharmony_ci .str = "ether_pkts8192to10239octets", 42062306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_ether_stats_pkts8192to10239octets_get, 42162306a36Sopenharmony_ci }, 42262306a36Sopenharmony_ci}; 42362306a36Sopenharmony_ci 42462306a36Sopenharmony_ci#define MLXSW_SP_PORT_HW_RFC_2819_STATS_LEN \ 42562306a36Sopenharmony_ci ARRAY_SIZE(mlxsw_sp_port_hw_rfc_2819_stats) 42662306a36Sopenharmony_ci 42762306a36Sopenharmony_cistatic struct mlxsw_sp_port_hw_stats mlxsw_sp_port_hw_rfc_3635_stats[] = { 42862306a36Sopenharmony_ci { 42962306a36Sopenharmony_ci .str = "dot3stats_fcs_errors", 43062306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_dot3stats_fcs_errors_get, 43162306a36Sopenharmony_ci }, 43262306a36Sopenharmony_ci { 43362306a36Sopenharmony_ci .str = "dot3stats_symbol_errors", 43462306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_dot3stats_symbol_errors_get, 43562306a36Sopenharmony_ci }, 43662306a36Sopenharmony_ci { 43762306a36Sopenharmony_ci .str = "dot3control_in_unknown_opcodes", 43862306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_dot3control_in_unknown_opcodes_get, 43962306a36Sopenharmony_ci }, 44062306a36Sopenharmony_ci { 44162306a36Sopenharmony_ci .str = "dot3in_pause_frames", 44262306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_dot3in_pause_frames_get, 44362306a36Sopenharmony_ci }, 44462306a36Sopenharmony_ci}; 44562306a36Sopenharmony_ci 44662306a36Sopenharmony_ci#define MLXSW_SP_PORT_HW_RFC_3635_STATS_LEN \ 44762306a36Sopenharmony_ci ARRAY_SIZE(mlxsw_sp_port_hw_rfc_3635_stats) 44862306a36Sopenharmony_ci 44962306a36Sopenharmony_cistatic struct mlxsw_sp_port_hw_stats mlxsw_sp_port_hw_ext_stats[] = { 45062306a36Sopenharmony_ci { 45162306a36Sopenharmony_ci .str = "ecn_marked", 45262306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_ecn_marked_get, 45362306a36Sopenharmony_ci }, 45462306a36Sopenharmony_ci}; 45562306a36Sopenharmony_ci 45662306a36Sopenharmony_ci#define MLXSW_SP_PORT_HW_EXT_STATS_LEN ARRAY_SIZE(mlxsw_sp_port_hw_ext_stats) 45762306a36Sopenharmony_ci 45862306a36Sopenharmony_cistatic struct mlxsw_sp_port_hw_stats mlxsw_sp_port_hw_discard_stats[] = { 45962306a36Sopenharmony_ci { 46062306a36Sopenharmony_ci .str = "discard_ingress_general", 46162306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_ingress_general_get, 46262306a36Sopenharmony_ci }, 46362306a36Sopenharmony_ci { 46462306a36Sopenharmony_ci .str = "discard_ingress_policy_engine", 46562306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_ingress_policy_engine_get, 46662306a36Sopenharmony_ci }, 46762306a36Sopenharmony_ci { 46862306a36Sopenharmony_ci .str = "discard_ingress_vlan_membership", 46962306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_ingress_vlan_membership_get, 47062306a36Sopenharmony_ci }, 47162306a36Sopenharmony_ci { 47262306a36Sopenharmony_ci .str = "discard_ingress_tag_frame_type", 47362306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_ingress_tag_frame_type_get, 47462306a36Sopenharmony_ci }, 47562306a36Sopenharmony_ci { 47662306a36Sopenharmony_ci .str = "discard_egress_vlan_membership", 47762306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_egress_vlan_membership_get, 47862306a36Sopenharmony_ci }, 47962306a36Sopenharmony_ci { 48062306a36Sopenharmony_ci .str = "discard_loopback_filter", 48162306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_loopback_filter_get, 48262306a36Sopenharmony_ci }, 48362306a36Sopenharmony_ci { 48462306a36Sopenharmony_ci .str = "discard_egress_general", 48562306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_egress_general_get, 48662306a36Sopenharmony_ci }, 48762306a36Sopenharmony_ci { 48862306a36Sopenharmony_ci .str = "discard_egress_hoq", 48962306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_egress_hoq_get, 49062306a36Sopenharmony_ci }, 49162306a36Sopenharmony_ci { 49262306a36Sopenharmony_ci .str = "discard_egress_policy_engine", 49362306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_egress_policy_engine_get, 49462306a36Sopenharmony_ci }, 49562306a36Sopenharmony_ci { 49662306a36Sopenharmony_ci .str = "discard_ingress_tx_link_down", 49762306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_ingress_tx_link_down_get, 49862306a36Sopenharmony_ci }, 49962306a36Sopenharmony_ci { 50062306a36Sopenharmony_ci .str = "discard_egress_stp_filter", 50162306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_egress_stp_filter_get, 50262306a36Sopenharmony_ci }, 50362306a36Sopenharmony_ci { 50462306a36Sopenharmony_ci .str = "discard_egress_sll", 50562306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_egress_sll_get, 50662306a36Sopenharmony_ci }, 50762306a36Sopenharmony_ci}; 50862306a36Sopenharmony_ci 50962306a36Sopenharmony_ci#define MLXSW_SP_PORT_HW_DISCARD_STATS_LEN \ 51062306a36Sopenharmony_ci ARRAY_SIZE(mlxsw_sp_port_hw_discard_stats) 51162306a36Sopenharmony_ci 51262306a36Sopenharmony_cistatic struct mlxsw_sp_port_hw_stats mlxsw_sp_port_hw_prio_stats[] = { 51362306a36Sopenharmony_ci { 51462306a36Sopenharmony_ci .str = "rx_octets_prio", 51562306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_rx_octets_get, 51662306a36Sopenharmony_ci }, 51762306a36Sopenharmony_ci { 51862306a36Sopenharmony_ci .str = "rx_frames_prio", 51962306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_rx_frames_get, 52062306a36Sopenharmony_ci }, 52162306a36Sopenharmony_ci { 52262306a36Sopenharmony_ci .str = "tx_octets_prio", 52362306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_tx_octets_get, 52462306a36Sopenharmony_ci }, 52562306a36Sopenharmony_ci { 52662306a36Sopenharmony_ci .str = "tx_frames_prio", 52762306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_tx_frames_get, 52862306a36Sopenharmony_ci }, 52962306a36Sopenharmony_ci { 53062306a36Sopenharmony_ci .str = "rx_pause_prio", 53162306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_rx_pause_get, 53262306a36Sopenharmony_ci }, 53362306a36Sopenharmony_ci { 53462306a36Sopenharmony_ci .str = "rx_pause_duration_prio", 53562306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_rx_pause_duration_get, 53662306a36Sopenharmony_ci }, 53762306a36Sopenharmony_ci { 53862306a36Sopenharmony_ci .str = "tx_pause_prio", 53962306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_tx_pause_get, 54062306a36Sopenharmony_ci }, 54162306a36Sopenharmony_ci { 54262306a36Sopenharmony_ci .str = "tx_pause_duration_prio", 54362306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_tx_pause_duration_get, 54462306a36Sopenharmony_ci }, 54562306a36Sopenharmony_ci}; 54662306a36Sopenharmony_ci 54762306a36Sopenharmony_ci#define MLXSW_SP_PORT_HW_PRIO_STATS_LEN ARRAY_SIZE(mlxsw_sp_port_hw_prio_stats) 54862306a36Sopenharmony_ci 54962306a36Sopenharmony_cistatic struct mlxsw_sp_port_hw_stats mlxsw_sp_port_hw_tc_stats[] = { 55062306a36Sopenharmony_ci { 55162306a36Sopenharmony_ci .str = "tc_transmit_queue_tc", 55262306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_tc_transmit_queue_get, 55362306a36Sopenharmony_ci .cells_bytes = true, 55462306a36Sopenharmony_ci }, 55562306a36Sopenharmony_ci { 55662306a36Sopenharmony_ci .str = "tc_no_buffer_discard_uc_tc", 55762306a36Sopenharmony_ci .getter = mlxsw_reg_ppcnt_tc_no_buffer_discard_uc_get, 55862306a36Sopenharmony_ci }, 55962306a36Sopenharmony_ci}; 56062306a36Sopenharmony_ci 56162306a36Sopenharmony_ci#define MLXSW_SP_PORT_HW_TC_STATS_LEN ARRAY_SIZE(mlxsw_sp_port_hw_tc_stats) 56262306a36Sopenharmony_ci 56362306a36Sopenharmony_cistruct mlxsw_sp_port_stats { 56462306a36Sopenharmony_ci char str[ETH_GSTRING_LEN]; 56562306a36Sopenharmony_ci u64 (*getter)(struct mlxsw_sp_port *mlxsw_sp_port); 56662306a36Sopenharmony_ci}; 56762306a36Sopenharmony_ci 56862306a36Sopenharmony_cistatic u64 56962306a36Sopenharmony_cimlxsw_sp_port_get_transceiver_overheat_stats(struct mlxsw_sp_port *mlxsw_sp_port) 57062306a36Sopenharmony_ci{ 57162306a36Sopenharmony_ci struct mlxsw_core *mlxsw_core = mlxsw_sp_port->mlxsw_sp->core; 57262306a36Sopenharmony_ci u8 slot_index = mlxsw_sp_port->mapping.slot_index; 57362306a36Sopenharmony_ci u8 module = mlxsw_sp_port->mapping.module; 57462306a36Sopenharmony_ci u64 stats; 57562306a36Sopenharmony_ci int err; 57662306a36Sopenharmony_ci 57762306a36Sopenharmony_ci err = mlxsw_env_module_overheat_counter_get(mlxsw_core, slot_index, 57862306a36Sopenharmony_ci module, &stats); 57962306a36Sopenharmony_ci if (err) 58062306a36Sopenharmony_ci return mlxsw_sp_port->module_overheat_initial_val; 58162306a36Sopenharmony_ci 58262306a36Sopenharmony_ci return stats - mlxsw_sp_port->module_overheat_initial_val; 58362306a36Sopenharmony_ci} 58462306a36Sopenharmony_ci 58562306a36Sopenharmony_cistatic struct mlxsw_sp_port_stats mlxsw_sp_port_transceiver_stats[] = { 58662306a36Sopenharmony_ci { 58762306a36Sopenharmony_ci .str = "transceiver_overheat", 58862306a36Sopenharmony_ci .getter = mlxsw_sp_port_get_transceiver_overheat_stats, 58962306a36Sopenharmony_ci }, 59062306a36Sopenharmony_ci}; 59162306a36Sopenharmony_ci 59262306a36Sopenharmony_ci#define MLXSW_SP_PORT_HW_TRANSCEIVER_STATS_LEN ARRAY_SIZE(mlxsw_sp_port_transceiver_stats) 59362306a36Sopenharmony_ci 59462306a36Sopenharmony_ci#define MLXSW_SP_PORT_ETHTOOL_STATS_LEN (MLXSW_SP_PORT_HW_STATS_LEN + \ 59562306a36Sopenharmony_ci MLXSW_SP_PORT_HW_RFC_2863_STATS_LEN + \ 59662306a36Sopenharmony_ci MLXSW_SP_PORT_HW_RFC_2819_STATS_LEN + \ 59762306a36Sopenharmony_ci MLXSW_SP_PORT_HW_RFC_3635_STATS_LEN + \ 59862306a36Sopenharmony_ci MLXSW_SP_PORT_HW_EXT_STATS_LEN + \ 59962306a36Sopenharmony_ci MLXSW_SP_PORT_HW_DISCARD_STATS_LEN + \ 60062306a36Sopenharmony_ci (MLXSW_SP_PORT_HW_PRIO_STATS_LEN * \ 60162306a36Sopenharmony_ci IEEE_8021QAZ_MAX_TCS) + \ 60262306a36Sopenharmony_ci (MLXSW_SP_PORT_HW_TC_STATS_LEN * \ 60362306a36Sopenharmony_ci TC_MAX_QUEUE) + \ 60462306a36Sopenharmony_ci MLXSW_SP_PORT_HW_TRANSCEIVER_STATS_LEN) 60562306a36Sopenharmony_ci 60662306a36Sopenharmony_cistatic void mlxsw_sp_port_get_prio_strings(u8 **p, int prio) 60762306a36Sopenharmony_ci{ 60862306a36Sopenharmony_ci int i; 60962306a36Sopenharmony_ci 61062306a36Sopenharmony_ci for (i = 0; i < MLXSW_SP_PORT_HW_PRIO_STATS_LEN; i++) { 61162306a36Sopenharmony_ci snprintf(*p, ETH_GSTRING_LEN, "%.29s_%.1d", 61262306a36Sopenharmony_ci mlxsw_sp_port_hw_prio_stats[i].str, prio); 61362306a36Sopenharmony_ci *p += ETH_GSTRING_LEN; 61462306a36Sopenharmony_ci } 61562306a36Sopenharmony_ci} 61662306a36Sopenharmony_ci 61762306a36Sopenharmony_cistatic void mlxsw_sp_port_get_tc_strings(u8 **p, int tc) 61862306a36Sopenharmony_ci{ 61962306a36Sopenharmony_ci int i; 62062306a36Sopenharmony_ci 62162306a36Sopenharmony_ci for (i = 0; i < MLXSW_SP_PORT_HW_TC_STATS_LEN; i++) { 62262306a36Sopenharmony_ci snprintf(*p, ETH_GSTRING_LEN, "%.29s_%.1d", 62362306a36Sopenharmony_ci mlxsw_sp_port_hw_tc_stats[i].str, tc); 62462306a36Sopenharmony_ci *p += ETH_GSTRING_LEN; 62562306a36Sopenharmony_ci } 62662306a36Sopenharmony_ci} 62762306a36Sopenharmony_ci 62862306a36Sopenharmony_cistatic void mlxsw_sp_port_get_strings(struct net_device *dev, 62962306a36Sopenharmony_ci u32 stringset, u8 *data) 63062306a36Sopenharmony_ci{ 63162306a36Sopenharmony_ci struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); 63262306a36Sopenharmony_ci u8 *p = data; 63362306a36Sopenharmony_ci int i; 63462306a36Sopenharmony_ci 63562306a36Sopenharmony_ci switch (stringset) { 63662306a36Sopenharmony_ci case ETH_SS_STATS: 63762306a36Sopenharmony_ci for (i = 0; i < MLXSW_SP_PORT_HW_STATS_LEN; i++) { 63862306a36Sopenharmony_ci memcpy(p, mlxsw_sp_port_hw_stats[i].str, 63962306a36Sopenharmony_ci ETH_GSTRING_LEN); 64062306a36Sopenharmony_ci p += ETH_GSTRING_LEN; 64162306a36Sopenharmony_ci } 64262306a36Sopenharmony_ci 64362306a36Sopenharmony_ci for (i = 0; i < MLXSW_SP_PORT_HW_RFC_2863_STATS_LEN; i++) { 64462306a36Sopenharmony_ci memcpy(p, mlxsw_sp_port_hw_rfc_2863_stats[i].str, 64562306a36Sopenharmony_ci ETH_GSTRING_LEN); 64662306a36Sopenharmony_ci p += ETH_GSTRING_LEN; 64762306a36Sopenharmony_ci } 64862306a36Sopenharmony_ci 64962306a36Sopenharmony_ci for (i = 0; i < MLXSW_SP_PORT_HW_RFC_2819_STATS_LEN; i++) { 65062306a36Sopenharmony_ci memcpy(p, mlxsw_sp_port_hw_rfc_2819_stats[i].str, 65162306a36Sopenharmony_ci ETH_GSTRING_LEN); 65262306a36Sopenharmony_ci p += ETH_GSTRING_LEN; 65362306a36Sopenharmony_ci } 65462306a36Sopenharmony_ci 65562306a36Sopenharmony_ci for (i = 0; i < MLXSW_SP_PORT_HW_RFC_3635_STATS_LEN; i++) { 65662306a36Sopenharmony_ci memcpy(p, mlxsw_sp_port_hw_rfc_3635_stats[i].str, 65762306a36Sopenharmony_ci ETH_GSTRING_LEN); 65862306a36Sopenharmony_ci p += ETH_GSTRING_LEN; 65962306a36Sopenharmony_ci } 66062306a36Sopenharmony_ci 66162306a36Sopenharmony_ci for (i = 0; i < MLXSW_SP_PORT_HW_EXT_STATS_LEN; i++) { 66262306a36Sopenharmony_ci memcpy(p, mlxsw_sp_port_hw_ext_stats[i].str, 66362306a36Sopenharmony_ci ETH_GSTRING_LEN); 66462306a36Sopenharmony_ci p += ETH_GSTRING_LEN; 66562306a36Sopenharmony_ci } 66662306a36Sopenharmony_ci 66762306a36Sopenharmony_ci for (i = 0; i < MLXSW_SP_PORT_HW_DISCARD_STATS_LEN; i++) { 66862306a36Sopenharmony_ci memcpy(p, mlxsw_sp_port_hw_discard_stats[i].str, 66962306a36Sopenharmony_ci ETH_GSTRING_LEN); 67062306a36Sopenharmony_ci p += ETH_GSTRING_LEN; 67162306a36Sopenharmony_ci } 67262306a36Sopenharmony_ci 67362306a36Sopenharmony_ci for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) 67462306a36Sopenharmony_ci mlxsw_sp_port_get_prio_strings(&p, i); 67562306a36Sopenharmony_ci 67662306a36Sopenharmony_ci for (i = 0; i < TC_MAX_QUEUE; i++) 67762306a36Sopenharmony_ci mlxsw_sp_port_get_tc_strings(&p, i); 67862306a36Sopenharmony_ci 67962306a36Sopenharmony_ci mlxsw_sp_port->mlxsw_sp->ptp_ops->get_stats_strings(&p); 68062306a36Sopenharmony_ci 68162306a36Sopenharmony_ci for (i = 0; i < MLXSW_SP_PORT_HW_TRANSCEIVER_STATS_LEN; i++) { 68262306a36Sopenharmony_ci memcpy(p, mlxsw_sp_port_transceiver_stats[i].str, 68362306a36Sopenharmony_ci ETH_GSTRING_LEN); 68462306a36Sopenharmony_ci p += ETH_GSTRING_LEN; 68562306a36Sopenharmony_ci } 68662306a36Sopenharmony_ci break; 68762306a36Sopenharmony_ci } 68862306a36Sopenharmony_ci} 68962306a36Sopenharmony_ci 69062306a36Sopenharmony_cistatic int mlxsw_sp_port_set_phys_id(struct net_device *dev, 69162306a36Sopenharmony_ci enum ethtool_phys_id_state state) 69262306a36Sopenharmony_ci{ 69362306a36Sopenharmony_ci struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); 69462306a36Sopenharmony_ci struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 69562306a36Sopenharmony_ci char mlcr_pl[MLXSW_REG_MLCR_LEN]; 69662306a36Sopenharmony_ci bool active; 69762306a36Sopenharmony_ci 69862306a36Sopenharmony_ci switch (state) { 69962306a36Sopenharmony_ci case ETHTOOL_ID_ACTIVE: 70062306a36Sopenharmony_ci active = true; 70162306a36Sopenharmony_ci break; 70262306a36Sopenharmony_ci case ETHTOOL_ID_INACTIVE: 70362306a36Sopenharmony_ci active = false; 70462306a36Sopenharmony_ci break; 70562306a36Sopenharmony_ci default: 70662306a36Sopenharmony_ci return -EOPNOTSUPP; 70762306a36Sopenharmony_ci } 70862306a36Sopenharmony_ci 70962306a36Sopenharmony_ci mlxsw_reg_mlcr_pack(mlcr_pl, mlxsw_sp_port->local_port, active); 71062306a36Sopenharmony_ci return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mlcr), mlcr_pl); 71162306a36Sopenharmony_ci} 71262306a36Sopenharmony_ci 71362306a36Sopenharmony_cistatic int 71462306a36Sopenharmony_cimlxsw_sp_get_hw_stats_by_group(struct mlxsw_sp_port_hw_stats **p_hw_stats, 71562306a36Sopenharmony_ci int *p_len, enum mlxsw_reg_ppcnt_grp grp) 71662306a36Sopenharmony_ci{ 71762306a36Sopenharmony_ci switch (grp) { 71862306a36Sopenharmony_ci case MLXSW_REG_PPCNT_IEEE_8023_CNT: 71962306a36Sopenharmony_ci *p_hw_stats = mlxsw_sp_port_hw_stats; 72062306a36Sopenharmony_ci *p_len = MLXSW_SP_PORT_HW_STATS_LEN; 72162306a36Sopenharmony_ci break; 72262306a36Sopenharmony_ci case MLXSW_REG_PPCNT_RFC_2863_CNT: 72362306a36Sopenharmony_ci *p_hw_stats = mlxsw_sp_port_hw_rfc_2863_stats; 72462306a36Sopenharmony_ci *p_len = MLXSW_SP_PORT_HW_RFC_2863_STATS_LEN; 72562306a36Sopenharmony_ci break; 72662306a36Sopenharmony_ci case MLXSW_REG_PPCNT_RFC_2819_CNT: 72762306a36Sopenharmony_ci *p_hw_stats = mlxsw_sp_port_hw_rfc_2819_stats; 72862306a36Sopenharmony_ci *p_len = MLXSW_SP_PORT_HW_RFC_2819_STATS_LEN; 72962306a36Sopenharmony_ci break; 73062306a36Sopenharmony_ci case MLXSW_REG_PPCNT_RFC_3635_CNT: 73162306a36Sopenharmony_ci *p_hw_stats = mlxsw_sp_port_hw_rfc_3635_stats; 73262306a36Sopenharmony_ci *p_len = MLXSW_SP_PORT_HW_RFC_3635_STATS_LEN; 73362306a36Sopenharmony_ci break; 73462306a36Sopenharmony_ci case MLXSW_REG_PPCNT_EXT_CNT: 73562306a36Sopenharmony_ci *p_hw_stats = mlxsw_sp_port_hw_ext_stats; 73662306a36Sopenharmony_ci *p_len = MLXSW_SP_PORT_HW_EXT_STATS_LEN; 73762306a36Sopenharmony_ci break; 73862306a36Sopenharmony_ci case MLXSW_REG_PPCNT_DISCARD_CNT: 73962306a36Sopenharmony_ci *p_hw_stats = mlxsw_sp_port_hw_discard_stats; 74062306a36Sopenharmony_ci *p_len = MLXSW_SP_PORT_HW_DISCARD_STATS_LEN; 74162306a36Sopenharmony_ci break; 74262306a36Sopenharmony_ci case MLXSW_REG_PPCNT_PRIO_CNT: 74362306a36Sopenharmony_ci *p_hw_stats = mlxsw_sp_port_hw_prio_stats; 74462306a36Sopenharmony_ci *p_len = MLXSW_SP_PORT_HW_PRIO_STATS_LEN; 74562306a36Sopenharmony_ci break; 74662306a36Sopenharmony_ci case MLXSW_REG_PPCNT_TC_CNT: 74762306a36Sopenharmony_ci *p_hw_stats = mlxsw_sp_port_hw_tc_stats; 74862306a36Sopenharmony_ci *p_len = MLXSW_SP_PORT_HW_TC_STATS_LEN; 74962306a36Sopenharmony_ci break; 75062306a36Sopenharmony_ci default: 75162306a36Sopenharmony_ci WARN_ON(1); 75262306a36Sopenharmony_ci return -EOPNOTSUPP; 75362306a36Sopenharmony_ci } 75462306a36Sopenharmony_ci return 0; 75562306a36Sopenharmony_ci} 75662306a36Sopenharmony_ci 75762306a36Sopenharmony_cistatic void __mlxsw_sp_port_get_stats(struct net_device *dev, 75862306a36Sopenharmony_ci enum mlxsw_reg_ppcnt_grp grp, int prio, 75962306a36Sopenharmony_ci u64 *data, int data_index) 76062306a36Sopenharmony_ci{ 76162306a36Sopenharmony_ci struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); 76262306a36Sopenharmony_ci struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 76362306a36Sopenharmony_ci struct mlxsw_sp_port_hw_stats *hw_stats; 76462306a36Sopenharmony_ci char ppcnt_pl[MLXSW_REG_PPCNT_LEN]; 76562306a36Sopenharmony_ci int i, len; 76662306a36Sopenharmony_ci int err; 76762306a36Sopenharmony_ci 76862306a36Sopenharmony_ci err = mlxsw_sp_get_hw_stats_by_group(&hw_stats, &len, grp); 76962306a36Sopenharmony_ci if (err) 77062306a36Sopenharmony_ci return; 77162306a36Sopenharmony_ci mlxsw_sp_port_get_stats_raw(dev, grp, prio, ppcnt_pl); 77262306a36Sopenharmony_ci for (i = 0; i < len; i++) { 77362306a36Sopenharmony_ci data[data_index + i] = hw_stats[i].getter(ppcnt_pl); 77462306a36Sopenharmony_ci if (!hw_stats[i].cells_bytes) 77562306a36Sopenharmony_ci continue; 77662306a36Sopenharmony_ci data[data_index + i] = mlxsw_sp_cells_bytes(mlxsw_sp, 77762306a36Sopenharmony_ci data[data_index + i]); 77862306a36Sopenharmony_ci } 77962306a36Sopenharmony_ci} 78062306a36Sopenharmony_ci 78162306a36Sopenharmony_cistatic void __mlxsw_sp_port_get_env_stats(struct net_device *dev, u64 *data, int data_index, 78262306a36Sopenharmony_ci struct mlxsw_sp_port_stats *port_stats, 78362306a36Sopenharmony_ci int len) 78462306a36Sopenharmony_ci{ 78562306a36Sopenharmony_ci struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); 78662306a36Sopenharmony_ci int i; 78762306a36Sopenharmony_ci 78862306a36Sopenharmony_ci for (i = 0; i < len; i++) 78962306a36Sopenharmony_ci data[data_index + i] = port_stats[i].getter(mlxsw_sp_port); 79062306a36Sopenharmony_ci} 79162306a36Sopenharmony_ci 79262306a36Sopenharmony_cistatic void mlxsw_sp_port_get_stats(struct net_device *dev, 79362306a36Sopenharmony_ci struct ethtool_stats *stats, u64 *data) 79462306a36Sopenharmony_ci{ 79562306a36Sopenharmony_ci struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); 79662306a36Sopenharmony_ci int i, data_index = 0; 79762306a36Sopenharmony_ci 79862306a36Sopenharmony_ci /* IEEE 802.3 Counters */ 79962306a36Sopenharmony_ci __mlxsw_sp_port_get_stats(dev, MLXSW_REG_PPCNT_IEEE_8023_CNT, 0, 80062306a36Sopenharmony_ci data, data_index); 80162306a36Sopenharmony_ci data_index = MLXSW_SP_PORT_HW_STATS_LEN; 80262306a36Sopenharmony_ci 80362306a36Sopenharmony_ci /* RFC 2863 Counters */ 80462306a36Sopenharmony_ci __mlxsw_sp_port_get_stats(dev, MLXSW_REG_PPCNT_RFC_2863_CNT, 0, 80562306a36Sopenharmony_ci data, data_index); 80662306a36Sopenharmony_ci data_index += MLXSW_SP_PORT_HW_RFC_2863_STATS_LEN; 80762306a36Sopenharmony_ci 80862306a36Sopenharmony_ci /* RFC 2819 Counters */ 80962306a36Sopenharmony_ci __mlxsw_sp_port_get_stats(dev, MLXSW_REG_PPCNT_RFC_2819_CNT, 0, 81062306a36Sopenharmony_ci data, data_index); 81162306a36Sopenharmony_ci data_index += MLXSW_SP_PORT_HW_RFC_2819_STATS_LEN; 81262306a36Sopenharmony_ci 81362306a36Sopenharmony_ci /* RFC 3635 Counters */ 81462306a36Sopenharmony_ci __mlxsw_sp_port_get_stats(dev, MLXSW_REG_PPCNT_RFC_3635_CNT, 0, 81562306a36Sopenharmony_ci data, data_index); 81662306a36Sopenharmony_ci data_index += MLXSW_SP_PORT_HW_RFC_3635_STATS_LEN; 81762306a36Sopenharmony_ci 81862306a36Sopenharmony_ci /* Extended Counters */ 81962306a36Sopenharmony_ci __mlxsw_sp_port_get_stats(dev, MLXSW_REG_PPCNT_EXT_CNT, 0, 82062306a36Sopenharmony_ci data, data_index); 82162306a36Sopenharmony_ci data_index += MLXSW_SP_PORT_HW_EXT_STATS_LEN; 82262306a36Sopenharmony_ci 82362306a36Sopenharmony_ci /* Discard Counters */ 82462306a36Sopenharmony_ci __mlxsw_sp_port_get_stats(dev, MLXSW_REG_PPCNT_DISCARD_CNT, 0, 82562306a36Sopenharmony_ci data, data_index); 82662306a36Sopenharmony_ci data_index += MLXSW_SP_PORT_HW_DISCARD_STATS_LEN; 82762306a36Sopenharmony_ci 82862306a36Sopenharmony_ci /* Per-Priority Counters */ 82962306a36Sopenharmony_ci for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) { 83062306a36Sopenharmony_ci __mlxsw_sp_port_get_stats(dev, MLXSW_REG_PPCNT_PRIO_CNT, i, 83162306a36Sopenharmony_ci data, data_index); 83262306a36Sopenharmony_ci data_index += MLXSW_SP_PORT_HW_PRIO_STATS_LEN; 83362306a36Sopenharmony_ci } 83462306a36Sopenharmony_ci 83562306a36Sopenharmony_ci /* Per-TC Counters */ 83662306a36Sopenharmony_ci for (i = 0; i < TC_MAX_QUEUE; i++) { 83762306a36Sopenharmony_ci __mlxsw_sp_port_get_stats(dev, MLXSW_REG_PPCNT_TC_CNT, i, 83862306a36Sopenharmony_ci data, data_index); 83962306a36Sopenharmony_ci data_index += MLXSW_SP_PORT_HW_TC_STATS_LEN; 84062306a36Sopenharmony_ci } 84162306a36Sopenharmony_ci 84262306a36Sopenharmony_ci /* PTP counters */ 84362306a36Sopenharmony_ci mlxsw_sp_port->mlxsw_sp->ptp_ops->get_stats(mlxsw_sp_port, 84462306a36Sopenharmony_ci data, data_index); 84562306a36Sopenharmony_ci data_index += mlxsw_sp_port->mlxsw_sp->ptp_ops->get_stats_count(); 84662306a36Sopenharmony_ci 84762306a36Sopenharmony_ci /* Transceiver counters */ 84862306a36Sopenharmony_ci __mlxsw_sp_port_get_env_stats(dev, data, data_index, mlxsw_sp_port_transceiver_stats, 84962306a36Sopenharmony_ci MLXSW_SP_PORT_HW_TRANSCEIVER_STATS_LEN); 85062306a36Sopenharmony_ci data_index += MLXSW_SP_PORT_HW_TRANSCEIVER_STATS_LEN; 85162306a36Sopenharmony_ci} 85262306a36Sopenharmony_ci 85362306a36Sopenharmony_cistatic int mlxsw_sp_port_get_sset_count(struct net_device *dev, int sset) 85462306a36Sopenharmony_ci{ 85562306a36Sopenharmony_ci struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); 85662306a36Sopenharmony_ci 85762306a36Sopenharmony_ci switch (sset) { 85862306a36Sopenharmony_ci case ETH_SS_STATS: 85962306a36Sopenharmony_ci return MLXSW_SP_PORT_ETHTOOL_STATS_LEN + 86062306a36Sopenharmony_ci mlxsw_sp_port->mlxsw_sp->ptp_ops->get_stats_count(); 86162306a36Sopenharmony_ci default: 86262306a36Sopenharmony_ci return -EOPNOTSUPP; 86362306a36Sopenharmony_ci } 86462306a36Sopenharmony_ci} 86562306a36Sopenharmony_ci 86662306a36Sopenharmony_cistatic void 86762306a36Sopenharmony_cimlxsw_sp_port_get_link_supported(struct mlxsw_sp *mlxsw_sp, u32 eth_proto_cap, 86862306a36Sopenharmony_ci struct ethtool_link_ksettings *cmd) 86962306a36Sopenharmony_ci{ 87062306a36Sopenharmony_ci const struct mlxsw_sp_port_type_speed_ops *ops; 87162306a36Sopenharmony_ci 87262306a36Sopenharmony_ci ops = mlxsw_sp->port_type_speed_ops; 87362306a36Sopenharmony_ci 87462306a36Sopenharmony_ci ethtool_link_ksettings_add_link_mode(cmd, supported, Asym_Pause); 87562306a36Sopenharmony_ci ethtool_link_ksettings_add_link_mode(cmd, supported, Autoneg); 87662306a36Sopenharmony_ci ethtool_link_ksettings_add_link_mode(cmd, supported, Pause); 87762306a36Sopenharmony_ci 87862306a36Sopenharmony_ci ops->from_ptys_supported_port(mlxsw_sp, eth_proto_cap, cmd); 87962306a36Sopenharmony_ci ops->from_ptys_link(mlxsw_sp, eth_proto_cap, 88062306a36Sopenharmony_ci cmd->link_modes.supported); 88162306a36Sopenharmony_ci} 88262306a36Sopenharmony_ci 88362306a36Sopenharmony_cistatic void 88462306a36Sopenharmony_cimlxsw_sp_port_get_link_advertise(struct mlxsw_sp *mlxsw_sp, 88562306a36Sopenharmony_ci u32 eth_proto_admin, bool autoneg, 88662306a36Sopenharmony_ci struct ethtool_link_ksettings *cmd) 88762306a36Sopenharmony_ci{ 88862306a36Sopenharmony_ci const struct mlxsw_sp_port_type_speed_ops *ops; 88962306a36Sopenharmony_ci 89062306a36Sopenharmony_ci ops = mlxsw_sp->port_type_speed_ops; 89162306a36Sopenharmony_ci 89262306a36Sopenharmony_ci if (!autoneg) 89362306a36Sopenharmony_ci return; 89462306a36Sopenharmony_ci 89562306a36Sopenharmony_ci ethtool_link_ksettings_add_link_mode(cmd, advertising, Autoneg); 89662306a36Sopenharmony_ci ops->from_ptys_link(mlxsw_sp, eth_proto_admin, 89762306a36Sopenharmony_ci cmd->link_modes.advertising); 89862306a36Sopenharmony_ci} 89962306a36Sopenharmony_ci 90062306a36Sopenharmony_cistatic u8 90162306a36Sopenharmony_cimlxsw_sp_port_connector_port(enum mlxsw_reg_ptys_connector_type connector_type) 90262306a36Sopenharmony_ci{ 90362306a36Sopenharmony_ci switch (connector_type) { 90462306a36Sopenharmony_ci case MLXSW_REG_PTYS_CONNECTOR_TYPE_UNKNOWN_OR_NO_CONNECTOR: 90562306a36Sopenharmony_ci return PORT_OTHER; 90662306a36Sopenharmony_ci case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_NONE: 90762306a36Sopenharmony_ci return PORT_NONE; 90862306a36Sopenharmony_ci case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_TP: 90962306a36Sopenharmony_ci return PORT_TP; 91062306a36Sopenharmony_ci case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_AUI: 91162306a36Sopenharmony_ci return PORT_AUI; 91262306a36Sopenharmony_ci case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_BNC: 91362306a36Sopenharmony_ci return PORT_BNC; 91462306a36Sopenharmony_ci case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_MII: 91562306a36Sopenharmony_ci return PORT_MII; 91662306a36Sopenharmony_ci case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_FIBRE: 91762306a36Sopenharmony_ci return PORT_FIBRE; 91862306a36Sopenharmony_ci case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_DA: 91962306a36Sopenharmony_ci return PORT_DA; 92062306a36Sopenharmony_ci case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_OTHER: 92162306a36Sopenharmony_ci return PORT_OTHER; 92262306a36Sopenharmony_ci default: 92362306a36Sopenharmony_ci WARN_ON_ONCE(1); 92462306a36Sopenharmony_ci return PORT_OTHER; 92562306a36Sopenharmony_ci } 92662306a36Sopenharmony_ci} 92762306a36Sopenharmony_ci 92862306a36Sopenharmony_cistatic int mlxsw_sp_port_ptys_query(struct mlxsw_sp_port *mlxsw_sp_port, 92962306a36Sopenharmony_ci u32 *p_eth_proto_cap, u32 *p_eth_proto_admin, 93062306a36Sopenharmony_ci u32 *p_eth_proto_oper, u8 *p_connector_type) 93162306a36Sopenharmony_ci{ 93262306a36Sopenharmony_ci struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 93362306a36Sopenharmony_ci const struct mlxsw_sp_port_type_speed_ops *ops; 93462306a36Sopenharmony_ci char ptys_pl[MLXSW_REG_PTYS_LEN]; 93562306a36Sopenharmony_ci int err; 93662306a36Sopenharmony_ci 93762306a36Sopenharmony_ci ops = mlxsw_sp->port_type_speed_ops; 93862306a36Sopenharmony_ci 93962306a36Sopenharmony_ci ops->reg_ptys_eth_pack(mlxsw_sp, ptys_pl, mlxsw_sp_port->local_port, 0, false); 94062306a36Sopenharmony_ci err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl); 94162306a36Sopenharmony_ci if (err) 94262306a36Sopenharmony_ci return err; 94362306a36Sopenharmony_ci 94462306a36Sopenharmony_ci ops->reg_ptys_eth_unpack(mlxsw_sp, ptys_pl, p_eth_proto_cap, p_eth_proto_admin, 94562306a36Sopenharmony_ci p_eth_proto_oper); 94662306a36Sopenharmony_ci if (p_connector_type) 94762306a36Sopenharmony_ci *p_connector_type = mlxsw_reg_ptys_connector_type_get(ptys_pl); 94862306a36Sopenharmony_ci return 0; 94962306a36Sopenharmony_ci} 95062306a36Sopenharmony_ci 95162306a36Sopenharmony_cistatic int mlxsw_sp_port_get_link_ksettings(struct net_device *dev, 95262306a36Sopenharmony_ci struct ethtool_link_ksettings *cmd) 95362306a36Sopenharmony_ci{ 95462306a36Sopenharmony_ci u32 eth_proto_cap, eth_proto_admin, eth_proto_oper; 95562306a36Sopenharmony_ci struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); 95662306a36Sopenharmony_ci struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 95762306a36Sopenharmony_ci const struct mlxsw_sp_port_type_speed_ops *ops; 95862306a36Sopenharmony_ci u8 connector_type; 95962306a36Sopenharmony_ci bool autoneg; 96062306a36Sopenharmony_ci int err; 96162306a36Sopenharmony_ci 96262306a36Sopenharmony_ci err = mlxsw_sp_port_ptys_query(mlxsw_sp_port, ð_proto_cap, ð_proto_admin, 96362306a36Sopenharmony_ci ð_proto_oper, &connector_type); 96462306a36Sopenharmony_ci if (err) 96562306a36Sopenharmony_ci return err; 96662306a36Sopenharmony_ci 96762306a36Sopenharmony_ci ops = mlxsw_sp->port_type_speed_ops; 96862306a36Sopenharmony_ci autoneg = mlxsw_sp_port->link.autoneg; 96962306a36Sopenharmony_ci 97062306a36Sopenharmony_ci mlxsw_sp_port_get_link_supported(mlxsw_sp, eth_proto_cap, cmd); 97162306a36Sopenharmony_ci 97262306a36Sopenharmony_ci mlxsw_sp_port_get_link_advertise(mlxsw_sp, eth_proto_admin, autoneg, cmd); 97362306a36Sopenharmony_ci 97462306a36Sopenharmony_ci cmd->base.autoneg = autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE; 97562306a36Sopenharmony_ci cmd->base.port = mlxsw_sp_port_connector_port(connector_type); 97662306a36Sopenharmony_ci ops->from_ptys_link_mode(mlxsw_sp, netif_carrier_ok(dev), 97762306a36Sopenharmony_ci eth_proto_oper, cmd); 97862306a36Sopenharmony_ci 97962306a36Sopenharmony_ci return 0; 98062306a36Sopenharmony_ci} 98162306a36Sopenharmony_ci 98262306a36Sopenharmony_cistatic int 98362306a36Sopenharmony_cimlxsw_sp_port_set_link_ksettings(struct net_device *dev, 98462306a36Sopenharmony_ci const struct ethtool_link_ksettings *cmd) 98562306a36Sopenharmony_ci{ 98662306a36Sopenharmony_ci struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); 98762306a36Sopenharmony_ci struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 98862306a36Sopenharmony_ci const struct mlxsw_sp_port_type_speed_ops *ops; 98962306a36Sopenharmony_ci char ptys_pl[MLXSW_REG_PTYS_LEN]; 99062306a36Sopenharmony_ci u32 eth_proto_cap, eth_proto_new; 99162306a36Sopenharmony_ci bool autoneg; 99262306a36Sopenharmony_ci int err; 99362306a36Sopenharmony_ci 99462306a36Sopenharmony_ci ops = mlxsw_sp->port_type_speed_ops; 99562306a36Sopenharmony_ci 99662306a36Sopenharmony_ci ops->reg_ptys_eth_pack(mlxsw_sp, ptys_pl, mlxsw_sp_port->local_port, 99762306a36Sopenharmony_ci 0, false); 99862306a36Sopenharmony_ci err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl); 99962306a36Sopenharmony_ci if (err) 100062306a36Sopenharmony_ci return err; 100162306a36Sopenharmony_ci ops->reg_ptys_eth_unpack(mlxsw_sp, ptys_pl, ð_proto_cap, NULL, NULL); 100262306a36Sopenharmony_ci 100362306a36Sopenharmony_ci autoneg = cmd->base.autoneg == AUTONEG_ENABLE; 100462306a36Sopenharmony_ci eth_proto_new = autoneg ? 100562306a36Sopenharmony_ci ops->to_ptys_advert_link(mlxsw_sp, cmd) : 100662306a36Sopenharmony_ci ops->to_ptys_speed_lanes(mlxsw_sp, mlxsw_sp_port->mapping.width, 100762306a36Sopenharmony_ci cmd); 100862306a36Sopenharmony_ci 100962306a36Sopenharmony_ci eth_proto_new = eth_proto_new & eth_proto_cap; 101062306a36Sopenharmony_ci if (!eth_proto_new) { 101162306a36Sopenharmony_ci netdev_err(dev, "No supported speed or lanes requested\n"); 101262306a36Sopenharmony_ci return -EINVAL; 101362306a36Sopenharmony_ci } 101462306a36Sopenharmony_ci 101562306a36Sopenharmony_ci ops->reg_ptys_eth_pack(mlxsw_sp, ptys_pl, mlxsw_sp_port->local_port, 101662306a36Sopenharmony_ci eth_proto_new, autoneg); 101762306a36Sopenharmony_ci err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl); 101862306a36Sopenharmony_ci if (err) 101962306a36Sopenharmony_ci return err; 102062306a36Sopenharmony_ci 102162306a36Sopenharmony_ci mlxsw_sp_port->link.autoneg = autoneg; 102262306a36Sopenharmony_ci 102362306a36Sopenharmony_ci if (!netif_running(dev)) 102462306a36Sopenharmony_ci return 0; 102562306a36Sopenharmony_ci 102662306a36Sopenharmony_ci mlxsw_sp_port_admin_status_set(mlxsw_sp_port, false); 102762306a36Sopenharmony_ci mlxsw_sp_port_admin_status_set(mlxsw_sp_port, true); 102862306a36Sopenharmony_ci 102962306a36Sopenharmony_ci return 0; 103062306a36Sopenharmony_ci} 103162306a36Sopenharmony_ci 103262306a36Sopenharmony_cistatic int mlxsw_sp_get_module_info(struct net_device *netdev, 103362306a36Sopenharmony_ci struct ethtool_modinfo *modinfo) 103462306a36Sopenharmony_ci{ 103562306a36Sopenharmony_ci struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(netdev); 103662306a36Sopenharmony_ci struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 103762306a36Sopenharmony_ci 103862306a36Sopenharmony_ci return mlxsw_env_get_module_info(netdev, mlxsw_sp->core, 103962306a36Sopenharmony_ci mlxsw_sp_port->mapping.slot_index, 104062306a36Sopenharmony_ci mlxsw_sp_port->mapping.module, 104162306a36Sopenharmony_ci modinfo); 104262306a36Sopenharmony_ci} 104362306a36Sopenharmony_ci 104462306a36Sopenharmony_cistatic int mlxsw_sp_get_module_eeprom(struct net_device *netdev, 104562306a36Sopenharmony_ci struct ethtool_eeprom *ee, u8 *data) 104662306a36Sopenharmony_ci{ 104762306a36Sopenharmony_ci struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(netdev); 104862306a36Sopenharmony_ci struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 104962306a36Sopenharmony_ci u8 slot_index = mlxsw_sp_port->mapping.slot_index; 105062306a36Sopenharmony_ci u8 module = mlxsw_sp_port->mapping.module; 105162306a36Sopenharmony_ci 105262306a36Sopenharmony_ci return mlxsw_env_get_module_eeprom(netdev, mlxsw_sp->core, slot_index, 105362306a36Sopenharmony_ci module, ee, data); 105462306a36Sopenharmony_ci} 105562306a36Sopenharmony_ci 105662306a36Sopenharmony_cistatic int 105762306a36Sopenharmony_cimlxsw_sp_get_module_eeprom_by_page(struct net_device *dev, 105862306a36Sopenharmony_ci const struct ethtool_module_eeprom *page, 105962306a36Sopenharmony_ci struct netlink_ext_ack *extack) 106062306a36Sopenharmony_ci{ 106162306a36Sopenharmony_ci struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); 106262306a36Sopenharmony_ci struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 106362306a36Sopenharmony_ci u8 slot_index = mlxsw_sp_port->mapping.slot_index; 106462306a36Sopenharmony_ci u8 module = mlxsw_sp_port->mapping.module; 106562306a36Sopenharmony_ci 106662306a36Sopenharmony_ci return mlxsw_env_get_module_eeprom_by_page(mlxsw_sp->core, slot_index, 106762306a36Sopenharmony_ci module, page, extack); 106862306a36Sopenharmony_ci} 106962306a36Sopenharmony_ci 107062306a36Sopenharmony_cistatic int 107162306a36Sopenharmony_cimlxsw_sp_get_ts_info(struct net_device *netdev, struct ethtool_ts_info *info) 107262306a36Sopenharmony_ci{ 107362306a36Sopenharmony_ci struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(netdev); 107462306a36Sopenharmony_ci struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 107562306a36Sopenharmony_ci 107662306a36Sopenharmony_ci return mlxsw_sp->ptp_ops->get_ts_info(mlxsw_sp, info); 107762306a36Sopenharmony_ci} 107862306a36Sopenharmony_ci 107962306a36Sopenharmony_cistatic void 108062306a36Sopenharmony_cimlxsw_sp_get_eth_phy_stats(struct net_device *dev, 108162306a36Sopenharmony_ci struct ethtool_eth_phy_stats *phy_stats) 108262306a36Sopenharmony_ci{ 108362306a36Sopenharmony_ci char ppcnt_pl[MLXSW_REG_PPCNT_LEN]; 108462306a36Sopenharmony_ci 108562306a36Sopenharmony_ci if (mlxsw_sp_port_get_stats_raw(dev, MLXSW_REG_PPCNT_IEEE_8023_CNT, 108662306a36Sopenharmony_ci 0, ppcnt_pl)) 108762306a36Sopenharmony_ci return; 108862306a36Sopenharmony_ci 108962306a36Sopenharmony_ci phy_stats->SymbolErrorDuringCarrier = 109062306a36Sopenharmony_ci mlxsw_reg_ppcnt_a_symbol_error_during_carrier_get(ppcnt_pl); 109162306a36Sopenharmony_ci} 109262306a36Sopenharmony_ci 109362306a36Sopenharmony_cistatic void 109462306a36Sopenharmony_cimlxsw_sp_get_eth_mac_stats(struct net_device *dev, 109562306a36Sopenharmony_ci struct ethtool_eth_mac_stats *mac_stats) 109662306a36Sopenharmony_ci{ 109762306a36Sopenharmony_ci char ppcnt_pl[MLXSW_REG_PPCNT_LEN]; 109862306a36Sopenharmony_ci 109962306a36Sopenharmony_ci if (mlxsw_sp_port_get_stats_raw(dev, MLXSW_REG_PPCNT_IEEE_8023_CNT, 110062306a36Sopenharmony_ci 0, ppcnt_pl)) 110162306a36Sopenharmony_ci return; 110262306a36Sopenharmony_ci 110362306a36Sopenharmony_ci mac_stats->FramesTransmittedOK = 110462306a36Sopenharmony_ci mlxsw_reg_ppcnt_a_frames_transmitted_ok_get(ppcnt_pl); 110562306a36Sopenharmony_ci mac_stats->FramesReceivedOK = 110662306a36Sopenharmony_ci mlxsw_reg_ppcnt_a_frames_received_ok_get(ppcnt_pl); 110762306a36Sopenharmony_ci mac_stats->FrameCheckSequenceErrors = 110862306a36Sopenharmony_ci mlxsw_reg_ppcnt_a_frame_check_sequence_errors_get(ppcnt_pl); 110962306a36Sopenharmony_ci mac_stats->AlignmentErrors = 111062306a36Sopenharmony_ci mlxsw_reg_ppcnt_a_alignment_errors_get(ppcnt_pl); 111162306a36Sopenharmony_ci mac_stats->OctetsTransmittedOK = 111262306a36Sopenharmony_ci mlxsw_reg_ppcnt_a_octets_transmitted_ok_get(ppcnt_pl); 111362306a36Sopenharmony_ci mac_stats->OctetsReceivedOK = 111462306a36Sopenharmony_ci mlxsw_reg_ppcnt_a_octets_received_ok_get(ppcnt_pl); 111562306a36Sopenharmony_ci mac_stats->MulticastFramesXmittedOK = 111662306a36Sopenharmony_ci mlxsw_reg_ppcnt_a_multicast_frames_xmitted_ok_get(ppcnt_pl); 111762306a36Sopenharmony_ci mac_stats->BroadcastFramesXmittedOK = 111862306a36Sopenharmony_ci mlxsw_reg_ppcnt_a_broadcast_frames_xmitted_ok_get(ppcnt_pl); 111962306a36Sopenharmony_ci mac_stats->MulticastFramesReceivedOK = 112062306a36Sopenharmony_ci mlxsw_reg_ppcnt_a_multicast_frames_received_ok_get(ppcnt_pl); 112162306a36Sopenharmony_ci mac_stats->BroadcastFramesReceivedOK = 112262306a36Sopenharmony_ci mlxsw_reg_ppcnt_a_broadcast_frames_received_ok_get(ppcnt_pl); 112362306a36Sopenharmony_ci mac_stats->InRangeLengthErrors = 112462306a36Sopenharmony_ci mlxsw_reg_ppcnt_a_in_range_length_errors_get(ppcnt_pl); 112562306a36Sopenharmony_ci mac_stats->OutOfRangeLengthField = 112662306a36Sopenharmony_ci mlxsw_reg_ppcnt_a_out_of_range_length_field_get(ppcnt_pl); 112762306a36Sopenharmony_ci mac_stats->FrameTooLongErrors = 112862306a36Sopenharmony_ci mlxsw_reg_ppcnt_a_frame_too_long_errors_get(ppcnt_pl); 112962306a36Sopenharmony_ci} 113062306a36Sopenharmony_ci 113162306a36Sopenharmony_cistatic void 113262306a36Sopenharmony_cimlxsw_sp_get_eth_ctrl_stats(struct net_device *dev, 113362306a36Sopenharmony_ci struct ethtool_eth_ctrl_stats *ctrl_stats) 113462306a36Sopenharmony_ci{ 113562306a36Sopenharmony_ci char ppcnt_pl[MLXSW_REG_PPCNT_LEN]; 113662306a36Sopenharmony_ci 113762306a36Sopenharmony_ci if (mlxsw_sp_port_get_stats_raw(dev, MLXSW_REG_PPCNT_IEEE_8023_CNT, 113862306a36Sopenharmony_ci 0, ppcnt_pl)) 113962306a36Sopenharmony_ci return; 114062306a36Sopenharmony_ci 114162306a36Sopenharmony_ci ctrl_stats->MACControlFramesTransmitted = 114262306a36Sopenharmony_ci mlxsw_reg_ppcnt_a_mac_control_frames_transmitted_get(ppcnt_pl); 114362306a36Sopenharmony_ci ctrl_stats->MACControlFramesReceived = 114462306a36Sopenharmony_ci mlxsw_reg_ppcnt_a_mac_control_frames_received_get(ppcnt_pl); 114562306a36Sopenharmony_ci ctrl_stats->UnsupportedOpcodesReceived = 114662306a36Sopenharmony_ci mlxsw_reg_ppcnt_a_unsupported_opcodes_received_get(ppcnt_pl); 114762306a36Sopenharmony_ci} 114862306a36Sopenharmony_ci 114962306a36Sopenharmony_cistatic const struct ethtool_rmon_hist_range mlxsw_rmon_ranges[] = { 115062306a36Sopenharmony_ci { 0, 64 }, 115162306a36Sopenharmony_ci { 65, 127 }, 115262306a36Sopenharmony_ci { 128, 255 }, 115362306a36Sopenharmony_ci { 256, 511 }, 115462306a36Sopenharmony_ci { 512, 1023 }, 115562306a36Sopenharmony_ci { 1024, 1518 }, 115662306a36Sopenharmony_ci { 1519, 2047 }, 115762306a36Sopenharmony_ci { 2048, 4095 }, 115862306a36Sopenharmony_ci { 4096, 8191 }, 115962306a36Sopenharmony_ci { 8192, 10239 }, 116062306a36Sopenharmony_ci {} 116162306a36Sopenharmony_ci}; 116262306a36Sopenharmony_ci 116362306a36Sopenharmony_cistatic void 116462306a36Sopenharmony_cimlxsw_sp_get_rmon_stats(struct net_device *dev, 116562306a36Sopenharmony_ci struct ethtool_rmon_stats *rmon, 116662306a36Sopenharmony_ci const struct ethtool_rmon_hist_range **ranges) 116762306a36Sopenharmony_ci{ 116862306a36Sopenharmony_ci char ppcnt_pl[MLXSW_REG_PPCNT_LEN]; 116962306a36Sopenharmony_ci 117062306a36Sopenharmony_ci if (mlxsw_sp_port_get_stats_raw(dev, MLXSW_REG_PPCNT_RFC_2819_CNT, 117162306a36Sopenharmony_ci 0, ppcnt_pl)) 117262306a36Sopenharmony_ci return; 117362306a36Sopenharmony_ci 117462306a36Sopenharmony_ci rmon->undersize_pkts = 117562306a36Sopenharmony_ci mlxsw_reg_ppcnt_ether_stats_undersize_pkts_get(ppcnt_pl); 117662306a36Sopenharmony_ci rmon->oversize_pkts = 117762306a36Sopenharmony_ci mlxsw_reg_ppcnt_ether_stats_oversize_pkts_get(ppcnt_pl); 117862306a36Sopenharmony_ci rmon->fragments = 117962306a36Sopenharmony_ci mlxsw_reg_ppcnt_ether_stats_fragments_get(ppcnt_pl); 118062306a36Sopenharmony_ci 118162306a36Sopenharmony_ci rmon->hist[0] = mlxsw_reg_ppcnt_ether_stats_pkts64octets_get(ppcnt_pl); 118262306a36Sopenharmony_ci rmon->hist[1] = 118362306a36Sopenharmony_ci mlxsw_reg_ppcnt_ether_stats_pkts65to127octets_get(ppcnt_pl); 118462306a36Sopenharmony_ci rmon->hist[2] = 118562306a36Sopenharmony_ci mlxsw_reg_ppcnt_ether_stats_pkts128to255octets_get(ppcnt_pl); 118662306a36Sopenharmony_ci rmon->hist[3] = 118762306a36Sopenharmony_ci mlxsw_reg_ppcnt_ether_stats_pkts256to511octets_get(ppcnt_pl); 118862306a36Sopenharmony_ci rmon->hist[4] = 118962306a36Sopenharmony_ci mlxsw_reg_ppcnt_ether_stats_pkts512to1023octets_get(ppcnt_pl); 119062306a36Sopenharmony_ci rmon->hist[5] = 119162306a36Sopenharmony_ci mlxsw_reg_ppcnt_ether_stats_pkts1024to1518octets_get(ppcnt_pl); 119262306a36Sopenharmony_ci rmon->hist[6] = 119362306a36Sopenharmony_ci mlxsw_reg_ppcnt_ether_stats_pkts1519to2047octets_get(ppcnt_pl); 119462306a36Sopenharmony_ci rmon->hist[7] = 119562306a36Sopenharmony_ci mlxsw_reg_ppcnt_ether_stats_pkts2048to4095octets_get(ppcnt_pl); 119662306a36Sopenharmony_ci rmon->hist[8] = 119762306a36Sopenharmony_ci mlxsw_reg_ppcnt_ether_stats_pkts4096to8191octets_get(ppcnt_pl); 119862306a36Sopenharmony_ci rmon->hist[9] = 119962306a36Sopenharmony_ci mlxsw_reg_ppcnt_ether_stats_pkts8192to10239octets_get(ppcnt_pl); 120062306a36Sopenharmony_ci 120162306a36Sopenharmony_ci *ranges = mlxsw_rmon_ranges; 120262306a36Sopenharmony_ci} 120362306a36Sopenharmony_ci 120462306a36Sopenharmony_cistatic int mlxsw_sp_reset(struct net_device *dev, u32 *flags) 120562306a36Sopenharmony_ci{ 120662306a36Sopenharmony_ci struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); 120762306a36Sopenharmony_ci struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 120862306a36Sopenharmony_ci u8 slot_index = mlxsw_sp_port->mapping.slot_index; 120962306a36Sopenharmony_ci u8 module = mlxsw_sp_port->mapping.module; 121062306a36Sopenharmony_ci 121162306a36Sopenharmony_ci return mlxsw_env_reset_module(dev, mlxsw_sp->core, slot_index, 121262306a36Sopenharmony_ci module, flags); 121362306a36Sopenharmony_ci} 121462306a36Sopenharmony_ci 121562306a36Sopenharmony_cistatic int 121662306a36Sopenharmony_cimlxsw_sp_get_module_power_mode(struct net_device *dev, 121762306a36Sopenharmony_ci struct ethtool_module_power_mode_params *params, 121862306a36Sopenharmony_ci struct netlink_ext_ack *extack) 121962306a36Sopenharmony_ci{ 122062306a36Sopenharmony_ci struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); 122162306a36Sopenharmony_ci struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 122262306a36Sopenharmony_ci u8 slot_index = mlxsw_sp_port->mapping.slot_index; 122362306a36Sopenharmony_ci u8 module = mlxsw_sp_port->mapping.module; 122462306a36Sopenharmony_ci 122562306a36Sopenharmony_ci return mlxsw_env_get_module_power_mode(mlxsw_sp->core, slot_index, 122662306a36Sopenharmony_ci module, params, extack); 122762306a36Sopenharmony_ci} 122862306a36Sopenharmony_ci 122962306a36Sopenharmony_cistatic int 123062306a36Sopenharmony_cimlxsw_sp_set_module_power_mode(struct net_device *dev, 123162306a36Sopenharmony_ci const struct ethtool_module_power_mode_params *params, 123262306a36Sopenharmony_ci struct netlink_ext_ack *extack) 123362306a36Sopenharmony_ci{ 123462306a36Sopenharmony_ci struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev); 123562306a36Sopenharmony_ci struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp; 123662306a36Sopenharmony_ci u8 slot_index = mlxsw_sp_port->mapping.slot_index; 123762306a36Sopenharmony_ci u8 module = mlxsw_sp_port->mapping.module; 123862306a36Sopenharmony_ci 123962306a36Sopenharmony_ci return mlxsw_env_set_module_power_mode(mlxsw_sp->core, slot_index, 124062306a36Sopenharmony_ci module, params->policy, extack); 124162306a36Sopenharmony_ci} 124262306a36Sopenharmony_ci 124362306a36Sopenharmony_ciconst struct ethtool_ops mlxsw_sp_port_ethtool_ops = { 124462306a36Sopenharmony_ci .cap_link_lanes_supported = true, 124562306a36Sopenharmony_ci .get_drvinfo = mlxsw_sp_port_get_drvinfo, 124662306a36Sopenharmony_ci .get_link = ethtool_op_get_link, 124762306a36Sopenharmony_ci .get_link_ext_state = mlxsw_sp_port_get_link_ext_state, 124862306a36Sopenharmony_ci .get_pauseparam = mlxsw_sp_port_get_pauseparam, 124962306a36Sopenharmony_ci .set_pauseparam = mlxsw_sp_port_set_pauseparam, 125062306a36Sopenharmony_ci .get_strings = mlxsw_sp_port_get_strings, 125162306a36Sopenharmony_ci .set_phys_id = mlxsw_sp_port_set_phys_id, 125262306a36Sopenharmony_ci .get_ethtool_stats = mlxsw_sp_port_get_stats, 125362306a36Sopenharmony_ci .get_sset_count = mlxsw_sp_port_get_sset_count, 125462306a36Sopenharmony_ci .get_link_ksettings = mlxsw_sp_port_get_link_ksettings, 125562306a36Sopenharmony_ci .set_link_ksettings = mlxsw_sp_port_set_link_ksettings, 125662306a36Sopenharmony_ci .get_module_info = mlxsw_sp_get_module_info, 125762306a36Sopenharmony_ci .get_module_eeprom = mlxsw_sp_get_module_eeprom, 125862306a36Sopenharmony_ci .get_module_eeprom_by_page = mlxsw_sp_get_module_eeprom_by_page, 125962306a36Sopenharmony_ci .get_ts_info = mlxsw_sp_get_ts_info, 126062306a36Sopenharmony_ci .get_eth_phy_stats = mlxsw_sp_get_eth_phy_stats, 126162306a36Sopenharmony_ci .get_eth_mac_stats = mlxsw_sp_get_eth_mac_stats, 126262306a36Sopenharmony_ci .get_eth_ctrl_stats = mlxsw_sp_get_eth_ctrl_stats, 126362306a36Sopenharmony_ci .get_rmon_stats = mlxsw_sp_get_rmon_stats, 126462306a36Sopenharmony_ci .reset = mlxsw_sp_reset, 126562306a36Sopenharmony_ci .get_module_power_mode = mlxsw_sp_get_module_power_mode, 126662306a36Sopenharmony_ci .set_module_power_mode = mlxsw_sp_set_module_power_mode, 126762306a36Sopenharmony_ci}; 126862306a36Sopenharmony_ci 126962306a36Sopenharmony_cistruct mlxsw_sp1_port_link_mode { 127062306a36Sopenharmony_ci enum ethtool_link_mode_bit_indices mask_ethtool; 127162306a36Sopenharmony_ci u32 mask; 127262306a36Sopenharmony_ci u32 speed; 127362306a36Sopenharmony_ci}; 127462306a36Sopenharmony_ci 127562306a36Sopenharmony_cistatic const struct mlxsw_sp1_port_link_mode mlxsw_sp1_port_link_mode[] = { 127662306a36Sopenharmony_ci { 127762306a36Sopenharmony_ci .mask = MLXSW_REG_PTYS_ETH_SPEED_100BASE_T, 127862306a36Sopenharmony_ci .mask_ethtool = ETHTOOL_LINK_MODE_100baseT_Full_BIT, 127962306a36Sopenharmony_ci .speed = SPEED_100, 128062306a36Sopenharmony_ci }, 128162306a36Sopenharmony_ci { 128262306a36Sopenharmony_ci .mask = MLXSW_REG_PTYS_ETH_SPEED_SGMII | 128362306a36Sopenharmony_ci MLXSW_REG_PTYS_ETH_SPEED_1000BASE_KX, 128462306a36Sopenharmony_ci .mask_ethtool = ETHTOOL_LINK_MODE_1000baseKX_Full_BIT, 128562306a36Sopenharmony_ci .speed = SPEED_1000, 128662306a36Sopenharmony_ci }, 128762306a36Sopenharmony_ci { 128862306a36Sopenharmony_ci .mask = MLXSW_REG_PTYS_ETH_SPEED_1000BASE_T, 128962306a36Sopenharmony_ci .mask_ethtool = ETHTOOL_LINK_MODE_1000baseT_Full_BIT, 129062306a36Sopenharmony_ci .speed = SPEED_1000, 129162306a36Sopenharmony_ci }, 129262306a36Sopenharmony_ci { 129362306a36Sopenharmony_ci .mask = MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CX4 | 129462306a36Sopenharmony_ci MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KX4, 129562306a36Sopenharmony_ci .mask_ethtool = ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT, 129662306a36Sopenharmony_ci .speed = SPEED_10000, 129762306a36Sopenharmony_ci }, 129862306a36Sopenharmony_ci { 129962306a36Sopenharmony_ci .mask = MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KR | 130062306a36Sopenharmony_ci MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CR | 130162306a36Sopenharmony_ci MLXSW_REG_PTYS_ETH_SPEED_10GBASE_SR | 130262306a36Sopenharmony_ci MLXSW_REG_PTYS_ETH_SPEED_10GBASE_ER_LR, 130362306a36Sopenharmony_ci .mask_ethtool = ETHTOOL_LINK_MODE_10000baseKR_Full_BIT, 130462306a36Sopenharmony_ci .speed = SPEED_10000, 130562306a36Sopenharmony_ci }, 130662306a36Sopenharmony_ci { 130762306a36Sopenharmony_ci .mask = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_CR4, 130862306a36Sopenharmony_ci .mask_ethtool = ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT, 130962306a36Sopenharmony_ci .speed = SPEED_40000, 131062306a36Sopenharmony_ci }, 131162306a36Sopenharmony_ci { 131262306a36Sopenharmony_ci .mask = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_KR4, 131362306a36Sopenharmony_ci .mask_ethtool = ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT, 131462306a36Sopenharmony_ci .speed = SPEED_40000, 131562306a36Sopenharmony_ci }, 131662306a36Sopenharmony_ci { 131762306a36Sopenharmony_ci .mask = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_SR4, 131862306a36Sopenharmony_ci .mask_ethtool = ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT, 131962306a36Sopenharmony_ci .speed = SPEED_40000, 132062306a36Sopenharmony_ci }, 132162306a36Sopenharmony_ci { 132262306a36Sopenharmony_ci .mask = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_LR4_ER4, 132362306a36Sopenharmony_ci .mask_ethtool = ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT, 132462306a36Sopenharmony_ci .speed = SPEED_40000, 132562306a36Sopenharmony_ci }, 132662306a36Sopenharmony_ci { 132762306a36Sopenharmony_ci .mask = MLXSW_REG_PTYS_ETH_SPEED_25GBASE_CR, 132862306a36Sopenharmony_ci .mask_ethtool = ETHTOOL_LINK_MODE_25000baseCR_Full_BIT, 132962306a36Sopenharmony_ci .speed = SPEED_25000, 133062306a36Sopenharmony_ci }, 133162306a36Sopenharmony_ci { 133262306a36Sopenharmony_ci .mask = MLXSW_REG_PTYS_ETH_SPEED_25GBASE_KR, 133362306a36Sopenharmony_ci .mask_ethtool = ETHTOOL_LINK_MODE_25000baseKR_Full_BIT, 133462306a36Sopenharmony_ci .speed = SPEED_25000, 133562306a36Sopenharmony_ci }, 133662306a36Sopenharmony_ci { 133762306a36Sopenharmony_ci .mask = MLXSW_REG_PTYS_ETH_SPEED_25GBASE_SR, 133862306a36Sopenharmony_ci .mask_ethtool = ETHTOOL_LINK_MODE_25000baseSR_Full_BIT, 133962306a36Sopenharmony_ci .speed = SPEED_25000, 134062306a36Sopenharmony_ci }, 134162306a36Sopenharmony_ci { 134262306a36Sopenharmony_ci .mask = MLXSW_REG_PTYS_ETH_SPEED_50GBASE_CR2, 134362306a36Sopenharmony_ci .mask_ethtool = ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT, 134462306a36Sopenharmony_ci .speed = SPEED_50000, 134562306a36Sopenharmony_ci }, 134662306a36Sopenharmony_ci { 134762306a36Sopenharmony_ci .mask = MLXSW_REG_PTYS_ETH_SPEED_50GBASE_KR2, 134862306a36Sopenharmony_ci .mask_ethtool = ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT, 134962306a36Sopenharmony_ci .speed = SPEED_50000, 135062306a36Sopenharmony_ci }, 135162306a36Sopenharmony_ci { 135262306a36Sopenharmony_ci .mask = MLXSW_REG_PTYS_ETH_SPEED_50GBASE_SR2, 135362306a36Sopenharmony_ci .mask_ethtool = ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT, 135462306a36Sopenharmony_ci .speed = SPEED_50000, 135562306a36Sopenharmony_ci }, 135662306a36Sopenharmony_ci { 135762306a36Sopenharmony_ci .mask = MLXSW_REG_PTYS_ETH_SPEED_100GBASE_CR4, 135862306a36Sopenharmony_ci .mask_ethtool = ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT, 135962306a36Sopenharmony_ci .speed = SPEED_100000, 136062306a36Sopenharmony_ci }, 136162306a36Sopenharmony_ci { 136262306a36Sopenharmony_ci .mask = MLXSW_REG_PTYS_ETH_SPEED_100GBASE_SR4, 136362306a36Sopenharmony_ci .mask_ethtool = ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT, 136462306a36Sopenharmony_ci .speed = SPEED_100000, 136562306a36Sopenharmony_ci }, 136662306a36Sopenharmony_ci { 136762306a36Sopenharmony_ci .mask = MLXSW_REG_PTYS_ETH_SPEED_100GBASE_KR4, 136862306a36Sopenharmony_ci .mask_ethtool = ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT, 136962306a36Sopenharmony_ci .speed = SPEED_100000, 137062306a36Sopenharmony_ci }, 137162306a36Sopenharmony_ci { 137262306a36Sopenharmony_ci .mask = MLXSW_REG_PTYS_ETH_SPEED_100GBASE_LR4_ER4, 137362306a36Sopenharmony_ci .mask_ethtool = ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT, 137462306a36Sopenharmony_ci .speed = SPEED_100000, 137562306a36Sopenharmony_ci }, 137662306a36Sopenharmony_ci}; 137762306a36Sopenharmony_ci 137862306a36Sopenharmony_ci#define MLXSW_SP1_PORT_LINK_MODE_LEN ARRAY_SIZE(mlxsw_sp1_port_link_mode) 137962306a36Sopenharmony_ci 138062306a36Sopenharmony_cistatic void 138162306a36Sopenharmony_cimlxsw_sp1_from_ptys_supported_port(struct mlxsw_sp *mlxsw_sp, 138262306a36Sopenharmony_ci u32 ptys_eth_proto, 138362306a36Sopenharmony_ci struct ethtool_link_ksettings *cmd) 138462306a36Sopenharmony_ci{ 138562306a36Sopenharmony_ci if (ptys_eth_proto & (MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CR | 138662306a36Sopenharmony_ci MLXSW_REG_PTYS_ETH_SPEED_10GBASE_SR | 138762306a36Sopenharmony_ci MLXSW_REG_PTYS_ETH_SPEED_40GBASE_CR4 | 138862306a36Sopenharmony_ci MLXSW_REG_PTYS_ETH_SPEED_40GBASE_SR4 | 138962306a36Sopenharmony_ci MLXSW_REG_PTYS_ETH_SPEED_100GBASE_SR4 | 139062306a36Sopenharmony_ci MLXSW_REG_PTYS_ETH_SPEED_SGMII)) 139162306a36Sopenharmony_ci ethtool_link_ksettings_add_link_mode(cmd, supported, FIBRE); 139262306a36Sopenharmony_ci 139362306a36Sopenharmony_ci if (ptys_eth_proto & (MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KR | 139462306a36Sopenharmony_ci MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KX4 | 139562306a36Sopenharmony_ci MLXSW_REG_PTYS_ETH_SPEED_40GBASE_KR4 | 139662306a36Sopenharmony_ci MLXSW_REG_PTYS_ETH_SPEED_100GBASE_KR4 | 139762306a36Sopenharmony_ci MLXSW_REG_PTYS_ETH_SPEED_1000BASE_KX)) 139862306a36Sopenharmony_ci ethtool_link_ksettings_add_link_mode(cmd, supported, Backplane); 139962306a36Sopenharmony_ci} 140062306a36Sopenharmony_ci 140162306a36Sopenharmony_cistatic void 140262306a36Sopenharmony_cimlxsw_sp1_from_ptys_link(struct mlxsw_sp *mlxsw_sp, u32 ptys_eth_proto, 140362306a36Sopenharmony_ci unsigned long *mode) 140462306a36Sopenharmony_ci{ 140562306a36Sopenharmony_ci int i; 140662306a36Sopenharmony_ci 140762306a36Sopenharmony_ci for (i = 0; i < MLXSW_SP1_PORT_LINK_MODE_LEN; i++) { 140862306a36Sopenharmony_ci if (ptys_eth_proto & mlxsw_sp1_port_link_mode[i].mask) 140962306a36Sopenharmony_ci __set_bit(mlxsw_sp1_port_link_mode[i].mask_ethtool, 141062306a36Sopenharmony_ci mode); 141162306a36Sopenharmony_ci } 141262306a36Sopenharmony_ci} 141362306a36Sopenharmony_ci 141462306a36Sopenharmony_cistatic u32 141562306a36Sopenharmony_cimlxsw_sp1_from_ptys_speed(struct mlxsw_sp *mlxsw_sp, u32 ptys_eth_proto) 141662306a36Sopenharmony_ci{ 141762306a36Sopenharmony_ci int i; 141862306a36Sopenharmony_ci 141962306a36Sopenharmony_ci for (i = 0; i < MLXSW_SP1_PORT_LINK_MODE_LEN; i++) { 142062306a36Sopenharmony_ci if (ptys_eth_proto & mlxsw_sp1_port_link_mode[i].mask) 142162306a36Sopenharmony_ci return mlxsw_sp1_port_link_mode[i].speed; 142262306a36Sopenharmony_ci } 142362306a36Sopenharmony_ci 142462306a36Sopenharmony_ci return SPEED_UNKNOWN; 142562306a36Sopenharmony_ci} 142662306a36Sopenharmony_ci 142762306a36Sopenharmony_cistatic void 142862306a36Sopenharmony_cimlxsw_sp1_from_ptys_link_mode(struct mlxsw_sp *mlxsw_sp, bool carrier_ok, 142962306a36Sopenharmony_ci u32 ptys_eth_proto, 143062306a36Sopenharmony_ci struct ethtool_link_ksettings *cmd) 143162306a36Sopenharmony_ci{ 143262306a36Sopenharmony_ci struct mlxsw_sp1_port_link_mode link; 143362306a36Sopenharmony_ci int i; 143462306a36Sopenharmony_ci 143562306a36Sopenharmony_ci cmd->base.speed = SPEED_UNKNOWN; 143662306a36Sopenharmony_ci cmd->base.duplex = DUPLEX_UNKNOWN; 143762306a36Sopenharmony_ci cmd->lanes = 0; 143862306a36Sopenharmony_ci 143962306a36Sopenharmony_ci if (!carrier_ok) 144062306a36Sopenharmony_ci return; 144162306a36Sopenharmony_ci 144262306a36Sopenharmony_ci for (i = 0; i < MLXSW_SP1_PORT_LINK_MODE_LEN; i++) { 144362306a36Sopenharmony_ci if (ptys_eth_proto & mlxsw_sp1_port_link_mode[i].mask) { 144462306a36Sopenharmony_ci link = mlxsw_sp1_port_link_mode[i]; 144562306a36Sopenharmony_ci ethtool_params_from_link_mode(cmd, 144662306a36Sopenharmony_ci link.mask_ethtool); 144762306a36Sopenharmony_ci } 144862306a36Sopenharmony_ci } 144962306a36Sopenharmony_ci} 145062306a36Sopenharmony_ci 145162306a36Sopenharmony_cistatic int mlxsw_sp1_ptys_max_speed(struct mlxsw_sp_port *mlxsw_sp_port, u32 *p_max_speed) 145262306a36Sopenharmony_ci{ 145362306a36Sopenharmony_ci u32 eth_proto_cap; 145462306a36Sopenharmony_ci u32 max_speed = 0; 145562306a36Sopenharmony_ci int err; 145662306a36Sopenharmony_ci int i; 145762306a36Sopenharmony_ci 145862306a36Sopenharmony_ci err = mlxsw_sp_port_ptys_query(mlxsw_sp_port, ð_proto_cap, NULL, NULL, NULL); 145962306a36Sopenharmony_ci if (err) 146062306a36Sopenharmony_ci return err; 146162306a36Sopenharmony_ci 146262306a36Sopenharmony_ci for (i = 0; i < MLXSW_SP1_PORT_LINK_MODE_LEN; i++) { 146362306a36Sopenharmony_ci if ((eth_proto_cap & mlxsw_sp1_port_link_mode[i].mask) && 146462306a36Sopenharmony_ci mlxsw_sp1_port_link_mode[i].speed > max_speed) 146562306a36Sopenharmony_ci max_speed = mlxsw_sp1_port_link_mode[i].speed; 146662306a36Sopenharmony_ci } 146762306a36Sopenharmony_ci 146862306a36Sopenharmony_ci *p_max_speed = max_speed; 146962306a36Sopenharmony_ci return 0; 147062306a36Sopenharmony_ci} 147162306a36Sopenharmony_ci 147262306a36Sopenharmony_cistatic u32 147362306a36Sopenharmony_cimlxsw_sp1_to_ptys_advert_link(struct mlxsw_sp *mlxsw_sp, 147462306a36Sopenharmony_ci const struct ethtool_link_ksettings *cmd) 147562306a36Sopenharmony_ci{ 147662306a36Sopenharmony_ci u32 ptys_proto = 0; 147762306a36Sopenharmony_ci int i; 147862306a36Sopenharmony_ci 147962306a36Sopenharmony_ci for (i = 0; i < MLXSW_SP1_PORT_LINK_MODE_LEN; i++) { 148062306a36Sopenharmony_ci if (test_bit(mlxsw_sp1_port_link_mode[i].mask_ethtool, 148162306a36Sopenharmony_ci cmd->link_modes.advertising)) 148262306a36Sopenharmony_ci ptys_proto |= mlxsw_sp1_port_link_mode[i].mask; 148362306a36Sopenharmony_ci } 148462306a36Sopenharmony_ci return ptys_proto; 148562306a36Sopenharmony_ci} 148662306a36Sopenharmony_ci 148762306a36Sopenharmony_cistatic u32 mlxsw_sp1_to_ptys_speed_lanes(struct mlxsw_sp *mlxsw_sp, u8 width, 148862306a36Sopenharmony_ci const struct ethtool_link_ksettings *cmd) 148962306a36Sopenharmony_ci{ 149062306a36Sopenharmony_ci u32 ptys_proto = 0; 149162306a36Sopenharmony_ci int i; 149262306a36Sopenharmony_ci 149362306a36Sopenharmony_ci if (cmd->lanes > width) 149462306a36Sopenharmony_ci return ptys_proto; 149562306a36Sopenharmony_ci 149662306a36Sopenharmony_ci for (i = 0; i < MLXSW_SP1_PORT_LINK_MODE_LEN; i++) { 149762306a36Sopenharmony_ci if (cmd->base.speed == mlxsw_sp1_port_link_mode[i].speed) 149862306a36Sopenharmony_ci ptys_proto |= mlxsw_sp1_port_link_mode[i].mask; 149962306a36Sopenharmony_ci } 150062306a36Sopenharmony_ci return ptys_proto; 150162306a36Sopenharmony_ci} 150262306a36Sopenharmony_ci 150362306a36Sopenharmony_cistatic void 150462306a36Sopenharmony_cimlxsw_sp1_reg_ptys_eth_pack(struct mlxsw_sp *mlxsw_sp, char *payload, 150562306a36Sopenharmony_ci u16 local_port, u32 proto_admin, bool autoneg) 150662306a36Sopenharmony_ci{ 150762306a36Sopenharmony_ci mlxsw_reg_ptys_eth_pack(payload, local_port, proto_admin, autoneg); 150862306a36Sopenharmony_ci} 150962306a36Sopenharmony_ci 151062306a36Sopenharmony_cistatic void 151162306a36Sopenharmony_cimlxsw_sp1_reg_ptys_eth_unpack(struct mlxsw_sp *mlxsw_sp, char *payload, 151262306a36Sopenharmony_ci u32 *p_eth_proto_cap, u32 *p_eth_proto_admin, 151362306a36Sopenharmony_ci u32 *p_eth_proto_oper) 151462306a36Sopenharmony_ci{ 151562306a36Sopenharmony_ci mlxsw_reg_ptys_eth_unpack(payload, p_eth_proto_cap, p_eth_proto_admin, 151662306a36Sopenharmony_ci p_eth_proto_oper); 151762306a36Sopenharmony_ci} 151862306a36Sopenharmony_ci 151962306a36Sopenharmony_cistatic u32 mlxsw_sp1_ptys_proto_cap_masked_get(u32 eth_proto_cap) 152062306a36Sopenharmony_ci{ 152162306a36Sopenharmony_ci u32 ptys_proto_cap_masked = 0; 152262306a36Sopenharmony_ci int i; 152362306a36Sopenharmony_ci 152462306a36Sopenharmony_ci for (i = 0; i < MLXSW_SP1_PORT_LINK_MODE_LEN; i++) { 152562306a36Sopenharmony_ci if (mlxsw_sp1_port_link_mode[i].mask & eth_proto_cap) 152662306a36Sopenharmony_ci ptys_proto_cap_masked |= 152762306a36Sopenharmony_ci mlxsw_sp1_port_link_mode[i].mask; 152862306a36Sopenharmony_ci } 152962306a36Sopenharmony_ci 153062306a36Sopenharmony_ci return ptys_proto_cap_masked; 153162306a36Sopenharmony_ci} 153262306a36Sopenharmony_ci 153362306a36Sopenharmony_ciconst struct mlxsw_sp_port_type_speed_ops mlxsw_sp1_port_type_speed_ops = { 153462306a36Sopenharmony_ci .from_ptys_supported_port = mlxsw_sp1_from_ptys_supported_port, 153562306a36Sopenharmony_ci .from_ptys_link = mlxsw_sp1_from_ptys_link, 153662306a36Sopenharmony_ci .from_ptys_speed = mlxsw_sp1_from_ptys_speed, 153762306a36Sopenharmony_ci .from_ptys_link_mode = mlxsw_sp1_from_ptys_link_mode, 153862306a36Sopenharmony_ci .ptys_max_speed = mlxsw_sp1_ptys_max_speed, 153962306a36Sopenharmony_ci .to_ptys_advert_link = mlxsw_sp1_to_ptys_advert_link, 154062306a36Sopenharmony_ci .to_ptys_speed_lanes = mlxsw_sp1_to_ptys_speed_lanes, 154162306a36Sopenharmony_ci .reg_ptys_eth_pack = mlxsw_sp1_reg_ptys_eth_pack, 154262306a36Sopenharmony_ci .reg_ptys_eth_unpack = mlxsw_sp1_reg_ptys_eth_unpack, 154362306a36Sopenharmony_ci .ptys_proto_cap_masked_get = mlxsw_sp1_ptys_proto_cap_masked_get, 154462306a36Sopenharmony_ci}; 154562306a36Sopenharmony_ci 154662306a36Sopenharmony_cistatic const enum ethtool_link_mode_bit_indices 154762306a36Sopenharmony_cimlxsw_sp2_mask_ethtool_sgmii_100m[] = { 154862306a36Sopenharmony_ci ETHTOOL_LINK_MODE_100baseT_Full_BIT, 154962306a36Sopenharmony_ci}; 155062306a36Sopenharmony_ci 155162306a36Sopenharmony_ci#define MLXSW_SP2_MASK_ETHTOOL_SGMII_100M_LEN \ 155262306a36Sopenharmony_ci ARRAY_SIZE(mlxsw_sp2_mask_ethtool_sgmii_100m) 155362306a36Sopenharmony_ci 155462306a36Sopenharmony_cistatic const enum ethtool_link_mode_bit_indices 155562306a36Sopenharmony_cimlxsw_sp2_mask_ethtool_1000base_x_sgmii[] = { 155662306a36Sopenharmony_ci ETHTOOL_LINK_MODE_1000baseT_Full_BIT, 155762306a36Sopenharmony_ci ETHTOOL_LINK_MODE_1000baseKX_Full_BIT, 155862306a36Sopenharmony_ci}; 155962306a36Sopenharmony_ci 156062306a36Sopenharmony_ci#define MLXSW_SP2_MASK_ETHTOOL_1000BASE_X_SGMII_LEN \ 156162306a36Sopenharmony_ci ARRAY_SIZE(mlxsw_sp2_mask_ethtool_1000base_x_sgmii) 156262306a36Sopenharmony_ci 156362306a36Sopenharmony_cistatic const enum ethtool_link_mode_bit_indices 156462306a36Sopenharmony_cimlxsw_sp2_mask_ethtool_5gbase_r[] = { 156562306a36Sopenharmony_ci ETHTOOL_LINK_MODE_5000baseT_Full_BIT, 156662306a36Sopenharmony_ci}; 156762306a36Sopenharmony_ci 156862306a36Sopenharmony_ci#define MLXSW_SP2_MASK_ETHTOOL_5GBASE_R_LEN \ 156962306a36Sopenharmony_ci ARRAY_SIZE(mlxsw_sp2_mask_ethtool_5gbase_r) 157062306a36Sopenharmony_ci 157162306a36Sopenharmony_cistatic const enum ethtool_link_mode_bit_indices 157262306a36Sopenharmony_cimlxsw_sp2_mask_ethtool_xfi_xaui_1_10g[] = { 157362306a36Sopenharmony_ci ETHTOOL_LINK_MODE_10000baseT_Full_BIT, 157462306a36Sopenharmony_ci ETHTOOL_LINK_MODE_10000baseKR_Full_BIT, 157562306a36Sopenharmony_ci ETHTOOL_LINK_MODE_10000baseR_FEC_BIT, 157662306a36Sopenharmony_ci ETHTOOL_LINK_MODE_10000baseCR_Full_BIT, 157762306a36Sopenharmony_ci ETHTOOL_LINK_MODE_10000baseSR_Full_BIT, 157862306a36Sopenharmony_ci ETHTOOL_LINK_MODE_10000baseLR_Full_BIT, 157962306a36Sopenharmony_ci ETHTOOL_LINK_MODE_10000baseER_Full_BIT, 158062306a36Sopenharmony_ci}; 158162306a36Sopenharmony_ci 158262306a36Sopenharmony_ci#define MLXSW_SP2_MASK_ETHTOOL_XFI_XAUI_1_10G_LEN \ 158362306a36Sopenharmony_ci ARRAY_SIZE(mlxsw_sp2_mask_ethtool_xfi_xaui_1_10g) 158462306a36Sopenharmony_ci 158562306a36Sopenharmony_cistatic const enum ethtool_link_mode_bit_indices 158662306a36Sopenharmony_cimlxsw_sp2_mask_ethtool_xlaui_4_xlppi_4_40g[] = { 158762306a36Sopenharmony_ci ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT, 158862306a36Sopenharmony_ci ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT, 158962306a36Sopenharmony_ci ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT, 159062306a36Sopenharmony_ci ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT, 159162306a36Sopenharmony_ci}; 159262306a36Sopenharmony_ci 159362306a36Sopenharmony_ci#define MLXSW_SP2_MASK_ETHTOOL_XLAUI_4_XLPPI_4_40G_LEN \ 159462306a36Sopenharmony_ci ARRAY_SIZE(mlxsw_sp2_mask_ethtool_xlaui_4_xlppi_4_40g) 159562306a36Sopenharmony_ci 159662306a36Sopenharmony_cistatic const enum ethtool_link_mode_bit_indices 159762306a36Sopenharmony_cimlxsw_sp2_mask_ethtool_25gaui_1_25gbase_cr_kr[] = { 159862306a36Sopenharmony_ci ETHTOOL_LINK_MODE_25000baseCR_Full_BIT, 159962306a36Sopenharmony_ci ETHTOOL_LINK_MODE_25000baseKR_Full_BIT, 160062306a36Sopenharmony_ci ETHTOOL_LINK_MODE_25000baseSR_Full_BIT, 160162306a36Sopenharmony_ci}; 160262306a36Sopenharmony_ci 160362306a36Sopenharmony_ci#define MLXSW_SP2_MASK_ETHTOOL_25GAUI_1_25GBASE_CR_KR_LEN \ 160462306a36Sopenharmony_ci ARRAY_SIZE(mlxsw_sp2_mask_ethtool_25gaui_1_25gbase_cr_kr) 160562306a36Sopenharmony_ci 160662306a36Sopenharmony_cistatic const enum ethtool_link_mode_bit_indices 160762306a36Sopenharmony_cimlxsw_sp2_mask_ethtool_50gaui_2_laui_2_50gbase_cr2_kr2[] = { 160862306a36Sopenharmony_ci ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT, 160962306a36Sopenharmony_ci ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT, 161062306a36Sopenharmony_ci ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT, 161162306a36Sopenharmony_ci}; 161262306a36Sopenharmony_ci 161362306a36Sopenharmony_ci#define MLXSW_SP2_MASK_ETHTOOL_50GAUI_2_LAUI_2_50GBASE_CR2_KR2_LEN \ 161462306a36Sopenharmony_ci ARRAY_SIZE(mlxsw_sp2_mask_ethtool_50gaui_2_laui_2_50gbase_cr2_kr2) 161562306a36Sopenharmony_ci 161662306a36Sopenharmony_cistatic const enum ethtool_link_mode_bit_indices 161762306a36Sopenharmony_cimlxsw_sp2_mask_ethtool_50gaui_1_laui_1_50gbase_cr_kr[] = { 161862306a36Sopenharmony_ci ETHTOOL_LINK_MODE_50000baseKR_Full_BIT, 161962306a36Sopenharmony_ci ETHTOOL_LINK_MODE_50000baseSR_Full_BIT, 162062306a36Sopenharmony_ci ETHTOOL_LINK_MODE_50000baseCR_Full_BIT, 162162306a36Sopenharmony_ci ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT, 162262306a36Sopenharmony_ci ETHTOOL_LINK_MODE_50000baseDR_Full_BIT, 162362306a36Sopenharmony_ci}; 162462306a36Sopenharmony_ci 162562306a36Sopenharmony_ci#define MLXSW_SP2_MASK_ETHTOOL_50GAUI_1_LAUI_1_50GBASE_CR_KR_LEN \ 162662306a36Sopenharmony_ci ARRAY_SIZE(mlxsw_sp2_mask_ethtool_50gaui_1_laui_1_50gbase_cr_kr) 162762306a36Sopenharmony_ci 162862306a36Sopenharmony_cistatic const enum ethtool_link_mode_bit_indices 162962306a36Sopenharmony_cimlxsw_sp2_mask_ethtool_caui_4_100gbase_cr4_kr4[] = { 163062306a36Sopenharmony_ci ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT, 163162306a36Sopenharmony_ci ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT, 163262306a36Sopenharmony_ci ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT, 163362306a36Sopenharmony_ci ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT, 163462306a36Sopenharmony_ci}; 163562306a36Sopenharmony_ci 163662306a36Sopenharmony_ci#define MLXSW_SP2_MASK_ETHTOOL_CAUI_4_100GBASE_CR4_KR4_LEN \ 163762306a36Sopenharmony_ci ARRAY_SIZE(mlxsw_sp2_mask_ethtool_caui_4_100gbase_cr4_kr4) 163862306a36Sopenharmony_ci 163962306a36Sopenharmony_cistatic const enum ethtool_link_mode_bit_indices 164062306a36Sopenharmony_cimlxsw_sp2_mask_ethtool_100gaui_2_100gbase_cr2_kr2[] = { 164162306a36Sopenharmony_ci ETHTOOL_LINK_MODE_100000baseKR2_Full_BIT, 164262306a36Sopenharmony_ci ETHTOOL_LINK_MODE_100000baseSR2_Full_BIT, 164362306a36Sopenharmony_ci ETHTOOL_LINK_MODE_100000baseCR2_Full_BIT, 164462306a36Sopenharmony_ci ETHTOOL_LINK_MODE_100000baseLR2_ER2_FR2_Full_BIT, 164562306a36Sopenharmony_ci ETHTOOL_LINK_MODE_100000baseDR2_Full_BIT, 164662306a36Sopenharmony_ci}; 164762306a36Sopenharmony_ci 164862306a36Sopenharmony_ci#define MLXSW_SP2_MASK_ETHTOOL_100GAUI_2_100GBASE_CR2_KR2_LEN \ 164962306a36Sopenharmony_ci ARRAY_SIZE(mlxsw_sp2_mask_ethtool_100gaui_2_100gbase_cr2_kr2) 165062306a36Sopenharmony_ci 165162306a36Sopenharmony_cistatic const enum ethtool_link_mode_bit_indices 165262306a36Sopenharmony_cimlxsw_sp2_mask_ethtool_200gaui_4_200gbase_cr4_kr4[] = { 165362306a36Sopenharmony_ci ETHTOOL_LINK_MODE_200000baseKR4_Full_BIT, 165462306a36Sopenharmony_ci ETHTOOL_LINK_MODE_200000baseSR4_Full_BIT, 165562306a36Sopenharmony_ci ETHTOOL_LINK_MODE_200000baseLR4_ER4_FR4_Full_BIT, 165662306a36Sopenharmony_ci ETHTOOL_LINK_MODE_200000baseDR4_Full_BIT, 165762306a36Sopenharmony_ci ETHTOOL_LINK_MODE_200000baseCR4_Full_BIT, 165862306a36Sopenharmony_ci}; 165962306a36Sopenharmony_ci 166062306a36Sopenharmony_ci#define MLXSW_SP2_MASK_ETHTOOL_200GAUI_4_200GBASE_CR4_KR4_LEN \ 166162306a36Sopenharmony_ci ARRAY_SIZE(mlxsw_sp2_mask_ethtool_200gaui_4_200gbase_cr4_kr4) 166262306a36Sopenharmony_ci 166362306a36Sopenharmony_cistatic const enum ethtool_link_mode_bit_indices 166462306a36Sopenharmony_cimlxsw_sp2_mask_ethtool_400gaui_8[] = { 166562306a36Sopenharmony_ci ETHTOOL_LINK_MODE_400000baseKR8_Full_BIT, 166662306a36Sopenharmony_ci ETHTOOL_LINK_MODE_400000baseSR8_Full_BIT, 166762306a36Sopenharmony_ci ETHTOOL_LINK_MODE_400000baseLR8_ER8_FR8_Full_BIT, 166862306a36Sopenharmony_ci ETHTOOL_LINK_MODE_400000baseDR8_Full_BIT, 166962306a36Sopenharmony_ci ETHTOOL_LINK_MODE_400000baseCR8_Full_BIT, 167062306a36Sopenharmony_ci}; 167162306a36Sopenharmony_ci 167262306a36Sopenharmony_ci#define MLXSW_SP2_MASK_ETHTOOL_400GAUI_8_LEN \ 167362306a36Sopenharmony_ci ARRAY_SIZE(mlxsw_sp2_mask_ethtool_400gaui_8) 167462306a36Sopenharmony_ci 167562306a36Sopenharmony_cistatic const enum ethtool_link_mode_bit_indices 167662306a36Sopenharmony_cimlxsw_sp2_mask_ethtool_800gaui_8[] = { 167762306a36Sopenharmony_ci ETHTOOL_LINK_MODE_800000baseCR8_Full_BIT, 167862306a36Sopenharmony_ci ETHTOOL_LINK_MODE_800000baseKR8_Full_BIT, 167962306a36Sopenharmony_ci ETHTOOL_LINK_MODE_800000baseDR8_Full_BIT, 168062306a36Sopenharmony_ci ETHTOOL_LINK_MODE_800000baseDR8_2_Full_BIT, 168162306a36Sopenharmony_ci ETHTOOL_LINK_MODE_800000baseSR8_Full_BIT, 168262306a36Sopenharmony_ci ETHTOOL_LINK_MODE_800000baseVR8_Full_BIT, 168362306a36Sopenharmony_ci}; 168462306a36Sopenharmony_ci 168562306a36Sopenharmony_ci#define MLXSW_SP2_MASK_ETHTOOL_800GAUI_8_LEN \ 168662306a36Sopenharmony_ci ARRAY_SIZE(mlxsw_sp2_mask_ethtool_800gaui_8) 168762306a36Sopenharmony_ci 168862306a36Sopenharmony_ci#define MLXSW_SP_PORT_MASK_WIDTH_1X BIT(0) 168962306a36Sopenharmony_ci#define MLXSW_SP_PORT_MASK_WIDTH_2X BIT(1) 169062306a36Sopenharmony_ci#define MLXSW_SP_PORT_MASK_WIDTH_4X BIT(2) 169162306a36Sopenharmony_ci#define MLXSW_SP_PORT_MASK_WIDTH_8X BIT(3) 169262306a36Sopenharmony_ci 169362306a36Sopenharmony_cistatic u8 mlxsw_sp_port_mask_width_get(u8 width) 169462306a36Sopenharmony_ci{ 169562306a36Sopenharmony_ci switch (width) { 169662306a36Sopenharmony_ci case 1: 169762306a36Sopenharmony_ci return MLXSW_SP_PORT_MASK_WIDTH_1X; 169862306a36Sopenharmony_ci case 2: 169962306a36Sopenharmony_ci return MLXSW_SP_PORT_MASK_WIDTH_2X; 170062306a36Sopenharmony_ci case 4: 170162306a36Sopenharmony_ci return MLXSW_SP_PORT_MASK_WIDTH_4X; 170262306a36Sopenharmony_ci case 8: 170362306a36Sopenharmony_ci return MLXSW_SP_PORT_MASK_WIDTH_8X; 170462306a36Sopenharmony_ci default: 170562306a36Sopenharmony_ci WARN_ON_ONCE(1); 170662306a36Sopenharmony_ci return 0; 170762306a36Sopenharmony_ci } 170862306a36Sopenharmony_ci} 170962306a36Sopenharmony_ci 171062306a36Sopenharmony_cistruct mlxsw_sp2_port_link_mode { 171162306a36Sopenharmony_ci const enum ethtool_link_mode_bit_indices *mask_ethtool; 171262306a36Sopenharmony_ci int m_ethtool_len; 171362306a36Sopenharmony_ci u32 mask; 171462306a36Sopenharmony_ci u32 speed; 171562306a36Sopenharmony_ci u32 width; 171662306a36Sopenharmony_ci u8 mask_sup_width; 171762306a36Sopenharmony_ci}; 171862306a36Sopenharmony_ci 171962306a36Sopenharmony_cistatic const struct mlxsw_sp2_port_link_mode mlxsw_sp2_port_link_mode[] = { 172062306a36Sopenharmony_ci { 172162306a36Sopenharmony_ci .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_SGMII_100M, 172262306a36Sopenharmony_ci .mask_ethtool = mlxsw_sp2_mask_ethtool_sgmii_100m, 172362306a36Sopenharmony_ci .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_SGMII_100M_LEN, 172462306a36Sopenharmony_ci .mask_sup_width = MLXSW_SP_PORT_MASK_WIDTH_1X | 172562306a36Sopenharmony_ci MLXSW_SP_PORT_MASK_WIDTH_2X | 172662306a36Sopenharmony_ci MLXSW_SP_PORT_MASK_WIDTH_4X | 172762306a36Sopenharmony_ci MLXSW_SP_PORT_MASK_WIDTH_8X, 172862306a36Sopenharmony_ci .speed = SPEED_100, 172962306a36Sopenharmony_ci .width = 1, 173062306a36Sopenharmony_ci }, 173162306a36Sopenharmony_ci { 173262306a36Sopenharmony_ci .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_1000BASE_X_SGMII, 173362306a36Sopenharmony_ci .mask_ethtool = mlxsw_sp2_mask_ethtool_1000base_x_sgmii, 173462306a36Sopenharmony_ci .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_1000BASE_X_SGMII_LEN, 173562306a36Sopenharmony_ci .mask_sup_width = MLXSW_SP_PORT_MASK_WIDTH_1X | 173662306a36Sopenharmony_ci MLXSW_SP_PORT_MASK_WIDTH_2X | 173762306a36Sopenharmony_ci MLXSW_SP_PORT_MASK_WIDTH_4X | 173862306a36Sopenharmony_ci MLXSW_SP_PORT_MASK_WIDTH_8X, 173962306a36Sopenharmony_ci .speed = SPEED_1000, 174062306a36Sopenharmony_ci .width = 1, 174162306a36Sopenharmony_ci }, 174262306a36Sopenharmony_ci { 174362306a36Sopenharmony_ci .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_5GBASE_R, 174462306a36Sopenharmony_ci .mask_ethtool = mlxsw_sp2_mask_ethtool_5gbase_r, 174562306a36Sopenharmony_ci .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_5GBASE_R_LEN, 174662306a36Sopenharmony_ci .mask_sup_width = MLXSW_SP_PORT_MASK_WIDTH_1X | 174762306a36Sopenharmony_ci MLXSW_SP_PORT_MASK_WIDTH_2X | 174862306a36Sopenharmony_ci MLXSW_SP_PORT_MASK_WIDTH_4X | 174962306a36Sopenharmony_ci MLXSW_SP_PORT_MASK_WIDTH_8X, 175062306a36Sopenharmony_ci .speed = SPEED_5000, 175162306a36Sopenharmony_ci .width = 1, 175262306a36Sopenharmony_ci }, 175362306a36Sopenharmony_ci { 175462306a36Sopenharmony_ci .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_XFI_XAUI_1_10G, 175562306a36Sopenharmony_ci .mask_ethtool = mlxsw_sp2_mask_ethtool_xfi_xaui_1_10g, 175662306a36Sopenharmony_ci .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_XFI_XAUI_1_10G_LEN, 175762306a36Sopenharmony_ci .mask_sup_width = MLXSW_SP_PORT_MASK_WIDTH_1X | 175862306a36Sopenharmony_ci MLXSW_SP_PORT_MASK_WIDTH_2X | 175962306a36Sopenharmony_ci MLXSW_SP_PORT_MASK_WIDTH_4X | 176062306a36Sopenharmony_ci MLXSW_SP_PORT_MASK_WIDTH_8X, 176162306a36Sopenharmony_ci .speed = SPEED_10000, 176262306a36Sopenharmony_ci .width = 1, 176362306a36Sopenharmony_ci }, 176462306a36Sopenharmony_ci { 176562306a36Sopenharmony_ci .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_XLAUI_4_XLPPI_4_40G, 176662306a36Sopenharmony_ci .mask_ethtool = mlxsw_sp2_mask_ethtool_xlaui_4_xlppi_4_40g, 176762306a36Sopenharmony_ci .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_XLAUI_4_XLPPI_4_40G_LEN, 176862306a36Sopenharmony_ci .mask_sup_width = MLXSW_SP_PORT_MASK_WIDTH_4X | 176962306a36Sopenharmony_ci MLXSW_SP_PORT_MASK_WIDTH_8X, 177062306a36Sopenharmony_ci .speed = SPEED_40000, 177162306a36Sopenharmony_ci .width = 4, 177262306a36Sopenharmony_ci }, 177362306a36Sopenharmony_ci { 177462306a36Sopenharmony_ci .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_25GAUI_1_25GBASE_CR_KR, 177562306a36Sopenharmony_ci .mask_ethtool = mlxsw_sp2_mask_ethtool_25gaui_1_25gbase_cr_kr, 177662306a36Sopenharmony_ci .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_25GAUI_1_25GBASE_CR_KR_LEN, 177762306a36Sopenharmony_ci .mask_sup_width = MLXSW_SP_PORT_MASK_WIDTH_1X | 177862306a36Sopenharmony_ci MLXSW_SP_PORT_MASK_WIDTH_2X | 177962306a36Sopenharmony_ci MLXSW_SP_PORT_MASK_WIDTH_4X | 178062306a36Sopenharmony_ci MLXSW_SP_PORT_MASK_WIDTH_8X, 178162306a36Sopenharmony_ci .speed = SPEED_25000, 178262306a36Sopenharmony_ci .width = 1, 178362306a36Sopenharmony_ci }, 178462306a36Sopenharmony_ci { 178562306a36Sopenharmony_ci .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_50GAUI_2_LAUI_2_50GBASE_CR2_KR2, 178662306a36Sopenharmony_ci .mask_ethtool = mlxsw_sp2_mask_ethtool_50gaui_2_laui_2_50gbase_cr2_kr2, 178762306a36Sopenharmony_ci .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_50GAUI_2_LAUI_2_50GBASE_CR2_KR2_LEN, 178862306a36Sopenharmony_ci .mask_sup_width = MLXSW_SP_PORT_MASK_WIDTH_2X | 178962306a36Sopenharmony_ci MLXSW_SP_PORT_MASK_WIDTH_4X | 179062306a36Sopenharmony_ci MLXSW_SP_PORT_MASK_WIDTH_8X, 179162306a36Sopenharmony_ci .speed = SPEED_50000, 179262306a36Sopenharmony_ci .width = 2, 179362306a36Sopenharmony_ci }, 179462306a36Sopenharmony_ci { 179562306a36Sopenharmony_ci .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_50GAUI_1_LAUI_1_50GBASE_CR_KR, 179662306a36Sopenharmony_ci .mask_ethtool = mlxsw_sp2_mask_ethtool_50gaui_1_laui_1_50gbase_cr_kr, 179762306a36Sopenharmony_ci .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_50GAUI_1_LAUI_1_50GBASE_CR_KR_LEN, 179862306a36Sopenharmony_ci .mask_sup_width = MLXSW_SP_PORT_MASK_WIDTH_1X, 179962306a36Sopenharmony_ci .speed = SPEED_50000, 180062306a36Sopenharmony_ci .width = 1, 180162306a36Sopenharmony_ci }, 180262306a36Sopenharmony_ci { 180362306a36Sopenharmony_ci .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_CAUI_4_100GBASE_CR4_KR4, 180462306a36Sopenharmony_ci .mask_ethtool = mlxsw_sp2_mask_ethtool_caui_4_100gbase_cr4_kr4, 180562306a36Sopenharmony_ci .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_CAUI_4_100GBASE_CR4_KR4_LEN, 180662306a36Sopenharmony_ci .mask_sup_width = MLXSW_SP_PORT_MASK_WIDTH_4X | 180762306a36Sopenharmony_ci MLXSW_SP_PORT_MASK_WIDTH_8X, 180862306a36Sopenharmony_ci .speed = SPEED_100000, 180962306a36Sopenharmony_ci .width = 4, 181062306a36Sopenharmony_ci }, 181162306a36Sopenharmony_ci { 181262306a36Sopenharmony_ci .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_100GAUI_2_100GBASE_CR2_KR2, 181362306a36Sopenharmony_ci .mask_ethtool = mlxsw_sp2_mask_ethtool_100gaui_2_100gbase_cr2_kr2, 181462306a36Sopenharmony_ci .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_100GAUI_2_100GBASE_CR2_KR2_LEN, 181562306a36Sopenharmony_ci .mask_sup_width = MLXSW_SP_PORT_MASK_WIDTH_2X, 181662306a36Sopenharmony_ci .speed = SPEED_100000, 181762306a36Sopenharmony_ci .width = 2, 181862306a36Sopenharmony_ci }, 181962306a36Sopenharmony_ci { 182062306a36Sopenharmony_ci .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_200GAUI_4_200GBASE_CR4_KR4, 182162306a36Sopenharmony_ci .mask_ethtool = mlxsw_sp2_mask_ethtool_200gaui_4_200gbase_cr4_kr4, 182262306a36Sopenharmony_ci .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_200GAUI_4_200GBASE_CR4_KR4_LEN, 182362306a36Sopenharmony_ci .mask_sup_width = MLXSW_SP_PORT_MASK_WIDTH_4X | 182462306a36Sopenharmony_ci MLXSW_SP_PORT_MASK_WIDTH_8X, 182562306a36Sopenharmony_ci .speed = SPEED_200000, 182662306a36Sopenharmony_ci .width = 4, 182762306a36Sopenharmony_ci }, 182862306a36Sopenharmony_ci { 182962306a36Sopenharmony_ci .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_400GAUI_8, 183062306a36Sopenharmony_ci .mask_ethtool = mlxsw_sp2_mask_ethtool_400gaui_8, 183162306a36Sopenharmony_ci .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_400GAUI_8_LEN, 183262306a36Sopenharmony_ci .mask_sup_width = MLXSW_SP_PORT_MASK_WIDTH_8X, 183362306a36Sopenharmony_ci .speed = SPEED_400000, 183462306a36Sopenharmony_ci .width = 8, 183562306a36Sopenharmony_ci }, 183662306a36Sopenharmony_ci { 183762306a36Sopenharmony_ci .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_800GAUI_8, 183862306a36Sopenharmony_ci .mask_ethtool = mlxsw_sp2_mask_ethtool_800gaui_8, 183962306a36Sopenharmony_ci .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_800GAUI_8_LEN, 184062306a36Sopenharmony_ci .mask_sup_width = MLXSW_SP_PORT_MASK_WIDTH_8X, 184162306a36Sopenharmony_ci .speed = SPEED_800000, 184262306a36Sopenharmony_ci .width = 8, 184362306a36Sopenharmony_ci }, 184462306a36Sopenharmony_ci}; 184562306a36Sopenharmony_ci 184662306a36Sopenharmony_ci#define MLXSW_SP2_PORT_LINK_MODE_LEN ARRAY_SIZE(mlxsw_sp2_port_link_mode) 184762306a36Sopenharmony_ci 184862306a36Sopenharmony_cistatic void 184962306a36Sopenharmony_cimlxsw_sp2_from_ptys_supported_port(struct mlxsw_sp *mlxsw_sp, 185062306a36Sopenharmony_ci u32 ptys_eth_proto, 185162306a36Sopenharmony_ci struct ethtool_link_ksettings *cmd) 185262306a36Sopenharmony_ci{ 185362306a36Sopenharmony_ci ethtool_link_ksettings_add_link_mode(cmd, supported, FIBRE); 185462306a36Sopenharmony_ci ethtool_link_ksettings_add_link_mode(cmd, supported, Backplane); 185562306a36Sopenharmony_ci} 185662306a36Sopenharmony_ci 185762306a36Sopenharmony_cistatic void 185862306a36Sopenharmony_cimlxsw_sp2_set_bit_ethtool(const struct mlxsw_sp2_port_link_mode *link_mode, 185962306a36Sopenharmony_ci unsigned long *mode) 186062306a36Sopenharmony_ci{ 186162306a36Sopenharmony_ci int i; 186262306a36Sopenharmony_ci 186362306a36Sopenharmony_ci for (i = 0; i < link_mode->m_ethtool_len; i++) 186462306a36Sopenharmony_ci __set_bit(link_mode->mask_ethtool[i], mode); 186562306a36Sopenharmony_ci} 186662306a36Sopenharmony_ci 186762306a36Sopenharmony_cistatic void 186862306a36Sopenharmony_cimlxsw_sp2_from_ptys_link(struct mlxsw_sp *mlxsw_sp, u32 ptys_eth_proto, 186962306a36Sopenharmony_ci unsigned long *mode) 187062306a36Sopenharmony_ci{ 187162306a36Sopenharmony_ci int i; 187262306a36Sopenharmony_ci 187362306a36Sopenharmony_ci for (i = 0; i < MLXSW_SP2_PORT_LINK_MODE_LEN; i++) { 187462306a36Sopenharmony_ci if (ptys_eth_proto & mlxsw_sp2_port_link_mode[i].mask) 187562306a36Sopenharmony_ci mlxsw_sp2_set_bit_ethtool(&mlxsw_sp2_port_link_mode[i], 187662306a36Sopenharmony_ci mode); 187762306a36Sopenharmony_ci } 187862306a36Sopenharmony_ci} 187962306a36Sopenharmony_ci 188062306a36Sopenharmony_cistatic u32 188162306a36Sopenharmony_cimlxsw_sp2_from_ptys_speed(struct mlxsw_sp *mlxsw_sp, u32 ptys_eth_proto) 188262306a36Sopenharmony_ci{ 188362306a36Sopenharmony_ci int i; 188462306a36Sopenharmony_ci 188562306a36Sopenharmony_ci for (i = 0; i < MLXSW_SP2_PORT_LINK_MODE_LEN; i++) { 188662306a36Sopenharmony_ci if (ptys_eth_proto & mlxsw_sp2_port_link_mode[i].mask) 188762306a36Sopenharmony_ci return mlxsw_sp2_port_link_mode[i].speed; 188862306a36Sopenharmony_ci } 188962306a36Sopenharmony_ci 189062306a36Sopenharmony_ci return SPEED_UNKNOWN; 189162306a36Sopenharmony_ci} 189262306a36Sopenharmony_ci 189362306a36Sopenharmony_cistatic void 189462306a36Sopenharmony_cimlxsw_sp2_from_ptys_link_mode(struct mlxsw_sp *mlxsw_sp, bool carrier_ok, 189562306a36Sopenharmony_ci u32 ptys_eth_proto, 189662306a36Sopenharmony_ci struct ethtool_link_ksettings *cmd) 189762306a36Sopenharmony_ci{ 189862306a36Sopenharmony_ci struct mlxsw_sp2_port_link_mode link; 189962306a36Sopenharmony_ci int i; 190062306a36Sopenharmony_ci 190162306a36Sopenharmony_ci cmd->base.speed = SPEED_UNKNOWN; 190262306a36Sopenharmony_ci cmd->base.duplex = DUPLEX_UNKNOWN; 190362306a36Sopenharmony_ci cmd->lanes = 0; 190462306a36Sopenharmony_ci 190562306a36Sopenharmony_ci if (!carrier_ok) 190662306a36Sopenharmony_ci return; 190762306a36Sopenharmony_ci 190862306a36Sopenharmony_ci for (i = 0; i < MLXSW_SP2_PORT_LINK_MODE_LEN; i++) { 190962306a36Sopenharmony_ci if (ptys_eth_proto & mlxsw_sp2_port_link_mode[i].mask) { 191062306a36Sopenharmony_ci link = mlxsw_sp2_port_link_mode[i]; 191162306a36Sopenharmony_ci ethtool_params_from_link_mode(cmd, 191262306a36Sopenharmony_ci link.mask_ethtool[1]); 191362306a36Sopenharmony_ci } 191462306a36Sopenharmony_ci } 191562306a36Sopenharmony_ci} 191662306a36Sopenharmony_ci 191762306a36Sopenharmony_cistatic int mlxsw_sp2_ptys_max_speed(struct mlxsw_sp_port *mlxsw_sp_port, u32 *p_max_speed) 191862306a36Sopenharmony_ci{ 191962306a36Sopenharmony_ci u32 eth_proto_cap; 192062306a36Sopenharmony_ci u32 max_speed = 0; 192162306a36Sopenharmony_ci int err; 192262306a36Sopenharmony_ci int i; 192362306a36Sopenharmony_ci 192462306a36Sopenharmony_ci err = mlxsw_sp_port_ptys_query(mlxsw_sp_port, ð_proto_cap, NULL, NULL, NULL); 192562306a36Sopenharmony_ci if (err) 192662306a36Sopenharmony_ci return err; 192762306a36Sopenharmony_ci 192862306a36Sopenharmony_ci for (i = 0; i < MLXSW_SP2_PORT_LINK_MODE_LEN; i++) { 192962306a36Sopenharmony_ci if ((eth_proto_cap & mlxsw_sp2_port_link_mode[i].mask) && 193062306a36Sopenharmony_ci mlxsw_sp2_port_link_mode[i].speed > max_speed) 193162306a36Sopenharmony_ci max_speed = mlxsw_sp2_port_link_mode[i].speed; 193262306a36Sopenharmony_ci } 193362306a36Sopenharmony_ci 193462306a36Sopenharmony_ci *p_max_speed = max_speed; 193562306a36Sopenharmony_ci return 0; 193662306a36Sopenharmony_ci} 193762306a36Sopenharmony_ci 193862306a36Sopenharmony_cistatic bool 193962306a36Sopenharmony_cimlxsw_sp2_test_bit_ethtool(const struct mlxsw_sp2_port_link_mode *link_mode, 194062306a36Sopenharmony_ci const unsigned long *mode) 194162306a36Sopenharmony_ci{ 194262306a36Sopenharmony_ci int cnt = 0; 194362306a36Sopenharmony_ci int i; 194462306a36Sopenharmony_ci 194562306a36Sopenharmony_ci for (i = 0; i < link_mode->m_ethtool_len; i++) { 194662306a36Sopenharmony_ci if (test_bit(link_mode->mask_ethtool[i], mode)) 194762306a36Sopenharmony_ci cnt++; 194862306a36Sopenharmony_ci } 194962306a36Sopenharmony_ci 195062306a36Sopenharmony_ci return cnt == link_mode->m_ethtool_len; 195162306a36Sopenharmony_ci} 195262306a36Sopenharmony_ci 195362306a36Sopenharmony_cistatic u32 195462306a36Sopenharmony_cimlxsw_sp2_to_ptys_advert_link(struct mlxsw_sp *mlxsw_sp, 195562306a36Sopenharmony_ci const struct ethtool_link_ksettings *cmd) 195662306a36Sopenharmony_ci{ 195762306a36Sopenharmony_ci u32 ptys_proto = 0; 195862306a36Sopenharmony_ci int i; 195962306a36Sopenharmony_ci 196062306a36Sopenharmony_ci for (i = 0; i < MLXSW_SP2_PORT_LINK_MODE_LEN; i++) { 196162306a36Sopenharmony_ci if (mlxsw_sp2_test_bit_ethtool(&mlxsw_sp2_port_link_mode[i], 196262306a36Sopenharmony_ci cmd->link_modes.advertising)) 196362306a36Sopenharmony_ci ptys_proto |= mlxsw_sp2_port_link_mode[i].mask; 196462306a36Sopenharmony_ci } 196562306a36Sopenharmony_ci return ptys_proto; 196662306a36Sopenharmony_ci} 196762306a36Sopenharmony_ci 196862306a36Sopenharmony_cistatic u32 mlxsw_sp2_to_ptys_speed_lanes(struct mlxsw_sp *mlxsw_sp, u8 width, 196962306a36Sopenharmony_ci const struct ethtool_link_ksettings *cmd) 197062306a36Sopenharmony_ci{ 197162306a36Sopenharmony_ci u8 mask_width = mlxsw_sp_port_mask_width_get(width); 197262306a36Sopenharmony_ci struct mlxsw_sp2_port_link_mode link_mode; 197362306a36Sopenharmony_ci u32 ptys_proto = 0; 197462306a36Sopenharmony_ci int i; 197562306a36Sopenharmony_ci 197662306a36Sopenharmony_ci if (cmd->lanes > width) 197762306a36Sopenharmony_ci return ptys_proto; 197862306a36Sopenharmony_ci 197962306a36Sopenharmony_ci for (i = 0; i < MLXSW_SP2_PORT_LINK_MODE_LEN; i++) { 198062306a36Sopenharmony_ci if (cmd->base.speed == mlxsw_sp2_port_link_mode[i].speed) { 198162306a36Sopenharmony_ci link_mode = mlxsw_sp2_port_link_mode[i]; 198262306a36Sopenharmony_ci 198362306a36Sopenharmony_ci if (!cmd->lanes) { 198462306a36Sopenharmony_ci /* If number of lanes was not set by user space, 198562306a36Sopenharmony_ci * choose the link mode that supports the width 198662306a36Sopenharmony_ci * of the port. 198762306a36Sopenharmony_ci */ 198862306a36Sopenharmony_ci if (mask_width & link_mode.mask_sup_width) 198962306a36Sopenharmony_ci ptys_proto |= link_mode.mask; 199062306a36Sopenharmony_ci } else if (cmd->lanes == link_mode.width) { 199162306a36Sopenharmony_ci /* Else if the number of lanes was set, choose 199262306a36Sopenharmony_ci * the link mode that its actual width equals to 199362306a36Sopenharmony_ci * it. 199462306a36Sopenharmony_ci */ 199562306a36Sopenharmony_ci ptys_proto |= link_mode.mask; 199662306a36Sopenharmony_ci } 199762306a36Sopenharmony_ci } 199862306a36Sopenharmony_ci } 199962306a36Sopenharmony_ci return ptys_proto; 200062306a36Sopenharmony_ci} 200162306a36Sopenharmony_ci 200262306a36Sopenharmony_cistatic void 200362306a36Sopenharmony_cimlxsw_sp2_reg_ptys_eth_pack(struct mlxsw_sp *mlxsw_sp, char *payload, 200462306a36Sopenharmony_ci u16 local_port, u32 proto_admin, 200562306a36Sopenharmony_ci bool autoneg) 200662306a36Sopenharmony_ci{ 200762306a36Sopenharmony_ci mlxsw_reg_ptys_ext_eth_pack(payload, local_port, proto_admin, autoneg); 200862306a36Sopenharmony_ci} 200962306a36Sopenharmony_ci 201062306a36Sopenharmony_cistatic void 201162306a36Sopenharmony_cimlxsw_sp2_reg_ptys_eth_unpack(struct mlxsw_sp *mlxsw_sp, char *payload, 201262306a36Sopenharmony_ci u32 *p_eth_proto_cap, u32 *p_eth_proto_admin, 201362306a36Sopenharmony_ci u32 *p_eth_proto_oper) 201462306a36Sopenharmony_ci{ 201562306a36Sopenharmony_ci mlxsw_reg_ptys_ext_eth_unpack(payload, p_eth_proto_cap, 201662306a36Sopenharmony_ci p_eth_proto_admin, p_eth_proto_oper); 201762306a36Sopenharmony_ci} 201862306a36Sopenharmony_ci 201962306a36Sopenharmony_cistatic u32 mlxsw_sp2_ptys_proto_cap_masked_get(u32 eth_proto_cap) 202062306a36Sopenharmony_ci{ 202162306a36Sopenharmony_ci u32 ptys_proto_cap_masked = 0; 202262306a36Sopenharmony_ci int i; 202362306a36Sopenharmony_ci 202462306a36Sopenharmony_ci for (i = 0; i < MLXSW_SP2_PORT_LINK_MODE_LEN; i++) { 202562306a36Sopenharmony_ci if (mlxsw_sp2_port_link_mode[i].mask & eth_proto_cap) 202662306a36Sopenharmony_ci ptys_proto_cap_masked |= 202762306a36Sopenharmony_ci mlxsw_sp2_port_link_mode[i].mask; 202862306a36Sopenharmony_ci } 202962306a36Sopenharmony_ci 203062306a36Sopenharmony_ci return ptys_proto_cap_masked; 203162306a36Sopenharmony_ci} 203262306a36Sopenharmony_ci 203362306a36Sopenharmony_ciconst struct mlxsw_sp_port_type_speed_ops mlxsw_sp2_port_type_speed_ops = { 203462306a36Sopenharmony_ci .from_ptys_supported_port = mlxsw_sp2_from_ptys_supported_port, 203562306a36Sopenharmony_ci .from_ptys_link = mlxsw_sp2_from_ptys_link, 203662306a36Sopenharmony_ci .from_ptys_speed = mlxsw_sp2_from_ptys_speed, 203762306a36Sopenharmony_ci .from_ptys_link_mode = mlxsw_sp2_from_ptys_link_mode, 203862306a36Sopenharmony_ci .ptys_max_speed = mlxsw_sp2_ptys_max_speed, 203962306a36Sopenharmony_ci .to_ptys_advert_link = mlxsw_sp2_to_ptys_advert_link, 204062306a36Sopenharmony_ci .to_ptys_speed_lanes = mlxsw_sp2_to_ptys_speed_lanes, 204162306a36Sopenharmony_ci .reg_ptys_eth_pack = mlxsw_sp2_reg_ptys_eth_pack, 204262306a36Sopenharmony_ci .reg_ptys_eth_unpack = mlxsw_sp2_reg_ptys_eth_unpack, 204362306a36Sopenharmony_ci .ptys_proto_cap_masked_get = mlxsw_sp2_ptys_proto_cap_masked_get, 204462306a36Sopenharmony_ci}; 2045