Skip to content

Commit d021dd2

Browse files
Amit Cohengregkh
authored andcommitted
mlxsw: Only advertise link modes supported by both driver and device
[ Upstream commit 1601559 ] During port creation the driver instructs the device to advertise all the supported link modes queried from the device. Since cited commit not all the link modes supported by the device are supported by the driver. This can result in the device negotiating a link mode that is not recognized by the driver causing ethtool to show an unsupported speed: $ ethtool swp1 ... Speed: Unknown! This is especially problematic when the netdev is enslaved to a bond, as the bond driver uses unknown speed as an indication that the link is down: [13048.900895] net_ratelimit: 86 callbacks suppressed [13048.900902] t_bond0: (slave swp52): failed to get link speed/duplex [13048.912160] t_bond0: (slave swp49): failed to get link speed/duplex Fix this by making sure that only link modes that are supported by both the device and the driver are advertised. Fixes: b97cd89 ("mlxsw: Remove 56G speed support") Signed-off-by: Amit Cohen <amcohen@nvidia.com> Signed-off-by: Ido Schimmel <idosch@nvidia.com> Signed-off-by: Jakub Kicinski <kuba@kernel.org> Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
1 parent f267b0a commit d021dd2

3 files changed

Lines changed: 38 additions & 2 deletions

File tree

drivers/net/ethernet/mellanox/mlxsw/spectrum.c

Lines changed: 7 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1546,11 +1546,14 @@ mlxsw_sp_port_speed_by_width_set(struct mlxsw_sp_port *mlxsw_sp_port)
15461546
u32 eth_proto_cap, eth_proto_admin, eth_proto_oper;
15471547
const struct mlxsw_sp_port_type_speed_ops *ops;
15481548
char ptys_pl[MLXSW_REG_PTYS_LEN];
1549+
u32 eth_proto_cap_masked;
15491550
int err;
15501551

15511552
ops = mlxsw_sp->port_type_speed_ops;
15521553

1553-
/* Set advertised speeds to supported speeds. */
1554+
/* Set advertised speeds to speeds supported by both the driver
1555+
* and the device.
1556+
*/
15541557
ops->reg_ptys_eth_pack(mlxsw_sp, ptys_pl, mlxsw_sp_port->local_port,
15551558
0, false);
15561559
err = mlxsw_reg_query(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl);
@@ -1559,8 +1562,10 @@ mlxsw_sp_port_speed_by_width_set(struct mlxsw_sp_port *mlxsw_sp_port)
15591562

15601563
ops->reg_ptys_eth_unpack(mlxsw_sp, ptys_pl, &eth_proto_cap,
15611564
&eth_proto_admin, &eth_proto_oper);
1565+
eth_proto_cap_masked = ops->ptys_proto_cap_masked_get(eth_proto_cap);
15621566
ops->reg_ptys_eth_pack(mlxsw_sp, ptys_pl, mlxsw_sp_port->local_port,
1563-
eth_proto_cap, mlxsw_sp_port->link.autoneg);
1567+
eth_proto_cap_masked,
1568+
mlxsw_sp_port->link.autoneg);
15641569
return mlxsw_reg_write(mlxsw_sp->core, MLXSW_REG(ptys), ptys_pl);
15651570
}
15661571

drivers/net/ethernet/mellanox/mlxsw/spectrum.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -340,6 +340,7 @@ struct mlxsw_sp_port_type_speed_ops {
340340
u32 *p_eth_proto_cap,
341341
u32 *p_eth_proto_admin,
342342
u32 *p_eth_proto_oper);
343+
u32 (*ptys_proto_cap_masked_get)(u32 eth_proto_cap);
343344
};
344345

345346
static inline struct net_device *

drivers/net/ethernet/mellanox/mlxsw/spectrum_ethtool.c

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1208,6 +1208,20 @@ mlxsw_sp1_reg_ptys_eth_unpack(struct mlxsw_sp *mlxsw_sp, char *payload,
12081208
p_eth_proto_oper);
12091209
}
12101210

1211+
static u32 mlxsw_sp1_ptys_proto_cap_masked_get(u32 eth_proto_cap)
1212+
{
1213+
u32 ptys_proto_cap_masked = 0;
1214+
int i;
1215+
1216+
for (i = 0; i < MLXSW_SP1_PORT_LINK_MODE_LEN; i++) {
1217+
if (mlxsw_sp1_port_link_mode[i].mask & eth_proto_cap)
1218+
ptys_proto_cap_masked |=
1219+
mlxsw_sp1_port_link_mode[i].mask;
1220+
}
1221+
1222+
return ptys_proto_cap_masked;
1223+
}
1224+
12111225
const struct mlxsw_sp_port_type_speed_ops mlxsw_sp1_port_type_speed_ops = {
12121226
.from_ptys_supported_port = mlxsw_sp1_from_ptys_supported_port,
12131227
.from_ptys_link = mlxsw_sp1_from_ptys_link,
@@ -1217,6 +1231,7 @@ const struct mlxsw_sp_port_type_speed_ops mlxsw_sp1_port_type_speed_ops = {
12171231
.to_ptys_speed = mlxsw_sp1_to_ptys_speed,
12181232
.reg_ptys_eth_pack = mlxsw_sp1_reg_ptys_eth_pack,
12191233
.reg_ptys_eth_unpack = mlxsw_sp1_reg_ptys_eth_unpack,
1234+
.ptys_proto_cap_masked_get = mlxsw_sp1_ptys_proto_cap_masked_get,
12201235
};
12211236

12221237
static const enum ethtool_link_mode_bit_indices
@@ -1632,6 +1647,20 @@ mlxsw_sp2_reg_ptys_eth_unpack(struct mlxsw_sp *mlxsw_sp, char *payload,
16321647
p_eth_proto_admin, p_eth_proto_oper);
16331648
}
16341649

1650+
static u32 mlxsw_sp2_ptys_proto_cap_masked_get(u32 eth_proto_cap)
1651+
{
1652+
u32 ptys_proto_cap_masked = 0;
1653+
int i;
1654+
1655+
for (i = 0; i < MLXSW_SP2_PORT_LINK_MODE_LEN; i++) {
1656+
if (mlxsw_sp2_port_link_mode[i].mask & eth_proto_cap)
1657+
ptys_proto_cap_masked |=
1658+
mlxsw_sp2_port_link_mode[i].mask;
1659+
}
1660+
1661+
return ptys_proto_cap_masked;
1662+
}
1663+
16351664
const struct mlxsw_sp_port_type_speed_ops mlxsw_sp2_port_type_speed_ops = {
16361665
.from_ptys_supported_port = mlxsw_sp2_from_ptys_supported_port,
16371666
.from_ptys_link = mlxsw_sp2_from_ptys_link,
@@ -1641,4 +1670,5 @@ const struct mlxsw_sp_port_type_speed_ops mlxsw_sp2_port_type_speed_ops = {
16411670
.to_ptys_speed = mlxsw_sp2_to_ptys_speed,
16421671
.reg_ptys_eth_pack = mlxsw_sp2_reg_ptys_eth_pack,
16431672
.reg_ptys_eth_unpack = mlxsw_sp2_reg_ptys_eth_unpack,
1673+
.ptys_proto_cap_masked_get = mlxsw_sp2_ptys_proto_cap_masked_get,
16441674
};

0 commit comments

Comments
 (0)