net/mlx4_en: Adding support of turning off link autonegotiation via ethtool
This feature will allow the user to disable auto negotiation on the port for mlx4 devices while setting the speed is limited to 1GbE speeds. Other speeds will not be accepted in autoneg off mode. This functionality is permitted providing that the firmware is compatible with this feature. The above is determined by querying a new dedicated capability bit in the device. Signed-off-by: Ariel Levkovich <lariel@mellanox.com> Signed-off-by: Tariq Toukan <tariqt@mellanox.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
4b5e5b7ece
commit
297e1cf29e
|
@ -902,6 +902,7 @@ mlx4_en_set_link_ksettings(struct net_device *dev,
|
||||||
struct mlx4_en_priv *priv = netdev_priv(dev);
|
struct mlx4_en_priv *priv = netdev_priv(dev);
|
||||||
struct mlx4_ptys_reg ptys_reg;
|
struct mlx4_ptys_reg ptys_reg;
|
||||||
__be32 proto_admin;
|
__be32 proto_admin;
|
||||||
|
u8 cur_autoneg;
|
||||||
int ret;
|
int ret;
|
||||||
|
|
||||||
u32 ptys_adv = ethtool2ptys_link_modes(
|
u32 ptys_adv = ethtool2ptys_link_modes(
|
||||||
|
@ -931,10 +932,21 @@ mlx4_en_set_link_ksettings(struct net_device *dev,
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
proto_admin = link_ksettings->base.autoneg == AUTONEG_ENABLE ?
|
cur_autoneg = ptys_reg.flags & MLX4_PTYS_AN_DISABLE_ADMIN ?
|
||||||
cpu_to_be32(ptys_adv) :
|
AUTONEG_DISABLE : AUTONEG_ENABLE;
|
||||||
speed_set_ptys_admin(priv, speed,
|
|
||||||
ptys_reg.eth_proto_cap);
|
if (link_ksettings->base.autoneg == AUTONEG_DISABLE) {
|
||||||
|
proto_admin = speed_set_ptys_admin(priv, speed,
|
||||||
|
ptys_reg.eth_proto_cap);
|
||||||
|
if ((be32_to_cpu(proto_admin) &
|
||||||
|
(MLX4_PROT_MASK(MLX4_1000BASE_CX_SGMII) |
|
||||||
|
MLX4_PROT_MASK(MLX4_1000BASE_KX))) &&
|
||||||
|
(ptys_reg.flags & MLX4_PTYS_AN_DISABLE_CAP))
|
||||||
|
ptys_reg.flags |= MLX4_PTYS_AN_DISABLE_ADMIN;
|
||||||
|
} else {
|
||||||
|
proto_admin = cpu_to_be32(ptys_adv);
|
||||||
|
ptys_reg.flags &= ~MLX4_PTYS_AN_DISABLE_ADMIN;
|
||||||
|
}
|
||||||
|
|
||||||
proto_admin &= ptys_reg.eth_proto_cap;
|
proto_admin &= ptys_reg.eth_proto_cap;
|
||||||
if (!proto_admin) {
|
if (!proto_admin) {
|
||||||
|
@ -942,7 +954,9 @@ mlx4_en_set_link_ksettings(struct net_device *dev,
|
||||||
return -EINVAL; /* nothing to change due to bad input */
|
return -EINVAL; /* nothing to change due to bad input */
|
||||||
}
|
}
|
||||||
|
|
||||||
if (proto_admin == ptys_reg.eth_proto_admin)
|
if ((proto_admin == ptys_reg.eth_proto_admin) &&
|
||||||
|
((ptys_reg.flags & MLX4_PTYS_AN_DISABLE_CAP) &&
|
||||||
|
(link_ksettings->base.autoneg == cur_autoneg)))
|
||||||
return 0; /* Nothing to change */
|
return 0; /* Nothing to change */
|
||||||
|
|
||||||
en_dbg(DRV, priv, "mlx4_ACCESS_PTYS_REG SET: ptys_reg.eth_proto_admin = 0x%x\n",
|
en_dbg(DRV, priv, "mlx4_ACCESS_PTYS_REG SET: ptys_reg.eth_proto_admin = 0x%x\n",
|
||||||
|
|
|
@ -1539,8 +1539,13 @@ enum mlx4_ptys_proto {
|
||||||
MLX4_PTYS_EN = 1<<2,
|
MLX4_PTYS_EN = 1<<2,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
enum mlx4_ptys_flags {
|
||||||
|
MLX4_PTYS_AN_DISABLE_CAP = 1 << 5,
|
||||||
|
MLX4_PTYS_AN_DISABLE_ADMIN = 1 << 6,
|
||||||
|
};
|
||||||
|
|
||||||
struct mlx4_ptys_reg {
|
struct mlx4_ptys_reg {
|
||||||
u8 resrvd1;
|
u8 flags;
|
||||||
u8 local_port;
|
u8 local_port;
|
||||||
u8 resrvd2;
|
u8 resrvd2;
|
||||||
u8 proto_mask;
|
u8 proto_mask;
|
||||||
|
|
Loading…
Reference in New Issue