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, &eth_proto_cap, &eth_proto_admin,
96362306a36Sopenharmony_ci				       &eth_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, &eth_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, &eth_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, &eth_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