mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/stable/linux.git
synced 2024-09-06 02:50:43 +00:00
net/mlx5: Add support to ext_* fields introduced in Port Type and Speed register
This patch exposes new link modes (including 50Gbps per lane), and ext_* fields which describes the new link modes in Port Type and Speed register (PTYS). Access functions, translation functions (speed <-> HW bits) and link max speed function were modified. Signed-off-by: Aya Levin <ayal@mellanox.com> Reviewed-by: Eran Ben Elisha <eranbe@mellanox.com> Signed-off-by: Saeed Mahameed <saeedm@mellanox.com>
This commit is contained in:
parent
a0a8998956
commit
a08b4ed137
5 changed files with 94 additions and 30 deletions
|
@ -421,7 +421,8 @@ static int mlx5_query_port_roce(struct ib_device *device, u8 port_num,
|
|||
mdev_port_num);
|
||||
if (err)
|
||||
goto out;
|
||||
eth_prot_oper = MLX5_GET(ptys_reg, out, eth_proto_oper);
|
||||
eth_prot_oper = MLX5_GET_ETH_PROTO(ptys_reg, out, false,
|
||||
eth_proto_oper);
|
||||
|
||||
props->active_width = IB_WIDTH_4X;
|
||||
props->active_speed = IB_SPEED_QDR;
|
||||
|
|
|
@ -63,7 +63,31 @@ static const u32 mlx5e_link_speed[MLX5E_LINK_MODES_NUMBER] = {
|
|||
[MLX5E_50GBASE_KR2] = 50000,
|
||||
};
|
||||
|
||||
int mlx5_port_query_eth_proto(struct mlx5_core_dev *dev, u8 port,
|
||||
static const u32 mlx5e_ext_link_speed[MLX5E_EXT_LINK_MODES_NUMBER] = {
|
||||
[MLX5E_SGMII_100M] = 100,
|
||||
[MLX5E_1000BASE_X_SGMII] = 1000,
|
||||
[MLX5E_5GBASE_R] = 5000,
|
||||
[MLX5E_10GBASE_XFI_XAUI_1] = 10000,
|
||||
[MLX5E_40GBASE_XLAUI_4_XLPPI_4] = 40000,
|
||||
[MLX5E_25GAUI_1_25GBASE_CR_KR] = 25000,
|
||||
[MLX5E_50GAUI_2_LAUI_2_50GBASE_CR2_KR2] = 50000,
|
||||
[MLX5E_50GAUI_1_LAUI_1_50GBASE_CR_KR] = 50000,
|
||||
[MLX5E_CAUI_4_100GBASE_CR4_KR4] = 100000,
|
||||
[MLX5E_200GAUI_4_200GBASE_CR4_KR4] = 200000,
|
||||
[MLX5E_400GAUI_8] = 400000,
|
||||
};
|
||||
|
||||
static void mlx5e_port_get_speed_arr(struct mlx5_core_dev *mdev,
|
||||
const u32 **arr, u32 *size)
|
||||
{
|
||||
bool ext = MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet);
|
||||
|
||||
*size = ext ? ARRAY_SIZE(mlx5e_ext_link_speed) :
|
||||
ARRAY_SIZE(mlx5e_link_speed);
|
||||
*arr = ext ? mlx5e_ext_link_speed : mlx5e_link_speed;
|
||||
}
|
||||
|
||||
int mlx5_port_query_eth_proto(struct mlx5_core_dev *dev, u8 port, bool ext,
|
||||
struct mlx5e_port_eth_proto *eproto)
|
||||
{
|
||||
u32 out[MLX5_ST_SZ_DW(ptys_reg)];
|
||||
|
@ -72,13 +96,17 @@ int mlx5_port_query_eth_proto(struct mlx5_core_dev *dev, u8 port,
|
|||
if (!eproto)
|
||||
return -EINVAL;
|
||||
|
||||
if (ext != MLX5_CAP_PCAM_FEATURE(dev, ptys_extended_ethernet))
|
||||
return -EOPNOTSUPP;
|
||||
|
||||
err = mlx5_query_port_ptys(dev, out, sizeof(out), MLX5_PTYS_EN, port);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
eproto->cap = MLX5_GET(ptys_reg, out, eth_proto_capability);
|
||||
eproto->admin = MLX5_GET(ptys_reg, out, eth_proto_admin);
|
||||
eproto->oper = MLX5_GET(ptys_reg, out, eth_proto_oper);
|
||||
eproto->cap = MLX5_GET_ETH_PROTO(ptys_reg, out, ext,
|
||||
eth_proto_capability);
|
||||
eproto->admin = MLX5_GET_ETH_PROTO(ptys_reg, out, ext, eth_proto_admin);
|
||||
eproto->oper = MLX5_GET_ETH_PROTO(ptys_reg, out, ext, eth_proto_oper);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -100,7 +128,7 @@ void mlx5_port_query_eth_autoneg(struct mlx5_core_dev *dev, u8 *an_status,
|
|||
}
|
||||
|
||||
int mlx5_port_set_eth_ptys(struct mlx5_core_dev *dev, bool an_disable,
|
||||
u32 proto_admin)
|
||||
u32 proto_admin, bool ext)
|
||||
{
|
||||
u32 out[MLX5_ST_SZ_DW(ptys_reg)];
|
||||
u32 in[MLX5_ST_SZ_DW(ptys_reg)];
|
||||
|
@ -118,38 +146,46 @@ int mlx5_port_set_eth_ptys(struct mlx5_core_dev *dev, bool an_disable,
|
|||
MLX5_SET(ptys_reg, in, local_port, 1);
|
||||
MLX5_SET(ptys_reg, in, an_disable_admin, an_disable);
|
||||
MLX5_SET(ptys_reg, in, proto_mask, MLX5_PTYS_EN);
|
||||
MLX5_SET(ptys_reg, in, eth_proto_admin, proto_admin);
|
||||
if (ext)
|
||||
MLX5_SET(ptys_reg, in, ext_eth_proto_admin, proto_admin);
|
||||
else
|
||||
MLX5_SET(ptys_reg, in, eth_proto_admin, proto_admin);
|
||||
|
||||
return mlx5_core_access_reg(dev, in, sizeof(in), out,
|
||||
sizeof(out), MLX5_REG_PTYS, 0, 1);
|
||||
}
|
||||
|
||||
u32 mlx5e_port_ptys2speed(u32 eth_proto_oper)
|
||||
u32 mlx5e_port_ptys2speed(struct mlx5_core_dev *mdev, u32 eth_proto_oper)
|
||||
{
|
||||
unsigned long temp = eth_proto_oper;
|
||||
const u32 *table;
|
||||
u32 speed = 0;
|
||||
u32 max_size;
|
||||
int i;
|
||||
|
||||
i = find_first_bit(&temp, MLX5E_LINK_MODES_NUMBER);
|
||||
if (i < MLX5E_LINK_MODES_NUMBER)
|
||||
speed = mlx5e_link_speed[i];
|
||||
|
||||
mlx5e_port_get_speed_arr(mdev, &table, &max_size);
|
||||
i = find_first_bit(&temp, max_size);
|
||||
if (i < max_size)
|
||||
speed = table[i];
|
||||
return speed;
|
||||
}
|
||||
|
||||
int mlx5e_port_linkspeed(struct mlx5_core_dev *mdev, u32 *speed)
|
||||
{
|
||||
struct mlx5e_port_eth_proto eproto;
|
||||
bool ext;
|
||||
int err;
|
||||
|
||||
err = mlx5_port_query_eth_proto(mdev, 1, &eproto);
|
||||
ext = MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet);
|
||||
err = mlx5_port_query_eth_proto(mdev, 1, ext, &eproto);
|
||||
if (err)
|
||||
return err;
|
||||
goto out;
|
||||
|
||||
*speed = mlx5e_port_ptys2speed(eproto.oper);
|
||||
*speed = mlx5e_port_ptys2speed(mdev, eproto.oper);
|
||||
if (!(*speed))
|
||||
err = -EINVAL;
|
||||
|
||||
out:
|
||||
return err;
|
||||
}
|
||||
|
||||
|
@ -157,31 +193,38 @@ int mlx5e_port_max_linkspeed(struct mlx5_core_dev *mdev, u32 *speed)
|
|||
{
|
||||
struct mlx5e_port_eth_proto eproto;
|
||||
u32 max_speed = 0;
|
||||
const u32 *table;
|
||||
u32 max_size;
|
||||
bool ext;
|
||||
int err;
|
||||
int i;
|
||||
|
||||
err = mlx5_port_query_eth_proto(mdev, 1, &eproto);
|
||||
ext = MLX5_CAP_PCAM_FEATURE(mdev, ptys_extended_ethernet);
|
||||
err = mlx5_port_query_eth_proto(mdev, 1, ext, &eproto);
|
||||
if (err)
|
||||
return err;
|
||||
|
||||
for (i = 0; i < MLX5E_LINK_MODES_NUMBER; ++i)
|
||||
mlx5e_port_get_speed_arr(mdev, &table, &max_size);
|
||||
for (i = 0; i < max_size; ++i)
|
||||
if (eproto.cap & MLX5E_PROT_MASK(i))
|
||||
max_speed = max(max_speed, mlx5e_link_speed[i]);
|
||||
max_speed = max(max_speed, table[i]);
|
||||
|
||||
*speed = max_speed;
|
||||
return 0;
|
||||
}
|
||||
|
||||
u32 mlx5e_port_speed2linkmodes(u32 speed)
|
||||
u32 mlx5e_port_speed2linkmodes(struct mlx5_core_dev *mdev, u32 speed)
|
||||
{
|
||||
u32 link_modes = 0;
|
||||
const u32 *table;
|
||||
u32 max_size;
|
||||
int i;
|
||||
|
||||
for (i = 0; i < MLX5E_LINK_MODES_NUMBER; ++i) {
|
||||
if (mlx5e_link_speed[i] == speed)
|
||||
mlx5e_port_get_speed_arr(mdev, &table, &max_size);
|
||||
for (i = 0; i < max_size; ++i) {
|
||||
if (table[i] == speed)
|
||||
link_modes |= MLX5E_PROT_MASK(i);
|
||||
}
|
||||
|
||||
return link_modes;
|
||||
}
|
||||
|
||||
|
|
|
@ -42,16 +42,16 @@ struct mlx5e_port_eth_proto {
|
|||
u32 oper;
|
||||
};
|
||||
|
||||
int mlx5_port_query_eth_proto(struct mlx5_core_dev *dev, u8 port,
|
||||
int mlx5_port_query_eth_proto(struct mlx5_core_dev *dev, u8 port, bool ext,
|
||||
struct mlx5e_port_eth_proto *eproto);
|
||||
void mlx5_port_query_eth_autoneg(struct mlx5_core_dev *dev, u8 *an_status,
|
||||
u8 *an_disable_cap, u8 *an_disable_admin);
|
||||
int mlx5_port_set_eth_ptys(struct mlx5_core_dev *dev, bool an_disable,
|
||||
u32 proto_admin);
|
||||
u32 mlx5e_port_ptys2speed(u32 eth_proto_oper);
|
||||
u32 proto_admin, bool ext);
|
||||
u32 mlx5e_port_ptys2speed(struct mlx5_core_dev *mdev, u32 eth_proto_oper);
|
||||
int mlx5e_port_linkspeed(struct mlx5_core_dev *mdev, u32 *speed);
|
||||
int mlx5e_port_max_linkspeed(struct mlx5_core_dev *mdev, u32 *speed);
|
||||
u32 mlx5e_port_speed2linkmodes(u32 speed);
|
||||
u32 mlx5e_port_speed2linkmodes(struct mlx5_core_dev *mdev, u32 speed);
|
||||
|
||||
int mlx5e_port_query_pbmc(struct mlx5_core_dev *mdev, void *out);
|
||||
int mlx5e_port_set_pbmc(struct mlx5_core_dev *mdev, void *in);
|
||||
|
|
|
@ -695,13 +695,14 @@ static void get_speed_duplex(struct net_device *netdev,
|
|||
u32 eth_proto_oper,
|
||||
struct ethtool_link_ksettings *link_ksettings)
|
||||
{
|
||||
struct mlx5e_priv *priv = netdev_priv(netdev);
|
||||
u32 speed = SPEED_UNKNOWN;
|
||||
u8 duplex = DUPLEX_UNKNOWN;
|
||||
|
||||
if (!netif_carrier_ok(netdev))
|
||||
goto out;
|
||||
|
||||
speed = mlx5e_port_ptys2speed(eth_proto_oper);
|
||||
speed = mlx5e_port_ptys2speed(priv->mdev, eth_proto_oper);
|
||||
if (!speed) {
|
||||
speed = SPEED_UNKNOWN;
|
||||
goto out;
|
||||
|
@ -896,9 +897,9 @@ int mlx5e_ethtool_set_link_ksettings(struct mlx5e_priv *priv,
|
|||
|
||||
link_modes = link_ksettings->base.autoneg == AUTONEG_ENABLE ?
|
||||
mlx5e_ethtool2ptys_adver_link(link_ksettings->link_modes.advertising) :
|
||||
mlx5e_port_speed2linkmodes(speed);
|
||||
mlx5e_port_speed2linkmodes(mdev, speed);
|
||||
|
||||
err = mlx5_port_query_eth_proto(mdev, 1, &eproto);
|
||||
err = mlx5_port_query_eth_proto(mdev, 1, false, &eproto);
|
||||
if (err) {
|
||||
netdev_err(priv->netdev, "%s: query port eth proto failed: %d\n",
|
||||
__func__, err);
|
||||
|
@ -923,7 +924,7 @@ int mlx5e_ethtool_set_link_ksettings(struct mlx5e_priv *priv,
|
|||
if (!an_changes && link_modes == eproto.admin)
|
||||
goto out;
|
||||
|
||||
mlx5_port_set_eth_ptys(mdev, an_disable, link_modes);
|
||||
mlx5_port_set_eth_ptys(mdev, an_disable, link_modes, false);
|
||||
mlx5_toggle_port_link(mdev);
|
||||
|
||||
out:
|
||||
|
|
|
@ -92,6 +92,22 @@ enum mlx5e_link_mode {
|
|||
MLX5E_LINK_MODES_NUMBER,
|
||||
};
|
||||
|
||||
enum mlx5e_ext_link_mode {
|
||||
MLX5E_SGMII_100M = 0,
|
||||
MLX5E_1000BASE_X_SGMII = 1,
|
||||
MLX5E_5GBASE_R = 3,
|
||||
MLX5E_10GBASE_XFI_XAUI_1 = 4,
|
||||
MLX5E_40GBASE_XLAUI_4_XLPPI_4 = 5,
|
||||
MLX5E_25GAUI_1_25GBASE_CR_KR = 6,
|
||||
MLX5E_50GAUI_2_LAUI_2_50GBASE_CR2_KR2 = 7,
|
||||
MLX5E_50GAUI_1_LAUI_1_50GBASE_CR_KR = 8,
|
||||
MLX5E_CAUI_4_100GBASE_CR4_KR4 = 9,
|
||||
MLX5E_100GAUI_2_100GBASE_CR2_KR2 = 10,
|
||||
MLX5E_200GAUI_4_200GBASE_CR4_KR4 = 12,
|
||||
MLX5E_400GAUI_8 = 15,
|
||||
MLX5E_EXT_LINK_MODES_NUMBER,
|
||||
};
|
||||
|
||||
enum mlx5e_connector_type {
|
||||
MLX5E_PORT_UNKNOWN = 0,
|
||||
MLX5E_PORT_NONE = 1,
|
||||
|
@ -106,6 +122,9 @@ enum mlx5e_connector_type {
|
|||
};
|
||||
|
||||
#define MLX5E_PROT_MASK(link_mode) (1 << link_mode)
|
||||
#define MLX5_GET_ETH_PROTO(reg, out, ext, field) \
|
||||
(ext ? MLX5_GET(reg, out, ext_##field) : \
|
||||
MLX5_GET(reg, out, field))
|
||||
|
||||
int mlx5_set_port_caps(struct mlx5_core_dev *dev, u8 port_num, u32 caps);
|
||||
int mlx5_query_port_ptys(struct mlx5_core_dev *dev, u32 *ptys,
|
||||
|
|
Loading…
Reference in a new issue