1614d509aSAmit Cohen // SPDX-License-Identifier: BSD-3-Clause OR GPL-2.0
2614d509aSAmit Cohen /* Copyright (c) 2020 Mellanox Technologies. All rights reserved */
3614d509aSAmit Cohen
4614d509aSAmit Cohen #include "reg.h"
569f6d4eeSAmit Cohen #include "core.h"
6614d509aSAmit Cohen #include "spectrum.h"
7614d509aSAmit Cohen #include "core_env.h"
8614d509aSAmit Cohen
9614d509aSAmit Cohen static const char mlxsw_sp_driver_version[] = "1.0";
10614d509aSAmit Cohen
mlxsw_sp_port_get_drvinfo(struct net_device * dev,struct ethtool_drvinfo * drvinfo)11614d509aSAmit Cohen static void mlxsw_sp_port_get_drvinfo(struct net_device *dev,
12614d509aSAmit Cohen struct ethtool_drvinfo *drvinfo)
13614d509aSAmit Cohen {
14614d509aSAmit Cohen struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
15614d509aSAmit Cohen struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
16614d509aSAmit Cohen
17f029c781SWolfram Sang strscpy(drvinfo->driver, mlxsw_sp->bus_info->device_kind,
18614d509aSAmit Cohen sizeof(drvinfo->driver));
19f029c781SWolfram Sang strscpy(drvinfo->version, mlxsw_sp_driver_version,
20614d509aSAmit Cohen sizeof(drvinfo->version));
21614d509aSAmit Cohen snprintf(drvinfo->fw_version, sizeof(drvinfo->fw_version),
22614d509aSAmit Cohen "%d.%d.%d",
23614d509aSAmit Cohen mlxsw_sp->bus_info->fw_rev.major,
24614d509aSAmit Cohen mlxsw_sp->bus_info->fw_rev.minor,
25614d509aSAmit Cohen mlxsw_sp->bus_info->fw_rev.subminor);
26f029c781SWolfram Sang strscpy(drvinfo->bus_info, mlxsw_sp->bus_info->device_name,
27614d509aSAmit Cohen sizeof(drvinfo->bus_info));
28614d509aSAmit Cohen }
29614d509aSAmit Cohen
3060f30cd6SAmit Cohen struct mlxsw_sp_ethtool_link_ext_state_opcode_mapping {
3160f30cd6SAmit Cohen u32 status_opcode;
3260f30cd6SAmit Cohen enum ethtool_link_ext_state link_ext_state;
3360f30cd6SAmit Cohen u8 link_ext_substate;
3460f30cd6SAmit Cohen };
3560f30cd6SAmit Cohen
3660f30cd6SAmit Cohen static const struct mlxsw_sp_ethtool_link_ext_state_opcode_mapping
3760f30cd6SAmit Cohen mlxsw_sp_link_ext_state_opcode_map[] = {
3860f30cd6SAmit Cohen {2, ETHTOOL_LINK_EXT_STATE_AUTONEG,
3960f30cd6SAmit Cohen ETHTOOL_LINK_EXT_SUBSTATE_AN_NO_PARTNER_DETECTED},
4060f30cd6SAmit Cohen {3, ETHTOOL_LINK_EXT_STATE_AUTONEG,
4160f30cd6SAmit Cohen ETHTOOL_LINK_EXT_SUBSTATE_AN_ACK_NOT_RECEIVED},
4260f30cd6SAmit Cohen {4, ETHTOOL_LINK_EXT_STATE_AUTONEG,
4360f30cd6SAmit Cohen ETHTOOL_LINK_EXT_SUBSTATE_AN_NEXT_PAGE_EXCHANGE_FAILED},
4460f30cd6SAmit Cohen {36, ETHTOOL_LINK_EXT_STATE_AUTONEG,
4560f30cd6SAmit Cohen ETHTOOL_LINK_EXT_SUBSTATE_AN_NO_PARTNER_DETECTED_FORCE_MODE},
4660f30cd6SAmit Cohen {38, ETHTOOL_LINK_EXT_STATE_AUTONEG,
4760f30cd6SAmit Cohen ETHTOOL_LINK_EXT_SUBSTATE_AN_FEC_MISMATCH_DURING_OVERRIDE},
4860f30cd6SAmit Cohen {39, ETHTOOL_LINK_EXT_STATE_AUTONEG,
4960f30cd6SAmit Cohen ETHTOOL_LINK_EXT_SUBSTATE_AN_NO_HCD},
5060f30cd6SAmit Cohen
5160f30cd6SAmit Cohen {5, ETHTOOL_LINK_EXT_STATE_LINK_TRAINING_FAILURE,
5260f30cd6SAmit Cohen ETHTOOL_LINK_EXT_SUBSTATE_LT_KR_FRAME_LOCK_NOT_ACQUIRED},
5360f30cd6SAmit Cohen {6, ETHTOOL_LINK_EXT_STATE_LINK_TRAINING_FAILURE,
5460f30cd6SAmit Cohen ETHTOOL_LINK_EXT_SUBSTATE_LT_KR_LINK_INHIBIT_TIMEOUT},
5560f30cd6SAmit Cohen {7, ETHTOOL_LINK_EXT_STATE_LINK_TRAINING_FAILURE,
5660f30cd6SAmit Cohen ETHTOOL_LINK_EXT_SUBSTATE_LT_KR_LINK_PARTNER_DID_NOT_SET_RECEIVER_READY},
5760f30cd6SAmit Cohen {8, ETHTOOL_LINK_EXT_STATE_LINK_TRAINING_FAILURE, 0},
5860f30cd6SAmit Cohen {14, ETHTOOL_LINK_EXT_STATE_LINK_TRAINING_FAILURE,
5960f30cd6SAmit Cohen ETHTOOL_LINK_EXT_SUBSTATE_LT_REMOTE_FAULT},
6060f30cd6SAmit Cohen
6160f30cd6SAmit Cohen {9, ETHTOOL_LINK_EXT_STATE_LINK_LOGICAL_MISMATCH,
6260f30cd6SAmit Cohen ETHTOOL_LINK_EXT_SUBSTATE_LLM_PCS_DID_NOT_ACQUIRE_BLOCK_LOCK},
6360f30cd6SAmit Cohen {10, ETHTOOL_LINK_EXT_STATE_LINK_LOGICAL_MISMATCH,
6460f30cd6SAmit Cohen ETHTOOL_LINK_EXT_SUBSTATE_LLM_PCS_DID_NOT_ACQUIRE_AM_LOCK},
6560f30cd6SAmit Cohen {11, ETHTOOL_LINK_EXT_STATE_LINK_LOGICAL_MISMATCH,
6660f30cd6SAmit Cohen ETHTOOL_LINK_EXT_SUBSTATE_LLM_PCS_DID_NOT_GET_ALIGN_STATUS},
6760f30cd6SAmit Cohen {12, ETHTOOL_LINK_EXT_STATE_LINK_LOGICAL_MISMATCH,
6860f30cd6SAmit Cohen ETHTOOL_LINK_EXT_SUBSTATE_LLM_FC_FEC_IS_NOT_LOCKED},
6960f30cd6SAmit Cohen {13, ETHTOOL_LINK_EXT_STATE_LINK_LOGICAL_MISMATCH,
7060f30cd6SAmit Cohen ETHTOOL_LINK_EXT_SUBSTATE_LLM_RS_FEC_IS_NOT_LOCKED},
7160f30cd6SAmit Cohen
7260f30cd6SAmit Cohen {15, ETHTOOL_LINK_EXT_STATE_BAD_SIGNAL_INTEGRITY, 0},
7360f30cd6SAmit Cohen {17, ETHTOOL_LINK_EXT_STATE_BAD_SIGNAL_INTEGRITY,
7460f30cd6SAmit Cohen ETHTOOL_LINK_EXT_SUBSTATE_BSI_LARGE_NUMBER_OF_PHYSICAL_ERRORS},
7560f30cd6SAmit Cohen {42, ETHTOOL_LINK_EXT_STATE_BAD_SIGNAL_INTEGRITY,
7660f30cd6SAmit Cohen ETHTOOL_LINK_EXT_SUBSTATE_BSI_UNSUPPORTED_RATE},
7760f30cd6SAmit Cohen
7860f30cd6SAmit Cohen {1024, ETHTOOL_LINK_EXT_STATE_NO_CABLE, 0},
7960f30cd6SAmit Cohen
8060f30cd6SAmit Cohen {16, ETHTOOL_LINK_EXT_STATE_CABLE_ISSUE,
8160f30cd6SAmit Cohen ETHTOOL_LINK_EXT_SUBSTATE_CI_UNSUPPORTED_CABLE},
8260f30cd6SAmit Cohen {20, ETHTOOL_LINK_EXT_STATE_CABLE_ISSUE,
8360f30cd6SAmit Cohen ETHTOOL_LINK_EXT_SUBSTATE_CI_UNSUPPORTED_CABLE},
8460f30cd6SAmit Cohen {29, ETHTOOL_LINK_EXT_STATE_CABLE_ISSUE,
8560f30cd6SAmit Cohen ETHTOOL_LINK_EXT_SUBSTATE_CI_UNSUPPORTED_CABLE},
8660f30cd6SAmit Cohen {1025, ETHTOOL_LINK_EXT_STATE_CABLE_ISSUE,
8760f30cd6SAmit Cohen ETHTOOL_LINK_EXT_SUBSTATE_CI_UNSUPPORTED_CABLE},
8860f30cd6SAmit Cohen {1029, ETHTOOL_LINK_EXT_STATE_CABLE_ISSUE,
8960f30cd6SAmit Cohen ETHTOOL_LINK_EXT_SUBSTATE_CI_UNSUPPORTED_CABLE},
9060f30cd6SAmit Cohen {1031, ETHTOOL_LINK_EXT_STATE_CABLE_ISSUE, 0},
9160f30cd6SAmit Cohen
9260f30cd6SAmit Cohen {1027, ETHTOOL_LINK_EXT_STATE_EEPROM_ISSUE, 0},
9360f30cd6SAmit Cohen
9460f30cd6SAmit Cohen {23, ETHTOOL_LINK_EXT_STATE_CALIBRATION_FAILURE, 0},
9560f30cd6SAmit Cohen
9660f30cd6SAmit Cohen {1032, ETHTOOL_LINK_EXT_STATE_POWER_BUDGET_EXCEEDED, 0},
9760f30cd6SAmit Cohen
9860f30cd6SAmit Cohen {1030, ETHTOOL_LINK_EXT_STATE_OVERHEAT, 0},
99235dbbecSIdo Schimmel
100235dbbecSIdo Schimmel {1042, ETHTOOL_LINK_EXT_STATE_MODULE,
101235dbbecSIdo Schimmel ETHTOOL_LINK_EXT_SUBSTATE_MODULE_CMIS_NOT_READY},
10260f30cd6SAmit Cohen };
10360f30cd6SAmit Cohen
10460f30cd6SAmit Cohen static void
mlxsw_sp_port_set_link_ext_state(struct mlxsw_sp_ethtool_link_ext_state_opcode_mapping link_ext_state_mapping,struct ethtool_link_ext_state_info * link_ext_state_info)10560f30cd6SAmit Cohen mlxsw_sp_port_set_link_ext_state(struct mlxsw_sp_ethtool_link_ext_state_opcode_mapping
10660f30cd6SAmit Cohen link_ext_state_mapping,
10760f30cd6SAmit Cohen struct ethtool_link_ext_state_info *link_ext_state_info)
10860f30cd6SAmit Cohen {
10960f30cd6SAmit Cohen switch (link_ext_state_mapping.link_ext_state) {
11060f30cd6SAmit Cohen case ETHTOOL_LINK_EXT_STATE_AUTONEG:
11160f30cd6SAmit Cohen link_ext_state_info->autoneg =
11260f30cd6SAmit Cohen link_ext_state_mapping.link_ext_substate;
11360f30cd6SAmit Cohen break;
11460f30cd6SAmit Cohen case ETHTOOL_LINK_EXT_STATE_LINK_TRAINING_FAILURE:
11560f30cd6SAmit Cohen link_ext_state_info->link_training =
11660f30cd6SAmit Cohen link_ext_state_mapping.link_ext_substate;
11760f30cd6SAmit Cohen break;
11860f30cd6SAmit Cohen case ETHTOOL_LINK_EXT_STATE_LINK_LOGICAL_MISMATCH:
11960f30cd6SAmit Cohen link_ext_state_info->link_logical_mismatch =
12060f30cd6SAmit Cohen link_ext_state_mapping.link_ext_substate;
12160f30cd6SAmit Cohen break;
12260f30cd6SAmit Cohen case ETHTOOL_LINK_EXT_STATE_BAD_SIGNAL_INTEGRITY:
12360f30cd6SAmit Cohen link_ext_state_info->bad_signal_integrity =
12460f30cd6SAmit Cohen link_ext_state_mapping.link_ext_substate;
12560f30cd6SAmit Cohen break;
12660f30cd6SAmit Cohen case ETHTOOL_LINK_EXT_STATE_CABLE_ISSUE:
12760f30cd6SAmit Cohen link_ext_state_info->cable_issue =
12860f30cd6SAmit Cohen link_ext_state_mapping.link_ext_substate;
12960f30cd6SAmit Cohen break;
130235dbbecSIdo Schimmel case ETHTOOL_LINK_EXT_STATE_MODULE:
131235dbbecSIdo Schimmel link_ext_state_info->module =
132235dbbecSIdo Schimmel link_ext_state_mapping.link_ext_substate;
133235dbbecSIdo Schimmel break;
13460f30cd6SAmit Cohen default:
13560f30cd6SAmit Cohen break;
13660f30cd6SAmit Cohen }
13760f30cd6SAmit Cohen
13860f30cd6SAmit Cohen link_ext_state_info->link_ext_state = link_ext_state_mapping.link_ext_state;
13960f30cd6SAmit Cohen }
14060f30cd6SAmit Cohen
14160f30cd6SAmit Cohen static int
mlxsw_sp_port_get_link_ext_state(struct net_device * dev,struct ethtool_link_ext_state_info * link_ext_state_info)14260f30cd6SAmit Cohen mlxsw_sp_port_get_link_ext_state(struct net_device *dev,
14360f30cd6SAmit Cohen struct ethtool_link_ext_state_info *link_ext_state_info)
14460f30cd6SAmit Cohen {
14560f30cd6SAmit Cohen struct mlxsw_sp_ethtool_link_ext_state_opcode_mapping link_ext_state_mapping;
14660f30cd6SAmit Cohen struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
14760f30cd6SAmit Cohen char pddr_pl[MLXSW_REG_PDDR_LEN];
14860f30cd6SAmit Cohen int opcode, err, i;
14960f30cd6SAmit Cohen u32 status_opcode;
15060f30cd6SAmit Cohen
15160f30cd6SAmit Cohen if (netif_carrier_ok(dev))
15260f30cd6SAmit Cohen return -ENODATA;
15360f30cd6SAmit Cohen
15460f30cd6SAmit Cohen mlxsw_reg_pddr_pack(pddr_pl, mlxsw_sp_port->local_port,
15560f30cd6SAmit Cohen MLXSW_REG_PDDR_PAGE_SELECT_TROUBLESHOOTING_INFO);
15660f30cd6SAmit Cohen
15760f30cd6SAmit Cohen opcode = MLXSW_REG_PDDR_TRBLSH_GROUP_OPCODE_MONITOR;
15860f30cd6SAmit Cohen mlxsw_reg_pddr_trblsh_group_opcode_set(pddr_pl, opcode);
15960f30cd6SAmit Cohen
16060f30cd6SAmit Cohen err = mlxsw_reg_query(mlxsw_sp_port->mlxsw_sp->core, MLXSW_REG(pddr),
16160f30cd6SAmit Cohen pddr_pl);
16260f30cd6SAmit Cohen if (err)
16360f30cd6SAmit Cohen return err;
16460f30cd6SAmit Cohen
16560f30cd6SAmit Cohen status_opcode = mlxsw_reg_pddr_trblsh_status_opcode_get(pddr_pl);
16660f30cd6SAmit Cohen if (!status_opcode)
16760f30cd6SAmit Cohen return -ENODATA;
16860f30cd6SAmit Cohen
16960f30cd6SAmit Cohen for (i = 0; i < ARRAY_SIZE(mlxsw_sp_link_ext_state_opcode_map); i++) {
17060f30cd6SAmit Cohen link_ext_state_mapping = mlxsw_sp_link_ext_state_opcode_map[i];
17160f30cd6SAmit Cohen if (link_ext_state_mapping.status_opcode == status_opcode) {
17260f30cd6SAmit Cohen mlxsw_sp_port_set_link_ext_state(link_ext_state_mapping,
17360f30cd6SAmit Cohen link_ext_state_info);
17460f30cd6SAmit Cohen return 0;
17560f30cd6SAmit Cohen }
17660f30cd6SAmit Cohen }
17760f30cd6SAmit Cohen
17860f30cd6SAmit Cohen return -ENODATA;
17960f30cd6SAmit Cohen }
18060f30cd6SAmit Cohen
mlxsw_sp_port_get_pauseparam(struct net_device * dev,struct ethtool_pauseparam * pause)181614d509aSAmit Cohen static void mlxsw_sp_port_get_pauseparam(struct net_device *dev,
182614d509aSAmit Cohen struct ethtool_pauseparam *pause)
183614d509aSAmit Cohen {
184614d509aSAmit Cohen struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
185614d509aSAmit Cohen
186614d509aSAmit Cohen pause->rx_pause = mlxsw_sp_port->link.rx_pause;
187614d509aSAmit Cohen pause->tx_pause = mlxsw_sp_port->link.tx_pause;
188614d509aSAmit Cohen }
189614d509aSAmit Cohen
mlxsw_sp_port_pause_set(struct mlxsw_sp_port * mlxsw_sp_port,struct ethtool_pauseparam * pause)190614d509aSAmit Cohen static int mlxsw_sp_port_pause_set(struct mlxsw_sp_port *mlxsw_sp_port,
191614d509aSAmit Cohen struct ethtool_pauseparam *pause)
192614d509aSAmit Cohen {
193614d509aSAmit Cohen char pfcc_pl[MLXSW_REG_PFCC_LEN];
194614d509aSAmit Cohen
195614d509aSAmit Cohen mlxsw_reg_pfcc_pack(pfcc_pl, mlxsw_sp_port->local_port);
196614d509aSAmit Cohen mlxsw_reg_pfcc_pprx_set(pfcc_pl, pause->rx_pause);
197614d509aSAmit Cohen mlxsw_reg_pfcc_pptx_set(pfcc_pl, pause->tx_pause);
198614d509aSAmit Cohen
199614d509aSAmit Cohen return mlxsw_reg_write(mlxsw_sp_port->mlxsw_sp->core, MLXSW_REG(pfcc),
200614d509aSAmit Cohen pfcc_pl);
201614d509aSAmit Cohen }
202614d509aSAmit Cohen
203b7e07bbdSPetr Machata /* Maximum delay buffer needed in case of PAUSE frames. Similar to PFC delay, but is
204b7e07bbdSPetr Machata * measured in bytes. Assumes 100m cable and does not take into account MTU.
205b7e07bbdSPetr Machata */
206b7e07bbdSPetr Machata #define MLXSW_SP_PAUSE_DELAY_BYTES 19476
207b7e07bbdSPetr Machata
mlxsw_sp_port_set_pauseparam(struct net_device * dev,struct ethtool_pauseparam * pause)208614d509aSAmit Cohen static int mlxsw_sp_port_set_pauseparam(struct net_device *dev,
209614d509aSAmit Cohen struct ethtool_pauseparam *pause)
210614d509aSAmit Cohen {
211614d509aSAmit Cohen struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
212614d509aSAmit Cohen bool pause_en = pause->tx_pause || pause->rx_pause;
213b7e07bbdSPetr Machata struct mlxsw_sp_hdroom orig_hdroom;
214b7e07bbdSPetr Machata struct mlxsw_sp_hdroom hdroom;
215ca21e84eSPetr Machata int prio;
216614d509aSAmit Cohen int err;
217614d509aSAmit Cohen
218614d509aSAmit Cohen if (mlxsw_sp_port->dcb.pfc && mlxsw_sp_port->dcb.pfc->pfc_en) {
219614d509aSAmit Cohen netdev_err(dev, "PFC already enabled on port\n");
220614d509aSAmit Cohen return -EINVAL;
221614d509aSAmit Cohen }
222614d509aSAmit Cohen
223614d509aSAmit Cohen if (pause->autoneg) {
224614d509aSAmit Cohen netdev_err(dev, "PAUSE frames autonegotiation isn't supported\n");
225614d509aSAmit Cohen return -EINVAL;
226614d509aSAmit Cohen }
227614d509aSAmit Cohen
228b7e07bbdSPetr Machata orig_hdroom = *mlxsw_sp_port->hdroom;
229b7e07bbdSPetr Machata
230b7e07bbdSPetr Machata hdroom = orig_hdroom;
231b7e07bbdSPetr Machata if (pause_en)
232b7e07bbdSPetr Machata hdroom.delay_bytes = MLXSW_SP_PAUSE_DELAY_BYTES;
233b7e07bbdSPetr Machata else
234b7e07bbdSPetr Machata hdroom.delay_bytes = 0;
235b7e07bbdSPetr Machata
236ca21e84eSPetr Machata for (prio = 0; prio < IEEE_8021QAZ_MAX_TCS; prio++)
237ca21e84eSPetr Machata hdroom.prios.prio[prio].lossy = !pause_en;
238ca21e84eSPetr Machata
239ca21e84eSPetr Machata mlxsw_sp_hdroom_bufs_reset_lossiness(&hdroom);
2402d9f703fSPetr Machata mlxsw_sp_hdroom_bufs_reset_sizes(mlxsw_sp_port, &hdroom);
241ca21e84eSPetr Machata
2422d9f703fSPetr Machata err = mlxsw_sp_hdroom_configure(mlxsw_sp_port, &hdroom);
243614d509aSAmit Cohen if (err) {
244614d509aSAmit Cohen netdev_err(dev, "Failed to configure port's headroom\n");
245614d509aSAmit Cohen return err;
246614d509aSAmit Cohen }
247614d509aSAmit Cohen
248614d509aSAmit Cohen err = mlxsw_sp_port_pause_set(mlxsw_sp_port, pause);
249614d509aSAmit Cohen if (err) {
250614d509aSAmit Cohen netdev_err(dev, "Failed to set PAUSE parameters\n");
251614d509aSAmit Cohen goto err_port_pause_configure;
252614d509aSAmit Cohen }
253614d509aSAmit Cohen
254614d509aSAmit Cohen mlxsw_sp_port->link.rx_pause = pause->rx_pause;
255614d509aSAmit Cohen mlxsw_sp_port->link.tx_pause = pause->tx_pause;
256614d509aSAmit Cohen
257614d509aSAmit Cohen return 0;
258614d509aSAmit Cohen
259614d509aSAmit Cohen err_port_pause_configure:
2602d9f703fSPetr Machata mlxsw_sp_hdroom_configure(mlxsw_sp_port, &orig_hdroom);
261614d509aSAmit Cohen return err;
262614d509aSAmit Cohen }
263614d509aSAmit Cohen
264614d509aSAmit Cohen struct mlxsw_sp_port_hw_stats {
265614d509aSAmit Cohen char str[ETH_GSTRING_LEN];
266614d509aSAmit Cohen u64 (*getter)(const char *payload);
267614d509aSAmit Cohen bool cells_bytes;
268614d509aSAmit Cohen };
269614d509aSAmit Cohen
270614d509aSAmit Cohen static struct mlxsw_sp_port_hw_stats mlxsw_sp_port_hw_stats[] = {
271614d509aSAmit Cohen {
272614d509aSAmit Cohen .str = "a_frames_transmitted_ok",
273614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_a_frames_transmitted_ok_get,
274614d509aSAmit Cohen },
275614d509aSAmit Cohen {
276614d509aSAmit Cohen .str = "a_frames_received_ok",
277614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_a_frames_received_ok_get,
278614d509aSAmit Cohen },
279614d509aSAmit Cohen {
280614d509aSAmit Cohen .str = "a_frame_check_sequence_errors",
281614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_a_frame_check_sequence_errors_get,
282614d509aSAmit Cohen },
283614d509aSAmit Cohen {
284614d509aSAmit Cohen .str = "a_alignment_errors",
285614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_a_alignment_errors_get,
286614d509aSAmit Cohen },
287614d509aSAmit Cohen {
288614d509aSAmit Cohen .str = "a_octets_transmitted_ok",
289614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_a_octets_transmitted_ok_get,
290614d509aSAmit Cohen },
291614d509aSAmit Cohen {
292614d509aSAmit Cohen .str = "a_octets_received_ok",
293614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_a_octets_received_ok_get,
294614d509aSAmit Cohen },
295614d509aSAmit Cohen {
296614d509aSAmit Cohen .str = "a_multicast_frames_xmitted_ok",
297614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_a_multicast_frames_xmitted_ok_get,
298614d509aSAmit Cohen },
299614d509aSAmit Cohen {
300614d509aSAmit Cohen .str = "a_broadcast_frames_xmitted_ok",
301614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_a_broadcast_frames_xmitted_ok_get,
302614d509aSAmit Cohen },
303614d509aSAmit Cohen {
304614d509aSAmit Cohen .str = "a_multicast_frames_received_ok",
305614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_a_multicast_frames_received_ok_get,
306614d509aSAmit Cohen },
307614d509aSAmit Cohen {
308614d509aSAmit Cohen .str = "a_broadcast_frames_received_ok",
309614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_a_broadcast_frames_received_ok_get,
310614d509aSAmit Cohen },
311614d509aSAmit Cohen {
312614d509aSAmit Cohen .str = "a_in_range_length_errors",
313614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_a_in_range_length_errors_get,
314614d509aSAmit Cohen },
315614d509aSAmit Cohen {
316614d509aSAmit Cohen .str = "a_out_of_range_length_field",
317614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_a_out_of_range_length_field_get,
318614d509aSAmit Cohen },
319614d509aSAmit Cohen {
320614d509aSAmit Cohen .str = "a_frame_too_long_errors",
321614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_a_frame_too_long_errors_get,
322614d509aSAmit Cohen },
323614d509aSAmit Cohen {
324614d509aSAmit Cohen .str = "a_symbol_error_during_carrier",
325614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_a_symbol_error_during_carrier_get,
326614d509aSAmit Cohen },
327614d509aSAmit Cohen {
328614d509aSAmit Cohen .str = "a_mac_control_frames_transmitted",
329614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_a_mac_control_frames_transmitted_get,
330614d509aSAmit Cohen },
331614d509aSAmit Cohen {
332614d509aSAmit Cohen .str = "a_mac_control_frames_received",
333614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_a_mac_control_frames_received_get,
334614d509aSAmit Cohen },
335614d509aSAmit Cohen {
336614d509aSAmit Cohen .str = "a_unsupported_opcodes_received",
337614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_a_unsupported_opcodes_received_get,
338614d509aSAmit Cohen },
339614d509aSAmit Cohen {
340614d509aSAmit Cohen .str = "a_pause_mac_ctrl_frames_received",
341614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_a_pause_mac_ctrl_frames_received_get,
342614d509aSAmit Cohen },
343614d509aSAmit Cohen {
344614d509aSAmit Cohen .str = "a_pause_mac_ctrl_frames_xmitted",
345614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_a_pause_mac_ctrl_frames_transmitted_get,
346614d509aSAmit Cohen },
347614d509aSAmit Cohen };
348614d509aSAmit Cohen
349614d509aSAmit Cohen #define MLXSW_SP_PORT_HW_STATS_LEN ARRAY_SIZE(mlxsw_sp_port_hw_stats)
350614d509aSAmit Cohen
351614d509aSAmit Cohen static struct mlxsw_sp_port_hw_stats mlxsw_sp_port_hw_rfc_2863_stats[] = {
352614d509aSAmit Cohen {
353614d509aSAmit Cohen .str = "if_in_discards",
354614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_if_in_discards_get,
355614d509aSAmit Cohen },
356614d509aSAmit Cohen {
357614d509aSAmit Cohen .str = "if_out_discards",
358614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_if_out_discards_get,
359614d509aSAmit Cohen },
360614d509aSAmit Cohen {
361614d509aSAmit Cohen .str = "if_out_errors",
362614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_if_out_errors_get,
363614d509aSAmit Cohen },
364614d509aSAmit Cohen };
365614d509aSAmit Cohen
366614d509aSAmit Cohen #define MLXSW_SP_PORT_HW_RFC_2863_STATS_LEN \
367614d509aSAmit Cohen ARRAY_SIZE(mlxsw_sp_port_hw_rfc_2863_stats)
368614d509aSAmit Cohen
369614d509aSAmit Cohen static struct mlxsw_sp_port_hw_stats mlxsw_sp_port_hw_rfc_2819_stats[] = {
370614d509aSAmit Cohen {
371614d509aSAmit Cohen .str = "ether_stats_undersize_pkts",
372614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_ether_stats_undersize_pkts_get,
373614d509aSAmit Cohen },
374614d509aSAmit Cohen {
375614d509aSAmit Cohen .str = "ether_stats_oversize_pkts",
376614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_ether_stats_oversize_pkts_get,
377614d509aSAmit Cohen },
378614d509aSAmit Cohen {
379614d509aSAmit Cohen .str = "ether_stats_fragments",
380614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_ether_stats_fragments_get,
381614d509aSAmit Cohen },
382614d509aSAmit Cohen {
383614d509aSAmit Cohen .str = "ether_pkts64octets",
384614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_ether_stats_pkts64octets_get,
385614d509aSAmit Cohen },
386614d509aSAmit Cohen {
387614d509aSAmit Cohen .str = "ether_pkts65to127octets",
388614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_ether_stats_pkts65to127octets_get,
389614d509aSAmit Cohen },
390614d509aSAmit Cohen {
391614d509aSAmit Cohen .str = "ether_pkts128to255octets",
392614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_ether_stats_pkts128to255octets_get,
393614d509aSAmit Cohen },
394614d509aSAmit Cohen {
395614d509aSAmit Cohen .str = "ether_pkts256to511octets",
396614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_ether_stats_pkts256to511octets_get,
397614d509aSAmit Cohen },
398614d509aSAmit Cohen {
399614d509aSAmit Cohen .str = "ether_pkts512to1023octets",
400614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_ether_stats_pkts512to1023octets_get,
401614d509aSAmit Cohen },
402614d509aSAmit Cohen {
403614d509aSAmit Cohen .str = "ether_pkts1024to1518octets",
404614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_ether_stats_pkts1024to1518octets_get,
405614d509aSAmit Cohen },
406614d509aSAmit Cohen {
407614d509aSAmit Cohen .str = "ether_pkts1519to2047octets",
408614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_ether_stats_pkts1519to2047octets_get,
409614d509aSAmit Cohen },
410614d509aSAmit Cohen {
411614d509aSAmit Cohen .str = "ether_pkts2048to4095octets",
412614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_ether_stats_pkts2048to4095octets_get,
413614d509aSAmit Cohen },
414614d509aSAmit Cohen {
415614d509aSAmit Cohen .str = "ether_pkts4096to8191octets",
416614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_ether_stats_pkts4096to8191octets_get,
417614d509aSAmit Cohen },
418614d509aSAmit Cohen {
419614d509aSAmit Cohen .str = "ether_pkts8192to10239octets",
420614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_ether_stats_pkts8192to10239octets_get,
421614d509aSAmit Cohen },
422614d509aSAmit Cohen };
423614d509aSAmit Cohen
424614d509aSAmit Cohen #define MLXSW_SP_PORT_HW_RFC_2819_STATS_LEN \
425614d509aSAmit Cohen ARRAY_SIZE(mlxsw_sp_port_hw_rfc_2819_stats)
426614d509aSAmit Cohen
427614d509aSAmit Cohen static struct mlxsw_sp_port_hw_stats mlxsw_sp_port_hw_rfc_3635_stats[] = {
428614d509aSAmit Cohen {
429614d509aSAmit Cohen .str = "dot3stats_fcs_errors",
430614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_dot3stats_fcs_errors_get,
431614d509aSAmit Cohen },
432614d509aSAmit Cohen {
433614d509aSAmit Cohen .str = "dot3stats_symbol_errors",
434614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_dot3stats_symbol_errors_get,
435614d509aSAmit Cohen },
436614d509aSAmit Cohen {
437614d509aSAmit Cohen .str = "dot3control_in_unknown_opcodes",
438614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_dot3control_in_unknown_opcodes_get,
439614d509aSAmit Cohen },
440614d509aSAmit Cohen {
441614d509aSAmit Cohen .str = "dot3in_pause_frames",
442614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_dot3in_pause_frames_get,
443614d509aSAmit Cohen },
444614d509aSAmit Cohen };
445614d509aSAmit Cohen
446614d509aSAmit Cohen #define MLXSW_SP_PORT_HW_RFC_3635_STATS_LEN \
447614d509aSAmit Cohen ARRAY_SIZE(mlxsw_sp_port_hw_rfc_3635_stats)
448614d509aSAmit Cohen
449614d509aSAmit Cohen static struct mlxsw_sp_port_hw_stats mlxsw_sp_port_hw_ext_stats[] = {
450614d509aSAmit Cohen {
451614d509aSAmit Cohen .str = "ecn_marked",
452614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_ecn_marked_get,
453614d509aSAmit Cohen },
454614d509aSAmit Cohen };
455614d509aSAmit Cohen
456614d509aSAmit Cohen #define MLXSW_SP_PORT_HW_EXT_STATS_LEN ARRAY_SIZE(mlxsw_sp_port_hw_ext_stats)
457614d509aSAmit Cohen
458614d509aSAmit Cohen static struct mlxsw_sp_port_hw_stats mlxsw_sp_port_hw_discard_stats[] = {
459614d509aSAmit Cohen {
460614d509aSAmit Cohen .str = "discard_ingress_general",
461614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_ingress_general_get,
462614d509aSAmit Cohen },
463614d509aSAmit Cohen {
464614d509aSAmit Cohen .str = "discard_ingress_policy_engine",
465614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_ingress_policy_engine_get,
466614d509aSAmit Cohen },
467614d509aSAmit Cohen {
468614d509aSAmit Cohen .str = "discard_ingress_vlan_membership",
469614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_ingress_vlan_membership_get,
470614d509aSAmit Cohen },
471614d509aSAmit Cohen {
472614d509aSAmit Cohen .str = "discard_ingress_tag_frame_type",
473614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_ingress_tag_frame_type_get,
474614d509aSAmit Cohen },
475614d509aSAmit Cohen {
476614d509aSAmit Cohen .str = "discard_egress_vlan_membership",
477614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_egress_vlan_membership_get,
478614d509aSAmit Cohen },
479614d509aSAmit Cohen {
480614d509aSAmit Cohen .str = "discard_loopback_filter",
481614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_loopback_filter_get,
482614d509aSAmit Cohen },
483614d509aSAmit Cohen {
484614d509aSAmit Cohen .str = "discard_egress_general",
485614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_egress_general_get,
486614d509aSAmit Cohen },
487614d509aSAmit Cohen {
488614d509aSAmit Cohen .str = "discard_egress_hoq",
489614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_egress_hoq_get,
490614d509aSAmit Cohen },
491614d509aSAmit Cohen {
492614d509aSAmit Cohen .str = "discard_egress_policy_engine",
493614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_egress_policy_engine_get,
494614d509aSAmit Cohen },
495614d509aSAmit Cohen {
496614d509aSAmit Cohen .str = "discard_ingress_tx_link_down",
497614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_ingress_tx_link_down_get,
498614d509aSAmit Cohen },
499614d509aSAmit Cohen {
500614d509aSAmit Cohen .str = "discard_egress_stp_filter",
501614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_egress_stp_filter_get,
502614d509aSAmit Cohen },
503614d509aSAmit Cohen {
504614d509aSAmit Cohen .str = "discard_egress_sll",
505614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_egress_sll_get,
506614d509aSAmit Cohen },
507614d509aSAmit Cohen };
508614d509aSAmit Cohen
509614d509aSAmit Cohen #define MLXSW_SP_PORT_HW_DISCARD_STATS_LEN \
510614d509aSAmit Cohen ARRAY_SIZE(mlxsw_sp_port_hw_discard_stats)
511614d509aSAmit Cohen
512614d509aSAmit Cohen static struct mlxsw_sp_port_hw_stats mlxsw_sp_port_hw_prio_stats[] = {
513614d509aSAmit Cohen {
514614d509aSAmit Cohen .str = "rx_octets_prio",
515614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_rx_octets_get,
516614d509aSAmit Cohen },
517614d509aSAmit Cohen {
518614d509aSAmit Cohen .str = "rx_frames_prio",
519614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_rx_frames_get,
520614d509aSAmit Cohen },
521614d509aSAmit Cohen {
522614d509aSAmit Cohen .str = "tx_octets_prio",
523614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_tx_octets_get,
524614d509aSAmit Cohen },
525614d509aSAmit Cohen {
526614d509aSAmit Cohen .str = "tx_frames_prio",
527614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_tx_frames_get,
528614d509aSAmit Cohen },
529614d509aSAmit Cohen {
530614d509aSAmit Cohen .str = "rx_pause_prio",
531614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_rx_pause_get,
532614d509aSAmit Cohen },
533614d509aSAmit Cohen {
534614d509aSAmit Cohen .str = "rx_pause_duration_prio",
535614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_rx_pause_duration_get,
536614d509aSAmit Cohen },
537614d509aSAmit Cohen {
538614d509aSAmit Cohen .str = "tx_pause_prio",
539614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_tx_pause_get,
540614d509aSAmit Cohen },
541614d509aSAmit Cohen {
542614d509aSAmit Cohen .str = "tx_pause_duration_prio",
543614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_tx_pause_duration_get,
544614d509aSAmit Cohen },
545614d509aSAmit Cohen };
546614d509aSAmit Cohen
547614d509aSAmit Cohen #define MLXSW_SP_PORT_HW_PRIO_STATS_LEN ARRAY_SIZE(mlxsw_sp_port_hw_prio_stats)
548614d509aSAmit Cohen
549614d509aSAmit Cohen static struct mlxsw_sp_port_hw_stats mlxsw_sp_port_hw_tc_stats[] = {
550614d509aSAmit Cohen {
551614d509aSAmit Cohen .str = "tc_transmit_queue_tc",
552614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_tc_transmit_queue_get,
553614d509aSAmit Cohen .cells_bytes = true,
554614d509aSAmit Cohen },
555614d509aSAmit Cohen {
556614d509aSAmit Cohen .str = "tc_no_buffer_discard_uc_tc",
557614d509aSAmit Cohen .getter = mlxsw_reg_ppcnt_tc_no_buffer_discard_uc_get,
558614d509aSAmit Cohen },
559614d509aSAmit Cohen };
560614d509aSAmit Cohen
561614d509aSAmit Cohen #define MLXSW_SP_PORT_HW_TC_STATS_LEN ARRAY_SIZE(mlxsw_sp_port_hw_tc_stats)
562614d509aSAmit Cohen
56369f6d4eeSAmit Cohen struct mlxsw_sp_port_stats {
56469f6d4eeSAmit Cohen char str[ETH_GSTRING_LEN];
56569f6d4eeSAmit Cohen u64 (*getter)(struct mlxsw_sp_port *mlxsw_sp_port);
56669f6d4eeSAmit Cohen };
56769f6d4eeSAmit Cohen
56869f6d4eeSAmit Cohen static u64
mlxsw_sp_port_get_transceiver_overheat_stats(struct mlxsw_sp_port * mlxsw_sp_port)56969f6d4eeSAmit Cohen mlxsw_sp_port_get_transceiver_overheat_stats(struct mlxsw_sp_port *mlxsw_sp_port)
57069f6d4eeSAmit Cohen {
57169f6d4eeSAmit Cohen struct mlxsw_core *mlxsw_core = mlxsw_sp_port->mlxsw_sp->core;
5726445eef0SJiri Pirko u8 slot_index = mlxsw_sp_port->mapping.slot_index;
5736445eef0SJiri Pirko u8 module = mlxsw_sp_port->mapping.module;
57469f6d4eeSAmit Cohen u64 stats;
57569f6d4eeSAmit Cohen int err;
57669f6d4eeSAmit Cohen
5776445eef0SJiri Pirko err = mlxsw_env_module_overheat_counter_get(mlxsw_core, slot_index,
5786445eef0SJiri Pirko module, &stats);
57969f6d4eeSAmit Cohen if (err)
58069f6d4eeSAmit Cohen return mlxsw_sp_port->module_overheat_initial_val;
58169f6d4eeSAmit Cohen
58269f6d4eeSAmit Cohen return stats - mlxsw_sp_port->module_overheat_initial_val;
58369f6d4eeSAmit Cohen }
58469f6d4eeSAmit Cohen
58569f6d4eeSAmit Cohen static struct mlxsw_sp_port_stats mlxsw_sp_port_transceiver_stats[] = {
58669f6d4eeSAmit Cohen {
58769f6d4eeSAmit Cohen .str = "transceiver_overheat",
58869f6d4eeSAmit Cohen .getter = mlxsw_sp_port_get_transceiver_overheat_stats,
58969f6d4eeSAmit Cohen },
59069f6d4eeSAmit Cohen };
59169f6d4eeSAmit Cohen
59269f6d4eeSAmit Cohen #define MLXSW_SP_PORT_HW_TRANSCEIVER_STATS_LEN ARRAY_SIZE(mlxsw_sp_port_transceiver_stats)
59369f6d4eeSAmit Cohen
594614d509aSAmit Cohen #define MLXSW_SP_PORT_ETHTOOL_STATS_LEN (MLXSW_SP_PORT_HW_STATS_LEN + \
595614d509aSAmit Cohen MLXSW_SP_PORT_HW_RFC_2863_STATS_LEN + \
596614d509aSAmit Cohen MLXSW_SP_PORT_HW_RFC_2819_STATS_LEN + \
597614d509aSAmit Cohen MLXSW_SP_PORT_HW_RFC_3635_STATS_LEN + \
598614d509aSAmit Cohen MLXSW_SP_PORT_HW_EXT_STATS_LEN + \
599614d509aSAmit Cohen MLXSW_SP_PORT_HW_DISCARD_STATS_LEN + \
600614d509aSAmit Cohen (MLXSW_SP_PORT_HW_PRIO_STATS_LEN * \
601614d509aSAmit Cohen IEEE_8021QAZ_MAX_TCS) + \
602614d509aSAmit Cohen (MLXSW_SP_PORT_HW_TC_STATS_LEN * \
60369f6d4eeSAmit Cohen TC_MAX_QUEUE) + \
60469f6d4eeSAmit Cohen MLXSW_SP_PORT_HW_TRANSCEIVER_STATS_LEN)
605614d509aSAmit Cohen
mlxsw_sp_port_get_prio_strings(u8 ** p,int prio)606614d509aSAmit Cohen static void mlxsw_sp_port_get_prio_strings(u8 **p, int prio)
607614d509aSAmit Cohen {
608614d509aSAmit Cohen int i;
609614d509aSAmit Cohen
610614d509aSAmit Cohen for (i = 0; i < MLXSW_SP_PORT_HW_PRIO_STATS_LEN; i++) {
611614d509aSAmit Cohen snprintf(*p, ETH_GSTRING_LEN, "%.29s_%.1d",
612614d509aSAmit Cohen mlxsw_sp_port_hw_prio_stats[i].str, prio);
613614d509aSAmit Cohen *p += ETH_GSTRING_LEN;
614614d509aSAmit Cohen }
615614d509aSAmit Cohen }
616614d509aSAmit Cohen
mlxsw_sp_port_get_tc_strings(u8 ** p,int tc)617614d509aSAmit Cohen static void mlxsw_sp_port_get_tc_strings(u8 **p, int tc)
618614d509aSAmit Cohen {
619614d509aSAmit Cohen int i;
620614d509aSAmit Cohen
621614d509aSAmit Cohen for (i = 0; i < MLXSW_SP_PORT_HW_TC_STATS_LEN; i++) {
622614d509aSAmit Cohen snprintf(*p, ETH_GSTRING_LEN, "%.29s_%.1d",
623614d509aSAmit Cohen mlxsw_sp_port_hw_tc_stats[i].str, tc);
624614d509aSAmit Cohen *p += ETH_GSTRING_LEN;
625614d509aSAmit Cohen }
626614d509aSAmit Cohen }
627614d509aSAmit Cohen
mlxsw_sp_port_get_strings(struct net_device * dev,u32 stringset,u8 * data)628614d509aSAmit Cohen static void mlxsw_sp_port_get_strings(struct net_device *dev,
629614d509aSAmit Cohen u32 stringset, u8 *data)
630614d509aSAmit Cohen {
631614d509aSAmit Cohen struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
632614d509aSAmit Cohen u8 *p = data;
633614d509aSAmit Cohen int i;
634614d509aSAmit Cohen
635614d509aSAmit Cohen switch (stringset) {
636614d509aSAmit Cohen case ETH_SS_STATS:
637614d509aSAmit Cohen for (i = 0; i < MLXSW_SP_PORT_HW_STATS_LEN; i++) {
638614d509aSAmit Cohen memcpy(p, mlxsw_sp_port_hw_stats[i].str,
639614d509aSAmit Cohen ETH_GSTRING_LEN);
640614d509aSAmit Cohen p += ETH_GSTRING_LEN;
641614d509aSAmit Cohen }
642614d509aSAmit Cohen
643614d509aSAmit Cohen for (i = 0; i < MLXSW_SP_PORT_HW_RFC_2863_STATS_LEN; i++) {
644614d509aSAmit Cohen memcpy(p, mlxsw_sp_port_hw_rfc_2863_stats[i].str,
645614d509aSAmit Cohen ETH_GSTRING_LEN);
646614d509aSAmit Cohen p += ETH_GSTRING_LEN;
647614d509aSAmit Cohen }
648614d509aSAmit Cohen
649614d509aSAmit Cohen for (i = 0; i < MLXSW_SP_PORT_HW_RFC_2819_STATS_LEN; i++) {
650614d509aSAmit Cohen memcpy(p, mlxsw_sp_port_hw_rfc_2819_stats[i].str,
651614d509aSAmit Cohen ETH_GSTRING_LEN);
652614d509aSAmit Cohen p += ETH_GSTRING_LEN;
653614d509aSAmit Cohen }
654614d509aSAmit Cohen
655614d509aSAmit Cohen for (i = 0; i < MLXSW_SP_PORT_HW_RFC_3635_STATS_LEN; i++) {
656614d509aSAmit Cohen memcpy(p, mlxsw_sp_port_hw_rfc_3635_stats[i].str,
657614d509aSAmit Cohen ETH_GSTRING_LEN);
658614d509aSAmit Cohen p += ETH_GSTRING_LEN;
659614d509aSAmit Cohen }
660614d509aSAmit Cohen
661614d509aSAmit Cohen for (i = 0; i < MLXSW_SP_PORT_HW_EXT_STATS_LEN; i++) {
662614d509aSAmit Cohen memcpy(p, mlxsw_sp_port_hw_ext_stats[i].str,
663614d509aSAmit Cohen ETH_GSTRING_LEN);
664614d509aSAmit Cohen p += ETH_GSTRING_LEN;
665614d509aSAmit Cohen }
666614d509aSAmit Cohen
667614d509aSAmit Cohen for (i = 0; i < MLXSW_SP_PORT_HW_DISCARD_STATS_LEN; i++) {
668614d509aSAmit Cohen memcpy(p, mlxsw_sp_port_hw_discard_stats[i].str,
669614d509aSAmit Cohen ETH_GSTRING_LEN);
670614d509aSAmit Cohen p += ETH_GSTRING_LEN;
671614d509aSAmit Cohen }
672614d509aSAmit Cohen
673614d509aSAmit Cohen for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++)
674614d509aSAmit Cohen mlxsw_sp_port_get_prio_strings(&p, i);
675614d509aSAmit Cohen
676614d509aSAmit Cohen for (i = 0; i < TC_MAX_QUEUE; i++)
677614d509aSAmit Cohen mlxsw_sp_port_get_tc_strings(&p, i);
678614d509aSAmit Cohen
679614d509aSAmit Cohen mlxsw_sp_port->mlxsw_sp->ptp_ops->get_stats_strings(&p);
68069f6d4eeSAmit Cohen
68169f6d4eeSAmit Cohen for (i = 0; i < MLXSW_SP_PORT_HW_TRANSCEIVER_STATS_LEN; i++) {
68269f6d4eeSAmit Cohen memcpy(p, mlxsw_sp_port_transceiver_stats[i].str,
68369f6d4eeSAmit Cohen ETH_GSTRING_LEN);
68469f6d4eeSAmit Cohen p += ETH_GSTRING_LEN;
68569f6d4eeSAmit Cohen }
686614d509aSAmit Cohen break;
687614d509aSAmit Cohen }
688614d509aSAmit Cohen }
689614d509aSAmit Cohen
mlxsw_sp_port_set_phys_id(struct net_device * dev,enum ethtool_phys_id_state state)690614d509aSAmit Cohen static int mlxsw_sp_port_set_phys_id(struct net_device *dev,
691614d509aSAmit Cohen enum ethtool_phys_id_state state)
692614d509aSAmit Cohen {
693614d509aSAmit Cohen struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
694614d509aSAmit Cohen struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
695614d509aSAmit Cohen char mlcr_pl[MLXSW_REG_MLCR_LEN];
696614d509aSAmit Cohen bool active;
697614d509aSAmit Cohen
698614d509aSAmit Cohen switch (state) {
699614d509aSAmit Cohen case ETHTOOL_ID_ACTIVE:
700614d509aSAmit Cohen active = true;
701614d509aSAmit Cohen break;
702614d509aSAmit Cohen case ETHTOOL_ID_INACTIVE:
703614d509aSAmit Cohen active = false;
704614d509aSAmit Cohen break;
705614d509aSAmit Cohen default:
706614d509aSAmit Cohen return -EOPNOTSUPP;
707614d509aSAmit Cohen }
708614d509aSAmit Cohen
709614d509aSAmit Cohen mlxsw_reg_mlcr_pack(mlcr_pl, mlxsw_sp_port->local_port, active);
710614d509aSAmit Cohen return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(mlcr), mlcr_pl);
711614d509aSAmit Cohen }
712614d509aSAmit Cohen
713614d509aSAmit Cohen static int
mlxsw_sp_get_hw_stats_by_group(struct mlxsw_sp_port_hw_stats ** p_hw_stats,int * p_len,enum mlxsw_reg_ppcnt_grp grp)714614d509aSAmit Cohen mlxsw_sp_get_hw_stats_by_group(struct mlxsw_sp_port_hw_stats **p_hw_stats,
715614d509aSAmit Cohen int *p_len, enum mlxsw_reg_ppcnt_grp grp)
716614d509aSAmit Cohen {
717614d509aSAmit Cohen switch (grp) {
718614d509aSAmit Cohen case MLXSW_REG_PPCNT_IEEE_8023_CNT:
719614d509aSAmit Cohen *p_hw_stats = mlxsw_sp_port_hw_stats;
720614d509aSAmit Cohen *p_len = MLXSW_SP_PORT_HW_STATS_LEN;
721614d509aSAmit Cohen break;
722614d509aSAmit Cohen case MLXSW_REG_PPCNT_RFC_2863_CNT:
723614d509aSAmit Cohen *p_hw_stats = mlxsw_sp_port_hw_rfc_2863_stats;
724614d509aSAmit Cohen *p_len = MLXSW_SP_PORT_HW_RFC_2863_STATS_LEN;
725614d509aSAmit Cohen break;
726614d509aSAmit Cohen case MLXSW_REG_PPCNT_RFC_2819_CNT:
727614d509aSAmit Cohen *p_hw_stats = mlxsw_sp_port_hw_rfc_2819_stats;
728614d509aSAmit Cohen *p_len = MLXSW_SP_PORT_HW_RFC_2819_STATS_LEN;
729614d509aSAmit Cohen break;
730614d509aSAmit Cohen case MLXSW_REG_PPCNT_RFC_3635_CNT:
731614d509aSAmit Cohen *p_hw_stats = mlxsw_sp_port_hw_rfc_3635_stats;
732614d509aSAmit Cohen *p_len = MLXSW_SP_PORT_HW_RFC_3635_STATS_LEN;
733614d509aSAmit Cohen break;
734614d509aSAmit Cohen case MLXSW_REG_PPCNT_EXT_CNT:
735614d509aSAmit Cohen *p_hw_stats = mlxsw_sp_port_hw_ext_stats;
736614d509aSAmit Cohen *p_len = MLXSW_SP_PORT_HW_EXT_STATS_LEN;
737614d509aSAmit Cohen break;
738614d509aSAmit Cohen case MLXSW_REG_PPCNT_DISCARD_CNT:
739614d509aSAmit Cohen *p_hw_stats = mlxsw_sp_port_hw_discard_stats;
740614d509aSAmit Cohen *p_len = MLXSW_SP_PORT_HW_DISCARD_STATS_LEN;
741614d509aSAmit Cohen break;
742614d509aSAmit Cohen case MLXSW_REG_PPCNT_PRIO_CNT:
743614d509aSAmit Cohen *p_hw_stats = mlxsw_sp_port_hw_prio_stats;
744614d509aSAmit Cohen *p_len = MLXSW_SP_PORT_HW_PRIO_STATS_LEN;
745614d509aSAmit Cohen break;
746614d509aSAmit Cohen case MLXSW_REG_PPCNT_TC_CNT:
747614d509aSAmit Cohen *p_hw_stats = mlxsw_sp_port_hw_tc_stats;
748614d509aSAmit Cohen *p_len = MLXSW_SP_PORT_HW_TC_STATS_LEN;
749614d509aSAmit Cohen break;
750614d509aSAmit Cohen default:
751614d509aSAmit Cohen WARN_ON(1);
752614d509aSAmit Cohen return -EOPNOTSUPP;
753614d509aSAmit Cohen }
754614d509aSAmit Cohen return 0;
755614d509aSAmit Cohen }
756614d509aSAmit Cohen
__mlxsw_sp_port_get_stats(struct net_device * dev,enum mlxsw_reg_ppcnt_grp grp,int prio,u64 * data,int data_index)757614d509aSAmit Cohen static void __mlxsw_sp_port_get_stats(struct net_device *dev,
758614d509aSAmit Cohen enum mlxsw_reg_ppcnt_grp grp, int prio,
759614d509aSAmit Cohen u64 *data, int data_index)
760614d509aSAmit Cohen {
761614d509aSAmit Cohen struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
762614d509aSAmit Cohen struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
763614d509aSAmit Cohen struct mlxsw_sp_port_hw_stats *hw_stats;
764614d509aSAmit Cohen char ppcnt_pl[MLXSW_REG_PPCNT_LEN];
765614d509aSAmit Cohen int i, len;
766614d509aSAmit Cohen int err;
767614d509aSAmit Cohen
768614d509aSAmit Cohen err = mlxsw_sp_get_hw_stats_by_group(&hw_stats, &len, grp);
769614d509aSAmit Cohen if (err)
770614d509aSAmit Cohen return;
771614d509aSAmit Cohen mlxsw_sp_port_get_stats_raw(dev, grp, prio, ppcnt_pl);
772614d509aSAmit Cohen for (i = 0; i < len; i++) {
773614d509aSAmit Cohen data[data_index + i] = hw_stats[i].getter(ppcnt_pl);
774614d509aSAmit Cohen if (!hw_stats[i].cells_bytes)
775614d509aSAmit Cohen continue;
776614d509aSAmit Cohen data[data_index + i] = mlxsw_sp_cells_bytes(mlxsw_sp,
777614d509aSAmit Cohen data[data_index + i]);
778614d509aSAmit Cohen }
779614d509aSAmit Cohen }
780614d509aSAmit Cohen
__mlxsw_sp_port_get_env_stats(struct net_device * dev,u64 * data,int data_index,struct mlxsw_sp_port_stats * port_stats,int len)78169f6d4eeSAmit Cohen static void __mlxsw_sp_port_get_env_stats(struct net_device *dev, u64 *data, int data_index,
78269f6d4eeSAmit Cohen struct mlxsw_sp_port_stats *port_stats,
78369f6d4eeSAmit Cohen int len)
78469f6d4eeSAmit Cohen {
78569f6d4eeSAmit Cohen struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
78669f6d4eeSAmit Cohen int i;
78769f6d4eeSAmit Cohen
78869f6d4eeSAmit Cohen for (i = 0; i < len; i++)
78969f6d4eeSAmit Cohen data[data_index + i] = port_stats[i].getter(mlxsw_sp_port);
79069f6d4eeSAmit Cohen }
79169f6d4eeSAmit Cohen
mlxsw_sp_port_get_stats(struct net_device * dev,struct ethtool_stats * stats,u64 * data)792614d509aSAmit Cohen static void mlxsw_sp_port_get_stats(struct net_device *dev,
793614d509aSAmit Cohen struct ethtool_stats *stats, u64 *data)
794614d509aSAmit Cohen {
795614d509aSAmit Cohen struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
796614d509aSAmit Cohen int i, data_index = 0;
797614d509aSAmit Cohen
798614d509aSAmit Cohen /* IEEE 802.3 Counters */
799614d509aSAmit Cohen __mlxsw_sp_port_get_stats(dev, MLXSW_REG_PPCNT_IEEE_8023_CNT, 0,
800614d509aSAmit Cohen data, data_index);
801614d509aSAmit Cohen data_index = MLXSW_SP_PORT_HW_STATS_LEN;
802614d509aSAmit Cohen
803614d509aSAmit Cohen /* RFC 2863 Counters */
804614d509aSAmit Cohen __mlxsw_sp_port_get_stats(dev, MLXSW_REG_PPCNT_RFC_2863_CNT, 0,
805614d509aSAmit Cohen data, data_index);
806614d509aSAmit Cohen data_index += MLXSW_SP_PORT_HW_RFC_2863_STATS_LEN;
807614d509aSAmit Cohen
808614d509aSAmit Cohen /* RFC 2819 Counters */
809614d509aSAmit Cohen __mlxsw_sp_port_get_stats(dev, MLXSW_REG_PPCNT_RFC_2819_CNT, 0,
810614d509aSAmit Cohen data, data_index);
811614d509aSAmit Cohen data_index += MLXSW_SP_PORT_HW_RFC_2819_STATS_LEN;
812614d509aSAmit Cohen
813614d509aSAmit Cohen /* RFC 3635 Counters */
814614d509aSAmit Cohen __mlxsw_sp_port_get_stats(dev, MLXSW_REG_PPCNT_RFC_3635_CNT, 0,
815614d509aSAmit Cohen data, data_index);
816614d509aSAmit Cohen data_index += MLXSW_SP_PORT_HW_RFC_3635_STATS_LEN;
817614d509aSAmit Cohen
818614d509aSAmit Cohen /* Extended Counters */
819614d509aSAmit Cohen __mlxsw_sp_port_get_stats(dev, MLXSW_REG_PPCNT_EXT_CNT, 0,
820614d509aSAmit Cohen data, data_index);
821614d509aSAmit Cohen data_index += MLXSW_SP_PORT_HW_EXT_STATS_LEN;
822614d509aSAmit Cohen
823614d509aSAmit Cohen /* Discard Counters */
824614d509aSAmit Cohen __mlxsw_sp_port_get_stats(dev, MLXSW_REG_PPCNT_DISCARD_CNT, 0,
825614d509aSAmit Cohen data, data_index);
826614d509aSAmit Cohen data_index += MLXSW_SP_PORT_HW_DISCARD_STATS_LEN;
827614d509aSAmit Cohen
828614d509aSAmit Cohen /* Per-Priority Counters */
829614d509aSAmit Cohen for (i = 0; i < IEEE_8021QAZ_MAX_TCS; i++) {
830614d509aSAmit Cohen __mlxsw_sp_port_get_stats(dev, MLXSW_REG_PPCNT_PRIO_CNT, i,
831614d509aSAmit Cohen data, data_index);
832614d509aSAmit Cohen data_index += MLXSW_SP_PORT_HW_PRIO_STATS_LEN;
833614d509aSAmit Cohen }
834614d509aSAmit Cohen
835614d509aSAmit Cohen /* Per-TC Counters */
836614d509aSAmit Cohen for (i = 0; i < TC_MAX_QUEUE; i++) {
837614d509aSAmit Cohen __mlxsw_sp_port_get_stats(dev, MLXSW_REG_PPCNT_TC_CNT, i,
838614d509aSAmit Cohen data, data_index);
839614d509aSAmit Cohen data_index += MLXSW_SP_PORT_HW_TC_STATS_LEN;
840614d509aSAmit Cohen }
841614d509aSAmit Cohen
842614d509aSAmit Cohen /* PTP counters */
843614d509aSAmit Cohen mlxsw_sp_port->mlxsw_sp->ptp_ops->get_stats(mlxsw_sp_port,
844614d509aSAmit Cohen data, data_index);
845614d509aSAmit Cohen data_index += mlxsw_sp_port->mlxsw_sp->ptp_ops->get_stats_count();
84669f6d4eeSAmit Cohen
84769f6d4eeSAmit Cohen /* Transceiver counters */
84869f6d4eeSAmit Cohen __mlxsw_sp_port_get_env_stats(dev, data, data_index, mlxsw_sp_port_transceiver_stats,
84969f6d4eeSAmit Cohen MLXSW_SP_PORT_HW_TRANSCEIVER_STATS_LEN);
85069f6d4eeSAmit Cohen data_index += MLXSW_SP_PORT_HW_TRANSCEIVER_STATS_LEN;
851614d509aSAmit Cohen }
852614d509aSAmit Cohen
mlxsw_sp_port_get_sset_count(struct net_device * dev,int sset)853614d509aSAmit Cohen static int mlxsw_sp_port_get_sset_count(struct net_device *dev, int sset)
854614d509aSAmit Cohen {
855614d509aSAmit Cohen struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
856614d509aSAmit Cohen
857614d509aSAmit Cohen switch (sset) {
858614d509aSAmit Cohen case ETH_SS_STATS:
859614d509aSAmit Cohen return MLXSW_SP_PORT_ETHTOOL_STATS_LEN +
860614d509aSAmit Cohen mlxsw_sp_port->mlxsw_sp->ptp_ops->get_stats_count();
861614d509aSAmit Cohen default:
862614d509aSAmit Cohen return -EOPNOTSUPP;
863614d509aSAmit Cohen }
864614d509aSAmit Cohen }
865614d509aSAmit Cohen
866614d509aSAmit Cohen static void
mlxsw_sp_port_get_link_supported(struct mlxsw_sp * mlxsw_sp,u32 eth_proto_cap,struct ethtool_link_ksettings * cmd)867614d509aSAmit Cohen mlxsw_sp_port_get_link_supported(struct mlxsw_sp *mlxsw_sp, u32 eth_proto_cap,
8685fc4053dSDanielle Ratson struct ethtool_link_ksettings *cmd)
869614d509aSAmit Cohen {
870614d509aSAmit Cohen const struct mlxsw_sp_port_type_speed_ops *ops;
871614d509aSAmit Cohen
872614d509aSAmit Cohen ops = mlxsw_sp->port_type_speed_ops;
873614d509aSAmit Cohen
874614d509aSAmit Cohen ethtool_link_ksettings_add_link_mode(cmd, supported, Asym_Pause);
875614d509aSAmit Cohen ethtool_link_ksettings_add_link_mode(cmd, supported, Autoneg);
876614d509aSAmit Cohen ethtool_link_ksettings_add_link_mode(cmd, supported, Pause);
877614d509aSAmit Cohen
878614d509aSAmit Cohen ops->from_ptys_supported_port(mlxsw_sp, eth_proto_cap, cmd);
8795fc4053dSDanielle Ratson ops->from_ptys_link(mlxsw_sp, eth_proto_cap,
880614d509aSAmit Cohen cmd->link_modes.supported);
881614d509aSAmit Cohen }
882614d509aSAmit Cohen
883614d509aSAmit Cohen static void
mlxsw_sp_port_get_link_advertise(struct mlxsw_sp * mlxsw_sp,u32 eth_proto_admin,bool autoneg,struct ethtool_link_ksettings * cmd)884614d509aSAmit Cohen mlxsw_sp_port_get_link_advertise(struct mlxsw_sp *mlxsw_sp,
8855fc4053dSDanielle Ratson u32 eth_proto_admin, bool autoneg,
886614d509aSAmit Cohen struct ethtool_link_ksettings *cmd)
887614d509aSAmit Cohen {
888614d509aSAmit Cohen const struct mlxsw_sp_port_type_speed_ops *ops;
889614d509aSAmit Cohen
890614d509aSAmit Cohen ops = mlxsw_sp->port_type_speed_ops;
891614d509aSAmit Cohen
892614d509aSAmit Cohen if (!autoneg)
893614d509aSAmit Cohen return;
894614d509aSAmit Cohen
895614d509aSAmit Cohen ethtool_link_ksettings_add_link_mode(cmd, advertising, Autoneg);
8965fc4053dSDanielle Ratson ops->from_ptys_link(mlxsw_sp, eth_proto_admin,
897614d509aSAmit Cohen cmd->link_modes.advertising);
898614d509aSAmit Cohen }
899614d509aSAmit Cohen
900614d509aSAmit Cohen static u8
mlxsw_sp_port_connector_port(enum mlxsw_reg_ptys_connector_type connector_type)901614d509aSAmit Cohen mlxsw_sp_port_connector_port(enum mlxsw_reg_ptys_connector_type connector_type)
902614d509aSAmit Cohen {
903614d509aSAmit Cohen switch (connector_type) {
904614d509aSAmit Cohen case MLXSW_REG_PTYS_CONNECTOR_TYPE_UNKNOWN_OR_NO_CONNECTOR:
905614d509aSAmit Cohen return PORT_OTHER;
906614d509aSAmit Cohen case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_NONE:
907614d509aSAmit Cohen return PORT_NONE;
908614d509aSAmit Cohen case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_TP:
909614d509aSAmit Cohen return PORT_TP;
910614d509aSAmit Cohen case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_AUI:
911614d509aSAmit Cohen return PORT_AUI;
912614d509aSAmit Cohen case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_BNC:
913614d509aSAmit Cohen return PORT_BNC;
914614d509aSAmit Cohen case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_MII:
915614d509aSAmit Cohen return PORT_MII;
916614d509aSAmit Cohen case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_FIBRE:
917614d509aSAmit Cohen return PORT_FIBRE;
918614d509aSAmit Cohen case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_DA:
919614d509aSAmit Cohen return PORT_DA;
920614d509aSAmit Cohen case MLXSW_REG_PTYS_CONNECTOR_TYPE_PORT_OTHER:
921614d509aSAmit Cohen return PORT_OTHER;
922614d509aSAmit Cohen default:
923614d509aSAmit Cohen WARN_ON_ONCE(1);
924614d509aSAmit Cohen return PORT_OTHER;
925614d509aSAmit Cohen }
926614d509aSAmit Cohen }
927614d509aSAmit Cohen
mlxsw_sp_port_ptys_query(struct mlxsw_sp_port * mlxsw_sp_port,u32 * p_eth_proto_cap,u32 * p_eth_proto_admin,u32 * p_eth_proto_oper,u8 * p_connector_type)928d24ca6c0SPetr Machata static int mlxsw_sp_port_ptys_query(struct mlxsw_sp_port *mlxsw_sp_port,
929d24ca6c0SPetr Machata u32 *p_eth_proto_cap, u32 *p_eth_proto_admin,
930d24ca6c0SPetr Machata u32 *p_eth_proto_oper, u8 *p_connector_type)
931d24ca6c0SPetr Machata {
932d24ca6c0SPetr Machata struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
933d24ca6c0SPetr Machata const struct mlxsw_sp_port_type_speed_ops *ops;
934d24ca6c0SPetr Machata char ptys_pl[MLXSW_REG_PTYS_LEN];
935d24ca6c0SPetr Machata int err;
936d24ca6c0SPetr Machata
937d24ca6c0SPetr Machata ops = mlxsw_sp->port_type_speed_ops;
938d24ca6c0SPetr Machata
939d24ca6c0SPetr Machata ops->reg_ptys_eth_pack(mlxsw_sp, ptys_pl, mlxsw_sp_port->local_port, 0, false);
940d24ca6c0SPetr Machata err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl);
941d24ca6c0SPetr Machata if (err)
942d24ca6c0SPetr Machata return err;
943d24ca6c0SPetr Machata
944d24ca6c0SPetr Machata ops->reg_ptys_eth_unpack(mlxsw_sp, ptys_pl, p_eth_proto_cap, p_eth_proto_admin,
945d24ca6c0SPetr Machata p_eth_proto_oper);
946d24ca6c0SPetr Machata if (p_connector_type)
947d24ca6c0SPetr Machata *p_connector_type = mlxsw_reg_ptys_connector_type_get(ptys_pl);
948d24ca6c0SPetr Machata return 0;
949d24ca6c0SPetr Machata }
950d24ca6c0SPetr Machata
mlxsw_sp_port_get_link_ksettings(struct net_device * dev,struct ethtool_link_ksettings * cmd)951614d509aSAmit Cohen static int mlxsw_sp_port_get_link_ksettings(struct net_device *dev,
952614d509aSAmit Cohen struct ethtool_link_ksettings *cmd)
953614d509aSAmit Cohen {
954614d509aSAmit Cohen u32 eth_proto_cap, eth_proto_admin, eth_proto_oper;
955614d509aSAmit Cohen struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
956614d509aSAmit Cohen struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
957614d509aSAmit Cohen const struct mlxsw_sp_port_type_speed_ops *ops;
958614d509aSAmit Cohen u8 connector_type;
959614d509aSAmit Cohen bool autoneg;
960614d509aSAmit Cohen int err;
961614d509aSAmit Cohen
962d24ca6c0SPetr Machata err = mlxsw_sp_port_ptys_query(mlxsw_sp_port, ð_proto_cap, ð_proto_admin,
963d24ca6c0SPetr Machata ð_proto_oper, &connector_type);
964614d509aSAmit Cohen if (err)
965614d509aSAmit Cohen return err;
966d24ca6c0SPetr Machata
967d24ca6c0SPetr Machata ops = mlxsw_sp->port_type_speed_ops;
968d24ca6c0SPetr Machata autoneg = mlxsw_sp_port->link.autoneg;
969614d509aSAmit Cohen
9705fc4053dSDanielle Ratson mlxsw_sp_port_get_link_supported(mlxsw_sp, eth_proto_cap, cmd);
971614d509aSAmit Cohen
9725fc4053dSDanielle Ratson mlxsw_sp_port_get_link_advertise(mlxsw_sp, eth_proto_admin, autoneg, cmd);
973614d509aSAmit Cohen
974614d509aSAmit Cohen cmd->base.autoneg = autoneg ? AUTONEG_ENABLE : AUTONEG_DISABLE;
975614d509aSAmit Cohen cmd->base.port = mlxsw_sp_port_connector_port(connector_type);
97625a96f05SDanielle Ratson ops->from_ptys_link_mode(mlxsw_sp, netif_carrier_ok(dev),
977614d509aSAmit Cohen eth_proto_oper, cmd);
978614d509aSAmit Cohen
979614d509aSAmit Cohen return 0;
980614d509aSAmit Cohen }
981614d509aSAmit Cohen
982614d509aSAmit Cohen static int
mlxsw_sp_port_set_link_ksettings(struct net_device * dev,const struct ethtool_link_ksettings * cmd)983614d509aSAmit Cohen mlxsw_sp_port_set_link_ksettings(struct net_device *dev,
984614d509aSAmit Cohen const struct ethtool_link_ksettings *cmd)
985614d509aSAmit Cohen {
986614d509aSAmit Cohen struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
987614d509aSAmit Cohen struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
988614d509aSAmit Cohen const struct mlxsw_sp_port_type_speed_ops *ops;
989614d509aSAmit Cohen char ptys_pl[MLXSW_REG_PTYS_LEN];
990614d509aSAmit Cohen u32 eth_proto_cap, eth_proto_new;
991614d509aSAmit Cohen bool autoneg;
992614d509aSAmit Cohen int err;
993614d509aSAmit Cohen
994614d509aSAmit Cohen ops = mlxsw_sp->port_type_speed_ops;
995614d509aSAmit Cohen
996614d509aSAmit Cohen ops->reg_ptys_eth_pack(mlxsw_sp, ptys_pl, mlxsw_sp_port->local_port,
997614d509aSAmit Cohen 0, false);
998614d509aSAmit Cohen err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl);
999614d509aSAmit Cohen if (err)
1000614d509aSAmit Cohen return err;
1001614d509aSAmit Cohen ops->reg_ptys_eth_unpack(mlxsw_sp, ptys_pl, ð_proto_cap, NULL, NULL);
1002614d509aSAmit Cohen
1003614d509aSAmit Cohen autoneg = cmd->base.autoneg == AUTONEG_ENABLE;
1004614d509aSAmit Cohen eth_proto_new = autoneg ?
10055fc4053dSDanielle Ratson ops->to_ptys_advert_link(mlxsw_sp, cmd) :
1006763ece86SDanielle Ratson ops->to_ptys_speed_lanes(mlxsw_sp, mlxsw_sp_port->mapping.width,
1007763ece86SDanielle Ratson cmd);
1008614d509aSAmit Cohen
1009614d509aSAmit Cohen eth_proto_new = eth_proto_new & eth_proto_cap;
1010614d509aSAmit Cohen if (!eth_proto_new) {
1011763ece86SDanielle Ratson netdev_err(dev, "No supported speed or lanes requested\n");
1012614d509aSAmit Cohen return -EINVAL;
1013614d509aSAmit Cohen }
1014614d509aSAmit Cohen
1015614d509aSAmit Cohen ops->reg_ptys_eth_pack(mlxsw_sp, ptys_pl, mlxsw_sp_port->local_port,
1016614d509aSAmit Cohen eth_proto_new, autoneg);
1017614d509aSAmit Cohen err = mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl);
1018614d509aSAmit Cohen if (err)
1019614d509aSAmit Cohen return err;
1020614d509aSAmit Cohen
1021614d509aSAmit Cohen mlxsw_sp_port->link.autoneg = autoneg;
1022614d509aSAmit Cohen
1023614d509aSAmit Cohen if (!netif_running(dev))
1024614d509aSAmit Cohen return 0;
1025614d509aSAmit Cohen
1026614d509aSAmit Cohen mlxsw_sp_port_admin_status_set(mlxsw_sp_port, false);
1027614d509aSAmit Cohen mlxsw_sp_port_admin_status_set(mlxsw_sp_port, true);
1028614d509aSAmit Cohen
1029614d509aSAmit Cohen return 0;
1030614d509aSAmit Cohen }
1031614d509aSAmit Cohen
mlxsw_sp_get_module_info(struct net_device * netdev,struct ethtool_modinfo * modinfo)1032614d509aSAmit Cohen static int mlxsw_sp_get_module_info(struct net_device *netdev,
1033614d509aSAmit Cohen struct ethtool_modinfo *modinfo)
1034614d509aSAmit Cohen {
1035614d509aSAmit Cohen struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(netdev);
1036614d509aSAmit Cohen struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1037614d509aSAmit Cohen
10386445eef0SJiri Pirko return mlxsw_env_get_module_info(netdev, mlxsw_sp->core,
10396445eef0SJiri Pirko mlxsw_sp_port->mapping.slot_index,
1040614d509aSAmit Cohen mlxsw_sp_port->mapping.module,
1041614d509aSAmit Cohen modinfo);
1042614d509aSAmit Cohen }
1043614d509aSAmit Cohen
mlxsw_sp_get_module_eeprom(struct net_device * netdev,struct ethtool_eeprom * ee,u8 * data)1044614d509aSAmit Cohen static int mlxsw_sp_get_module_eeprom(struct net_device *netdev,
1045614d509aSAmit Cohen struct ethtool_eeprom *ee, u8 *data)
1046614d509aSAmit Cohen {
1047614d509aSAmit Cohen struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(netdev);
1048614d509aSAmit Cohen struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
10496445eef0SJiri Pirko u8 slot_index = mlxsw_sp_port->mapping.slot_index;
10506445eef0SJiri Pirko u8 module = mlxsw_sp_port->mapping.module;
1051614d509aSAmit Cohen
10526445eef0SJiri Pirko return mlxsw_env_get_module_eeprom(netdev, mlxsw_sp->core, slot_index,
10536445eef0SJiri Pirko module, ee, data);
1054614d509aSAmit Cohen }
1055614d509aSAmit Cohen
1056614d509aSAmit Cohen static int
mlxsw_sp_get_module_eeprom_by_page(struct net_device * dev,const struct ethtool_module_eeprom * page,struct netlink_ext_ack * extack)10571e27b9e4SIdo Schimmel mlxsw_sp_get_module_eeprom_by_page(struct net_device *dev,
10581e27b9e4SIdo Schimmel const struct ethtool_module_eeprom *page,
10591e27b9e4SIdo Schimmel struct netlink_ext_ack *extack)
10601e27b9e4SIdo Schimmel {
10611e27b9e4SIdo Schimmel struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
10621e27b9e4SIdo Schimmel struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
10636445eef0SJiri Pirko u8 slot_index = mlxsw_sp_port->mapping.slot_index;
10641e27b9e4SIdo Schimmel u8 module = mlxsw_sp_port->mapping.module;
10651e27b9e4SIdo Schimmel
10666445eef0SJiri Pirko return mlxsw_env_get_module_eeprom_by_page(mlxsw_sp->core, slot_index,
10676445eef0SJiri Pirko module, page, extack);
10681e27b9e4SIdo Schimmel }
10691e27b9e4SIdo Schimmel
10701e27b9e4SIdo Schimmel static int
mlxsw_sp_get_ts_info(struct net_device * netdev,struct ethtool_ts_info * info)1071614d509aSAmit Cohen mlxsw_sp_get_ts_info(struct net_device *netdev, struct ethtool_ts_info *info)
1072614d509aSAmit Cohen {
1073614d509aSAmit Cohen struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(netdev);
1074614d509aSAmit Cohen struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
1075614d509aSAmit Cohen
1076614d509aSAmit Cohen return mlxsw_sp->ptp_ops->get_ts_info(mlxsw_sp, info);
1077614d509aSAmit Cohen }
1078614d509aSAmit Cohen
1079c1912ab0SJakub Kicinski static void
mlxsw_sp_get_eth_phy_stats(struct net_device * dev,struct ethtool_eth_phy_stats * phy_stats)1080c1912ab0SJakub Kicinski mlxsw_sp_get_eth_phy_stats(struct net_device *dev,
1081c1912ab0SJakub Kicinski struct ethtool_eth_phy_stats *phy_stats)
1082c1912ab0SJakub Kicinski {
1083c1912ab0SJakub Kicinski char ppcnt_pl[MLXSW_REG_PPCNT_LEN];
1084c1912ab0SJakub Kicinski
1085c1912ab0SJakub Kicinski if (mlxsw_sp_port_get_stats_raw(dev, MLXSW_REG_PPCNT_IEEE_8023_CNT,
1086c1912ab0SJakub Kicinski 0, ppcnt_pl))
1087c1912ab0SJakub Kicinski return;
1088c1912ab0SJakub Kicinski
1089c1912ab0SJakub Kicinski phy_stats->SymbolErrorDuringCarrier =
1090c1912ab0SJakub Kicinski mlxsw_reg_ppcnt_a_symbol_error_during_carrier_get(ppcnt_pl);
1091c1912ab0SJakub Kicinski }
1092c1912ab0SJakub Kicinski
1093c1912ab0SJakub Kicinski static void
mlxsw_sp_get_eth_mac_stats(struct net_device * dev,struct ethtool_eth_mac_stats * mac_stats)1094c1912ab0SJakub Kicinski mlxsw_sp_get_eth_mac_stats(struct net_device *dev,
1095c1912ab0SJakub Kicinski struct ethtool_eth_mac_stats *mac_stats)
1096c1912ab0SJakub Kicinski {
1097c1912ab0SJakub Kicinski char ppcnt_pl[MLXSW_REG_PPCNT_LEN];
1098c1912ab0SJakub Kicinski
1099c1912ab0SJakub Kicinski if (mlxsw_sp_port_get_stats_raw(dev, MLXSW_REG_PPCNT_IEEE_8023_CNT,
1100c1912ab0SJakub Kicinski 0, ppcnt_pl))
1101c1912ab0SJakub Kicinski return;
1102c1912ab0SJakub Kicinski
1103c1912ab0SJakub Kicinski mac_stats->FramesTransmittedOK =
1104c1912ab0SJakub Kicinski mlxsw_reg_ppcnt_a_frames_transmitted_ok_get(ppcnt_pl);
1105c1912ab0SJakub Kicinski mac_stats->FramesReceivedOK =
1106c1912ab0SJakub Kicinski mlxsw_reg_ppcnt_a_frames_received_ok_get(ppcnt_pl);
1107c1912ab0SJakub Kicinski mac_stats->FrameCheckSequenceErrors =
1108c1912ab0SJakub Kicinski mlxsw_reg_ppcnt_a_frame_check_sequence_errors_get(ppcnt_pl);
1109c1912ab0SJakub Kicinski mac_stats->AlignmentErrors =
1110c1912ab0SJakub Kicinski mlxsw_reg_ppcnt_a_alignment_errors_get(ppcnt_pl);
1111c1912ab0SJakub Kicinski mac_stats->OctetsTransmittedOK =
1112c1912ab0SJakub Kicinski mlxsw_reg_ppcnt_a_octets_transmitted_ok_get(ppcnt_pl);
1113c1912ab0SJakub Kicinski mac_stats->OctetsReceivedOK =
1114c1912ab0SJakub Kicinski mlxsw_reg_ppcnt_a_octets_received_ok_get(ppcnt_pl);
1115c1912ab0SJakub Kicinski mac_stats->MulticastFramesXmittedOK =
1116c1912ab0SJakub Kicinski mlxsw_reg_ppcnt_a_multicast_frames_xmitted_ok_get(ppcnt_pl);
1117c1912ab0SJakub Kicinski mac_stats->BroadcastFramesXmittedOK =
1118c1912ab0SJakub Kicinski mlxsw_reg_ppcnt_a_broadcast_frames_xmitted_ok_get(ppcnt_pl);
1119c1912ab0SJakub Kicinski mac_stats->MulticastFramesReceivedOK =
1120c1912ab0SJakub Kicinski mlxsw_reg_ppcnt_a_multicast_frames_received_ok_get(ppcnt_pl);
1121c1912ab0SJakub Kicinski mac_stats->BroadcastFramesReceivedOK =
1122c1912ab0SJakub Kicinski mlxsw_reg_ppcnt_a_broadcast_frames_received_ok_get(ppcnt_pl);
1123c1912ab0SJakub Kicinski mac_stats->InRangeLengthErrors =
1124c1912ab0SJakub Kicinski mlxsw_reg_ppcnt_a_in_range_length_errors_get(ppcnt_pl);
1125c1912ab0SJakub Kicinski mac_stats->OutOfRangeLengthField =
1126c1912ab0SJakub Kicinski mlxsw_reg_ppcnt_a_out_of_range_length_field_get(ppcnt_pl);
1127c1912ab0SJakub Kicinski mac_stats->FrameTooLongErrors =
1128c1912ab0SJakub Kicinski mlxsw_reg_ppcnt_a_frame_too_long_errors_get(ppcnt_pl);
1129c1912ab0SJakub Kicinski }
1130c1912ab0SJakub Kicinski
1131c1912ab0SJakub Kicinski static void
mlxsw_sp_get_eth_ctrl_stats(struct net_device * dev,struct ethtool_eth_ctrl_stats * ctrl_stats)1132c1912ab0SJakub Kicinski mlxsw_sp_get_eth_ctrl_stats(struct net_device *dev,
1133c1912ab0SJakub Kicinski struct ethtool_eth_ctrl_stats *ctrl_stats)
1134c1912ab0SJakub Kicinski {
1135c1912ab0SJakub Kicinski char ppcnt_pl[MLXSW_REG_PPCNT_LEN];
1136c1912ab0SJakub Kicinski
1137c1912ab0SJakub Kicinski if (mlxsw_sp_port_get_stats_raw(dev, MLXSW_REG_PPCNT_IEEE_8023_CNT,
1138c1912ab0SJakub Kicinski 0, ppcnt_pl))
1139c1912ab0SJakub Kicinski return;
1140c1912ab0SJakub Kicinski
1141c1912ab0SJakub Kicinski ctrl_stats->MACControlFramesTransmitted =
1142c1912ab0SJakub Kicinski mlxsw_reg_ppcnt_a_mac_control_frames_transmitted_get(ppcnt_pl);
1143c1912ab0SJakub Kicinski ctrl_stats->MACControlFramesReceived =
1144c1912ab0SJakub Kicinski mlxsw_reg_ppcnt_a_mac_control_frames_received_get(ppcnt_pl);
1145c1912ab0SJakub Kicinski ctrl_stats->UnsupportedOpcodesReceived =
1146c1912ab0SJakub Kicinski mlxsw_reg_ppcnt_a_unsupported_opcodes_received_get(ppcnt_pl);
1147c1912ab0SJakub Kicinski }
1148c1912ab0SJakub Kicinski
1149c1912ab0SJakub Kicinski static const struct ethtool_rmon_hist_range mlxsw_rmon_ranges[] = {
1150c1912ab0SJakub Kicinski { 0, 64 },
1151c1912ab0SJakub Kicinski { 65, 127 },
1152c1912ab0SJakub Kicinski { 128, 255 },
1153c1912ab0SJakub Kicinski { 256, 511 },
1154c1912ab0SJakub Kicinski { 512, 1023 },
1155c1912ab0SJakub Kicinski { 1024, 1518 },
1156c1912ab0SJakub Kicinski { 1519, 2047 },
1157c1912ab0SJakub Kicinski { 2048, 4095 },
1158c1912ab0SJakub Kicinski { 4096, 8191 },
1159c1912ab0SJakub Kicinski { 8192, 10239 },
1160c1912ab0SJakub Kicinski {}
1161c1912ab0SJakub Kicinski };
1162c1912ab0SJakub Kicinski
1163c1912ab0SJakub Kicinski static void
mlxsw_sp_get_rmon_stats(struct net_device * dev,struct ethtool_rmon_stats * rmon,const struct ethtool_rmon_hist_range ** ranges)1164c1912ab0SJakub Kicinski mlxsw_sp_get_rmon_stats(struct net_device *dev,
1165c1912ab0SJakub Kicinski struct ethtool_rmon_stats *rmon,
1166c1912ab0SJakub Kicinski const struct ethtool_rmon_hist_range **ranges)
1167c1912ab0SJakub Kicinski {
1168c1912ab0SJakub Kicinski char ppcnt_pl[MLXSW_REG_PPCNT_LEN];
1169c1912ab0SJakub Kicinski
1170c1912ab0SJakub Kicinski if (mlxsw_sp_port_get_stats_raw(dev, MLXSW_REG_PPCNT_RFC_2819_CNT,
1171c1912ab0SJakub Kicinski 0, ppcnt_pl))
1172c1912ab0SJakub Kicinski return;
1173c1912ab0SJakub Kicinski
1174c1912ab0SJakub Kicinski rmon->undersize_pkts =
1175c1912ab0SJakub Kicinski mlxsw_reg_ppcnt_ether_stats_undersize_pkts_get(ppcnt_pl);
1176c1912ab0SJakub Kicinski rmon->oversize_pkts =
1177c1912ab0SJakub Kicinski mlxsw_reg_ppcnt_ether_stats_oversize_pkts_get(ppcnt_pl);
1178c1912ab0SJakub Kicinski rmon->fragments =
1179c1912ab0SJakub Kicinski mlxsw_reg_ppcnt_ether_stats_fragments_get(ppcnt_pl);
1180c1912ab0SJakub Kicinski
1181c1912ab0SJakub Kicinski rmon->hist[0] = mlxsw_reg_ppcnt_ether_stats_pkts64octets_get(ppcnt_pl);
1182c1912ab0SJakub Kicinski rmon->hist[1] =
1183c1912ab0SJakub Kicinski mlxsw_reg_ppcnt_ether_stats_pkts65to127octets_get(ppcnt_pl);
1184c1912ab0SJakub Kicinski rmon->hist[2] =
1185c1912ab0SJakub Kicinski mlxsw_reg_ppcnt_ether_stats_pkts128to255octets_get(ppcnt_pl);
1186c1912ab0SJakub Kicinski rmon->hist[3] =
1187c1912ab0SJakub Kicinski mlxsw_reg_ppcnt_ether_stats_pkts256to511octets_get(ppcnt_pl);
1188c1912ab0SJakub Kicinski rmon->hist[4] =
1189c1912ab0SJakub Kicinski mlxsw_reg_ppcnt_ether_stats_pkts512to1023octets_get(ppcnt_pl);
1190c1912ab0SJakub Kicinski rmon->hist[5] =
1191c1912ab0SJakub Kicinski mlxsw_reg_ppcnt_ether_stats_pkts1024to1518octets_get(ppcnt_pl);
1192c1912ab0SJakub Kicinski rmon->hist[6] =
1193c1912ab0SJakub Kicinski mlxsw_reg_ppcnt_ether_stats_pkts1519to2047octets_get(ppcnt_pl);
1194c1912ab0SJakub Kicinski rmon->hist[7] =
1195c1912ab0SJakub Kicinski mlxsw_reg_ppcnt_ether_stats_pkts2048to4095octets_get(ppcnt_pl);
1196c1912ab0SJakub Kicinski rmon->hist[8] =
1197c1912ab0SJakub Kicinski mlxsw_reg_ppcnt_ether_stats_pkts4096to8191octets_get(ppcnt_pl);
1198c1912ab0SJakub Kicinski rmon->hist[9] =
1199c1912ab0SJakub Kicinski mlxsw_reg_ppcnt_ether_stats_pkts8192to10239octets_get(ppcnt_pl);
1200c1912ab0SJakub Kicinski
1201c1912ab0SJakub Kicinski *ranges = mlxsw_rmon_ranges;
1202c1912ab0SJakub Kicinski }
1203c1912ab0SJakub Kicinski
mlxsw_sp_reset(struct net_device * dev,u32 * flags)120449fd3b64SIdo Schimmel static int mlxsw_sp_reset(struct net_device *dev, u32 *flags)
120549fd3b64SIdo Schimmel {
120649fd3b64SIdo Schimmel struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
120749fd3b64SIdo Schimmel struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
12086445eef0SJiri Pirko u8 slot_index = mlxsw_sp_port->mapping.slot_index;
120949fd3b64SIdo Schimmel u8 module = mlxsw_sp_port->mapping.module;
121049fd3b64SIdo Schimmel
12116445eef0SJiri Pirko return mlxsw_env_reset_module(dev, mlxsw_sp->core, slot_index,
12126445eef0SJiri Pirko module, flags);
121349fd3b64SIdo Schimmel }
121449fd3b64SIdo Schimmel
12150455dc50SIdo Schimmel static int
mlxsw_sp_get_module_power_mode(struct net_device * dev,struct ethtool_module_power_mode_params * params,struct netlink_ext_ack * extack)12160455dc50SIdo Schimmel mlxsw_sp_get_module_power_mode(struct net_device *dev,
12170455dc50SIdo Schimmel struct ethtool_module_power_mode_params *params,
12180455dc50SIdo Schimmel struct netlink_ext_ack *extack)
12190455dc50SIdo Schimmel {
12200455dc50SIdo Schimmel struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
12210455dc50SIdo Schimmel struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
12226445eef0SJiri Pirko u8 slot_index = mlxsw_sp_port->mapping.slot_index;
12230455dc50SIdo Schimmel u8 module = mlxsw_sp_port->mapping.module;
12240455dc50SIdo Schimmel
12256445eef0SJiri Pirko return mlxsw_env_get_module_power_mode(mlxsw_sp->core, slot_index,
12266445eef0SJiri Pirko module, params, extack);
12270455dc50SIdo Schimmel }
12280455dc50SIdo Schimmel
12290455dc50SIdo Schimmel static int
mlxsw_sp_set_module_power_mode(struct net_device * dev,const struct ethtool_module_power_mode_params * params,struct netlink_ext_ack * extack)12300455dc50SIdo Schimmel mlxsw_sp_set_module_power_mode(struct net_device *dev,
12310455dc50SIdo Schimmel const struct ethtool_module_power_mode_params *params,
12320455dc50SIdo Schimmel struct netlink_ext_ack *extack)
12330455dc50SIdo Schimmel {
12340455dc50SIdo Schimmel struct mlxsw_sp_port *mlxsw_sp_port = netdev_priv(dev);
12350455dc50SIdo Schimmel struct mlxsw_sp *mlxsw_sp = mlxsw_sp_port->mlxsw_sp;
12366445eef0SJiri Pirko u8 slot_index = mlxsw_sp_port->mapping.slot_index;
12370455dc50SIdo Schimmel u8 module = mlxsw_sp_port->mapping.module;
12380455dc50SIdo Schimmel
12396445eef0SJiri Pirko return mlxsw_env_set_module_power_mode(mlxsw_sp->core, slot_index,
12406445eef0SJiri Pirko module, params->policy, extack);
12410455dc50SIdo Schimmel }
12420455dc50SIdo Schimmel
1243614d509aSAmit Cohen const struct ethtool_ops mlxsw_sp_port_ethtool_ops = {
1244763ece86SDanielle Ratson .cap_link_lanes_supported = true,
1245614d509aSAmit Cohen .get_drvinfo = mlxsw_sp_port_get_drvinfo,
1246614d509aSAmit Cohen .get_link = ethtool_op_get_link,
124760f30cd6SAmit Cohen .get_link_ext_state = mlxsw_sp_port_get_link_ext_state,
1248614d509aSAmit Cohen .get_pauseparam = mlxsw_sp_port_get_pauseparam,
1249614d509aSAmit Cohen .set_pauseparam = mlxsw_sp_port_set_pauseparam,
1250614d509aSAmit Cohen .get_strings = mlxsw_sp_port_get_strings,
1251614d509aSAmit Cohen .set_phys_id = mlxsw_sp_port_set_phys_id,
1252614d509aSAmit Cohen .get_ethtool_stats = mlxsw_sp_port_get_stats,
1253614d509aSAmit Cohen .get_sset_count = mlxsw_sp_port_get_sset_count,
1254614d509aSAmit Cohen .get_link_ksettings = mlxsw_sp_port_get_link_ksettings,
1255614d509aSAmit Cohen .set_link_ksettings = mlxsw_sp_port_set_link_ksettings,
1256614d509aSAmit Cohen .get_module_info = mlxsw_sp_get_module_info,
1257614d509aSAmit Cohen .get_module_eeprom = mlxsw_sp_get_module_eeprom,
12581e27b9e4SIdo Schimmel .get_module_eeprom_by_page = mlxsw_sp_get_module_eeprom_by_page,
1259614d509aSAmit Cohen .get_ts_info = mlxsw_sp_get_ts_info,
1260c1912ab0SJakub Kicinski .get_eth_phy_stats = mlxsw_sp_get_eth_phy_stats,
1261c1912ab0SJakub Kicinski .get_eth_mac_stats = mlxsw_sp_get_eth_mac_stats,
1262c1912ab0SJakub Kicinski .get_eth_ctrl_stats = mlxsw_sp_get_eth_ctrl_stats,
1263c1912ab0SJakub Kicinski .get_rmon_stats = mlxsw_sp_get_rmon_stats,
126449fd3b64SIdo Schimmel .reset = mlxsw_sp_reset,
12650455dc50SIdo Schimmel .get_module_power_mode = mlxsw_sp_get_module_power_mode,
12660455dc50SIdo Schimmel .set_module_power_mode = mlxsw_sp_set_module_power_mode,
1267614d509aSAmit Cohen };
12682be5c8a9SAmit Cohen
12692be5c8a9SAmit Cohen struct mlxsw_sp1_port_link_mode {
12702be5c8a9SAmit Cohen enum ethtool_link_mode_bit_indices mask_ethtool;
12712be5c8a9SAmit Cohen u32 mask;
12722be5c8a9SAmit Cohen u32 speed;
12732be5c8a9SAmit Cohen };
12742be5c8a9SAmit Cohen
12752be5c8a9SAmit Cohen static const struct mlxsw_sp1_port_link_mode mlxsw_sp1_port_link_mode[] = {
12762be5c8a9SAmit Cohen {
127778cf4b92SDanielle Ratson .mask = MLXSW_REG_PTYS_ETH_SPEED_100BASE_T,
127878cf4b92SDanielle Ratson .mask_ethtool = ETHTOOL_LINK_MODE_100baseT_Full_BIT,
127978cf4b92SDanielle Ratson .speed = SPEED_100,
128078cf4b92SDanielle Ratson },
128178cf4b92SDanielle Ratson {
12822be5c8a9SAmit Cohen .mask = MLXSW_REG_PTYS_ETH_SPEED_SGMII |
12832be5c8a9SAmit Cohen MLXSW_REG_PTYS_ETH_SPEED_1000BASE_KX,
12842be5c8a9SAmit Cohen .mask_ethtool = ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
12852be5c8a9SAmit Cohen .speed = SPEED_1000,
12862be5c8a9SAmit Cohen },
12872be5c8a9SAmit Cohen {
128878cf4b92SDanielle Ratson .mask = MLXSW_REG_PTYS_ETH_SPEED_1000BASE_T,
128978cf4b92SDanielle Ratson .mask_ethtool = ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
129078cf4b92SDanielle Ratson .speed = SPEED_1000,
129178cf4b92SDanielle Ratson },
129278cf4b92SDanielle Ratson {
12932be5c8a9SAmit Cohen .mask = MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CX4 |
12942be5c8a9SAmit Cohen MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KX4,
12952be5c8a9SAmit Cohen .mask_ethtool = ETHTOOL_LINK_MODE_10000baseKX4_Full_BIT,
12962be5c8a9SAmit Cohen .speed = SPEED_10000,
12972be5c8a9SAmit Cohen },
12982be5c8a9SAmit Cohen {
12992be5c8a9SAmit Cohen .mask = MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KR |
13002be5c8a9SAmit Cohen MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CR |
13012be5c8a9SAmit Cohen MLXSW_REG_PTYS_ETH_SPEED_10GBASE_SR |
13022be5c8a9SAmit Cohen MLXSW_REG_PTYS_ETH_SPEED_10GBASE_ER_LR,
13032be5c8a9SAmit Cohen .mask_ethtool = ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
13042be5c8a9SAmit Cohen .speed = SPEED_10000,
13052be5c8a9SAmit Cohen },
13062be5c8a9SAmit Cohen {
13072be5c8a9SAmit Cohen .mask = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_CR4,
13082be5c8a9SAmit Cohen .mask_ethtool = ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT,
13092be5c8a9SAmit Cohen .speed = SPEED_40000,
13102be5c8a9SAmit Cohen },
13112be5c8a9SAmit Cohen {
13122be5c8a9SAmit Cohen .mask = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_KR4,
13132be5c8a9SAmit Cohen .mask_ethtool = ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT,
13142be5c8a9SAmit Cohen .speed = SPEED_40000,
13152be5c8a9SAmit Cohen },
13162be5c8a9SAmit Cohen {
13172be5c8a9SAmit Cohen .mask = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_SR4,
13182be5c8a9SAmit Cohen .mask_ethtool = ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT,
13192be5c8a9SAmit Cohen .speed = SPEED_40000,
13202be5c8a9SAmit Cohen },
13212be5c8a9SAmit Cohen {
13222be5c8a9SAmit Cohen .mask = MLXSW_REG_PTYS_ETH_SPEED_40GBASE_LR4_ER4,
13232be5c8a9SAmit Cohen .mask_ethtool = ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT,
13242be5c8a9SAmit Cohen .speed = SPEED_40000,
13252be5c8a9SAmit Cohen },
13262be5c8a9SAmit Cohen {
13272be5c8a9SAmit Cohen .mask = MLXSW_REG_PTYS_ETH_SPEED_25GBASE_CR,
13282be5c8a9SAmit Cohen .mask_ethtool = ETHTOOL_LINK_MODE_25000baseCR_Full_BIT,
13292be5c8a9SAmit Cohen .speed = SPEED_25000,
13302be5c8a9SAmit Cohen },
13312be5c8a9SAmit Cohen {
13322be5c8a9SAmit Cohen .mask = MLXSW_REG_PTYS_ETH_SPEED_25GBASE_KR,
13332be5c8a9SAmit Cohen .mask_ethtool = ETHTOOL_LINK_MODE_25000baseKR_Full_BIT,
13342be5c8a9SAmit Cohen .speed = SPEED_25000,
13352be5c8a9SAmit Cohen },
13362be5c8a9SAmit Cohen {
13372be5c8a9SAmit Cohen .mask = MLXSW_REG_PTYS_ETH_SPEED_25GBASE_SR,
13382be5c8a9SAmit Cohen .mask_ethtool = ETHTOOL_LINK_MODE_25000baseSR_Full_BIT,
13392be5c8a9SAmit Cohen .speed = SPEED_25000,
13402be5c8a9SAmit Cohen },
13412be5c8a9SAmit Cohen {
13422be5c8a9SAmit Cohen .mask = MLXSW_REG_PTYS_ETH_SPEED_50GBASE_CR2,
13432be5c8a9SAmit Cohen .mask_ethtool = ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT,
13442be5c8a9SAmit Cohen .speed = SPEED_50000,
13452be5c8a9SAmit Cohen },
13462be5c8a9SAmit Cohen {
13472be5c8a9SAmit Cohen .mask = MLXSW_REG_PTYS_ETH_SPEED_50GBASE_KR2,
13482be5c8a9SAmit Cohen .mask_ethtool = ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT,
13492be5c8a9SAmit Cohen .speed = SPEED_50000,
13502be5c8a9SAmit Cohen },
13512be5c8a9SAmit Cohen {
13522be5c8a9SAmit Cohen .mask = MLXSW_REG_PTYS_ETH_SPEED_50GBASE_SR2,
13532be5c8a9SAmit Cohen .mask_ethtool = ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT,
13542be5c8a9SAmit Cohen .speed = SPEED_50000,
13552be5c8a9SAmit Cohen },
13562be5c8a9SAmit Cohen {
13572be5c8a9SAmit Cohen .mask = MLXSW_REG_PTYS_ETH_SPEED_100GBASE_CR4,
13582be5c8a9SAmit Cohen .mask_ethtool = ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT,
13592be5c8a9SAmit Cohen .speed = SPEED_100000,
13602be5c8a9SAmit Cohen },
13612be5c8a9SAmit Cohen {
13622be5c8a9SAmit Cohen .mask = MLXSW_REG_PTYS_ETH_SPEED_100GBASE_SR4,
13632be5c8a9SAmit Cohen .mask_ethtool = ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT,
13642be5c8a9SAmit Cohen .speed = SPEED_100000,
13652be5c8a9SAmit Cohen },
13662be5c8a9SAmit Cohen {
13672be5c8a9SAmit Cohen .mask = MLXSW_REG_PTYS_ETH_SPEED_100GBASE_KR4,
13682be5c8a9SAmit Cohen .mask_ethtool = ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT,
13692be5c8a9SAmit Cohen .speed = SPEED_100000,
13702be5c8a9SAmit Cohen },
1371ae9b24ddSDanielle Ratson {
1372ae9b24ddSDanielle Ratson .mask = MLXSW_REG_PTYS_ETH_SPEED_100GBASE_LR4_ER4,
1373ae9b24ddSDanielle Ratson .mask_ethtool = ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT,
1374ae9b24ddSDanielle Ratson .speed = SPEED_100000,
1375ae9b24ddSDanielle Ratson },
13762be5c8a9SAmit Cohen };
13772be5c8a9SAmit Cohen
13782be5c8a9SAmit Cohen #define MLXSW_SP1_PORT_LINK_MODE_LEN ARRAY_SIZE(mlxsw_sp1_port_link_mode)
13792be5c8a9SAmit Cohen
13802be5c8a9SAmit Cohen static void
mlxsw_sp1_from_ptys_supported_port(struct mlxsw_sp * mlxsw_sp,u32 ptys_eth_proto,struct ethtool_link_ksettings * cmd)13812be5c8a9SAmit Cohen mlxsw_sp1_from_ptys_supported_port(struct mlxsw_sp *mlxsw_sp,
13822be5c8a9SAmit Cohen u32 ptys_eth_proto,
13832be5c8a9SAmit Cohen struct ethtool_link_ksettings *cmd)
13842be5c8a9SAmit Cohen {
13852be5c8a9SAmit Cohen if (ptys_eth_proto & (MLXSW_REG_PTYS_ETH_SPEED_10GBASE_CR |
13862be5c8a9SAmit Cohen MLXSW_REG_PTYS_ETH_SPEED_10GBASE_SR |
13872be5c8a9SAmit Cohen MLXSW_REG_PTYS_ETH_SPEED_40GBASE_CR4 |
13882be5c8a9SAmit Cohen MLXSW_REG_PTYS_ETH_SPEED_40GBASE_SR4 |
13892be5c8a9SAmit Cohen MLXSW_REG_PTYS_ETH_SPEED_100GBASE_SR4 |
13902be5c8a9SAmit Cohen MLXSW_REG_PTYS_ETH_SPEED_SGMII))
13912be5c8a9SAmit Cohen ethtool_link_ksettings_add_link_mode(cmd, supported, FIBRE);
13922be5c8a9SAmit Cohen
13932be5c8a9SAmit Cohen if (ptys_eth_proto & (MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KR |
13942be5c8a9SAmit Cohen MLXSW_REG_PTYS_ETH_SPEED_10GBASE_KX4 |
13952be5c8a9SAmit Cohen MLXSW_REG_PTYS_ETH_SPEED_40GBASE_KR4 |
13962be5c8a9SAmit Cohen MLXSW_REG_PTYS_ETH_SPEED_100GBASE_KR4 |
13972be5c8a9SAmit Cohen MLXSW_REG_PTYS_ETH_SPEED_1000BASE_KX))
13982be5c8a9SAmit Cohen ethtool_link_ksettings_add_link_mode(cmd, supported, Backplane);
13992be5c8a9SAmit Cohen }
14002be5c8a9SAmit Cohen
14012be5c8a9SAmit Cohen static void
mlxsw_sp1_from_ptys_link(struct mlxsw_sp * mlxsw_sp,u32 ptys_eth_proto,unsigned long * mode)14022be5c8a9SAmit Cohen mlxsw_sp1_from_ptys_link(struct mlxsw_sp *mlxsw_sp, u32 ptys_eth_proto,
14035fc4053dSDanielle Ratson unsigned long *mode)
14042be5c8a9SAmit Cohen {
14052be5c8a9SAmit Cohen int i;
14062be5c8a9SAmit Cohen
14072be5c8a9SAmit Cohen for (i = 0; i < MLXSW_SP1_PORT_LINK_MODE_LEN; i++) {
14082be5c8a9SAmit Cohen if (ptys_eth_proto & mlxsw_sp1_port_link_mode[i].mask)
14092be5c8a9SAmit Cohen __set_bit(mlxsw_sp1_port_link_mode[i].mask_ethtool,
14102be5c8a9SAmit Cohen mode);
14112be5c8a9SAmit Cohen }
14122be5c8a9SAmit Cohen }
14132be5c8a9SAmit Cohen
14142be5c8a9SAmit Cohen static u32
mlxsw_sp1_from_ptys_speed(struct mlxsw_sp * mlxsw_sp,u32 ptys_eth_proto)14152be5c8a9SAmit Cohen mlxsw_sp1_from_ptys_speed(struct mlxsw_sp *mlxsw_sp, u32 ptys_eth_proto)
14162be5c8a9SAmit Cohen {
14172be5c8a9SAmit Cohen int i;
14182be5c8a9SAmit Cohen
14192be5c8a9SAmit Cohen for (i = 0; i < MLXSW_SP1_PORT_LINK_MODE_LEN; i++) {
14202be5c8a9SAmit Cohen if (ptys_eth_proto & mlxsw_sp1_port_link_mode[i].mask)
14212be5c8a9SAmit Cohen return mlxsw_sp1_port_link_mode[i].speed;
14222be5c8a9SAmit Cohen }
14232be5c8a9SAmit Cohen
14242be5c8a9SAmit Cohen return SPEED_UNKNOWN;
14252be5c8a9SAmit Cohen }
14262be5c8a9SAmit Cohen
14272be5c8a9SAmit Cohen static void
mlxsw_sp1_from_ptys_link_mode(struct mlxsw_sp * mlxsw_sp,bool carrier_ok,u32 ptys_eth_proto,struct ethtool_link_ksettings * cmd)142825a96f05SDanielle Ratson mlxsw_sp1_from_ptys_link_mode(struct mlxsw_sp *mlxsw_sp, bool carrier_ok,
14292be5c8a9SAmit Cohen u32 ptys_eth_proto,
14302be5c8a9SAmit Cohen struct ethtool_link_ksettings *cmd)
14312be5c8a9SAmit Cohen {
1432a975d7d8SDanielle Ratson struct mlxsw_sp1_port_link_mode link;
143325a96f05SDanielle Ratson int i;
143425a96f05SDanielle Ratson
1435a975d7d8SDanielle Ratson cmd->base.speed = SPEED_UNKNOWN;
1436a975d7d8SDanielle Ratson cmd->base.duplex = DUPLEX_UNKNOWN;
1437a975d7d8SDanielle Ratson cmd->lanes = 0;
14382be5c8a9SAmit Cohen
14392be5c8a9SAmit Cohen if (!carrier_ok)
14402be5c8a9SAmit Cohen return;
14412be5c8a9SAmit Cohen
144225a96f05SDanielle Ratson for (i = 0; i < MLXSW_SP1_PORT_LINK_MODE_LEN; i++) {
1443a975d7d8SDanielle Ratson if (ptys_eth_proto & mlxsw_sp1_port_link_mode[i].mask) {
1444a975d7d8SDanielle Ratson link = mlxsw_sp1_port_link_mode[i];
1445a975d7d8SDanielle Ratson ethtool_params_from_link_mode(cmd,
1446a975d7d8SDanielle Ratson link.mask_ethtool);
1447a975d7d8SDanielle Ratson }
144825a96f05SDanielle Ratson }
14492be5c8a9SAmit Cohen }
14502be5c8a9SAmit Cohen
mlxsw_sp1_ptys_max_speed(struct mlxsw_sp_port * mlxsw_sp_port,u32 * p_max_speed)145160fbc521SPetr Machata static int mlxsw_sp1_ptys_max_speed(struct mlxsw_sp_port *mlxsw_sp_port, u32 *p_max_speed)
145260fbc521SPetr Machata {
145360fbc521SPetr Machata u32 eth_proto_cap;
145460fbc521SPetr Machata u32 max_speed = 0;
145560fbc521SPetr Machata int err;
145660fbc521SPetr Machata int i;
145760fbc521SPetr Machata
145860fbc521SPetr Machata err = mlxsw_sp_port_ptys_query(mlxsw_sp_port, ð_proto_cap, NULL, NULL, NULL);
145960fbc521SPetr Machata if (err)
146060fbc521SPetr Machata return err;
146160fbc521SPetr Machata
146260fbc521SPetr Machata for (i = 0; i < MLXSW_SP1_PORT_LINK_MODE_LEN; i++) {
146360fbc521SPetr Machata if ((eth_proto_cap & mlxsw_sp1_port_link_mode[i].mask) &&
146460fbc521SPetr Machata mlxsw_sp1_port_link_mode[i].speed > max_speed)
146560fbc521SPetr Machata max_speed = mlxsw_sp1_port_link_mode[i].speed;
146660fbc521SPetr Machata }
146760fbc521SPetr Machata
146860fbc521SPetr Machata *p_max_speed = max_speed;
146960fbc521SPetr Machata return 0;
147060fbc521SPetr Machata }
147160fbc521SPetr Machata
14722be5c8a9SAmit Cohen static u32
mlxsw_sp1_to_ptys_advert_link(struct mlxsw_sp * mlxsw_sp,const struct ethtool_link_ksettings * cmd)14735fc4053dSDanielle Ratson mlxsw_sp1_to_ptys_advert_link(struct mlxsw_sp *mlxsw_sp,
14742be5c8a9SAmit Cohen const struct ethtool_link_ksettings *cmd)
14752be5c8a9SAmit Cohen {
14762be5c8a9SAmit Cohen u32 ptys_proto = 0;
14772be5c8a9SAmit Cohen int i;
14782be5c8a9SAmit Cohen
14792be5c8a9SAmit Cohen for (i = 0; i < MLXSW_SP1_PORT_LINK_MODE_LEN; i++) {
14802be5c8a9SAmit Cohen if (test_bit(mlxsw_sp1_port_link_mode[i].mask_ethtool,
14812be5c8a9SAmit Cohen cmd->link_modes.advertising))
14822be5c8a9SAmit Cohen ptys_proto |= mlxsw_sp1_port_link_mode[i].mask;
14832be5c8a9SAmit Cohen }
14842be5c8a9SAmit Cohen return ptys_proto;
14852be5c8a9SAmit Cohen }
14862be5c8a9SAmit Cohen
mlxsw_sp1_to_ptys_speed_lanes(struct mlxsw_sp * mlxsw_sp,u8 width,const struct ethtool_link_ksettings * cmd)1487763ece86SDanielle Ratson static u32 mlxsw_sp1_to_ptys_speed_lanes(struct mlxsw_sp *mlxsw_sp, u8 width,
1488763ece86SDanielle Ratson const struct ethtool_link_ksettings *cmd)
14892be5c8a9SAmit Cohen {
14902be5c8a9SAmit Cohen u32 ptys_proto = 0;
14912be5c8a9SAmit Cohen int i;
14922be5c8a9SAmit Cohen
1493763ece86SDanielle Ratson if (cmd->lanes > width)
1494763ece86SDanielle Ratson return ptys_proto;
1495763ece86SDanielle Ratson
14962be5c8a9SAmit Cohen for (i = 0; i < MLXSW_SP1_PORT_LINK_MODE_LEN; i++) {
1497763ece86SDanielle Ratson if (cmd->base.speed == mlxsw_sp1_port_link_mode[i].speed)
14982be5c8a9SAmit Cohen ptys_proto |= mlxsw_sp1_port_link_mode[i].mask;
14992be5c8a9SAmit Cohen }
15002be5c8a9SAmit Cohen return ptys_proto;
15012be5c8a9SAmit Cohen }
15022be5c8a9SAmit Cohen
15032be5c8a9SAmit Cohen static void
mlxsw_sp1_reg_ptys_eth_pack(struct mlxsw_sp * mlxsw_sp,char * payload,u16 local_port,u32 proto_admin,bool autoneg)15042be5c8a9SAmit Cohen mlxsw_sp1_reg_ptys_eth_pack(struct mlxsw_sp *mlxsw_sp, char *payload,
1505c934757dSAmit Cohen u16 local_port, u32 proto_admin, bool autoneg)
15062be5c8a9SAmit Cohen {
15072be5c8a9SAmit Cohen mlxsw_reg_ptys_eth_pack(payload, local_port, proto_admin, autoneg);
15082be5c8a9SAmit Cohen }
15092be5c8a9SAmit Cohen
15102be5c8a9SAmit Cohen static void
mlxsw_sp1_reg_ptys_eth_unpack(struct mlxsw_sp * mlxsw_sp,char * payload,u32 * p_eth_proto_cap,u32 * p_eth_proto_admin,u32 * p_eth_proto_oper)15112be5c8a9SAmit Cohen mlxsw_sp1_reg_ptys_eth_unpack(struct mlxsw_sp *mlxsw_sp, char *payload,
15122be5c8a9SAmit Cohen u32 *p_eth_proto_cap, u32 *p_eth_proto_admin,
15132be5c8a9SAmit Cohen u32 *p_eth_proto_oper)
15142be5c8a9SAmit Cohen {
15152be5c8a9SAmit Cohen mlxsw_reg_ptys_eth_unpack(payload, p_eth_proto_cap, p_eth_proto_admin,
15162be5c8a9SAmit Cohen p_eth_proto_oper);
15172be5c8a9SAmit Cohen }
15182be5c8a9SAmit Cohen
mlxsw_sp1_ptys_proto_cap_masked_get(u32 eth_proto_cap)15191601559bSAmit Cohen static u32 mlxsw_sp1_ptys_proto_cap_masked_get(u32 eth_proto_cap)
15201601559bSAmit Cohen {
15211601559bSAmit Cohen u32 ptys_proto_cap_masked = 0;
15221601559bSAmit Cohen int i;
15231601559bSAmit Cohen
15241601559bSAmit Cohen for (i = 0; i < MLXSW_SP1_PORT_LINK_MODE_LEN; i++) {
15251601559bSAmit Cohen if (mlxsw_sp1_port_link_mode[i].mask & eth_proto_cap)
15261601559bSAmit Cohen ptys_proto_cap_masked |=
15271601559bSAmit Cohen mlxsw_sp1_port_link_mode[i].mask;
15281601559bSAmit Cohen }
15291601559bSAmit Cohen
15301601559bSAmit Cohen return ptys_proto_cap_masked;
15311601559bSAmit Cohen }
15321601559bSAmit Cohen
15332be5c8a9SAmit Cohen const struct mlxsw_sp_port_type_speed_ops mlxsw_sp1_port_type_speed_ops = {
15342be5c8a9SAmit Cohen .from_ptys_supported_port = mlxsw_sp1_from_ptys_supported_port,
15352be5c8a9SAmit Cohen .from_ptys_link = mlxsw_sp1_from_ptys_link,
15362be5c8a9SAmit Cohen .from_ptys_speed = mlxsw_sp1_from_ptys_speed,
153725a96f05SDanielle Ratson .from_ptys_link_mode = mlxsw_sp1_from_ptys_link_mode,
153860fbc521SPetr Machata .ptys_max_speed = mlxsw_sp1_ptys_max_speed,
15392be5c8a9SAmit Cohen .to_ptys_advert_link = mlxsw_sp1_to_ptys_advert_link,
1540763ece86SDanielle Ratson .to_ptys_speed_lanes = mlxsw_sp1_to_ptys_speed_lanes,
15412be5c8a9SAmit Cohen .reg_ptys_eth_pack = mlxsw_sp1_reg_ptys_eth_pack,
15422be5c8a9SAmit Cohen .reg_ptys_eth_unpack = mlxsw_sp1_reg_ptys_eth_unpack,
15431601559bSAmit Cohen .ptys_proto_cap_masked_get = mlxsw_sp1_ptys_proto_cap_masked_get,
15442be5c8a9SAmit Cohen };
15452be5c8a9SAmit Cohen
15462be5c8a9SAmit Cohen static const enum ethtool_link_mode_bit_indices
15472be5c8a9SAmit Cohen mlxsw_sp2_mask_ethtool_sgmii_100m[] = {
15482be5c8a9SAmit Cohen ETHTOOL_LINK_MODE_100baseT_Full_BIT,
15492be5c8a9SAmit Cohen };
15502be5c8a9SAmit Cohen
15512be5c8a9SAmit Cohen #define MLXSW_SP2_MASK_ETHTOOL_SGMII_100M_LEN \
15522be5c8a9SAmit Cohen ARRAY_SIZE(mlxsw_sp2_mask_ethtool_sgmii_100m)
15532be5c8a9SAmit Cohen
15542be5c8a9SAmit Cohen static const enum ethtool_link_mode_bit_indices
15552be5c8a9SAmit Cohen mlxsw_sp2_mask_ethtool_1000base_x_sgmii[] = {
15562be5c8a9SAmit Cohen ETHTOOL_LINK_MODE_1000baseT_Full_BIT,
15572be5c8a9SAmit Cohen ETHTOOL_LINK_MODE_1000baseKX_Full_BIT,
15582be5c8a9SAmit Cohen };
15592be5c8a9SAmit Cohen
15602be5c8a9SAmit Cohen #define MLXSW_SP2_MASK_ETHTOOL_1000BASE_X_SGMII_LEN \
15612be5c8a9SAmit Cohen ARRAY_SIZE(mlxsw_sp2_mask_ethtool_1000base_x_sgmii)
15622be5c8a9SAmit Cohen
15632be5c8a9SAmit Cohen static const enum ethtool_link_mode_bit_indices
15642be5c8a9SAmit Cohen mlxsw_sp2_mask_ethtool_5gbase_r[] = {
15652be5c8a9SAmit Cohen ETHTOOL_LINK_MODE_5000baseT_Full_BIT,
15662be5c8a9SAmit Cohen };
15672be5c8a9SAmit Cohen
15682be5c8a9SAmit Cohen #define MLXSW_SP2_MASK_ETHTOOL_5GBASE_R_LEN \
15692be5c8a9SAmit Cohen ARRAY_SIZE(mlxsw_sp2_mask_ethtool_5gbase_r)
15702be5c8a9SAmit Cohen
15712be5c8a9SAmit Cohen static const enum ethtool_link_mode_bit_indices
15722be5c8a9SAmit Cohen mlxsw_sp2_mask_ethtool_xfi_xaui_1_10g[] = {
15732be5c8a9SAmit Cohen ETHTOOL_LINK_MODE_10000baseT_Full_BIT,
15742be5c8a9SAmit Cohen ETHTOOL_LINK_MODE_10000baseKR_Full_BIT,
15752be5c8a9SAmit Cohen ETHTOOL_LINK_MODE_10000baseR_FEC_BIT,
15762be5c8a9SAmit Cohen ETHTOOL_LINK_MODE_10000baseCR_Full_BIT,
15772be5c8a9SAmit Cohen ETHTOOL_LINK_MODE_10000baseSR_Full_BIT,
15782be5c8a9SAmit Cohen ETHTOOL_LINK_MODE_10000baseLR_Full_BIT,
15792be5c8a9SAmit Cohen ETHTOOL_LINK_MODE_10000baseER_Full_BIT,
15802be5c8a9SAmit Cohen };
15812be5c8a9SAmit Cohen
15822be5c8a9SAmit Cohen #define MLXSW_SP2_MASK_ETHTOOL_XFI_XAUI_1_10G_LEN \
15832be5c8a9SAmit Cohen ARRAY_SIZE(mlxsw_sp2_mask_ethtool_xfi_xaui_1_10g)
15842be5c8a9SAmit Cohen
15852be5c8a9SAmit Cohen static const enum ethtool_link_mode_bit_indices
15862be5c8a9SAmit Cohen mlxsw_sp2_mask_ethtool_xlaui_4_xlppi_4_40g[] = {
15872be5c8a9SAmit Cohen ETHTOOL_LINK_MODE_40000baseKR4_Full_BIT,
15882be5c8a9SAmit Cohen ETHTOOL_LINK_MODE_40000baseCR4_Full_BIT,
15892be5c8a9SAmit Cohen ETHTOOL_LINK_MODE_40000baseSR4_Full_BIT,
15902be5c8a9SAmit Cohen ETHTOOL_LINK_MODE_40000baseLR4_Full_BIT,
15912be5c8a9SAmit Cohen };
15922be5c8a9SAmit Cohen
15932be5c8a9SAmit Cohen #define MLXSW_SP2_MASK_ETHTOOL_XLAUI_4_XLPPI_4_40G_LEN \
15942be5c8a9SAmit Cohen ARRAY_SIZE(mlxsw_sp2_mask_ethtool_xlaui_4_xlppi_4_40g)
15952be5c8a9SAmit Cohen
15962be5c8a9SAmit Cohen static const enum ethtool_link_mode_bit_indices
15972be5c8a9SAmit Cohen mlxsw_sp2_mask_ethtool_25gaui_1_25gbase_cr_kr[] = {
15982be5c8a9SAmit Cohen ETHTOOL_LINK_MODE_25000baseCR_Full_BIT,
15992be5c8a9SAmit Cohen ETHTOOL_LINK_MODE_25000baseKR_Full_BIT,
16002be5c8a9SAmit Cohen ETHTOOL_LINK_MODE_25000baseSR_Full_BIT,
16012be5c8a9SAmit Cohen };
16022be5c8a9SAmit Cohen
16032be5c8a9SAmit Cohen #define MLXSW_SP2_MASK_ETHTOOL_25GAUI_1_25GBASE_CR_KR_LEN \
16042be5c8a9SAmit Cohen ARRAY_SIZE(mlxsw_sp2_mask_ethtool_25gaui_1_25gbase_cr_kr)
16052be5c8a9SAmit Cohen
16062be5c8a9SAmit Cohen static const enum ethtool_link_mode_bit_indices
16072be5c8a9SAmit Cohen mlxsw_sp2_mask_ethtool_50gaui_2_laui_2_50gbase_cr2_kr2[] = {
16082be5c8a9SAmit Cohen ETHTOOL_LINK_MODE_50000baseCR2_Full_BIT,
16092be5c8a9SAmit Cohen ETHTOOL_LINK_MODE_50000baseKR2_Full_BIT,
16102be5c8a9SAmit Cohen ETHTOOL_LINK_MODE_50000baseSR2_Full_BIT,
16112be5c8a9SAmit Cohen };
16122be5c8a9SAmit Cohen
16132be5c8a9SAmit Cohen #define MLXSW_SP2_MASK_ETHTOOL_50GAUI_2_LAUI_2_50GBASE_CR2_KR2_LEN \
16142be5c8a9SAmit Cohen ARRAY_SIZE(mlxsw_sp2_mask_ethtool_50gaui_2_laui_2_50gbase_cr2_kr2)
16152be5c8a9SAmit Cohen
16162be5c8a9SAmit Cohen static const enum ethtool_link_mode_bit_indices
16172be5c8a9SAmit Cohen mlxsw_sp2_mask_ethtool_50gaui_1_laui_1_50gbase_cr_kr[] = {
16182be5c8a9SAmit Cohen ETHTOOL_LINK_MODE_50000baseKR_Full_BIT,
16192be5c8a9SAmit Cohen ETHTOOL_LINK_MODE_50000baseSR_Full_BIT,
16202be5c8a9SAmit Cohen ETHTOOL_LINK_MODE_50000baseCR_Full_BIT,
16212be5c8a9SAmit Cohen ETHTOOL_LINK_MODE_50000baseLR_ER_FR_Full_BIT,
16222be5c8a9SAmit Cohen ETHTOOL_LINK_MODE_50000baseDR_Full_BIT,
16232be5c8a9SAmit Cohen };
16242be5c8a9SAmit Cohen
16252be5c8a9SAmit Cohen #define MLXSW_SP2_MASK_ETHTOOL_50GAUI_1_LAUI_1_50GBASE_CR_KR_LEN \
16262be5c8a9SAmit Cohen ARRAY_SIZE(mlxsw_sp2_mask_ethtool_50gaui_1_laui_1_50gbase_cr_kr)
16272be5c8a9SAmit Cohen
16282be5c8a9SAmit Cohen static const enum ethtool_link_mode_bit_indices
16292be5c8a9SAmit Cohen mlxsw_sp2_mask_ethtool_caui_4_100gbase_cr4_kr4[] = {
16302be5c8a9SAmit Cohen ETHTOOL_LINK_MODE_100000baseKR4_Full_BIT,
16312be5c8a9SAmit Cohen ETHTOOL_LINK_MODE_100000baseSR4_Full_BIT,
16322be5c8a9SAmit Cohen ETHTOOL_LINK_MODE_100000baseCR4_Full_BIT,
16332be5c8a9SAmit Cohen ETHTOOL_LINK_MODE_100000baseLR4_ER4_Full_BIT,
16342be5c8a9SAmit Cohen };
16352be5c8a9SAmit Cohen
16362be5c8a9SAmit Cohen #define MLXSW_SP2_MASK_ETHTOOL_CAUI_4_100GBASE_CR4_KR4_LEN \
16372be5c8a9SAmit Cohen ARRAY_SIZE(mlxsw_sp2_mask_ethtool_caui_4_100gbase_cr4_kr4)
16382be5c8a9SAmit Cohen
16392be5c8a9SAmit Cohen static const enum ethtool_link_mode_bit_indices
16402be5c8a9SAmit Cohen mlxsw_sp2_mask_ethtool_100gaui_2_100gbase_cr2_kr2[] = {
16412be5c8a9SAmit Cohen ETHTOOL_LINK_MODE_100000baseKR2_Full_BIT,
16422be5c8a9SAmit Cohen ETHTOOL_LINK_MODE_100000baseSR2_Full_BIT,
16432be5c8a9SAmit Cohen ETHTOOL_LINK_MODE_100000baseCR2_Full_BIT,
16442be5c8a9SAmit Cohen ETHTOOL_LINK_MODE_100000baseLR2_ER2_FR2_Full_BIT,
16452be5c8a9SAmit Cohen ETHTOOL_LINK_MODE_100000baseDR2_Full_BIT,
16462be5c8a9SAmit Cohen };
16472be5c8a9SAmit Cohen
16482be5c8a9SAmit Cohen #define MLXSW_SP2_MASK_ETHTOOL_100GAUI_2_100GBASE_CR2_KR2_LEN \
16492be5c8a9SAmit Cohen ARRAY_SIZE(mlxsw_sp2_mask_ethtool_100gaui_2_100gbase_cr2_kr2)
16502be5c8a9SAmit Cohen
16512be5c8a9SAmit Cohen static const enum ethtool_link_mode_bit_indices
16522be5c8a9SAmit Cohen mlxsw_sp2_mask_ethtool_200gaui_4_200gbase_cr4_kr4[] = {
16532be5c8a9SAmit Cohen ETHTOOL_LINK_MODE_200000baseKR4_Full_BIT,
16542be5c8a9SAmit Cohen ETHTOOL_LINK_MODE_200000baseSR4_Full_BIT,
16552be5c8a9SAmit Cohen ETHTOOL_LINK_MODE_200000baseLR4_ER4_FR4_Full_BIT,
16562be5c8a9SAmit Cohen ETHTOOL_LINK_MODE_200000baseDR4_Full_BIT,
16572be5c8a9SAmit Cohen ETHTOOL_LINK_MODE_200000baseCR4_Full_BIT,
16582be5c8a9SAmit Cohen };
16592be5c8a9SAmit Cohen
16602be5c8a9SAmit Cohen #define MLXSW_SP2_MASK_ETHTOOL_200GAUI_4_200GBASE_CR4_KR4_LEN \
16612be5c8a9SAmit Cohen ARRAY_SIZE(mlxsw_sp2_mask_ethtool_200gaui_4_200gbase_cr4_kr4)
16622be5c8a9SAmit Cohen
16632be5c8a9SAmit Cohen static const enum ethtool_link_mode_bit_indices
16642be5c8a9SAmit Cohen mlxsw_sp2_mask_ethtool_400gaui_8[] = {
16652be5c8a9SAmit Cohen ETHTOOL_LINK_MODE_400000baseKR8_Full_BIT,
16662be5c8a9SAmit Cohen ETHTOOL_LINK_MODE_400000baseSR8_Full_BIT,
16672be5c8a9SAmit Cohen ETHTOOL_LINK_MODE_400000baseLR8_ER8_FR8_Full_BIT,
16682be5c8a9SAmit Cohen ETHTOOL_LINK_MODE_400000baseDR8_Full_BIT,
16692be5c8a9SAmit Cohen ETHTOOL_LINK_MODE_400000baseCR8_Full_BIT,
16702be5c8a9SAmit Cohen };
16712be5c8a9SAmit Cohen
16722be5c8a9SAmit Cohen #define MLXSW_SP2_MASK_ETHTOOL_400GAUI_8_LEN \
16732be5c8a9SAmit Cohen ARRAY_SIZE(mlxsw_sp2_mask_ethtool_400gaui_8)
16742be5c8a9SAmit Cohen
1675*cceef209SAmit Cohen static const enum ethtool_link_mode_bit_indices
1676*cceef209SAmit Cohen mlxsw_sp2_mask_ethtool_800gaui_8[] = {
1677*cceef209SAmit Cohen ETHTOOL_LINK_MODE_800000baseCR8_Full_BIT,
1678*cceef209SAmit Cohen ETHTOOL_LINK_MODE_800000baseKR8_Full_BIT,
1679*cceef209SAmit Cohen ETHTOOL_LINK_MODE_800000baseDR8_Full_BIT,
1680*cceef209SAmit Cohen ETHTOOL_LINK_MODE_800000baseDR8_2_Full_BIT,
1681*cceef209SAmit Cohen ETHTOOL_LINK_MODE_800000baseSR8_Full_BIT,
1682*cceef209SAmit Cohen ETHTOOL_LINK_MODE_800000baseVR8_Full_BIT,
1683*cceef209SAmit Cohen };
1684*cceef209SAmit Cohen
1685*cceef209SAmit Cohen #define MLXSW_SP2_MASK_ETHTOOL_800GAUI_8_LEN \
1686*cceef209SAmit Cohen ARRAY_SIZE(mlxsw_sp2_mask_ethtool_800gaui_8)
1687*cceef209SAmit Cohen
16882be5c8a9SAmit Cohen #define MLXSW_SP_PORT_MASK_WIDTH_1X BIT(0)
16892be5c8a9SAmit Cohen #define MLXSW_SP_PORT_MASK_WIDTH_2X BIT(1)
16902be5c8a9SAmit Cohen #define MLXSW_SP_PORT_MASK_WIDTH_4X BIT(2)
16912be5c8a9SAmit Cohen #define MLXSW_SP_PORT_MASK_WIDTH_8X BIT(3)
16922be5c8a9SAmit Cohen
mlxsw_sp_port_mask_width_get(u8 width)16932be5c8a9SAmit Cohen static u8 mlxsw_sp_port_mask_width_get(u8 width)
16942be5c8a9SAmit Cohen {
16952be5c8a9SAmit Cohen switch (width) {
16962be5c8a9SAmit Cohen case 1:
16972be5c8a9SAmit Cohen return MLXSW_SP_PORT_MASK_WIDTH_1X;
16982be5c8a9SAmit Cohen case 2:
16992be5c8a9SAmit Cohen return MLXSW_SP_PORT_MASK_WIDTH_2X;
17002be5c8a9SAmit Cohen case 4:
17012be5c8a9SAmit Cohen return MLXSW_SP_PORT_MASK_WIDTH_4X;
17022be5c8a9SAmit Cohen case 8:
17032be5c8a9SAmit Cohen return MLXSW_SP_PORT_MASK_WIDTH_8X;
17042be5c8a9SAmit Cohen default:
17052be5c8a9SAmit Cohen WARN_ON_ONCE(1);
17062be5c8a9SAmit Cohen return 0;
17072be5c8a9SAmit Cohen }
17082be5c8a9SAmit Cohen }
17092be5c8a9SAmit Cohen
17102be5c8a9SAmit Cohen struct mlxsw_sp2_port_link_mode {
17112be5c8a9SAmit Cohen const enum ethtool_link_mode_bit_indices *mask_ethtool;
17122be5c8a9SAmit Cohen int m_ethtool_len;
17132be5c8a9SAmit Cohen u32 mask;
17142be5c8a9SAmit Cohen u32 speed;
1715763ece86SDanielle Ratson u32 width;
1716763ece86SDanielle Ratson u8 mask_sup_width;
17172be5c8a9SAmit Cohen };
17182be5c8a9SAmit Cohen
17192be5c8a9SAmit Cohen static const struct mlxsw_sp2_port_link_mode mlxsw_sp2_port_link_mode[] = {
17202be5c8a9SAmit Cohen {
17212be5c8a9SAmit Cohen .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_SGMII_100M,
17222be5c8a9SAmit Cohen .mask_ethtool = mlxsw_sp2_mask_ethtool_sgmii_100m,
17232be5c8a9SAmit Cohen .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_SGMII_100M_LEN,
1724763ece86SDanielle Ratson .mask_sup_width = MLXSW_SP_PORT_MASK_WIDTH_1X |
17252be5c8a9SAmit Cohen MLXSW_SP_PORT_MASK_WIDTH_2X |
17262be5c8a9SAmit Cohen MLXSW_SP_PORT_MASK_WIDTH_4X |
17272be5c8a9SAmit Cohen MLXSW_SP_PORT_MASK_WIDTH_8X,
17282be5c8a9SAmit Cohen .speed = SPEED_100,
1729763ece86SDanielle Ratson .width = 1,
17302be5c8a9SAmit Cohen },
17312be5c8a9SAmit Cohen {
17322be5c8a9SAmit Cohen .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_1000BASE_X_SGMII,
17332be5c8a9SAmit Cohen .mask_ethtool = mlxsw_sp2_mask_ethtool_1000base_x_sgmii,
17342be5c8a9SAmit Cohen .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_1000BASE_X_SGMII_LEN,
1735763ece86SDanielle Ratson .mask_sup_width = MLXSW_SP_PORT_MASK_WIDTH_1X |
17362be5c8a9SAmit Cohen MLXSW_SP_PORT_MASK_WIDTH_2X |
17372be5c8a9SAmit Cohen MLXSW_SP_PORT_MASK_WIDTH_4X |
17382be5c8a9SAmit Cohen MLXSW_SP_PORT_MASK_WIDTH_8X,
17392be5c8a9SAmit Cohen .speed = SPEED_1000,
1740763ece86SDanielle Ratson .width = 1,
17412be5c8a9SAmit Cohen },
17422be5c8a9SAmit Cohen {
17432be5c8a9SAmit Cohen .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_5GBASE_R,
17442be5c8a9SAmit Cohen .mask_ethtool = mlxsw_sp2_mask_ethtool_5gbase_r,
17452be5c8a9SAmit Cohen .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_5GBASE_R_LEN,
1746763ece86SDanielle Ratson .mask_sup_width = MLXSW_SP_PORT_MASK_WIDTH_1X |
17472be5c8a9SAmit Cohen MLXSW_SP_PORT_MASK_WIDTH_2X |
17482be5c8a9SAmit Cohen MLXSW_SP_PORT_MASK_WIDTH_4X |
17492be5c8a9SAmit Cohen MLXSW_SP_PORT_MASK_WIDTH_8X,
17502be5c8a9SAmit Cohen .speed = SPEED_5000,
1751763ece86SDanielle Ratson .width = 1,
17522be5c8a9SAmit Cohen },
17532be5c8a9SAmit Cohen {
17542be5c8a9SAmit Cohen .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_XFI_XAUI_1_10G,
17552be5c8a9SAmit Cohen .mask_ethtool = mlxsw_sp2_mask_ethtool_xfi_xaui_1_10g,
17562be5c8a9SAmit Cohen .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_XFI_XAUI_1_10G_LEN,
1757763ece86SDanielle Ratson .mask_sup_width = MLXSW_SP_PORT_MASK_WIDTH_1X |
17582be5c8a9SAmit Cohen MLXSW_SP_PORT_MASK_WIDTH_2X |
17592be5c8a9SAmit Cohen MLXSW_SP_PORT_MASK_WIDTH_4X |
17602be5c8a9SAmit Cohen MLXSW_SP_PORT_MASK_WIDTH_8X,
17612be5c8a9SAmit Cohen .speed = SPEED_10000,
1762763ece86SDanielle Ratson .width = 1,
17632be5c8a9SAmit Cohen },
17642be5c8a9SAmit Cohen {
17652be5c8a9SAmit Cohen .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_XLAUI_4_XLPPI_4_40G,
17662be5c8a9SAmit Cohen .mask_ethtool = mlxsw_sp2_mask_ethtool_xlaui_4_xlppi_4_40g,
17672be5c8a9SAmit Cohen .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_XLAUI_4_XLPPI_4_40G_LEN,
1768763ece86SDanielle Ratson .mask_sup_width = MLXSW_SP_PORT_MASK_WIDTH_4X |
17692be5c8a9SAmit Cohen MLXSW_SP_PORT_MASK_WIDTH_8X,
17702be5c8a9SAmit Cohen .speed = SPEED_40000,
1771763ece86SDanielle Ratson .width = 4,
17722be5c8a9SAmit Cohen },
17732be5c8a9SAmit Cohen {
17742be5c8a9SAmit Cohen .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_25GAUI_1_25GBASE_CR_KR,
17752be5c8a9SAmit Cohen .mask_ethtool = mlxsw_sp2_mask_ethtool_25gaui_1_25gbase_cr_kr,
17762be5c8a9SAmit Cohen .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_25GAUI_1_25GBASE_CR_KR_LEN,
1777763ece86SDanielle Ratson .mask_sup_width = MLXSW_SP_PORT_MASK_WIDTH_1X |
17782be5c8a9SAmit Cohen MLXSW_SP_PORT_MASK_WIDTH_2X |
17792be5c8a9SAmit Cohen MLXSW_SP_PORT_MASK_WIDTH_4X |
17802be5c8a9SAmit Cohen MLXSW_SP_PORT_MASK_WIDTH_8X,
17812be5c8a9SAmit Cohen .speed = SPEED_25000,
1782763ece86SDanielle Ratson .width = 1,
17832be5c8a9SAmit Cohen },
17842be5c8a9SAmit Cohen {
17852be5c8a9SAmit Cohen .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_50GAUI_2_LAUI_2_50GBASE_CR2_KR2,
17862be5c8a9SAmit Cohen .mask_ethtool = mlxsw_sp2_mask_ethtool_50gaui_2_laui_2_50gbase_cr2_kr2,
17872be5c8a9SAmit Cohen .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_50GAUI_2_LAUI_2_50GBASE_CR2_KR2_LEN,
1788763ece86SDanielle Ratson .mask_sup_width = MLXSW_SP_PORT_MASK_WIDTH_2X |
17892be5c8a9SAmit Cohen MLXSW_SP_PORT_MASK_WIDTH_4X |
17902be5c8a9SAmit Cohen MLXSW_SP_PORT_MASK_WIDTH_8X,
17912be5c8a9SAmit Cohen .speed = SPEED_50000,
1792763ece86SDanielle Ratson .width = 2,
17932be5c8a9SAmit Cohen },
17942be5c8a9SAmit Cohen {
17952be5c8a9SAmit Cohen .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_50GAUI_1_LAUI_1_50GBASE_CR_KR,
17962be5c8a9SAmit Cohen .mask_ethtool = mlxsw_sp2_mask_ethtool_50gaui_1_laui_1_50gbase_cr_kr,
17972be5c8a9SAmit Cohen .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_50GAUI_1_LAUI_1_50GBASE_CR_KR_LEN,
1798763ece86SDanielle Ratson .mask_sup_width = MLXSW_SP_PORT_MASK_WIDTH_1X,
17992be5c8a9SAmit Cohen .speed = SPEED_50000,
1800763ece86SDanielle Ratson .width = 1,
18012be5c8a9SAmit Cohen },
18022be5c8a9SAmit Cohen {
18032be5c8a9SAmit Cohen .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_CAUI_4_100GBASE_CR4_KR4,
18042be5c8a9SAmit Cohen .mask_ethtool = mlxsw_sp2_mask_ethtool_caui_4_100gbase_cr4_kr4,
18052be5c8a9SAmit Cohen .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_CAUI_4_100GBASE_CR4_KR4_LEN,
1806763ece86SDanielle Ratson .mask_sup_width = MLXSW_SP_PORT_MASK_WIDTH_4X |
18072be5c8a9SAmit Cohen MLXSW_SP_PORT_MASK_WIDTH_8X,
18082be5c8a9SAmit Cohen .speed = SPEED_100000,
1809763ece86SDanielle Ratson .width = 4,
18102be5c8a9SAmit Cohen },
18112be5c8a9SAmit Cohen {
18122be5c8a9SAmit Cohen .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_100GAUI_2_100GBASE_CR2_KR2,
18132be5c8a9SAmit Cohen .mask_ethtool = mlxsw_sp2_mask_ethtool_100gaui_2_100gbase_cr2_kr2,
18142be5c8a9SAmit Cohen .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_100GAUI_2_100GBASE_CR2_KR2_LEN,
1815763ece86SDanielle Ratson .mask_sup_width = MLXSW_SP_PORT_MASK_WIDTH_2X,
18162be5c8a9SAmit Cohen .speed = SPEED_100000,
1817763ece86SDanielle Ratson .width = 2,
18182be5c8a9SAmit Cohen },
18192be5c8a9SAmit Cohen {
18202be5c8a9SAmit Cohen .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_200GAUI_4_200GBASE_CR4_KR4,
18212be5c8a9SAmit Cohen .mask_ethtool = mlxsw_sp2_mask_ethtool_200gaui_4_200gbase_cr4_kr4,
18222be5c8a9SAmit Cohen .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_200GAUI_4_200GBASE_CR4_KR4_LEN,
1823763ece86SDanielle Ratson .mask_sup_width = MLXSW_SP_PORT_MASK_WIDTH_4X |
18242be5c8a9SAmit Cohen MLXSW_SP_PORT_MASK_WIDTH_8X,
18252be5c8a9SAmit Cohen .speed = SPEED_200000,
1826763ece86SDanielle Ratson .width = 4,
18272be5c8a9SAmit Cohen },
18282be5c8a9SAmit Cohen {
18292be5c8a9SAmit Cohen .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_400GAUI_8,
18302be5c8a9SAmit Cohen .mask_ethtool = mlxsw_sp2_mask_ethtool_400gaui_8,
18312be5c8a9SAmit Cohen .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_400GAUI_8_LEN,
1832763ece86SDanielle Ratson .mask_sup_width = MLXSW_SP_PORT_MASK_WIDTH_8X,
18332be5c8a9SAmit Cohen .speed = SPEED_400000,
1834763ece86SDanielle Ratson .width = 8,
18352be5c8a9SAmit Cohen },
1836*cceef209SAmit Cohen {
1837*cceef209SAmit Cohen .mask = MLXSW_REG_PTYS_EXT_ETH_SPEED_800GAUI_8,
1838*cceef209SAmit Cohen .mask_ethtool = mlxsw_sp2_mask_ethtool_800gaui_8,
1839*cceef209SAmit Cohen .m_ethtool_len = MLXSW_SP2_MASK_ETHTOOL_800GAUI_8_LEN,
1840*cceef209SAmit Cohen .mask_sup_width = MLXSW_SP_PORT_MASK_WIDTH_8X,
1841*cceef209SAmit Cohen .speed = SPEED_800000,
1842*cceef209SAmit Cohen .width = 8,
1843*cceef209SAmit Cohen },
18442be5c8a9SAmit Cohen };
18452be5c8a9SAmit Cohen
18462be5c8a9SAmit Cohen #define MLXSW_SP2_PORT_LINK_MODE_LEN ARRAY_SIZE(mlxsw_sp2_port_link_mode)
18472be5c8a9SAmit Cohen
18482be5c8a9SAmit Cohen static void
mlxsw_sp2_from_ptys_supported_port(struct mlxsw_sp * mlxsw_sp,u32 ptys_eth_proto,struct ethtool_link_ksettings * cmd)18492be5c8a9SAmit Cohen mlxsw_sp2_from_ptys_supported_port(struct mlxsw_sp *mlxsw_sp,
18502be5c8a9SAmit Cohen u32 ptys_eth_proto,
18512be5c8a9SAmit Cohen struct ethtool_link_ksettings *cmd)
18522be5c8a9SAmit Cohen {
18532be5c8a9SAmit Cohen ethtool_link_ksettings_add_link_mode(cmd, supported, FIBRE);
18542be5c8a9SAmit Cohen ethtool_link_ksettings_add_link_mode(cmd, supported, Backplane);
18552be5c8a9SAmit Cohen }
18562be5c8a9SAmit Cohen
18572be5c8a9SAmit Cohen static void
mlxsw_sp2_set_bit_ethtool(const struct mlxsw_sp2_port_link_mode * link_mode,unsigned long * mode)18582be5c8a9SAmit Cohen mlxsw_sp2_set_bit_ethtool(const struct mlxsw_sp2_port_link_mode *link_mode,
18592be5c8a9SAmit Cohen unsigned long *mode)
18602be5c8a9SAmit Cohen {
18612be5c8a9SAmit Cohen int i;
18622be5c8a9SAmit Cohen
18632be5c8a9SAmit Cohen for (i = 0; i < link_mode->m_ethtool_len; i++)
18642be5c8a9SAmit Cohen __set_bit(link_mode->mask_ethtool[i], mode);
18652be5c8a9SAmit Cohen }
18662be5c8a9SAmit Cohen
18672be5c8a9SAmit Cohen static void
mlxsw_sp2_from_ptys_link(struct mlxsw_sp * mlxsw_sp,u32 ptys_eth_proto,unsigned long * mode)18682be5c8a9SAmit Cohen mlxsw_sp2_from_ptys_link(struct mlxsw_sp *mlxsw_sp, u32 ptys_eth_proto,
18695fc4053dSDanielle Ratson unsigned long *mode)
18702be5c8a9SAmit Cohen {
18712be5c8a9SAmit Cohen int i;
18722be5c8a9SAmit Cohen
18732be5c8a9SAmit Cohen for (i = 0; i < MLXSW_SP2_PORT_LINK_MODE_LEN; i++) {
18745fc4053dSDanielle Ratson if (ptys_eth_proto & mlxsw_sp2_port_link_mode[i].mask)
18752be5c8a9SAmit Cohen mlxsw_sp2_set_bit_ethtool(&mlxsw_sp2_port_link_mode[i],
18762be5c8a9SAmit Cohen mode);
18772be5c8a9SAmit Cohen }
18782be5c8a9SAmit Cohen }
18792be5c8a9SAmit Cohen
18802be5c8a9SAmit Cohen static u32
mlxsw_sp2_from_ptys_speed(struct mlxsw_sp * mlxsw_sp,u32 ptys_eth_proto)18812be5c8a9SAmit Cohen mlxsw_sp2_from_ptys_speed(struct mlxsw_sp *mlxsw_sp, u32 ptys_eth_proto)
18822be5c8a9SAmit Cohen {
18832be5c8a9SAmit Cohen int i;
18842be5c8a9SAmit Cohen
18852be5c8a9SAmit Cohen for (i = 0; i < MLXSW_SP2_PORT_LINK_MODE_LEN; i++) {
18862be5c8a9SAmit Cohen if (ptys_eth_proto & mlxsw_sp2_port_link_mode[i].mask)
18872be5c8a9SAmit Cohen return mlxsw_sp2_port_link_mode[i].speed;
18882be5c8a9SAmit Cohen }
18892be5c8a9SAmit Cohen
18902be5c8a9SAmit Cohen return SPEED_UNKNOWN;
18912be5c8a9SAmit Cohen }
18922be5c8a9SAmit Cohen
18932be5c8a9SAmit Cohen static void
mlxsw_sp2_from_ptys_link_mode(struct mlxsw_sp * mlxsw_sp,bool carrier_ok,u32 ptys_eth_proto,struct ethtool_link_ksettings * cmd)189425a96f05SDanielle Ratson mlxsw_sp2_from_ptys_link_mode(struct mlxsw_sp *mlxsw_sp, bool carrier_ok,
18952be5c8a9SAmit Cohen u32 ptys_eth_proto,
18962be5c8a9SAmit Cohen struct ethtool_link_ksettings *cmd)
18972be5c8a9SAmit Cohen {
189825a96f05SDanielle Ratson struct mlxsw_sp2_port_link_mode link;
189925a96f05SDanielle Ratson int i;
190025a96f05SDanielle Ratson
1901a975d7d8SDanielle Ratson cmd->base.speed = SPEED_UNKNOWN;
1902a975d7d8SDanielle Ratson cmd->base.duplex = DUPLEX_UNKNOWN;
1903a975d7d8SDanielle Ratson cmd->lanes = 0;
19042be5c8a9SAmit Cohen
19052be5c8a9SAmit Cohen if (!carrier_ok)
19062be5c8a9SAmit Cohen return;
19072be5c8a9SAmit Cohen
190825a96f05SDanielle Ratson for (i = 0; i < MLXSW_SP2_PORT_LINK_MODE_LEN; i++) {
190925a96f05SDanielle Ratson if (ptys_eth_proto & mlxsw_sp2_port_link_mode[i].mask) {
191025a96f05SDanielle Ratson link = mlxsw_sp2_port_link_mode[i];
1911a975d7d8SDanielle Ratson ethtool_params_from_link_mode(cmd,
1912a975d7d8SDanielle Ratson link.mask_ethtool[1]);
191325a96f05SDanielle Ratson }
191425a96f05SDanielle Ratson }
19152be5c8a9SAmit Cohen }
19162be5c8a9SAmit Cohen
mlxsw_sp2_ptys_max_speed(struct mlxsw_sp_port * mlxsw_sp_port,u32 * p_max_speed)191760fbc521SPetr Machata static int mlxsw_sp2_ptys_max_speed(struct mlxsw_sp_port *mlxsw_sp_port, u32 *p_max_speed)
191860fbc521SPetr Machata {
191960fbc521SPetr Machata u32 eth_proto_cap;
192060fbc521SPetr Machata u32 max_speed = 0;
192160fbc521SPetr Machata int err;
192260fbc521SPetr Machata int i;
192360fbc521SPetr Machata
192460fbc521SPetr Machata err = mlxsw_sp_port_ptys_query(mlxsw_sp_port, ð_proto_cap, NULL, NULL, NULL);
192560fbc521SPetr Machata if (err)
192660fbc521SPetr Machata return err;
192760fbc521SPetr Machata
192860fbc521SPetr Machata for (i = 0; i < MLXSW_SP2_PORT_LINK_MODE_LEN; i++) {
192960fbc521SPetr Machata if ((eth_proto_cap & mlxsw_sp2_port_link_mode[i].mask) &&
193060fbc521SPetr Machata mlxsw_sp2_port_link_mode[i].speed > max_speed)
193160fbc521SPetr Machata max_speed = mlxsw_sp2_port_link_mode[i].speed;
193260fbc521SPetr Machata }
193360fbc521SPetr Machata
193460fbc521SPetr Machata *p_max_speed = max_speed;
193560fbc521SPetr Machata return 0;
193660fbc521SPetr Machata }
193760fbc521SPetr Machata
19382be5c8a9SAmit Cohen static bool
mlxsw_sp2_test_bit_ethtool(const struct mlxsw_sp2_port_link_mode * link_mode,const unsigned long * mode)19392be5c8a9SAmit Cohen mlxsw_sp2_test_bit_ethtool(const struct mlxsw_sp2_port_link_mode *link_mode,
19402be5c8a9SAmit Cohen const unsigned long *mode)
19412be5c8a9SAmit Cohen {
19422be5c8a9SAmit Cohen int cnt = 0;
19432be5c8a9SAmit Cohen int i;
19442be5c8a9SAmit Cohen
19452be5c8a9SAmit Cohen for (i = 0; i < link_mode->m_ethtool_len; i++) {
19462be5c8a9SAmit Cohen if (test_bit(link_mode->mask_ethtool[i], mode))
19472be5c8a9SAmit Cohen cnt++;
19482be5c8a9SAmit Cohen }
19492be5c8a9SAmit Cohen
19502be5c8a9SAmit Cohen return cnt == link_mode->m_ethtool_len;
19512be5c8a9SAmit Cohen }
19522be5c8a9SAmit Cohen
19532be5c8a9SAmit Cohen static u32
mlxsw_sp2_to_ptys_advert_link(struct mlxsw_sp * mlxsw_sp,const struct ethtool_link_ksettings * cmd)19545fc4053dSDanielle Ratson mlxsw_sp2_to_ptys_advert_link(struct mlxsw_sp *mlxsw_sp,
19552be5c8a9SAmit Cohen const struct ethtool_link_ksettings *cmd)
19562be5c8a9SAmit Cohen {
19572be5c8a9SAmit Cohen u32 ptys_proto = 0;
19582be5c8a9SAmit Cohen int i;
19592be5c8a9SAmit Cohen
19602be5c8a9SAmit Cohen for (i = 0; i < MLXSW_SP2_PORT_LINK_MODE_LEN; i++) {
19615fc4053dSDanielle Ratson if (mlxsw_sp2_test_bit_ethtool(&mlxsw_sp2_port_link_mode[i],
19622be5c8a9SAmit Cohen cmd->link_modes.advertising))
19632be5c8a9SAmit Cohen ptys_proto |= mlxsw_sp2_port_link_mode[i].mask;
19642be5c8a9SAmit Cohen }
19652be5c8a9SAmit Cohen return ptys_proto;
19662be5c8a9SAmit Cohen }
19672be5c8a9SAmit Cohen
mlxsw_sp2_to_ptys_speed_lanes(struct mlxsw_sp * mlxsw_sp,u8 width,const struct ethtool_link_ksettings * cmd)1968763ece86SDanielle Ratson static u32 mlxsw_sp2_to_ptys_speed_lanes(struct mlxsw_sp *mlxsw_sp, u8 width,
1969763ece86SDanielle Ratson const struct ethtool_link_ksettings *cmd)
19702be5c8a9SAmit Cohen {
19712be5c8a9SAmit Cohen u8 mask_width = mlxsw_sp_port_mask_width_get(width);
1972763ece86SDanielle Ratson struct mlxsw_sp2_port_link_mode link_mode;
19732be5c8a9SAmit Cohen u32 ptys_proto = 0;
19742be5c8a9SAmit Cohen int i;
19752be5c8a9SAmit Cohen
1976763ece86SDanielle Ratson if (cmd->lanes > width)
1977763ece86SDanielle Ratson return ptys_proto;
1978763ece86SDanielle Ratson
19792be5c8a9SAmit Cohen for (i = 0; i < MLXSW_SP2_PORT_LINK_MODE_LEN; i++) {
1980763ece86SDanielle Ratson if (cmd->base.speed == mlxsw_sp2_port_link_mode[i].speed) {
1981763ece86SDanielle Ratson link_mode = mlxsw_sp2_port_link_mode[i];
1982763ece86SDanielle Ratson
1983763ece86SDanielle Ratson if (!cmd->lanes) {
1984763ece86SDanielle Ratson /* If number of lanes was not set by user space,
1985763ece86SDanielle Ratson * choose the link mode that supports the width
1986763ece86SDanielle Ratson * of the port.
1987763ece86SDanielle Ratson */
1988763ece86SDanielle Ratson if (mask_width & link_mode.mask_sup_width)
1989763ece86SDanielle Ratson ptys_proto |= link_mode.mask;
1990763ece86SDanielle Ratson } else if (cmd->lanes == link_mode.width) {
1991763ece86SDanielle Ratson /* Else if the number of lanes was set, choose
1992763ece86SDanielle Ratson * the link mode that its actual width equals to
1993763ece86SDanielle Ratson * it.
1994763ece86SDanielle Ratson */
1995763ece86SDanielle Ratson ptys_proto |= link_mode.mask;
1996763ece86SDanielle Ratson }
1997763ece86SDanielle Ratson }
19982be5c8a9SAmit Cohen }
19992be5c8a9SAmit Cohen return ptys_proto;
20002be5c8a9SAmit Cohen }
20012be5c8a9SAmit Cohen
20022be5c8a9SAmit Cohen static void
mlxsw_sp2_reg_ptys_eth_pack(struct mlxsw_sp * mlxsw_sp,char * payload,u16 local_port,u32 proto_admin,bool autoneg)20032be5c8a9SAmit Cohen mlxsw_sp2_reg_ptys_eth_pack(struct mlxsw_sp *mlxsw_sp, char *payload,
2004c934757dSAmit Cohen u16 local_port, u32 proto_admin,
20052be5c8a9SAmit Cohen bool autoneg)
20062be5c8a9SAmit Cohen {
20072be5c8a9SAmit Cohen mlxsw_reg_ptys_ext_eth_pack(payload, local_port, proto_admin, autoneg);
20082be5c8a9SAmit Cohen }
20092be5c8a9SAmit Cohen
20102be5c8a9SAmit Cohen static void
mlxsw_sp2_reg_ptys_eth_unpack(struct mlxsw_sp * mlxsw_sp,char * payload,u32 * p_eth_proto_cap,u32 * p_eth_proto_admin,u32 * p_eth_proto_oper)20112be5c8a9SAmit Cohen mlxsw_sp2_reg_ptys_eth_unpack(struct mlxsw_sp *mlxsw_sp, char *payload,
20122be5c8a9SAmit Cohen u32 *p_eth_proto_cap, u32 *p_eth_proto_admin,
20132be5c8a9SAmit Cohen u32 *p_eth_proto_oper)
20142be5c8a9SAmit Cohen {
20152be5c8a9SAmit Cohen mlxsw_reg_ptys_ext_eth_unpack(payload, p_eth_proto_cap,
20162be5c8a9SAmit Cohen p_eth_proto_admin, p_eth_proto_oper);
20172be5c8a9SAmit Cohen }
20182be5c8a9SAmit Cohen
mlxsw_sp2_ptys_proto_cap_masked_get(u32 eth_proto_cap)20191601559bSAmit Cohen static u32 mlxsw_sp2_ptys_proto_cap_masked_get(u32 eth_proto_cap)
20201601559bSAmit Cohen {
20211601559bSAmit Cohen u32 ptys_proto_cap_masked = 0;
20221601559bSAmit Cohen int i;
20231601559bSAmit Cohen
20241601559bSAmit Cohen for (i = 0; i < MLXSW_SP2_PORT_LINK_MODE_LEN; i++) {
20251601559bSAmit Cohen if (mlxsw_sp2_port_link_mode[i].mask & eth_proto_cap)
20261601559bSAmit Cohen ptys_proto_cap_masked |=
20271601559bSAmit Cohen mlxsw_sp2_port_link_mode[i].mask;
20281601559bSAmit Cohen }
20291601559bSAmit Cohen
20301601559bSAmit Cohen return ptys_proto_cap_masked;
20311601559bSAmit Cohen }
20321601559bSAmit Cohen
20332be5c8a9SAmit Cohen const struct mlxsw_sp_port_type_speed_ops mlxsw_sp2_port_type_speed_ops = {
20342be5c8a9SAmit Cohen .from_ptys_supported_port = mlxsw_sp2_from_ptys_supported_port,
20352be5c8a9SAmit Cohen .from_ptys_link = mlxsw_sp2_from_ptys_link,
20362be5c8a9SAmit Cohen .from_ptys_speed = mlxsw_sp2_from_ptys_speed,
203725a96f05SDanielle Ratson .from_ptys_link_mode = mlxsw_sp2_from_ptys_link_mode,
203860fbc521SPetr Machata .ptys_max_speed = mlxsw_sp2_ptys_max_speed,
20392be5c8a9SAmit Cohen .to_ptys_advert_link = mlxsw_sp2_to_ptys_advert_link,
2040763ece86SDanielle Ratson .to_ptys_speed_lanes = mlxsw_sp2_to_ptys_speed_lanes,
20412be5c8a9SAmit Cohen .reg_ptys_eth_pack = mlxsw_sp2_reg_ptys_eth_pack,
20422be5c8a9SAmit Cohen .reg_ptys_eth_unpack = mlxsw_sp2_reg_ptys_eth_unpack,
20431601559bSAmit Cohen .ptys_proto_cap_masked_get = mlxsw_sp2_ptys_proto_cap_masked_get,
20442be5c8a9SAmit Cohen };
2045