Commit a08b4ed1 authored by Aya Levin's avatar Aya Levin Committed by Saeed Mahameed

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: default avatarAya Levin <ayal@mellanox.com>
Reviewed-by: default avatarEran Ben Elisha <eranbe@mellanox.com>
Signed-off-by: default avatarSaeed Mahameed <saeedm@mellanox.com>
parent a0a89989
...@@ -421,7 +421,8 @@ static int mlx5_query_port_roce(struct ib_device *device, u8 port_num, ...@@ -421,7 +421,8 @@ static int mlx5_query_port_roce(struct ib_device *device, u8 port_num,
mdev_port_num); mdev_port_num);
if (err) if (err)
goto out; 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_width = IB_WIDTH_4X;
props->active_speed = IB_SPEED_QDR; props->active_speed = IB_SPEED_QDR;
......
...@@ -63,7 +63,31 @@ static const u32 mlx5e_link_speed[MLX5E_LINK_MODES_NUMBER] = { ...@@ -63,7 +63,31 @@ static const u32 mlx5e_link_speed[MLX5E_LINK_MODES_NUMBER] = {
[MLX5E_50GBASE_KR2] = 50000, [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) struct mlx5e_port_eth_proto *eproto)
{ {
u32 out[MLX5_ST_SZ_DW(ptys_reg)]; 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, ...@@ -72,13 +96,17 @@ int mlx5_port_query_eth_proto(struct mlx5_core_dev *dev, u8 port,
if (!eproto) if (!eproto)
return -EINVAL; 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); err = mlx5_query_port_ptys(dev, out, sizeof(out), MLX5_PTYS_EN, port);
if (err) if (err)
return err; return err;
eproto->cap = MLX5_GET(ptys_reg, out, eth_proto_capability); eproto->cap = MLX5_GET_ETH_PROTO(ptys_reg, out, ext,
eproto->admin = MLX5_GET(ptys_reg, out, eth_proto_admin); eth_proto_capability);
eproto->oper = MLX5_GET(ptys_reg, out, eth_proto_oper); 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; return 0;
} }
...@@ -100,7 +128,7 @@ void mlx5_port_query_eth_autoneg(struct mlx5_core_dev *dev, u8 *an_status, ...@@ -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, 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 out[MLX5_ST_SZ_DW(ptys_reg)];
u32 in[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, ...@@ -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, local_port, 1);
MLX5_SET(ptys_reg, in, an_disable_admin, an_disable); 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, 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, return mlx5_core_access_reg(dev, in, sizeof(in), out,
sizeof(out), MLX5_REG_PTYS, 0, 1); 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; unsigned long temp = eth_proto_oper;
const u32 *table;
u32 speed = 0; u32 speed = 0;
u32 max_size;
int i; int i;
i = find_first_bit(&temp, MLX5E_LINK_MODES_NUMBER); mlx5e_port_get_speed_arr(mdev, &table, &max_size);
if (i < MLX5E_LINK_MODES_NUMBER) i = find_first_bit(&temp, max_size);
speed = mlx5e_link_speed[i]; if (i < max_size)
speed = table[i];
return speed; return speed;
} }
int mlx5e_port_linkspeed(struct mlx5_core_dev *mdev, u32 *speed) int mlx5e_port_linkspeed(struct mlx5_core_dev *mdev, u32 *speed)
{ {
struct mlx5e_port_eth_proto eproto; struct mlx5e_port_eth_proto eproto;
bool ext;
int err; 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) if (err)
return err; goto out;
*speed = mlx5e_port_ptys2speed(eproto.oper); *speed = mlx5e_port_ptys2speed(mdev, eproto.oper);
if (!(*speed)) if (!(*speed))
err = -EINVAL; err = -EINVAL;
out:
return err; return err;
} }
...@@ -157,31 +193,38 @@ int mlx5e_port_max_linkspeed(struct mlx5_core_dev *mdev, u32 *speed) ...@@ -157,31 +193,38 @@ int mlx5e_port_max_linkspeed(struct mlx5_core_dev *mdev, u32 *speed)
{ {
struct mlx5e_port_eth_proto eproto; struct mlx5e_port_eth_proto eproto;
u32 max_speed = 0; u32 max_speed = 0;
const u32 *table;
u32 max_size;
bool ext;
int err; int err;
int i; 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) if (err)
return 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)) 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; *speed = max_speed;
return 0; return 0;
} }
u32 mlx5e_port_speed2linkmodes(u32 speed) u32 mlx5e_port_speed2linkmodes(struct mlx5_core_dev *mdev, u32 speed)
{ {
u32 link_modes = 0; u32 link_modes = 0;
const u32 *table;
u32 max_size;
int i; int i;
for (i = 0; i < MLX5E_LINK_MODES_NUMBER; ++i) { mlx5e_port_get_speed_arr(mdev, &table, &max_size);
if (mlx5e_link_speed[i] == speed) for (i = 0; i < max_size; ++i) {
if (table[i] == speed)
link_modes |= MLX5E_PROT_MASK(i); link_modes |= MLX5E_PROT_MASK(i);
} }
return link_modes; return link_modes;
} }
......
...@@ -42,16 +42,16 @@ struct mlx5e_port_eth_proto { ...@@ -42,16 +42,16 @@ struct mlx5e_port_eth_proto {
u32 oper; 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); struct mlx5e_port_eth_proto *eproto);
void mlx5_port_query_eth_autoneg(struct mlx5_core_dev *dev, u8 *an_status, void mlx5_port_query_eth_autoneg(struct mlx5_core_dev *dev, u8 *an_status,
u8 *an_disable_cap, u8 *an_disable_admin); u8 *an_disable_cap, u8 *an_disable_admin);
int mlx5_port_set_eth_ptys(struct mlx5_core_dev *dev, bool an_disable, int mlx5_port_set_eth_ptys(struct mlx5_core_dev *dev, bool an_disable,
u32 proto_admin); u32 proto_admin, bool ext);
u32 mlx5e_port_ptys2speed(u32 eth_proto_oper); 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_linkspeed(struct mlx5_core_dev *mdev, u32 *speed);
int mlx5e_port_max_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_query_pbmc(struct mlx5_core_dev *mdev, void *out);
int mlx5e_port_set_pbmc(struct mlx5_core_dev *mdev, void *in); 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, ...@@ -695,13 +695,14 @@ static void get_speed_duplex(struct net_device *netdev,
u32 eth_proto_oper, u32 eth_proto_oper,
struct ethtool_link_ksettings *link_ksettings) struct ethtool_link_ksettings *link_ksettings)
{ {
struct mlx5e_priv *priv = netdev_priv(netdev);
u32 speed = SPEED_UNKNOWN; u32 speed = SPEED_UNKNOWN;
u8 duplex = DUPLEX_UNKNOWN; u8 duplex = DUPLEX_UNKNOWN;
if (!netif_carrier_ok(netdev)) if (!netif_carrier_ok(netdev))
goto out; goto out;
speed = mlx5e_port_ptys2speed(eth_proto_oper); speed = mlx5e_port_ptys2speed(priv->mdev, eth_proto_oper);
if (!speed) { if (!speed) {
speed = SPEED_UNKNOWN; speed = SPEED_UNKNOWN;
goto out; goto out;
...@@ -896,9 +897,9 @@ int mlx5e_ethtool_set_link_ksettings(struct mlx5e_priv *priv, ...@@ -896,9 +897,9 @@ int mlx5e_ethtool_set_link_ksettings(struct mlx5e_priv *priv,
link_modes = link_ksettings->base.autoneg == AUTONEG_ENABLE ? link_modes = link_ksettings->base.autoneg == AUTONEG_ENABLE ?
mlx5e_ethtool2ptys_adver_link(link_ksettings->link_modes.advertising) : 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) { if (err) {
netdev_err(priv->netdev, "%s: query port eth proto failed: %d\n", netdev_err(priv->netdev, "%s: query port eth proto failed: %d\n",
__func__, err); __func__, err);
...@@ -923,7 +924,7 @@ int mlx5e_ethtool_set_link_ksettings(struct mlx5e_priv *priv, ...@@ -923,7 +924,7 @@ int mlx5e_ethtool_set_link_ksettings(struct mlx5e_priv *priv,
if (!an_changes && link_modes == eproto.admin) if (!an_changes && link_modes == eproto.admin)
goto out; 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); mlx5_toggle_port_link(mdev);
out: out:
......
...@@ -92,6 +92,22 @@ enum mlx5e_link_mode { ...@@ -92,6 +92,22 @@ enum mlx5e_link_mode {
MLX5E_LINK_MODES_NUMBER, 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 { enum mlx5e_connector_type {
MLX5E_PORT_UNKNOWN = 0, MLX5E_PORT_UNKNOWN = 0,
MLX5E_PORT_NONE = 1, MLX5E_PORT_NONE = 1,
...@@ -106,6 +122,9 @@ enum mlx5e_connector_type { ...@@ -106,6 +122,9 @@ enum mlx5e_connector_type {
}; };
#define MLX5E_PROT_MASK(link_mode) (1 << link_mode) #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_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, int mlx5_query_port_ptys(struct mlx5_core_dev *dev, u32 *ptys,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment